Repository: tree-sitter/tree-sitter-scala Branch: master Commit: a68000002745 Files: 77 Total size: 31.7 MB Directory structure: gitextract_igzcqol5/ ├── .editorconfig ├── .envrc ├── .git-blame-ignore-revs ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ └── bug_report.yml │ └── workflows/ │ ├── ci.yml │ ├── fuzz.yml │ ├── publish.yml │ └── sync.yml ├── .gitignore ├── .prettierrc.json ├── CMakeLists.txt ├── CONTRIBUTING.md ├── Cargo.toml ├── LICENSE ├── Makefile ├── Package.resolved ├── Package.swift ├── README.md ├── binding.gyp ├── bindings/ │ ├── c/ │ │ ├── tree-sitter-scala.h │ │ ├── tree-sitter-scala.pc.in │ │ └── tree_sitter/ │ │ └── tree-sitter-scala.h │ ├── go/ │ │ ├── binding.go │ │ └── binding_test.go │ ├── node/ │ │ ├── binding.cc │ │ ├── binding_test.js │ │ ├── index.d.ts │ │ └── index.js │ ├── python/ │ │ ├── tests/ │ │ │ └── test_binding.py │ │ └── tree_sitter_scala/ │ │ ├── __init__.py │ │ ├── __init__.pyi │ │ ├── binding.c │ │ └── py.typed │ ├── rust/ │ │ ├── build.rs │ │ └── lib.rs │ └── swift/ │ ├── TreeSitterScala/ │ │ └── scala.h │ └── TreeSitterScalaTests/ │ └── TreeSitterScalaTests.swift ├── examples/ │ ├── Packages.scala │ ├── PathResolver.scala │ ├── RefChecks.scala │ ├── SyntaxAnalyzer.scala │ └── Variance.scala ├── go.mod ├── go.sum ├── grammar.js ├── package.json ├── pyproject.toml ├── queries/ │ ├── highlights.scm │ ├── indents.scm │ ├── locals.scm │ └── tags.scm ├── script/ │ ├── parse-with-scalac │ └── smoke_test.sh ├── setup.py ├── src/ │ ├── grammar.json │ ├── node-types.json │ ├── parser.c │ ├── scanner.c │ └── tree_sitter/ │ ├── alloc.h │ ├── array.h │ └── parser.h ├── test/ │ ├── corpus/ │ │ ├── annotations.txt │ │ ├── comments.txt │ │ ├── definitions-pending.txt │ │ ├── definitions.txt │ │ ├── expressions.txt │ │ ├── literals.txt │ │ ├── patterns-pending.txt │ │ ├── patterns.txt │ │ ├── types-pending.txt │ │ └── types.txt │ ├── highlight/ │ │ ├── basics.scala │ │ ├── comments.scala │ │ └── scala3.scala │ └── tags/ │ └── basics.scala └── tree-sitter.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 [*.{json,toml,yml,gyp}] indent_style = space indent_size = 2 [*.js] indent_style = space indent_size = 2 [*.scm] indent_style = space indent_size = 2 [*.{c,cc,h}] indent_style = space indent_size = 4 [*.rs] indent_style = space indent_size = 4 [*.{py,pyi}] indent_style = space indent_size = 4 [*.swift] indent_style = space indent_size = 4 [*.go] indent_style = tab indent_size = 8 [Makefile] indent_style = tab indent_size = 8 [parser.c] indent_size = 2 [{alloc,array,parser}.h] indent_size = 2 ================================================ FILE: .envrc ================================================ use nix ================================================ FILE: .git-blame-ignore-revs ================================================ # Move queries to ./queries/scala sub-directory 889eb65aea8e0f9ce1694ab9ee528df1fa5f75d1 # Formatting using Prettier 0a8ca4c836d7e9f0fd6a0668088c0d82874abc85 ================================================ FILE: .gitattributes ================================================ * text=auto eol=lf # Generated source files src/*.json linguist-generated src/parser.c linguist-generated src/tree_sitter/* linguist-generated # C bindings bindings/c/* linguist-generated CMakeLists.txt linguist-generated Makefile linguist-generated # Rust bindings bindings/rust/* linguist-generated Cargo.toml linguist-generated Cargo.lock linguist-generated # Node.js bindings bindings/node/* linguist-generated binding.gyp linguist-generated package.json linguist-generated package-lock.json linguist-generated # Python bindings bindings/python/** linguist-generated setup.py linguist-generated pyproject.toml linguist-generated # Go bindings bindings/go/* linguist-generated go.mod linguist-generated go.sum linguist-generated # Swift bindings bindings/swift/** linguist-generated Package.swift linguist-generated Package.resolved linguist-generated ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ name: Bug Report description: Create an issue in tree-sitter-scala body: - type: input id: commit attributes: label: Commit of tree-sitter-scala you tested this on description: | Make sure you're validating you're on the latest commit of tree-sitter-scala. Note that depending on where you're experiencing the issue there is a chance you're on an old commit. validations: required: true - type: textarea id: code-sample attributes: label: A code sample showing the error description: Try to minimize the code sample as much as possible placeholder: | ```scala val y = x match { case A(_) if a => 1 } ``` validations: required: true - type: textarea id: error attributes: label: Show the error node description: Show us the output and where the ERROR node is appearing placeholder: | Check out [Obtaining an Error Reproduction](../../CONTRIBUTING.md#obtaining-an-error-reproduction) in the CONTRIBUTING docs if you're unsure how to get this. ``` (compilation_unit [0, 0] - [4, 0] (val_definition [0, 0] - [2, 1] pattern: (identifier [0, 4] - [0, 5]) value: (match_expression [0, 8] - [2, 1] value: (identifier [0, 8] - [0, 9]) body: (case_block [0, 16] - [2, 1] (ERROR [1, 2] - [2, 0] (case_class_pattern [1, 7] - [1, 11] type: (type_identifier [1, 7] - [1, 8]) pattern: (wildcard [1, 9] - [1, 10])) (lambda_expression [1, 15] - [2, 0] (identifier [1, 15] - [1, 16]) (integer_literal [1, 20] - [1, 21]))))))) ``` validations: required: true - type: textarea id: expectation attributes: label: What do you expect the tree to look like description: Show us what you expect the tree to look like - type: input id: where attributes: label: Where are you experiencing this error? description: Let us know where you're seeing this error (nvim-treesitter etc) ================================================ FILE: .github/workflows/ci.yml ================================================ name: Build/test on: push: pull_request: branches: - master jobs: changedfiles: runs-on: ubuntu-latest outputs: all: ${{ steps.changes.outputs.all}} c: ${{ steps.changes.outputs.c }} gen: ${{ steps.changes.outputs.gen }} steps: - name: checkout tree-sitter-scala uses: actions/checkout@v6 with: fetch-depth: 10 - name: Get changed files id: changes run: | echo "all=$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | xargs)" >> $GITHUB_OUTPUT echo "c=$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep '\.\(c\|h\)$' | xargs)" >> $GITHUB_OUTPUT # Generated C code echo "gen=$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep '\.\(c\)$' | grep -v 'src/scanner.c' | grep -v 'bindings/python/tree_sitter_scala/binding.c' | xargs)" >> $GITHUB_OUTPUT test: runs-on: ${{ matrix.os }} needs: changedfiles strategy: fail-fast: true matrix: os: [ubuntu-latest, macos-latest, windows-latest] steps: - name: checkout tree-sitter-scala uses: actions/checkout@v6 with: fetch-depth: 10 - name: checkout scala/scala if: ${{ runner.os == 'Linux' }} uses: actions/checkout@v6 with: repository: scala/scala ref: v2.13.14 path: scala_scala - name: checkout scala/scala3 if: ${{ runner.os == 'Linux' }} uses: actions/checkout@v6 with: repository: scala/scala3 ref: 3.5.2 path: dotty - name: checkout lichess-org/lila if: ${{ runner.os == 'Linux' }} uses: actions/checkout@v6 with: repository: lichess-org/lila ref: 83e61b9ef617164fe1d3a5112fcc611d0e5a7ea9 path: lila - name: checkout nvim-treesitter/nvim-treesitter if: ${{ runner.os == 'Linux' }} uses: actions/checkout@v6 with: repository: nvim-treesitter/nvim-treesitter path: nvim_treesitter - uses: actions/setup-node@v6 with: node-version: 24 - name: Set up tree-sitter uses: tree-sitter/setup-action/cli@v2 with: # Change also on sync.yaml tree-sitter-ref: v0.26.8 - name: Generate parser from scratch and test it shell: bash run: tree-sitter generate - name: Run parser and binding tests uses: tree-sitter/parser-test-action@v2 with: generate: false test-rust: true test-node: false test-python: true test-go: true test-swift: false - name: Parse sample files uses: tree-sitter/parse-action@v4 id: parse-files with: files: examples/** - name: Check fidelity of checked-in C code if: ${{ runner.os == 'Linux' && needs.changedfiles.outputs.gen }} shell: bash run: | # `git diff --quiet` doesn't seem to work on Github Actions changes=$(git diff --name-only --diff-filter=ACMRT | xargs) if [ ! -z "$changes" ]; then echo "::error file=grammar.js::Generated $changes differs from the checked in version" git diff --exit-code exit 1 fi - name: Smoke test if: ${{ runner.os == 'Linux' }} shell: bash env: SCALA_SCALA_DIR: scala_scala DOTTY_DIR: dotty LILA_DIR: lila run: script/smoke_test.sh - name: Check that prettier exists if: ${{ runner.os == 'Linux' }} run: | npm install export PATH=./node_modules/.bin:$PATH prettier --write --ignore-unknown grammar.js - name: copy nvim-treesitter queries if: ${{ runner.os == 'Linux' }} shell: bash run: cp ./nvim_treesitter/runtime/queries/scala/*.scm ./queries/ - name: Check if queries are out of sync with nvim-treesitter if: ${{ runner.os == 'Linux' }} uses: tj-actions/verify-changed-files@v19 id: verify-changed-files with: files: | queries/*.scm # TODO: uncomment when this works # - name: Test quries if out of sync with nvim-treesitter # if: steps.verify-changed-files.outputs.files_changed == 'true' # run: | # echo "::warning Queries in ${{ steps.verify-changed-files.outputs.changed_files }} in this repo are out of sync with nvim-treesitter" # git diff queries/ # npm run test ================================================ FILE: .github/workflows/fuzz.yml ================================================ name: Fuzz Parser on: push: branches: [master] paths: - src/scanner.c pull_request: paths: - src/scanner.c jobs: fuzz: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Run fuzzer uses: tree-sitter/fuzz-action@v4 ================================================ FILE: .github/workflows/publish.yml ================================================ name: Publish packages on: push: tags: ["*"] permissions: contents: write id-token: write attestations: write jobs: github: uses: tree-sitter/workflows/.github/workflows/release.yml@6a7388cecfbc00765d032b2fca8f8abbe092ae8d with: generate: true npm: uses: tree-sitter/workflows/.github/workflows/package-npm.yml@6a7388cecfbc00765d032b2fca8f8abbe092ae8d secrets: NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} with: generate: true crates: uses: tree-sitter/workflows/.github/workflows/package-crates.yml@6a7388cecfbc00765d032b2fca8f8abbe092ae8d secrets: CARGO_REGISTRY_TOKEN: ${{secrets.CARGO_REGISTRY_TOKEN}} with: generate: true pypi: uses: tree-sitter/workflows/.github/workflows/package-pypi.yml@6a7388cecfbc00765d032b2fca8f8abbe092ae8d secrets: PYPI_API_TOKEN: ${{secrets.PYPI_API_TOKEN}} with: generate: true ================================================ FILE: .github/workflows/sync.yml ================================================ name: "Check changes and sync" on: workflow_dispatch: schedule: - cron: 0 5 * * * jobs: check-and-sync: runs-on: ubuntu-latest if: github.repository == 'tree-sitter/tree-sitter-scala' outputs: all: ${{ steps.changes.outputs.all}} c: ${{ steps.changes.outputs.c }} steps: - name: checkout tree-sitter-scala uses: actions/checkout@v6 with: fetch-depth: 10 - name: Set up tree-sitter uses: tree-sitter/setup-action/cli@v2 with: tree-sitter-ref: v0.26.8 - name: Generate parser from scratch shell: bash run: tree-sitter generate - name: Format Javascipt run: | npm install export PATH=./node_modules/.bin:$PATH prettier --write --ignore-unknown grammar.js - name: Check for changes uses: tj-actions/verify-changed-files@v19 id: verify-changed-files with: files: | bindings/c/tree-sitter-scala.h bindings/c/tree-sitter-scala.pc.in grammar.js src/grammar.json src/node-types.json src/parser.c src/tree_sitter/alloc.h src/tree_sitter/array.h src/tree_sitter/parser.h - name: Commit changes if necessary if: steps.verify-changed-files.outputs.files_changed == 'true' run: | git config user.name "GitHub" git config user.email "noreply@github.com" git add . LAST_COMMIT=$(git log --format="%H" -n 1) git commit -m "chore: generate and sync from $LAST_COMMIT" git clean -xf - name: Create Pull Request if: steps.verify-changed-files.outputs.files_changed == 'true' uses: peter-evans/create-pull-request@v8 with: title: "chore: generate and sync latest changes" branch: generation base: ${{ github.head_ref }} - name: No changes detected if: steps.verify-changed-files.outputs.files_changed == 'false' run: echo "No changes detected" ================================================ FILE: .gitignore ================================================ # Rust artifacts target/ # Node artifacts build/ prebuilds/ node_modules/ # Swift artifacts .build/ # Go artifacts _obj/ # Python artifacts .venv/ dist/ *.egg-info *.whl # C artifacts *.a *.so *.so.* *.dylib *.dll *.pc # Example dirs /examples/*/ # Grammar volatiles *.wasm *.obj *.o # Archives *.tar.gz *.tgz *.zip # Scala tooling .metals .bsp .scala-build # AI assistants .aider* ================================================ FILE: .prettierrc.json ================================================ { "arrowParens": "avoid" } ================================================ FILE: CMakeLists.txt ================================================ cmake_minimum_required(VERSION 3.13) project(tree-sitter-scala VERSION "0.26.0" DESCRIPTION "Scala grammar for tree-sitter" HOMEPAGE_URL "https://github.com/tree-sitter/tree-sitter-scala" LANGUAGES C) option(BUILD_SHARED_LIBS "Build using shared libraries" ON) option(TREE_SITTER_REUSE_ALLOCATOR "Reuse the library allocator" OFF) set(TREE_SITTER_ABI_VERSION 15 CACHE STRING "Tree-sitter ABI version") if(NOT ${TREE_SITTER_ABI_VERSION} MATCHES "^[0-9]+$") unset(TREE_SITTER_ABI_VERSION CACHE) message(FATAL_ERROR "TREE_SITTER_ABI_VERSION must be an integer") endif() include(GNUInstallDirs) find_program(TREE_SITTER_CLI tree-sitter DOC "Tree-sitter CLI") add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json" "${CMAKE_CURRENT_SOURCE_DIR}/src/node-types.json" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/grammar.js" COMMAND "${TREE_SITTER_CLI}" generate grammar.js --no-parser WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMENT "Generating grammar.json") add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/src/parser.c" BYPRODUCTS "${CMAKE_CURRENT_SOURCE_DIR}/src/tree_sitter/parser.h" "${CMAKE_CURRENT_SOURCE_DIR}/src/tree_sitter/alloc.h" "${CMAKE_CURRENT_SOURCE_DIR}/src/tree_sitter/array.h" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/src/grammar.json" COMMAND "${TREE_SITTER_CLI}" generate src/grammar.json --abi=${TREE_SITTER_ABI_VERSION} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMENT "Generating parser.c") add_library(tree-sitter-scala src/parser.c) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src/scanner.c) target_sources(tree-sitter-scala PRIVATE src/scanner.c) endif() target_include_directories(tree-sitter-scala PRIVATE src INTERFACE $ $) target_compile_definitions(tree-sitter-scala PRIVATE $<$:TREE_SITTER_REUSE_ALLOCATOR> $<$:TREE_SITTER_DEBUG>) set_target_properties(tree-sitter-scala PROPERTIES C_STANDARD 11 POSITION_INDEPENDENT_CODE ON SOVERSION "${TREE_SITTER_ABI_VERSION}.${PROJECT_VERSION_MAJOR}" DEFINE_SYMBOL "") configure_file(bindings/c/tree-sitter-scala.pc.in "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-scala.pc" @ONLY) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bindings/c/tree_sitter" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" FILES_MATCHING PATTERN "*.h") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/tree-sitter-scala.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") install(TARGETS tree-sitter-scala LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") file(GLOB QUERIES queries/*.scm) install(FILES ${QUERIES} DESTINATION "${CMAKE_INSTALL_DATADIR}/tree-sitter/queries/scala") add_custom_target(ts-test "${TREE_SITTER_CLI}" test WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMMENT "tree-sitter test") ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to tree-sitter-scala First off, thanks for being willing to contribute to making syntax highlighting in Scala better! This document will hopefully help you get set up, understand how to work on the codebase, or link to places to help you understand tree-sitter. ## Requirements - [tree-sitter CLI](https://github.com/tree-sitter/tree-sitter/tree/master/cli) - Node.js version 18.0 or greater - C Compiler Refer to the [tree-sitter documentation](https://tree-sitter.github.io/tree-sitter/creating-parsers/1-getting-started.html) for more details and specifics. If you use nix you can enter a nix-shell (`nix-shell .`) which will install them for you. ## Getting Started To get started with contributing to the grammar you'll first need to install the project's dependencies: ```sh npm install ``` The general flow will often start with adding a test case to `./test/corpus`. You can find details on how testing works with tree-sitter [here](https://tree-sitter.github.io/tree-sitter/creating-parsers/5-writing-tests.html). Once you've added your test case you'll want to then make the required changes to `grammar.js`, regenerate and recompile the parser, and run the tests: ```sh tree-sitter generate tree-sitter test ``` Then adjust as necessary. Note that depending on your change you may also have to touch the `/src/scanner.c` file if you need more advanced features like look-ahead. ## Pending Tests In `./test/corpus`, there are several files named `*-pending.txt`. These contain tests labeled with `:skip`, meaning they are not currently run. Each test includes examples of valid Scala syntax that `tree-sitter-scala` is known to fail to parse. If you’d like to contribute to `tree-sitter-scala`, a good place to start is by trying to fix one of these tests. ## Syntax highlighting Right now the most common use-case for syntax highlight using tree-sitter is [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter), which means much of our testing is in relation to it. You can find the syntax highlighting tests in `test/highlight/*.scala`. You can read more about this type of testing [here](https://tree-sitter.github.io/tree-sitter/3-syntax-highlighting.html#unit-testing). These test will be run automatically with `tree-sitter test`. ### tree-sitter highlight Another way to test your syntax highlighting locally is to use the `tree-sitter highlight` command. Note that you'll need to have `tree-sitter` installed globally for this to work. Once you have it installed you'll want to follow the instructions [here](https://tree-sitter.github.io/tree-sitter/3-syntax-highlighting.html#overview) to setup a local config that points towards this repo to be used as a parser. Once done you can then do the following: ```sh tree-sitter highlight some/scala/file.scala ``` And see the syntax highlighting spit out. This is also the format used for testing, so it provides an easy way to get the output we use for testing. ## Generation In order to help not cause conflicts with multiple prs being open at the same time, we don't check in the parser on each pr. Instead, just check in the changes to the `grammar.js` and the CI will take care of the rest. Each night if changes are detected it will automatically be generated. ## Smoke testing You'll noticed that there is a part of CI that checks parsing against the Scala 2 and Scala 3 repositories to ensure we don't introduce unexpected regressions. The script for this is in `script/smoke_test.sh`. If you're change is increasing the coverage in either the library or compiler, please do update the expected percentages at the top of the file. ## Obtaining an error reproduction _With Neovim_ When creating an issue you'll want to ensure to include the `ERROR` node in it's context. There's a couple ways to do this. If you're using Neovim and utilizing treesitter, you can see the tree with `:lua vim.treesitter.show_tree()`. You can copy it directly from the open panel. _Manually_ A manual way to get this would be to ensure that when you're in the repo you have the latest parser with ```sh npm run build ``` Then you can copy your Scala code in a file and pass that file into `npm run parse`: ``` tree-sitter parse ``` Then the tree will be printed out for you to copy. ## Release 1. Update `version` in `tree-sitte.json` 2. Update `version` in `package.json`, then run `npm install` 3. Update `VERSION` in `CMakeLists.txt` 4. Update `VERSION` in `Makefile` 5. Update `version` in `Cargo.toml`, then run `cargo build` 6. Update `version` in `pyproject.toml` ================================================ FILE: Cargo.toml ================================================ [package] name = "tree-sitter-scala" description = "Scala grammar for tree-sitter" version = "0.26.0" authors = ["Max Brunsfeld "] license = "MIT" readme = "README.md" keywords = ["incremental", "parsing", "tree-sitter", "scala"] categories = ["parsing", "text-editors"] repository = "https://github.com/tree-sitter/tree-sitter-scala" edition = "2021" autoexamples = false build = "bindings/rust/build.rs" include = ["LICENSE", "bindings/rust/*", "grammar.js", "queries/*", "src/*", "tree-sitter.json"] [lib] path = "bindings/rust/lib.rs" [dependencies] tree-sitter-language = "0.1" [build-dependencies] cc = "1.1" [dev-dependencies] tree-sitter = "0.26" ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2018 Max Brunsfeld and GitHub Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ ifeq ($(OS),Windows_NT) $(error Windows is not supported) endif LANGUAGE_NAME := tree-sitter-scala HOMEPAGE_URL := https://github.com/tree-sitter/tree-sitter-scala VERSION := 0.26.0 # repository SRC_DIR := src TS ?= tree-sitter # install directory layout PREFIX ?= /usr/local INCLUDEDIR ?= $(PREFIX)/include LIBDIR ?= $(PREFIX)/lib PCLIBDIR ?= $(LIBDIR)/pkgconfig # source/object files PARSER := $(SRC_DIR)/parser.c EXTRAS := $(filter-out $(PARSER),$(wildcard $(SRC_DIR)/*.c)) OBJS := $(patsubst %.c,%.o,$(PARSER) $(EXTRAS)) # flags ARFLAGS ?= rcs override CFLAGS += -I$(SRC_DIR) -std=c11 -fPIC # ABI versioning SONAME_MAJOR = $(shell sed -n 's/\#define LANGUAGE_VERSION //p' $(PARSER)) SONAME_MINOR = $(word 1,$(subst ., ,$(VERSION))) # OS-specific bits ifeq ($(shell uname),Darwin) SOEXT = dylib SOEXTVER_MAJOR = $(SONAME_MAJOR).$(SOEXT) SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).$(SOEXT) LINKSHARED = -dynamiclib -Wl,-install_name,$(LIBDIR)/lib$(LANGUAGE_NAME).$(SOEXTVER),-rpath,@executable_path/../Frameworks else SOEXT = so SOEXTVER_MAJOR = $(SOEXT).$(SONAME_MAJOR) SOEXTVER = $(SOEXT).$(SONAME_MAJOR).$(SONAME_MINOR) LINKSHARED = -shared -Wl,-soname,lib$(LANGUAGE_NAME).$(SOEXTVER) endif ifneq ($(filter $(shell uname),FreeBSD NetBSD DragonFly),) PCLIBDIR := $(PREFIX)/libdata/pkgconfig endif all: lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a: $(OBJS) $(AR) $(ARFLAGS) $@ $^ lib$(LANGUAGE_NAME).$(SOEXT): $(OBJS) $(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@ ifneq ($(STRIP),) $(STRIP) $@ endif $(LANGUAGE_NAME).pc: bindings/c/$(LANGUAGE_NAME).pc.in sed -e 's|@PROJECT_VERSION@|$(VERSION)|' \ -e 's|@CMAKE_INSTALL_LIBDIR@|$(LIBDIR:$(PREFIX)/%=%)|' \ -e 's|@CMAKE_INSTALL_INCLUDEDIR@|$(INCLUDEDIR:$(PREFIX)/%=%)|' \ -e 's|@PROJECT_DESCRIPTION@|$(DESCRIPTION)|' \ -e 's|@PROJECT_HOMEPAGE_URL@|$(HOMEPAGE_URL)|' \ -e 's|@CMAKE_INSTALL_PREFIX@|$(PREFIX)|' $< > $@ $(PARSER): $(SRC_DIR)/grammar.json $(TS) generate $^ install: all install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter '$(DESTDIR)$(PCLIBDIR)' '$(DESTDIR)$(LIBDIR)' install -m644 bindings/c/$(LANGUAGE_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h install -m644 $(LANGUAGE_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc install -m644 lib$(LANGUAGE_NAME).a '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a install -m755 lib$(LANGUAGE_NAME).$(SOEXT) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) ln -sf lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) uninstall: $(RM) '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).a \ '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER) \ '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXTVER_MAJOR) \ '$(DESTDIR)$(LIBDIR)'/lib$(LANGUAGE_NAME).$(SOEXT) \ '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/$(LANGUAGE_NAME).h \ '$(DESTDIR)$(PCLIBDIR)'/$(LANGUAGE_NAME).pc clean: $(RM) $(OBJS) $(LANGUAGE_NAME).pc lib$(LANGUAGE_NAME).a lib$(LANGUAGE_NAME).$(SOEXT) test: $(TS) test .PHONY: all install uninstall clean test ================================================ FILE: Package.resolved ================================================ { "object": { "pins": [ { "package": "SwiftTreeSitter", "repositoryURL": "https://github.com/ChimeHQ/SwiftTreeSitter", "state": { "branch": null, "revision": "2599e95310b3159641469d8a21baf2d3d200e61f", "version": "0.8.0" } } ] }, "version": 1 } ================================================ FILE: Package.swift ================================================ // swift-tools-version:5.3 import PackageDescription let package = Package( name: "TreeSitterScala", products: [ .library(name: "TreeSitterScala", targets: ["TreeSitterScala"]), ], dependencies: [ .package(url: "https://github.com/ChimeHQ/SwiftTreeSitter", from: "0.8.0"), ], targets: [ .target( name: "TreeSitterScala", dependencies: [], path: ".", sources: [ "src/parser.c", "src/scanner.c", ], resources: [ .copy("queries") ], publicHeadersPath: "bindings/swift", cSettings: [.headerSearchPath("src")] ), .testTarget( name: "TreeSitterScalaTests", dependencies: [ "SwiftTreeSitter", "TreeSitterScala", ], path: "bindings/swift/TreeSitterScalaTests" ) ], cLanguageStandard: .c11 ) ================================================ FILE: README.md ================================================ # tree-sitter-scala [![CI][ci]](https://github.com/tree-sitter/tree-sitter-scala/actions/workflows/ci.yml) [![discord][discord]](https://discord.gg/w7nTvsVJhm) [![matrix][matrix]](https://matrix.to/#/#tree-sitter-chat:matrix.org) [![crates][crates]](https://crates.io/crates/tree-sitter-scala) [![npm][npm]](https://www.npmjs.com/package/tree-sitter-scala) Scala grammar for [tree-sitter](https://github.com/tree-sitter/tree-sitter) covering both Scala 2 and 3. ## References _Scala 2_ - [The Scala 2 Language Specification](https://www.scala-lang.org/files/archive/spec/2.13/) - [Scala 2 Syntax Summary](https://www.scala-lang.org/files/archive/spec/2.13/13-syntax-summary.html) _Scala 3_ - [Scala 3 Syntax Summary](https://docs.scala-lang.org/scala3/reference/syntax.html) ## Development and Contributing Please refer to the [CONTRIBUTING.md](./CONTRIBUTING.md) for instructions on getting set up. [ci]: https://img.shields.io/github/actions/workflow/status/tree-sitter/tree-sitter-scala/ci.yml?logo=github&label=CI [discord]: https://img.shields.io/discord/1063097320771698699?logo=discord&label=discord [matrix]: https://img.shields.io/matrix/tree-sitter-chat%3Amatrix.org?logo=matrix&label=matrix [npm]: https://img.shields.io/npm/v/tree-sitter-scala?logo=npm [crates]: https://img.shields.io/crates/v/tree-sitter-scala?logo=rust ================================================ FILE: binding.gyp ================================================ { "targets": [ { "target_name": "tree_sitter_scala_binding", "dependencies": [ " typedef struct TSLanguage TSLanguage; extern "C" TSLanguage *tree_sitter_scala(); // "tree-sitter", "language" hashed with BLAKE2 const napi_type_tag LANGUAGE_TYPE_TAG = { 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16 }; Napi::Object Init(Napi::Env env, Napi::Object exports) { exports["name"] = Napi::String::New(env, "scala"); auto language = Napi::External::New(env, tree_sitter_scala()); language.TypeTag(&LANGUAGE_TYPE_TAG); exports["language"] = language; return exports; } NODE_API_MODULE(tree_sitter_scala_binding, Init) ================================================ FILE: bindings/node/binding_test.js ================================================ const assert = require("node:assert"); const { test } = require("node:test"); const Parser = require("tree-sitter"); test("can load grammar", () => { const parser = new Parser(); assert.doesNotThrow(() => parser.setLanguage(require("."))); }); ================================================ FILE: bindings/node/index.d.ts ================================================ type BaseNode = { type: string; named: boolean; }; type ChildNode = { multiple: boolean; required: boolean; types: BaseNode[]; }; type NodeInfo = | (BaseNode & { subtypes: BaseNode[]; }) | (BaseNode & { fields: { [name: string]: ChildNode }; children: ChildNode[]; }); type Language = { name: string; language: unknown; nodeTypeInfo: NodeInfo[]; }; declare const language: Language; export = language; ================================================ FILE: bindings/node/index.js ================================================ const root = require("path").join(__dirname, "..", ".."); module.exports = typeof process.versions.bun === "string" // Support `bun build --compile` by being statically analyzable enough to find the .node file at build-time ? require(`../../prebuilds/${process.platform}-${process.arch}/tree-sitter-scala.node`) : require("node-gyp-build")(root); try { module.exports.nodeTypeInfo = require("../../src/node-types.json"); } catch (_) {} ================================================ FILE: bindings/python/tests/test_binding.py ================================================ from unittest import TestCase import tree_sitter, tree_sitter_scala class TestLanguage(TestCase): def test_can_load_grammar(self): try: tree_sitter.Language(tree_sitter_scala.language()) except Exception: self.fail("Error loading Scala grammar") ================================================ FILE: bindings/python/tree_sitter_scala/__init__.py ================================================ """Scala grammar for tree-sitter""" from importlib.resources import files as _files from ._binding import language def _get_query(name, file): query = _files(f"{__package__}.queries") / file globals()[name] = query.read_text() return globals()[name] def __getattr__(name): if name == "HIGHLIGHTS_QUERY": return _get_query("HIGHLIGHTS_QUERY", "highlights.scm") if name == "LOCALS_QUERY": return _get_query("LOCALS_QUERY", "locals.scm") raise AttributeError(f"module {__name__!r} has no attribute {name!r}") __all__ = [ "language", "HIGHLIGHTS_QUERY", "LOCALS_QUERY", ] def __dir__(): return sorted(__all__ + [ "__all__", "__builtins__", "__cached__", "__doc__", "__file__", "__loader__", "__name__", "__package__", "__path__", "__spec__", ]) ================================================ FILE: bindings/python/tree_sitter_scala/__init__.pyi ================================================ from typing import Final HIGHLIGHTS_QUERY: Final[str] LOCALS_QUERY: Final[str] def language() -> object: ... ================================================ FILE: bindings/python/tree_sitter_scala/binding.c ================================================ #include typedef struct TSLanguage TSLanguage; TSLanguage *tree_sitter_scala(void); static PyObject* _binding_language(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) { return PyCapsule_New(tree_sitter_scala(), "tree_sitter.Language", NULL); } static PyMethodDef methods[] = { {"language", _binding_language, METH_NOARGS, "Get the tree-sitter language for this grammar."}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef module = { .m_base = PyModuleDef_HEAD_INIT, .m_name = "_binding", .m_doc = NULL, .m_size = -1, .m_methods = methods }; PyMODINIT_FUNC PyInit__binding(void) { return PyModule_Create(&module); } ================================================ FILE: bindings/python/tree_sitter_scala/py.typed ================================================ ================================================ FILE: bindings/rust/build.rs ================================================ fn main() { let src_dir = std::path::Path::new("src"); let mut c_config = cc::Build::new(); c_config .std("c11") .include(src_dir) .flag_if_supported("-Wno-unused"); #[cfg(target_env = "msvc")] c_config.flag("-utf-8"); let parser_path = src_dir.join("parser.c"); c_config.file(&parser_path); println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap()); let scanner_path = src_dir.join("scanner.c"); c_config.file(&scanner_path); println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap()); c_config.compile("tree-sitter-scala"); } ================================================ FILE: bindings/rust/lib.rs ================================================ //! This crate provides Scala language support for the [tree-sitter][] parsing library. //! //! Typically, you will use the [LANGUAGE][] constant to add this language to a //! tree-sitter [Parser][], and then use the parser to parse some code: //! //! ``` //! use tree_sitter::Parser; //! //! let code = r#" //! object Hello { //! def main(args: Array[String]) = { //! println("Hello, world") //! } //! } //! "#; //! let mut parser = Parser::new(); //! let language = tree_sitter_scala::LANGUAGE; //! parser //! .set_language(&language.into()) //! .expect("Error loading Scala parser"); //! let tree = parser.parse(code, None).unwrap(); //! assert!(!tree.root_node().has_error()); //! ``` //! //! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html //! [tree-sitter]: https://tree-sitter.github.io/ use tree_sitter_language::LanguageFn; extern "C" { fn tree_sitter_scala() -> *const (); } /// The tree-sitter [`LanguageFn`][LanguageFn] for this grammar. /// /// [LanguageFn]: https://docs.rs/tree-sitter-language/*/tree_sitter_language/struct.LanguageFn.html pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_scala) }; /// The content of the [`node-types.json`][] file for this grammar. /// /// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types pub const NODE_TYPES: &str = include_str!("../../src/node-types.json"); /// The syntax highlighting query for this language. pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm"); /// The local-variable syntax highlighting query for this language. pub const LOCALS_QUERY: &str = include_str!("../../queries/locals.scm"); #[cfg(test)] mod tests { #[test] fn test_can_load_grammar() { let mut parser = tree_sitter::Parser::new(); parser .set_language(&super::LANGUAGE.into()) .expect("Error loading Scala parser"); } } ================================================ FILE: bindings/swift/TreeSitterScala/scala.h ================================================ #ifndef TREE_SITTER_SCALA_H_ #define TREE_SITTER_SCALA_H_ typedef struct TSLanguage TSLanguage; #ifdef __cplusplus extern "C" { #endif const TSLanguage *tree_sitter_scala(void); #ifdef __cplusplus } #endif #endif // TREE_SITTER_SCALA_H_ ================================================ FILE: bindings/swift/TreeSitterScalaTests/TreeSitterScalaTests.swift ================================================ import XCTest import SwiftTreeSitter import TreeSitterScala final class TreeSitterScalaTests: XCTestCase { func testCanLoadGrammar() throws { let parser = Parser() let language = Language(language: tree_sitter_scala()) XCTAssertNoThrow(try parser.setLanguage(language), "Error loading Scala grammar") } } ================================================ FILE: examples/Packages.scala ================================================ package a.b package c { object A } package c { package object d { val hello: String = "there" } } ================================================ FILE: examples/PathResolver.scala ================================================ /* NSC -- new Scala compiler * Copyright 2006-2013 LAMP/EPFL * @author Paul Phillips */ package scala package tools package util import java.net.URL import scala.tools.reflect.WrappedProperties.AccessControl import scala.tools.nsc.Settings import scala.tools.nsc.util.ClassPath import scala.reflect.io.{Directory, File, Path} import PartialFunction.condOpt import scala.tools.nsc.classpath._ // Loosely based on the draft specification at: // https://wiki.scala-lang.org/display/SIW/Classpath object PathResolver { // Imports property/environment functions which suppress security exceptions. import AccessControl._ import java.lang.System.{lineSeparator => EOL} implicit class MkLines(val t: TraversableOnce[_]) extends AnyVal { def mkLines: String = t.mkString("", EOL, EOL) def mkLines(header: String, indented: Boolean = false, embraced: Boolean = false): String = { val space = "\u0020" val sep = if (indented) EOL + space * 2 else EOL val (lbrace, rbrace) = if (embraced) (space + "{", EOL + "}") else ("", "") t.mkString(header + lbrace + sep, sep, rbrace + EOL) } } implicit class AsLines(val s: String) extends AnyVal { // sm"""...""" could do this in one pass def asLines = s.trim.stripMargin.lines.mkLines } /** pretty print class path */ def ppcp(s: String) = ClassPath.split(s) match { case Nil => "" case Seq(x) => x case xs => xs.mkString(EOL, EOL, "") } /** Values found solely by inspecting environment or property variables. */ object Environment { import scala.collection.JavaConverters._ private def searchForBootClasspath = System.getProperties.asScala collectFirst { case (k, v) if k endsWith ".boot.class.path" => v } getOrElse "" /** Environment variables which java pays attention to so it * seems we do as well. */ def sourcePathEnv = envOrElse("SOURCEPATH", "") def javaBootClassPath = propOrElse("sun.boot.class.path", searchForBootClasspath) def javaExtDirs = propOrEmpty("java.ext.dirs") def scalaHome = propOrEmpty("scala.home") def scalaExtDirs = propOrEmpty("scala.ext.dirs") /** The java classpath and whether to use it. */ def javaUserClassPath = propOrElse("java.class.path", "") def useJavaClassPath = propOrFalse("scala.usejavacp") override def toString = s""" |object Environment { | scalaHome = $scalaHome (useJavaClassPath = $useJavaClassPath) | javaBootClassPath = <${javaBootClassPath.length} chars> | javaExtDirs = ${ppcp(javaExtDirs)} | javaUserClassPath = ${ppcp(javaUserClassPath)} | scalaExtDirs = ${ppcp(scalaExtDirs)} |}""".asLines } /** Default values based on those in Environment as interpreted according * to the path resolution specification. */ object Defaults { def scalaSourcePath = Environment.sourcePathEnv def javaBootClassPath = Environment.javaBootClassPath def javaUserClassPath = Environment.javaUserClassPath def javaExtDirs = Environment.javaExtDirs def useJavaClassPath = Environment.useJavaClassPath def scalaHome = Environment.scalaHome def scalaHomeDir = Directory(scalaHome) def scalaLibDir = Directory(scalaHomeDir / "lib") def scalaClassesDir = Directory(scalaHomeDir / "classes") def scalaLibAsJar = File(scalaLibDir / "scala-library.jar") def scalaLibAsDir = Directory(scalaClassesDir / "library") def scalaLibDirFound: Option[Directory] = if (scalaLibAsJar.isFile) Some(scalaLibDir) else if (scalaLibAsDir.isDirectory) Some(scalaClassesDir) else None def scalaLibFound = if (scalaLibAsJar.isFile) scalaLibAsJar.path else if (scalaLibAsDir.isDirectory) scalaLibAsDir.path else "" // TODO It must be time for someone to figure out what all these things // are intended to do. This is disabled here because it was causing all // the scala jars to end up on the classpath twice: one on the boot // classpath as set up by the runner (or regular classpath under -nobootcp) // and then again here. def scalaBootClassPath = "" def scalaExtDirs = Environment.scalaExtDirs def scalaPluginPath = (scalaHomeDir / "misc" / "scala-devel" / "plugins").path override def toString = s""" |object Defaults { | scalaHome = $scalaHome | javaBootClassPath = ${ppcp(javaBootClassPath)} | scalaLibDirFound = $scalaLibDirFound | scalaLibFound = $scalaLibFound | scalaBootClassPath = ${ppcp(scalaBootClassPath)} | scalaPluginPath = ${ppcp(scalaPluginPath)} |}""".asLines } /** Locations discovered by supplemental heuristics. */ object SupplementalLocations { /** The platform-specific support jar. * * Usually this is `tools.jar` in the jdk/lib directory of the platform distribution. * * The file location is determined by probing the lib directory under JDK_HOME or JAVA_HOME, * if one of those environment variables is set, then the lib directory under java.home, * and finally the lib directory under the parent of java.home. Or, as a last resort, * search deeply under those locations (except for the parent of java.home, on the notion * that if this is not a canonical installation, then that search would have little * chance of succeeding). */ def platformTools: Option[File] = { val jarName = "tools.jar" def jarPath(path: Path) = (path / "lib" / jarName).toFile def jarAt(path: Path) = { val f = jarPath(path) if (f.isFile) Some(f) else None } val jdkDir = { val d = Directory(jdkHome) if (d.isDirectory) Some(d) else None } def deeply(dir: Directory) = dir.deepFiles find (_.name == jarName) val home = envOrSome("JDK_HOME", envOrNone("JAVA_HOME")) map (p => Path(p)) val install = Some(Path(javaHome)) (home flatMap jarAt) orElse (install flatMap jarAt) orElse (install map (_.parent) flatMap jarAt) orElse (jdkDir flatMap deeply) } override def toString = s""" |object SupplementalLocations { | platformTools = $platformTools |}""".asLines } /** With no arguments, show the interesting values in Environment and Defaults. * If there are arguments, show those in Calculated as if those options had been * given to a scala runner. */ def main(args: Array[String]): Unit = if (args.isEmpty) { println(Environment) println(Defaults) } else { val settings = new Settings() val rest = settings.processArguments(args.toList, processAll = false)._2 val pr = new PathResolver(settings) println("COMMAND: 'scala %s'".format(args.mkString(" "))) println("RESIDUAL: 'scala %s'\n".format(rest.mkString(" "))) pr.result match { case cp: AggregateClassPath => println(s"ClassPath has ${cp.aggregates.size} entries and results in:\n${cp.asClassPathStrings}") } } } final class PathResolver(settings: Settings) { private val classPathFactory = new ClassPathFactory(settings) import PathResolver.{ AsLines, Defaults, ppcp } private def cmdLineOrElse(name: String, alt: String) = { (commandLineFor(name) match { case Some("") => None case x => x }) getOrElse alt } private def commandLineFor(s: String): Option[String] = condOpt(s) { case "javabootclasspath" => settings.javabootclasspath.value case "javaextdirs" => settings.javaextdirs.value case "bootclasspath" => settings.bootclasspath.value case "extdirs" => settings.extdirs.value case "classpath" | "cp" => settings.classpath.value case "sourcepath" => settings.sourcepath.value } /** Calculated values based on any given command line options, falling back on * those in Defaults. */ object Calculated { def scalaHome = Defaults.scalaHome def useJavaClassPath = settings.usejavacp.value || Defaults.useJavaClassPath def useManifestClassPath= settings.usemanifestcp.value def javaBootClassPath = cmdLineOrElse("javabootclasspath", Defaults.javaBootClassPath) def javaExtDirs = cmdLineOrElse("javaextdirs", Defaults.javaExtDirs) def javaUserClassPath = if (useJavaClassPath) Defaults.javaUserClassPath else "" def scalaBootClassPath = cmdLineOrElse("bootclasspath", Defaults.scalaBootClassPath) def scalaExtDirs = cmdLineOrElse("extdirs", Defaults.scalaExtDirs) /** Scaladoc doesn't need any bootstrapping, otherwise will create errors such as: * [scaladoc] ../scala-trunk/src/reflect/scala/reflect/macros/Reifiers.scala:89: error: object api is not a member of package reflect * [scaladoc] case class ReificationException(val pos: reflect.api.PositionApi, val msg: String) extends Throwable(msg) * [scaladoc] ^ * because the bootstrapping will look at the sourcepath and create package "reflect" in "" * and then when typing relative names, instead of picking .scala.relect, typedIdentifier will pick up the * .reflect package created by the bootstrapping. Thus, no bootstrapping for scaladoc! * TODO: we should refactor this as a separate -bootstrap option to have a clean implementation, no? */ def sourcePath = if (!settings.isScaladoc) cmdLineOrElse("sourcepath", Defaults.scalaSourcePath) else "" def userClassPath = settings.classpath.value // default is specified by settings and can be overridden there import classPathFactory._ // Assemble the elements! def basis = List[Traversable[ClassPath]]( JrtClassPath.apply(), // 0. The Java 9 classpath (backed by the jrt:/ virtual system, if available) classesInPath(javaBootClassPath), // 1. The Java bootstrap class path. contentsOfDirsInPath(javaExtDirs), // 2. The Java extension class path. classesInExpandedPath(javaUserClassPath), // 3. The Java application class path. classesInPath(scalaBootClassPath), // 4. The Scala boot class path. contentsOfDirsInPath(scalaExtDirs), // 5. The Scala extension class path. classesInExpandedPath(userClassPath), // 6. The Scala application class path. classesInManifest(useManifestClassPath), // 8. The Manifest class path. sourcesInPath(sourcePath) // 7. The Scala source path. ) lazy val containers = basis.flatten.distinct override def toString = s""" |object Calculated { | scalaHome = $scalaHome | javaBootClassPath = ${ppcp(javaBootClassPath)} | javaExtDirs = ${ppcp(javaExtDirs)} | javaUserClassPath = ${ppcp(javaUserClassPath)} | useJavaClassPath = $useJavaClassPath | scalaBootClassPath = ${ppcp(scalaBootClassPath)} | scalaExtDirs = ${ppcp(scalaExtDirs)} | userClassPath = ${ppcp(userClassPath)} | sourcePath = ${ppcp(sourcePath)} |}""".asLines } def containers = Calculated.containers import PathResolver.MkLines def result: ClassPath = { val cp = computeResult() if (settings.Ylogcp) { Console print f"Classpath built from ${settings.toConciseString} %n" Console print s"Defaults: ${PathResolver.Defaults}" Console print s"Calculated: $Calculated" val xs = (Calculated.basis drop 2).flatten.distinct Console print (xs mkLines (s"After java boot/extdirs classpath has ${xs.size} entries:", indented = true)) } cp } def resultAsURLs: Seq[URL] = result.asURLs @deprecated("Use resultAsURLs instead of this one", "2.11.5") def asURLs: List[URL] = resultAsURLs.toList private def computeResult(): ClassPath = AggregateClassPath(containers.toIndexedSeq) } ================================================ FILE: examples/RefChecks.scala ================================================ /* * Scala (https://www.scala-lang.org) * * Copyright EPFL and Lightbend, Inc. * * Licensed under Apache License 2.0 * (http://www.apache.org/licenses/LICENSE-2.0). * * See the NOTICE file distributed with this work for * additional information regarding copyright ownership. */ package scala.tools.nsc package typechecker import scala.collection.mutable import scala.collection.mutable.ListBuffer import scala.reflect.internal.util.CodeAction import scala.tools.nsc.Reporting.WarningCategory import scala.tools.nsc.settings.ScalaVersion import scala.tools.nsc.settings.NoScalaVersion import symtab.Flags._ import transform.Transform /** Post-attribution checking and transformation. * * This phase checks the following postconditions: * * - All overrides conform to rules. * - All type arguments conform to bounds. * - Every use of a type variable conforms to the variance annotation of that variable. * - No forward reference to a term symbol extends beyond a value definition. * * It performs the following transformations: * * - Local modules are replaced by variables and classes. * - Calls to case factory methods are replaced by new's. * - Eliminate branches in a conditional if the condition is a constant. * * @author Martin Odersky */ abstract class RefChecks extends Transform { val global: Global // need to repeat here because otherwise last mixin defines global as // SymbolTable. If we had DOT this would not be an issue import global._ import definitions._ import typer.typed /** the following two members override abstract members in Transform */ val phaseName: String = "refchecks" def newTransformer(unit: CompilationUnit): RefCheckTransformer = new RefCheckTransformer(unit) val toJavaRepeatedParam = SubstSymMap(RepeatedParamClass -> JavaRepeatedParamClass) val toScalaRepeatedParam = SubstSymMap(JavaRepeatedParamClass -> RepeatedParamClass) def accessFlagsToString(sym: Symbol) = flagsToString( sym getFlag (PRIVATE | PROTECTED), if (sym.hasAccessBoundary) "" + sym.privateWithin.name else "" ) def overridesTypeInPrefix(tp1: Type, tp2: Type, prefix: Type): Boolean = (tp1.dealiasWiden, tp2.dealiasWiden) match { case (MethodType(List(), rtp1), NullaryMethodType(rtp2)) => rtp1 <:< rtp2 case (NullaryMethodType(rtp1), MethodType(List(), rtp2)) => rtp1 <:< rtp2 case (TypeRef(_, sym, _), _) if sym.isModuleClass => overridesTypeInPrefix(NullaryMethodType(tp1), tp2, prefix) case (_, TypeRef(_, sym, _)) if sym.isModuleClass => overridesTypeInPrefix(tp1, NullaryMethodType(tp2), prefix) case _ => tp1 <:< tp2 } private val separatelyCompiledScalaSuperclass = perRunCaches.newAnyRefMap[Symbol, Unit]() final def isSeparatelyCompiledScalaSuperclass(sym: Symbol) = if (globalPhase.refChecked){ separatelyCompiledScalaSuperclass.contains(sym) } else { // conservative approximation in case someone in pre-refchecks phase asks for `exitingFields(someClass.info)` // and we haven't run the refchecks tree transform which populates `separatelyCompiledScalaSuperclass` false } class RefCheckTransformer(unit: CompilationUnit) extends AstTransformer { private final val indent = " " var localTyper: analyzer.Typer = typer var currentApplication: Tree = EmptyTree var inAnnotation: Boolean = false var inPattern: Boolean = false @inline final def savingInPattern[A](body: => A): A = { val saved = inPattern try body finally inPattern = saved } // Track symbols of the refinement's parents and the base at which we've checked them, // as well as the entire refinement type seen at that base. // No need to check the same symbols again in a base that's a subclass of a previously checked base private val checkedCombinations = mutable.Map[List[Symbol], (Symbol, Type)]() private def notYetCheckedOrAdd(rt: RefinedType, currentBase: Symbol) = { val seen = checkedCombinations.get(rt.parents.map(_.typeSymbol)).exists { case (prevBase, prevTp) => currentBase.isSubClass(prevBase) && rt =:= prevTp.asSeenFrom(currentBase.thisType, prevBase) } if (!seen) checkedCombinations.addOne((rt.parents.map(_.typeSymbol), (currentBase, rt))) !seen } private def refchecksWarning(pos: Position, msg: String, cat: WarningCategory, actions: List[CodeAction] = Nil): Unit = runReporting.warning(pos, msg, cat, currentOwner, actions) // only one overloaded alternative is allowed to define default arguments private def checkOverloadedRestrictions(clazz: Symbol, defaultClass: Symbol): Unit = { // Using the default getters (such as methodName$default$1) as a cheap way of // finding methods with default parameters. This way, we can limit the members to // those with the DEFAULTPARAM flag, and infer the methods. Looking for the methods // directly requires inspecting the parameter list of every one. That modification // shaved 95% off the time spent in this method. val defaultGetters = defaultClass.info.findMembers(excludedFlags = PARAM, requiredFlags = DEFAULTPARAM) val defaultMethodNames = defaultGetters map (sym => nme.defaultGetterToMethod(sym.name)) defaultMethodNames.toList.distinct foreach { name => val methods = clazz.info.findMember(name, 0L, requiredFlags = METHOD, stableOnly = false).alternatives def hasDefaultParam(tpe: Type): Boolean = tpe match { case MethodType(params, restpe) => (params exists (_.hasDefault)) || hasDefaultParam(restpe) case _ => false } val haveDefaults = methods.filter(sym => mexists(sym.info.paramss)(_.hasDefault) && !nme.isProtectedAccessorName(sym.name)) if (haveDefaults.lengthCompare(1) > 0) { val owners = haveDefaults map (_.owner) // constructors of different classes are allowed to have defaults if (haveDefaults.exists(x => !x.isConstructor) || owners.distinct.size < haveDefaults.size) { reporter.error(clazz.pos, "in "+ clazz + ", multiple overloaded alternatives of "+ haveDefaults.head + " define default arguments" + ( if (owners.forall(_ == clazz)) "." else ".\nThe members with defaults are defined in "+owners.map(_.fullLocationString).mkString("", " and ", ".") ) ) } } } // Check for doomed attempt to overload applyDynamic if (clazz isSubClass DynamicClass) { for ((_, m1 :: m2 :: _) <- (clazz.info member nme.applyDynamic).alternatives groupBy (_.typeParams.length)) { reporter.error(m1.pos, "implementation restriction: applyDynamic cannot be overloaded except by methods with different numbers of type parameters, e.g. applyDynamic[T1](method: String)(arg: T1) and applyDynamic[T1, T2](method: String)(arg1: T1, arg2: T2)") } } // This has become noisy with implicit classes. if (settings.isDeveloper && settings.warnPolyImplicitOverload) { clazz.info.decls.foreach(sym => if (sym.isImplicit && sym.typeParams.nonEmpty) { // implicit classes leave both a module symbol and a method symbol as residue val alts = clazz.info.decl(sym.name).alternatives filterNot (_.isModule) if (alts.size > 1) alts foreach (x => refchecksWarning(x.pos, "parameterized overloaded implicit methods are not visible as view bounds", WarningCategory.LintPolyImplicitOverload)) }) } } // Override checking ------------------------------------------------------------ /** Add bridges for vararg methods that extend Java vararg methods */ def addVarargBridges(clazz: Symbol): List[Tree] = { // This is quite expensive, so attempt to skip it completely. // Insist there at least be a java-defined ancestor which // defines a varargs method. TODO: Find a cheaper way to exclude. if (inheritsJavaVarArgsMethod(clazz)) { log("Found java varargs ancestor in " + clazz.fullLocationString + ".") val self = clazz.thisType val bridges = new ListBuffer[Tree] def varargBridge(member: Symbol, bridgetpe: Type): Tree = { log(s"Generating varargs bridge for ${member.fullLocationString} of type $bridgetpe") val newFlags = (member.flags | VBRIDGE) & ~PRIVATE val bridge = member.cloneSymbolImpl(clazz, newFlags) setPos clazz.pos bridge.setInfo(bridgetpe.cloneInfo(bridge)) clazz.info.decls enter bridge val params = bridge.paramss.head val elemtp = params.last.tpe.typeArgs.head val idents = params map Ident val lastarg = gen.wildcardStar(gen.mkWrapVarargsArray(idents.last, elemtp)) val body = Apply(Select(This(clazz), member), idents.init :+ lastarg) localTyper typed DefDef(bridge, body) } // For all concrete non-private members (but: see below) that have a (Scala) repeated // parameter: compute the corresponding method type `jtpe` with a Java repeated parameter // if a method with type `jtpe` exists and that method is not a varargs bridge // then create a varargs bridge of type `jtpe` that forwards to the // member method with the Scala vararg type. // // @PP: Can't call nonPrivateMembers because we will miss refinement members, // which have been marked private. See scala/bug#4729. for (member <- nonTrivialMembers(clazz)) { log(s"Considering $member for java varargs bridge in $clazz") if (!member.isDeferred && member.isMethod && hasRepeatedParam(member.info)) { val inherited = clazz.info.nonPrivateMemberAdmitting(member.name, VBRIDGE) // Delaying calling memberType as long as possible if (inherited.exists) { val jtpe = toJavaRepeatedParam(self memberType member) // this is a bit tortuous: we look for non-private members or bridges // if we find a bridge everything is OK. If we find another member, // we need to create a bridge val inherited1 = inherited filter (sym => !(sym hasFlag VBRIDGE) && (self memberType sym matches jtpe)) if (inherited1.exists) bridges += varargBridge(member, jtpe) } } } if (bridges.size > 0) log(s"Adding ${bridges.size} bridges for methods extending java varargs.") bridges.toList } else Nil } /** 1. Check all members of class `clazz` for overriding conditions. * That is for overriding member M and overridden member O: * * 1.1. M must have the same or stronger access privileges as O. * 1.2. O must not be final. * 1.3. O is deferred, or M has `override` modifier. * 1.4. If O is stable, then so is M. * 1.6. If O is a type alias, then M is an alias of O. * 1.7. If O is an abstract type then * 1.7.1 either M is an abstract type, and M's bounds are sharper than O's bounds. * or M is a type alias or class which conforms to O's bounds. * 1.7.2 higher-order type arguments must respect bounds on higher-order type parameters -- @M * (explicit bounds and those implied by variance annotations) -- @see checkKindBounds * 1.8. If O and M are values, then * 1.8.1 M's type is a subtype of O's type, or * 1.8.2 M is of type []S, O is of type ()T and S <: T, or * 1.8.3 M is of type ()S, O is of type []T and S <: T, or * 1.9. If M is a macro def, O cannot be deferred unless there's a concrete method overriding O. * 1.10. If M is not a macro def, O cannot be a macro def. * 2. Check that only abstract classes have deferred members * 3. Check that concrete classes do not have deferred definitions * that are not implemented in a subclass. * 4. Check that every member with an `override` modifier * overrides some other member. * 5. Check that the nested class do not shadow other nested classes from outer class's parent. */ private def checkAllOverrides(clazz: Symbol, typesOnly: Boolean = false): Unit = { val self = clazz.thisType case class MixinOverrideError(member: Symbol, msg: String, actions: List[CodeAction], s3Migration: Boolean) val mixinOverrideErrors = new ListBuffer[MixinOverrideError]() def issue(pos: Position, msg: String, actions: List[CodeAction], s3Migration: Boolean) = if (s3Migration) runReporting.warning(pos, msg, WarningCategory.Scala3Migration, currentOwner, actions) else runReporting.error(pos, msg, actions) def printMixinOverrideErrors(): Unit = { mixinOverrideErrors.toList match { case List() => case List(MixinOverrideError(_, msg, actions, s3Migration)) => issue(clazz.pos, msg, actions, s3Migration) case MixinOverrideError(member, msg, actions, s3Migration) :: others => val others1 = others.map(_.member.name.decode).filter(member.name.decode != _).distinct issue( clazz.pos, if (others1.isEmpty) msg else s"$msg;\n other members with override errors are: ${others1.mkString(", ")}", actions, s3Migration) } } def infoString(sym: Symbol) = infoString0(sym, sym.owner != clazz) def infoStringWithLocation(sym: Symbol) = infoString0(sym, showLocation = true) def infoString0(member: Symbol, showLocation: Boolean) = { val location = if (!showLocation) "" else member.ownsString match { case "" => "" case s => s" (defined in $s)" } val macroStr = if (member.isTermMacro) "macro " else "" macroStr + member.defStringSeenAs(self.memberInfo(member)) + location } /* Check that all conditions for overriding `other` by `member` of class `clazz` are met. * * TODO: error messages could really be improved, including how they are composed */ def checkOverride(pair: SymbolPair): Unit = { import pair.{highType, lowType, highInfo, rootType} val member = pair.low val other = pair.high val memberClass = member.owner val otherClass = other.owner // debuglog(s"Checking validity of ${member.fullLocationString} overriding ${other.fullLocationString}") def noErrorType = !pair.isErroneous def isRootOrNone(sym: Symbol) = sym != null && sym.isRoot || sym == NoSymbol val isMemberClass = memberClass == clazz def isNeitherInClass = !isMemberClass && otherClass != clazz /** Emit an error if member is owned by current class, using the member position. * Otherwise, accumulate the error, to be emitted after other messages, using the class position. */ def emitOverrideError(fullmsg: String, actions: List[CodeAction] = Nil, s3Migration: Boolean = false): Unit = if (isMemberClass) issue(member.pos, fullmsg, actions, s3Migration) else mixinOverrideErrors += MixinOverrideError(member, fullmsg, actions, s3Migration) def overriddenWithAddendum(msg: String, foundReq: Boolean = settings.isDebug): String = { val isConcreteOverAbstract = otherClass.isSubClass(memberClass) && other.isDeferred && !member.isDeferred val addendum = if (isConcreteOverAbstract) sm"""|; |${indent}(note that ${infoStringWithLocation(other)} is abstract, |${indent}and is therefore overridden by concrete ${infoStringWithLocation(member)})""" else if (foundReq) { def info(sym: Symbol) = self.memberInfo(sym) match { case tp if sym.isGetter || sym.isValue && !sym.isMethod => tp.resultType case tp => tp } analyzer.foundReqMsg(info(member), info(other)) } else "" val msg1 = if (!msg.isEmpty) s"\n$indent$msg" else msg s"${infoStringWithLocation(other)}${msg1}${addendum}" } def overrideError(msg: String): Unit = if (noErrorType) emitOverrideError(msg) def getWithIt = if (isMemberClass) "" else s"with ${infoString(member)}" def overrideErrorWithMemberInfo(msg: String, actions: List[CodeAction] = Nil, s3Migration: Boolean = false): Unit = if (noErrorType) emitOverrideError(s"${msg}\n${overriddenWithAddendum(getWithIt)}", actions, s3Migration) def overrideErrorOrNullaryWarning(msg: String, actions: List[CodeAction]): Unit = if (isMemberClass || !member.owner.isSubClass(other.owner)) if (currentRun.isScala3) overrideErrorWithMemberInfo(msg, actions, s3Migration = true) else if (isMemberClass) refchecksWarning(member.pos, msg, WarningCategory.OtherNullaryOverride, actions) else refchecksWarning(clazz.pos, msg, WarningCategory.OtherNullaryOverride, actions) def overrideTypeError(): Unit = if (member.isModule && other.isModule) overrideError(sm"""|overriding ${other.fullLocationString} with ${member.fullLocationString}: |an overriding object must conform to the overridden object's class bound${ analyzer.foundReqMsg(pair.lowClassBound, pair.highClassBound)}""") else { val needSameType = !other.isDeferred && other.isAliasType val msg = s"${getWithIt}${if (needSameType) " (Equivalent type required when overriding a type alias.)" else ""}" overrideError(sm"""|incompatible type in overriding |${overriddenWithAddendum(msg, foundReq = !needSameType)}""") } def overrideErrorConcreteMissingOverride() = if (isNeitherInClass && !otherClass.isSubClass(memberClass)) emitOverrideError(sm"""|$clazz inherits conflicting members: |$indent${infoStringWithLocation(other)} and |$indent${infoStringWithLocation(member)} |$indent(note: this can be resolved by declaring an `override` in $clazz.)""") else overrideErrorWithMemberInfo("`override` modifier required to override concrete member:") def weakerAccessError(advice: String): Unit = overrideError(sm"""|weaker access privileges in overriding |${overriddenWithAddendum(advice)}""") def overrideAccessError(): Unit = weakerAccessError { accessFlagsToString(other) match { case "" => "override should be public" case otherAccess => s"override should at least be $otherAccess" } } //Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG /* Is the intersection between given two lists of overridden symbols empty? */ def intersectionIsEmpty(syms1: List[Symbol], syms2: List[Symbol]) = !syms1.exists(syms2.contains) if (memberClass == ObjectClass && otherClass == AnyClass) () // skip -- can we have a mode of symbolpairs where this pair doesn't even appear? else if (typesOnly) checkOverrideTypes() else { // o: public | protected | package-protected (aka java's default access) // ^-may be overridden by member with access privileges-v // m: public | public/protected | public/protected/package-protected-in-same-package-as-o if (member.isPrivate) // (1.1) weakerAccessError("override should not be private") // todo: align accessibility implication checking with isAccessible in Contexts @inline def protectedOK = !other.isProtected || member.isProtected @inline def accessBoundaryOK = { val ob = other.accessBoundary(memberClass) val mb = member.accessBoundary(memberClass) @inline def companionBoundaryOK = ob.isClass && mb.isModuleClass && mb.module == ob.companionSymbol !isRootOrNone(ob) && (ob.hasTransOwner(mb) || companionBoundaryOK) } @inline def otherIsJavaProtected = other.isJavaDefined && other.isProtected val isOverrideAccessOK = member.isPublic || // member is public, definitely same or relaxed access protectedOK && // if o is protected, so is m (accessBoundaryOK || // m relaxes o's access boundary otherIsJavaProtected // overriding a protected java member, see #3946 #12349 ) if (!isOverrideAccessOK) overrideAccessError() else if (other.isClass) overrideErrorWithMemberInfo("class definitions cannot be overridden:") else if (!other.isDeferred && member.isClass) overrideErrorWithMemberInfo("classes can only override abstract types; cannot override:") else if (other.isEffectivelyFinal) // (1.2) overrideErrorWithMemberInfo("cannot override final member:") else { // In Java, the OVERRIDE flag is implied val memberOverrides = member.isAnyOverride || (member.isJavaDefined && !member.isDeferred) // Concrete `other` requires `override` for `member`. // Synthetic exclusion for (at least) default getters, fixes scala/bug#5178. // We cannot assign the OVERRIDE flag to the default getter: // one default getter might sometimes override, sometimes not. Example in comment on ticket. if (!memberOverrides && !other.isDeferred && !member.isSynthetic) overrideErrorConcreteMissingOverride() else if (other.isAbstractOverride && other.isIncompleteIn(clazz) && !member.isAbstractOverride) overrideErrorWithMemberInfo("`abstract override` modifiers required to override:") else if (memberOverrides && other.hasFlag(ACCESSOR) && !other.hasFlag(STABLE | DEFERRED)) // TODO: this is not covered by the spec. overrideErrorWithMemberInfo("mutable variable cannot be overridden:") else if (memberOverrides && !memberClass.thisType.baseClasses.exists(_.isSubClass(otherClass)) && !member.isDeferred && !other.isDeferred && intersectionIsEmpty(member.extendedOverriddenSymbols, other.extendedOverriddenSymbols)) overrideErrorWithMemberInfo("cannot override a concrete member without a third member that's overridden by both " + "(this rule is designed to prevent accidental overrides)") else if (other.isStable && !member.isStable) // (1.4) overrideErrorWithMemberInfo("stable, immutable value required to override:") else if (member.isValue && member.isLazy && other.isValue && other.hasStableFlag && !other.isDeferred && !other.isLazy) overrideErrorWithMemberInfo("concrete non-lazy value cannot be overridden:") else if (other.isValue && other.isLazy && member.isValue && !member.isLazy) overrideErrorWithMemberInfo("value must be lazy when overriding concrete lazy value:") else if (other.isDeferred && member.isTermMacro && member.extendedOverriddenSymbols.forall(_.isDeferred)) // (1.9) overrideErrorWithMemberInfo("macro cannot override abstract method:") else if (other.isTermMacro && !member.isTermMacro) // (1.10) overrideErrorWithMemberInfo("macro can only be overridden by another macro:") else { checkOverrideTypes() // Don't bother users with deprecations caused by classes they inherit. // Only warn for the pair that has one leg in `clazz`. if (isMemberClass) checkOverrideDeprecated() def javaDetermined(sym: Symbol) = sym.isJavaDefined || isUniversalMember(sym) def exempted = javaDetermined(member) || javaDetermined(other) || member.overrides.exists(javaDetermined) // warn that nilary member matched nullary other, so either it was adapted by namer or will be silently mixed in by mixin def warnAdaptedNullaryOverride(): Unit = { val mbr = if (isMemberClass) "method" else s"${member.fullLocationString} defined" val msg = s"$mbr without a parameter list overrides ${other.fullLocationString} defined with a single empty parameter list" val namePos = member.pos val action = if (namePos.isDefined && namePos.source.sourceAt(namePos) == member.decodedName) runReporting.codeAction("add empty parameter list", namePos.focusEnd, "()", msg) else Nil overrideErrorOrNullaryWarning(msg, action) } def warnExtraParens(): Unit = { val mbr = if (isMemberClass) "method" else s"${member.fullLocationString} defined" val msg = s"$mbr with a single empty parameter list overrides ${other.fullLocationString} defined without a parameter list" val namePos = member.pos val action = if (namePos.isDefined && namePos.source.sourceAt(namePos) == member.decodedName) runReporting.codeAction("remove empty parameter list", namePos.focusEnd.withEnd(namePos.end + 2), "", msg, expected = Some(("()", currentUnit))) else Nil overrideErrorOrNullaryWarning(msg, action) } if (member.hasAttachment[NullaryOverrideAdapted.type]) { if (!exempted) warnAdaptedNullaryOverride() } else if (member.paramLists.isEmpty) { // Definitions that directly override get a parameter list and a `NullaryOverrideAdapted` attachment // in Namers. Here we also warn when there's a mismatch between two mixed-in members. if (!member.isStable && other.paramLists.nonEmpty && !exempted && !other.overrides.exists(javaDetermined)) warnAdaptedNullaryOverride() } else if (other.paramLists.isEmpty) { if (!exempted && !member.hasAnnotation(BeanPropertyAttr) && !member.hasAnnotation(BooleanBeanPropertyAttr)) warnExtraParens() } } } } def checkOverrideAlias(): Unit = { // Important: first check the pair has the same kind, since the substitution // carries high's type parameter's bounds over to low, so that // type equality doesn't consider potentially different bounds on low/high's type params. // In b781e25afe this went from using memberInfo to memberType (now lowType/highType), tested by neg/override.scala. // TODO: was that the right fix? it seems type alias's RHS should be checked by looking at the symbol's info if (pair.sameKind && lowType.substSym(member.typeParams, other.typeParams) =:= highType) () else overrideTypeError() // (1.6) } def checkOverrideAbstractType(): Unit = { if (!(highInfo.bounds containsType lowType)) { // (1.7.1) overrideTypeError(); // todo: do an explaintypes with bounds here explainTypes(_.bounds containsType _, highInfo, lowType) } // check overriding (abstract type --> abstract type or abstract type --> concrete type member (a type alias)) // making an abstract type member concrete is like passing a type argument typer.infer.checkKindBounds(other :: Nil, lowType :: Nil, rootType, memberClass) match { // (1.7.2) case Nil => case kindErrors => reporter.error(member.pos, "The kind of " + member.keyString+" " + member.varianceString + member.nameString+ " does not conform to the expected kind of " + other.defString + other.locationString + "." + kindErrors.toList.mkString("\n", ", ", "")) } // check a type alias's RHS corresponds to its declaration // this overlaps somewhat with validateVariance if (member.isAliasType) { typer.infer.checkKindBounds(member :: Nil, lowType.normalize :: Nil, rootType, memberClass) match { case Nil => case kindErrors => reporter.error(member.pos, "The kind of the right-hand side "+lowType.normalize+" of " + member.keyString+" "+ member.varianceString + member.nameString+ " does not conform to its expected kind."+ kindErrors.toList.mkString("\n", ", ", "")) } } else if (member.isAbstractType && lowType.isVolatile && !highInfo.upperBound.isVolatile) overrideErrorWithMemberInfo("volatile type member cannot override type member with non-volatile upper bound:") } def checkOverrideTerm(): Unit = { member.cookJavaRawInfo() // #11584, #11840 other.cookJavaRawInfo() // #2454 if (!overridesTypeInPrefix(lowType, highType, rootType)) { // 8 overrideTypeError() explainTypes(lowType, highType) } if (member.isStable && !highType.isVolatile) { if (lowType.isVolatile) overrideErrorWithMemberInfo("member with volatile type cannot override member with non-volatile type:") else lowType.normalize.resultType match { case rt: RefinedType if !(rt =:= highType) && notYetCheckedOrAdd(rt, pair.base) => // might mask some inconsistencies -- check overrides val tsym = rt.typeSymbol if (tsym.pos == NoPosition) tsym setPos member.pos checkAllOverrides(tsym, typesOnly = true) case _ => } } } def checkOverrideTypes(): Unit = { if (other.isAliasType) checkOverrideAlias() else if (other.isAbstractType) checkOverrideAbstractType() else if (other.isTerm) checkOverrideTerm() } def checkOverrideDeprecated(): Unit = { if (other.hasDeprecatedOverridingAnnotation && !(member.hasDeprecatedOverridingAnnotation || member.ownerChain.exists(_.isDeprecated))) { val version = other.deprecatedOverridingVersion.getOrElse("") val since = if (version.isEmpty) version else s" (since $version)" val message = other.deprecatedOverridingMessage map (msg => s": $msg") getOrElse "" val report = s"overriding ${other.fullLocationString} is deprecated$since$message" runReporting.deprecationWarning(member.pos, other, member, report, version) } } } val opc = new overridingPairs.PairsCursor(clazz) while (opc.hasNext) { if (!opc.high.isClass) checkOverride(opc.currentPair) opc.next() } printMixinOverrideErrors() // Verifying a concrete class has nothing unimplemented. if (clazz.isConcreteClass && !typesOnly) { val abstractErrors = ListBuffer.empty[String] def abstractErrorMessage = abstractErrors.mkString("\n") def abstractClassError(msg: String, supplement: String = "", mustBeMixin: Boolean = false): Unit = { def prelude = if (clazz.isAnonymousClass || clazz.isModuleClass) "object creation impossible." else if (mustBeMixin) s"$clazz needs to be a mixin." else s"$clazz needs to be abstract." if (abstractErrors.isEmpty) abstractErrors += prelude abstractErrors += msg if (!supplement.isEmpty) abstractErrors += supplement } def javaErasedOverridingSym(sym: Symbol): Symbol = clazz.tpe.nonPrivateMemberAdmitting(sym.name, BRIDGE).filter(other => !other.isDeferred && other.isJavaDefined && !sym.enclClass.isSubClass(other.enclClass) && { // #3622: erasure operates on uncurried types -- // note on passing sym in both cases: only sym.isType is relevant for uncurry.transformInfo // !!! erasure.erasure(sym, uncurry.transformInfo(sym, tp)) gives erroneous or inaccessible type - check whether that's still the case! def uncurryAndErase(tp: Type) = erasure.erasure(sym)(uncurry.transformInfo(sym, tp)) val tp1 = uncurryAndErase(clazz.thisType.memberType(sym)) val tp2 = uncurryAndErase(clazz.thisType.memberType(other)) exitingErasure(tp1 matches tp2) }) def ignoreDeferred(member: Symbol) = (member.isAbstractType && !member.isFBounded) || ( // the test requires exitingErasure so shouldn't be // done if the compiler has no erasure phase available member.isJavaDefined && (currentRun.erasurePhase == NoPhase || javaErasedOverridingSym(member) != NoSymbol) ) // 2. Check that only abstract classes have deferred members def checkNoAbstractMembers(): Unit = { val NoError = null.asInstanceOf[String] val EmptyDiagnostic = "" def diagnose(member: Symbol, accessors: List[Symbol], nonPrivateMembers: Scope, fastDiagnostics: Boolean): String = { val underlying = analyzer.underlyingSymbol(member) // TODO: don't use this method // Give a specific error message for abstract vars based on why it fails: // It could be unimplemented, have only one accessor, or be uninitialized. val isMultiple = accessors.size > 1 if (accessors.exists(_.isSetter) || (member.isGetter && !isMultiple && member.setterIn(member.owner).exists)) { if (member.isSetter && isMultiple) NoError // If both getter and setter are missing, squelch the setter error. else if (member.isSetter) "an abstract var requires a setter in addition to the getter" else if (member.isGetter && !isMultiple) "an abstract var requires a getter in addition to the setter" else "variables need to be initialized to be defined" } else if (!fastDiagnostics && underlying.isMethod) { // Highlight any member that nearly matches: same name and arity, // but differs in one param or param list. val abstractParamLists = underlying.paramLists val matchingArity = nonPrivateMembers.reverseIterator.filter { m => !m.isDeferred && m.name == underlying.name && sameLength(m.paramLists, abstractParamLists) && sumSize(m.paramLists, 0) == sumSize(abstractParamLists, 0) && sameLength(m.tpe.typeParams, underlying.tpe.typeParams) && !(m.isJavaDefined && m.hasFlag(JAVA_DEFAULTMETHOD)) }.toList matchingArity match { // So far so good: only one candidate method case concrete :: Nil => val concreteParamLists = concrete.paramLists val aplIter = abstractParamLists.iterator.flatten val cplIter = concreteParamLists.iterator.flatten def mismatch(apl: Symbol, cpl: Symbol): Option[(Type, Type)] = if (apl.tpe.asSeenFrom(clazz.tpe, underlying.owner) =:= cpl.tpe) None else Some(apl.tpe -> cpl.tpe) def missingImplicit = abstractParamLists.zip(concreteParamLists).exists { case (abss, konkrete) => abss.headOption.exists(_.isImplicit) && !konkrete.headOption.exists(_.isImplicit) } val mismatches = mapFilter2(aplIter, cplIter)(mismatch).take(2).toList mismatches match { // Only one mismatched parameter: say something useful. case (pa, pc) :: Nil => val abstractSym = pa.typeSymbol val concreteSym = pc.typeSymbol def subclassMsg(c1: Symbol, c2: Symbol) = s": ${c1.fullLocationString} is a subclass of ${c2.fullLocationString}, but method parameter types must match exactly." def wrongSig = { val m = concrete fullyInitializeSymbol(m) m.defStringSeenAs(clazz.tpe_*.memberType(m)) } val addendum = if (abstractSym == concreteSym) { if (underlying.isJavaDefined && pa.typeArgs.isEmpty && abstractSym.typeParams.nonEmpty) s". To implement this raw type, use ${rawToExistential(pa)}" else if (pa.prefix =:= pc.prefix) ": their type parameters differ" else ": their prefixes (i.e., enclosing instances) differ" } else if (abstractSym.isSubClass(concreteSym)) subclassMsg(abstractSym, concreteSym) else if (concreteSym.isSubClass(abstractSym)) subclassMsg(concreteSym, abstractSym) else s" in `$wrongSig`" s"$pa does not match $pc$addendum" case Nil if missingImplicit => "overriding member must declare implicit parameter list" // other overriding gotchas case _ => EmptyDiagnostic } case _ => EmptyDiagnostic } } else EmptyDiagnostic } def emitErrors(missing: List[Symbol], nonPrivateMembers: Scope): Unit = { val fastDiagnostics = missing.lengthCompare(100) > 0 // Group missing members by the name of the underlying symbol, to consolidate getters and setters. val byName = missing.groupBy(_.name.getterName) // There may be 1 or more missing members declared in 1 or more parents. // If a single parent, the message names it. Otherwise, missing members are grouped by declaring class. val byOwner = missing.groupBy(_.owner).toList val announceOwner = byOwner.size > 1 def membersStrings(members: List[Symbol]) = { members.sortBy(_.name).flatMap { m => val accessors = byName.getOrElse(m.name.getterName, Nil) val diagnostic = diagnose(m, accessors, nonPrivateMembers, fastDiagnostics) if (diagnostic == NoError) Nil else { val s0a = infoString0(m, showLocation = false) fullyInitializeSymbol(m) val s0b = m.defString val s1 = m.defStringSeenAs(clazz.tpe_*.memberType(m)) val implMsg = if (s1 != s0a) s"implements `$s0a`" else if (s1 != s0b) s"implements `$s0b`" else "" val spacer = if (diagnostic.nonEmpty && implMsg.nonEmpty) "; " else "" val comment = if (diagnostic.nonEmpty || implMsg.nonEmpty) s" // $implMsg$spacer$diagnostic" else "" s"$s1 = ???$comment" :: Nil } } } var count = 0 def isMulti = count > 1 def helpfulListing = byOwner.sortBy(_._1.name.toString).flatMap { case (owner, members) => val ms = membersStrings(members) :+ "" count += ms.size - 1 if (announceOwner) s"// Members declared in ${owner.fullName}" :: ms else ms }.init.map(s => s" $s\n").mkString val stubs = helpfulListing def singleParent = if (byOwner.size == 1 && byOwner.head._1 != clazz) s" member${if (isMulti) "s" else ""} of ${byOwner.head._1}" else "" val line0 = if (isMulti) s"Missing implementations for ${count}${val p = singleParent ; if (p.isEmpty) " members" else p}." else s"Missing implementation${val p = singleParent ; if (p.isEmpty) p else s" for$p"}:" abstractClassError(line0, supplement = stubs) } def filtered[A](it: Iterator[A])(p: A => Boolean)(q: A => Boolean): (List[A], List[A]) = { var ps, qs: List[A] = Nil while (it.hasNext) { val a = it.next() if (p(a)) ps ::= a else if (q(a)) qs ::= a } (ps, qs) } val nonPrivateMembers = clazz.info.nonPrivateMembersAdmitting(VBRIDGE) // Avoid extra allocations with reverseIterator. Filter for abstract members of interest, and bad abstract override. val (missing, abstractIncomplete): (List[Symbol], List[Symbol]) = filtered(nonPrivateMembers.reverseIterator)(m => m.isDeferred & !ignoreDeferred(m))(m => m.isAbstractOverride && m.isIncompleteIn(clazz)) if (missing.nonEmpty) emitErrors(missing, nonPrivateMembers) // Check the remainder for invalid absoverride. for (member <- abstractIncomplete) { val explanation = member.superSymbolIn(clazz) match { case NoSymbol => ", but no concrete implementation could be found in a base class" case other => " and overrides incomplete superclass member\n" + infoString(other) } abstractClassError(s"${infoString(member)} is marked `abstract` and `override`$explanation", mustBeMixin = true) } } // end checkNoAbstractMembers // 3. Check that concrete classes do not have deferred definitions // that are not implemented in a subclass. // Note that this is not the same as (2); In a situation like // // class C { def m: Int = 0} // class D extends C { def m: Int } // // (3) is violated but not (2). def checkNoAbstractDecls(bc: Symbol): Unit = { for (decl <- bc.info.decls) { if (decl.isDeferred && !ignoreDeferred(decl)) { val impl = decl.matchingSymbol(clazz.thisType, admit = VBRIDGE) if (impl == NoSymbol || decl.owner.isSubClass(impl.owner)) abstractClassError(s"No implementation found in a subclass for deferred declaration\n" + s"${infoString(decl)}${analyzer.abstractVarMessage(decl)}") } } if (bc.superClass hasFlag ABSTRACT) checkNoAbstractDecls(bc.superClass) } checkNoAbstractMembers() if (abstractErrors.isEmpty) checkNoAbstractDecls(clazz) if (abstractErrors.nonEmpty) reporter.error(clazz.pos, abstractErrorMessage) } else if (clazz.isTrait && !clazz.isSubClass(AnyValClass)) { // For non-AnyVal classes, prevent abstract methods in interfaces that override // final members in Object; see #4431 for (decl <- clazz.info.decls) { // Have to use matchingSymbol, not a method involving overridden symbols, // because the scala type system understands that an abstract method here does not // override a concrete method in Object. The jvm, however, does not. val overridden = decl.matchingSymbol(ObjectClass, ObjectTpe) if (overridden.isFinal) reporter.error(decl.pos, "trait cannot redefine final method from class AnyRef") } } /* Returns whether there is a symbol declared in class `inclazz` * (which must be different from `clazz`) whose name and type * seen as a member of `class.thisType` matches `member`'s. */ def hasMatchingSym(inclazz: Symbol, member: Symbol): Boolean = { val isVarargs = hasRepeatedParam(member.tpe) lazy val varargsType = toJavaRepeatedParam(member.tpe) def isSignatureMatch(sym: Symbol) = !sym.isTerm || { val symtpe = clazz.thisType.memberType(sym) member.tpe.matches(symtpe) || (isVarargs && varargsType.matches(symtpe)) } /* The rules for accessing members which have an access boundary are more * restrictive in java than scala. Since java has no concept of package nesting, * a member with "default" (package-level) access can only be accessed by members * in the exact same package. Example: * * package a.b; * public class JavaClass { void foo() { } } * * The member foo() can be accessed only from members of package a.b, and not * nested packages like a.b.c. In the analogous scala class: * * package a.b * class ScalaClass { private[b] def foo() = () } * * The member IS accessible to classes in package a.b.c. The javaAccessCheck logic * is restricting the set of matching signatures according to the above semantics. */ def javaAccessCheck(sym: Symbol) = ( !inclazz.isJavaDefined // not a java defined member || !sym.hasAccessBoundary // no access boundary || sym.isProtected // marked protected in java, thus accessible to subclasses || sym.privateWithin == member.enclosingPackageClass // exact package match ) def classDecl = inclazz.info.nonPrivateDecl(member.name) .orElse(inclazz.info.nonPrivateDecl(member.unexpandedName)) def matchingSyms = classDecl.filter(sym => isSignatureMatch(sym) && javaAccessCheck(sym)) (inclazz != clazz) && (matchingSyms != NoSymbol) } // 4. Check that every defined member with an `override` modifier overrides some other member. for (member <- clazz.info.decls) if (member.isAnyOverride && !clazz.thisType.baseClasses.exists(hasMatchingSym(_, member))) { // for (bc <- clazz.info.baseClasses.tail) Console.println("" + bc + " has " + bc.info.decl(member.name) + ":" + bc.info.decl(member.name).tpe);//DEBUG val nonMatching: List[Symbol] = clazz.info.member(member.name).alternatives.filterNot(_.owner == clazz).filterNot(_.isFinal) def issueError(suffix: String) = reporter.error(member.pos, member.toString() + " overrides nothing" + suffix) nonMatching match { case Nil => issueError("") case ms => val superSigs = ms.map(m => m.defStringSeenAs(clazz.tpe memberType m)).mkString("\n") issueError(s".\nNote: the super classes of ${member.owner} contain the following, non final members named ${member.name}:\n${superSigs}") } member resetFlag (OVERRIDE | ABSOVERRIDE) // Any Override } // 5. Check that the nested class do not shadow other nested classes from outer class's parent def checkNestedClassShadow(): Unit = if (clazz.isNestedClass && !clazz.isModuleClass) { val overridden = clazz.owner.ancestors .map(a => clazz.matchingSymbol(a, clazz.owner.thisType)) .filter(c => c.exists && c.isClass) overridden foreach { sym2 => def msg(what: String) = s"shadowing a nested class of a parent is $what but $clazz shadows $sym2 defined in ${sym2.owner}; rename the class to something else" if (currentRun.isScala3) runReporting.warning(clazz.pos, msg("deprecated"), WarningCategory.Scala3Migration, clazz) else runReporting.deprecationWarning(clazz.pos, clazz, currentOwner, msg("deprecated"), "2.13.2") } } checkNestedClassShadow() } // end checkAllOverrides // Basetype Checking -------------------------------------------------------- /**
    *
  1. * Check that later type instances in the base-type sequence * are subtypes of earlier type instances of the same mixin. *
  2. *
*/ private def validateBaseTypes(clazz: Symbol): Unit = { val seenParents = mutable.HashSet[Type]() val seenTypes = Array.fill[List[Type]](clazz.info.baseTypeSeq.length)(Nil) val warnCloneable = settings.warnCloneableObject && clazz.isModuleClass /* validate all base types of a class in reverse linear order. */ def register(tp: Type): Unit = { val baseClass = tp.typeSymbol if (baseClass.isClass) { if (!baseClass.isTrait && !baseClass.isJavaDefined && !currentRun.compiles(baseClass) && !separatelyCompiledScalaSuperclass.contains(baseClass)) separatelyCompiledScalaSuperclass.update(baseClass, ()) val index = clazz.info.baseTypeIndex(baseClass) if (index >= 0) { if (!seenTypes(index).exists(_ <:< tp)) seenTypes(index) = tp :: seenTypes(index).filterNot(tp <:< _) } } if (warnCloneable && baseClass.eq(JavaCloneableClass)) reporter.warning(clazz.pos, s"$clazz should not extend Cloneable.") val remaining = tp.parents.filterNot(seenParents) seenParents ++= remaining remaining.foreach(register) } register(clazz.tpe) for (i <- 0 until seenTypes.length) { val baseClass = clazz.info.baseTypeSeq(i).typeSymbol seenTypes(i) match { case Nil => devWarning(s"base $baseClass not found in basetypes of $clazz. This might indicate incorrect caching of TypeRef#parents.") case _ :: Nil => // OK case tp1 :: tp2 :: _ => reporter.error(clazz.pos, sm"""|illegal inheritance; | $clazz inherits different type instances of $baseClass: |$tp1 and $tp2""") explainTypes(tp1, tp2) explainTypes(tp2, tp1) } } } // Variance Checking -------------------------------------------------------- object varianceValidator extends VarianceValidator { private def tpString(tp: Type) = tp match { case ClassInfoType(parents, _, clazz) => "supertype "+intersectionType(parents, clazz.owner) case _ => "type "+tp } override def issueVarianceError(base: Symbol, sym: Symbol, required: Variance, tpe: Type): Unit = { reporter.error(base.pos, s"${sym.variance} $sym occurs in $required position in ${tpString(tpe)} of $base") } } // Forward reference checking --------------------------------------------------- class LevelInfo(val outer: LevelInfo) { val scope: Scope = if (outer eq null) newScope else newNestedScope(outer.scope) var maxindex: Int = Int.MinValue var refpos: Position = _ var refsym: Symbol = _ } private var currentLevel: LevelInfo = null private val symIndex = perRunCaches.newMap[Symbol, Int]() private def pushLevel(): Unit = { currentLevel = new LevelInfo(currentLevel) } private def popLevel(): Unit = { currentLevel = currentLevel.outer } private def enterSyms(stats: List[Tree]): Unit = { var index = -1 for (stat <- stats) { index = index + 1 stat match { case _ : MemberDef if stat.symbol.isLocalToBlock => currentLevel.scope.enter(stat.symbol) symIndex(stat.symbol) = index case _ => } } } private def enterReference(pos: Position, sym: Symbol): Unit = { if (sym.isLocalToBlock) { val e = currentLevel.scope.lookupEntry(sym.name) if ((e ne null) && sym == e.sym) { var l = currentLevel while (l.scope != e.owner) l = l.outer val symindex = symIndex(sym) if (l.maxindex < symindex) { l.refpos = pos l.refsym = sym l.maxindex = symindex } } } } // Comparison checking ------------------------------------------------------- object normalizeAll extends TypeMap { def apply(tp: Type) = mapOver(tp).normalize } def checkImplicitViewOptionApply(pos: Position, fn: Tree, args: List[Tree]): Unit = if (settings.warnOptionImplicit) (fn, args) match { case (tap@TypeApply(fun, targs), List(view: ApplyImplicitView)) if fun.symbol == currentRun.runDefinitions.Option_apply => refchecksWarning(pos, s"Suspicious application of an implicit view (${view.fun}) in the argument to Option.apply.", WarningCategory.LintOptionImplicit) // scala/bug#6567 case _ => } private def isObjectOrAnyComparisonMethod(sym: Symbol) = sym match { case Object_eq | Object_ne | Object_== | Object_!= | Any_== | Any_!= => true case _ => false } /** * Check the sensibility of using the given `equals` to compare `qual` and `other`. * * NOTE: I'm really not convinced by the logic here. I also think this would work better after erasure. */ private def checkSensibleEquals(pos: Position, qual: Tree, name: Name, sym: Symbol, other: Tree) = { def isReferenceOp = sym == Object_eq || sym == Object_ne def isNew(tree: Tree) = tree match { case Function(_, _) | Apply(Select(New(_), nme.CONSTRUCTOR), _) => true case _ => false } def underlyingClass(tp: Type): Symbol = { val sym = tp.widen.typeSymbol if (sym.isAbstractType) underlyingClass(sym.info.upperBound) else sym } val actual = underlyingClass(other.tpe) val receiver = underlyingClass(qual.tpe) def onTrees[T](f: List[Tree] => T) = f(List(qual, other)) def onSyms[T](f: List[Symbol] => T) = f(List(receiver, actual)) // @MAT normalize for consistency in error message, otherwise only part is normalized due to use of `typeSymbol` def typesString = s"${normalizeAll(qual.tpe.widen)} and ${normalizeAll(other.tpe.widen)}" // TODO: this should probably be used in more type comparisons in checkSensibleEquals def erasedClass(tp: Type) = erasure.javaErasure(tp).typeSymbol /* Symbols which limit the warnings we can issue since they may be value types */ val couldBeAnything = Set[Symbol](ObjectClass, ComparableClass, SerializableClass) def isMaybeValue(sym: Symbol): Boolean = couldBeAnything(erasedClass(sym.tpe)) // Whether def equals(other: Any) has known behavior: it is the default // inherited from java.lang.Object, or it is a synthetically generated // case equals. TODO - more cases are warnable if the target is a synthetic // equals. def isUsingWarnableEquals = { val m = receiver.info.member(nme.equals_) ((m == Object_equals) || (m == Any_equals) || isMethodCaseEquals(m)) } def isMethodCaseEquals(m: Symbol) = m.isSynthetic && m.owner.isCase def isCaseEquals = isMethodCaseEquals(receiver.info.member(nme.equals_)) // Whether this == or != is one of those defined in Any/AnyRef or an overload from elsewhere. def isUsingDefaultScalaOp = sym == Object_== || sym == Object_!= || sym == Any_== || sym == Any_!= def haveSubclassRelationship = (actual isSubClass receiver) || (receiver isSubClass actual) // Whether the operands+operator represent a warnable combo (assuming anyrefs) // Looking for comparisons performed with ==/!= in combination with either an // equals method inherited from Object or a case class synthetic equals (for // which we know the logic.) def isWarnable = isReferenceOp || (isUsingDefaultScalaOp && isUsingWarnableEquals) def isEitherNullable = (NullTpe <:< receiver.info) || (NullTpe <:< actual.info) def isEitherValueClass = actual.isDerivedValueClass || receiver.isDerivedValueClass def isBoolean(s: Symbol) = unboxedValueClass(s) == BooleanClass def isUnit(s: Symbol) = unboxedValueClass(s) == UnitClass def isNumeric(s: Symbol) = isNumericValueClass(unboxedValueClass(s)) || isAnyNumber(s) def isScalaNumber(s: Symbol) = s isSubClass ScalaNumberClass def isJavaNumber(s: Symbol) = s isSubClass JavaNumberClass // includes java.lang.Number if appropriate [scala/bug#5779] def isAnyNumber(s: Symbol) = isScalaNumber(s) || isJavaNumber(s) def isMaybeAnyValue(s: Symbol) = isPrimitiveValueClass(unboxedValueClass(s)) || isMaybeValue(s) // used to short-circuit unrelatedTypes check if both sides are special def isSpecial(s: Symbol) = isMaybeAnyValue(s) || isAnyNumber(s) val nullCount = onSyms(_.filter(_ == NullClass).size) def isNonsenseValueClassCompare = ( !haveSubclassRelationship && isUsingDefaultScalaOp && isEitherValueClass && !isCaseEquals ) def isEffectivelyFinalDeep(sym: Symbol): Boolean = ( sym.isEffectivelyFinal // If a parent of an intersection is final, the resulting type must effectively be final. // (Any subclass of the refinement would have to be a subclass of that final parent.) // OPT: this condition is not included in the standard isEffectivelyFinal check, as it's expensive || sym.isRefinementClass && sym.info.parents.exists { _.typeSymbol.isEffectivelyFinal } ) // Have we already determined that the comparison is non-sensible? I mean, non-sensical? var isNonSensible = false def nonSensibleWarning(what: String, alwaysEqual: Boolean) = { val msg = alwaysEqual == (name == nme.EQ || name == nme.eq) refchecksWarning(pos, s"comparing $what using `${name.decode}` will always yield $msg", WarningCategory.Other) isNonSensible = true } def nonSensible(pre: String, alwaysEqual: Boolean) = nonSensibleWarning(s"${pre}values of types $typesString", alwaysEqual) def nonSensiblyEq() = nonSensible("", alwaysEqual = true) def nonSensiblyNeq() = nonSensible("", alwaysEqual = false) def nonSensiblyNew() = nonSensibleWarning("a fresh object", alwaysEqual = false) def unrelatedMsg = name match { case nme.EQ | nme.eq => "never compare equal" case _ => "always compare unequal" } def unrelatedTypes() = if (!isNonSensible) { val weaselWord = if (isEitherValueClass) "" else " most likely" refchecksWarning(pos, s"$typesString are unrelated: they will$weaselWord $unrelatedMsg", WarningCategory.Other) } if (nullCount == 2) // null == null nonSensiblyEq() else if (nullCount == 1) { if (onSyms(_ exists isPrimitiveValueClass)) // null == 5 nonSensiblyNeq() else if (onTrees( _ exists isNew)) // null == new AnyRef nonSensiblyNew() } else if (isBoolean(receiver)) { if (!isBoolean(actual) && !isMaybeValue(actual)) // true == 5 nonSensiblyNeq() } else if (isUnit(receiver)) { if (isUnit(actual)) // () == () nonSensiblyEq() else if (!isUnit(actual) && !isMaybeValue(actual)) // () == "abc" nonSensiblyNeq() } else if (isNumeric(receiver)) { if (!isNumeric(actual)) if (isUnit(actual) || isBoolean(actual) || !isMaybeValue(actual)) // 5 == "abc" nonSensiblyNeq() } else if (isWarnable && !isCaseEquals) { if (isNew(qual)) // new X == y nonSensiblyNew() else if (isNew(other) && (isEffectivelyFinalDeep(receiver) || isReferenceOp)) // object X ; X == new Y nonSensiblyNew() else if (isEffectivelyFinalDeep(actual) && isEffectivelyFinalDeep(receiver) && !haveSubclassRelationship) { // object X, Y; X == Y if (isEitherNullable) nonSensible("non-null ", alwaysEqual = false) else nonSensiblyNeq() } } // warn if one but not the other is a derived value class // this is especially important to enable transitioning from // regular to value classes without silent failures. if (isNonsenseValueClassCompare) unrelatedTypes() // possibleNumericCount is insufficient or this will warn on e.g. Boolean == j.l.Boolean else if (isWarnable && nullCount == 0 && !(isSpecial(receiver) && isSpecial(actual))) { // Warn if types are unrelated, without interesting lub. (Don't bother if we don't know anything about the values we're comparing.) def warnIfLubless(): Unit = { if (isMaybeValue(actual) || isMaybeValue(receiver) || haveSubclassRelationship) {} // ignore trivial or related types else { // better to have lubbed and lost // We erase the lub because the erased type is closer to what happens at run time. // Also, the lub of `S` and `String` is, weirdly, the refined type `Serializable{}` (for `class S extends Serializable`), // which means we can't just take its type symbol and look it up in our isMaybeValue Set. val commonRuntimeClass = erasedClass(global.lub(List(actual.tpe, receiver.tpe))) if (commonRuntimeClass == ObjectClass) unrelatedTypes() } } // warn if actual has a case parent that is not same as receiver's; // if actual is not a case, then warn if no common supertype, as below if (isCaseEquals) { def thisCase = receiver.info.member(nme.equals_).owner actual.info.baseClasses.find(_.isCase) match { case Some(p) if p != thisCase => nonSensible("case class ", alwaysEqual = false) case None => // stronger message on (Some(1) == None) //if (receiver.isCase && receiver.isEffectivelyFinal && !(receiver isSubClass actual)) nonSensiblyNeq() //else // if a class, it must be super to thisCase (and receiver) since not <: thisCase if (!actual.isTrait && !(receiver isSubClass actual)) nonSensiblyNeq() else warnIfLubless() case _ => } } else warnIfLubless() } } private def checkSensibleAnyEquals(pos: Position, qual: Tree, name: Name, sym: Symbol, other: Tree) = { def underlyingClass(tp: Type): Symbol = { val sym = tp.widen.typeSymbol if (sym.isAbstractType) underlyingClass(sym.info.upperBound) else sym } val receiver = underlyingClass(qual.tpe) val actual = underlyingClass(other.tpe) def typesString = "" + normalizeAll(qual.tpe.widen) + " and " + normalizeAll(other.tpe.widen) def nonSensiblyEquals() = { refchecksWarning(pos, s"comparing values of types $typesString using `${name.decode}` unsafely bypasses cooperative equality; use `==` instead", WarningCategory.OtherNonCooperativeEquals) } def isScalaNumber(s: Symbol) = s isSubClass ScalaNumberClass def isJavaNumber(s: Symbol) = s isSubClass JavaNumberClass def isAnyNumber(s: Symbol) = isScalaNumber(s) || isJavaNumber(s) def isNumeric(s: Symbol) = isNumericValueClass(unboxedValueClass(s)) || isAnyNumber(s) def isReference(s: Symbol) = (unboxedValueClass(s) isSubClass AnyRefClass) || (s isSubClass ObjectClass) def isUnit(s: Symbol) = unboxedValueClass(s) == UnitClass def isNumOrNonRef(s: Symbol) = isNumeric(s) || (!isReference(s) && !isUnit(s)) if (isNumeric(receiver) && isNumOrNonRef(actual)) { if (receiver == actual) () else nonSensiblyEquals() } else if ((sym == Any_equals || sym == Object_equals) && isNumOrNonRef(actual) && !isReference(receiver)) { nonSensiblyEquals() } } /** Sensibility check examines flavors of equals. */ def checkSensible(pos: Position, fn: Tree, args: List[Tree]) = fn match { case Select(qual, name @ (nme.EQ | nme.NE | nme.eq | nme.ne)) if args.length == 1 && isObjectOrAnyComparisonMethod(fn.symbol) && (!currentOwner.isSynthetic || currentOwner.isAnonymousFunction) => checkSensibleEquals(pos, qual, name, fn.symbol, args.head) case Select(qual, name @ nme.equals_) if args.length == 1 && (!currentOwner.isSynthetic || currentOwner.isAnonymousFunction) => checkSensibleAnyEquals(pos, qual, name, fn.symbol, args.head) case _ => } // scala/bug#6276 warn for trivial recursion, such as `def foo = foo` or `val bar: X = bar`, which come up more frequently than you might think. // TODO: Move to abide rule. Also, this does not check that the def is final or not overridden, for example def checkInfiniteLoop(sym: Symbol, rhs: Tree): Unit = if (!sym.isValueParameter && sym.paramss.forall(_.isEmpty)) { rhs match { case Ident(_) | Select(This(_), _) | Apply(Select(This(_), _), _) if rhs hasSymbolWhich (_.accessedOrSelf == sym) => refchecksWarning(rhs.pos, s"${sym.fullLocationString} does nothing other than call itself recursively", WarningCategory.Other) case _ => } } // Transformation ------------------------------------------------------------ /* Convert a reference to a case factory of type `tpe` to a new of the class it produces. */ def toConstructor(pos: Position, tpe: Type): Tree = { val rtpe = tpe.finalResultType assert(rtpe.typeSymbol hasFlag CASE, tpe) val tree = localTyper.typedOperator { atPos(pos) { Select(New(TypeTree(rtpe)), rtpe.typeSymbol.primaryConstructor) } } checkUndesiredProperties(rtpe.typeSymbol, tree.pos) checkUndesiredProperties(rtpe.typeSymbol.primaryConstructor, tree.pos) tree } override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { pushLevel() try { enterSyms(stats) var index = -1 stats.mapConserve(stat => { index += 1; transformStat(stat, index) }).filter(_ ne EmptyTree) } finally popLevel() } private def showCurrentRef: String = { val refsym = currentLevel.refsym s"$refsym defined on line ${refsym.pos.line}" } def transformStat(tree: Tree, index: Int): Tree = tree match { case t if treeInfo.isSelfConstrCall(t) => assert(index == 0, index) try transform(tree) finally if (currentLevel.maxindex > 0) { // An implementation restriction to avoid VerifyErrors and lazy vals mishaps; see scala/bug#4717 reporter.error(currentLevel.refpos, s"forward reference to $showCurrentRef not allowed from self constructor invocation") } case ValDef(_, _, _, _) => val tree1 = transform(tree) // important to do before forward reference check if (tree1.symbol.isLazy) tree1 else { val sym = tree.symbol if (sym.isLocalToBlock && index <= currentLevel.maxindex) { reporter.error(currentLevel.refpos, s"forward reference to $showCurrentRef extends over definition of $sym") } tree1 } case Import(_, _) => EmptyTree case DefDef(mods, _, _, _, _, _) if (mods hasFlag MACRO) || (tree.symbol hasFlag MACRO) => EmptyTree case _ => transform(tree) } /* Check whether argument types conform to bounds of type parameters */ private def checkBounds(tree0: Tree, pre: Type, owner: Symbol, tparams: List[Symbol], argtps: List[Type]): Unit = try typer.infer.checkBounds(tree0, pre, owner, tparams, argtps, "") catch { case ex: TypeError => reporter.error(tree0.pos, ex.getMessage()) if (settings.explaintypes.value) { val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, argtps).bounds) foreach2(argtps, bounds)((targ, bound) => explainTypes(bound.lo, targ)) foreach2(argtps, bounds)((targ, bound) => explainTypes(targ, bound.hi)) } } private def isIrrefutable(pat: Tree, seltpe: Type): Boolean = pat match { case Apply(_, args) => val clazz = pat.tpe.typeSymbol clazz == seltpe.typeSymbol && clazz.isCaseClass && (args corresponds clazz.primaryConstructor.tpe.asSeenFrom(seltpe, clazz).paramTypes)(isIrrefutable) case Typed(pat, tpt) => seltpe <:< tpt.tpe case Ident(tpnme.WILDCARD) => true case Bind(_, pat) => isIrrefutable(pat, seltpe) case _ => false } // Note: if a symbol has both @deprecated and @migration annotations and both // warnings are enabled, only the first one checked here will be emitted. // I assume that's a consequence of some code trying to avoid noise by suppressing // warnings after the first, but I think it'd be better if we didn't have to // arbitrarily choose one as more important than the other. private def checkUndesiredProperties(sym: Symbol, pos: Position): Unit = { // Issue a warning if symbol is deprecated, unless the point of reference is enclosed by a deprecated member, // or has a deprecated companion. if (sym.isDeprecated && // synthetic calls to deprecated case class constructor !(sym.isConstructor && sym.owner.isCaseClass && currentOwner.isSynthetic) && !currentOwner.ownersIterator.exists(_.isDeprecated)) runReporting.deprecationWarning(pos, sym, currentOwner) // Similar to deprecation: check if the symbol is marked with @migration // indicating it has changed semantics between versions. if (sym.hasMigrationAnnotation && settings.Xmigration.value != NoScalaVersion) { val changed = try settings.Xmigration.value < ScalaVersion(sym.migrationVersion.get) catch { case e : NumberFormatException => refchecksWarning(pos, s"${sym.fullLocationString} has an unparsable version number: ${e.getMessage()}", WarningCategory.Other) // if we can't parse the format on the migration annotation just conservatively assume it changed true } if (changed) refchecksWarning(pos, s"${sym.fullLocationString} has changed semantics in version ${sym.migrationVersion.get}:\n${sym.migrationMessage.get}", WarningCategory.OtherMigration) } if (sym.isExperimental && !currentOwner.ownerChain.exists(x => x.isExperimental)) { val msg = s"${sym.fullLocationString} is marked @experimental and therefore its enclosing scope must be experimental." reporter.error(pos, msg) } // See an explanation of compileTimeOnly in its scaladoc at scala.annotation.compileTimeOnly. // async/await is expanded after erasure if (sym.isCompileTimeOnly && !inAnnotation && !currentOwner.ownerChain.exists(x => x.isCompileTimeOnly)) { if (!async.deferCompileTimeOnlyError(sym)) { def defaultMsg = sm"""Reference to ${sym.fullLocationString} should not have survived past type checking, |it should have been processed and eliminated during expansion of an enclosing macro.""" // The getOrElse part should never happen, it's just here as a backstop. val msg = sym.compileTimeOnlyMessage getOrElse defaultMsg reporter.error(pos, msg) } } } private def checkDelayedInitSelect(qual: Tree, sym: Symbol, pos: Position) = { def isLikelyUninitialized = ( (sym.owner isSubClass DelayedInitClass) && !qual.tpe.isInstanceOf[ThisType] && sym.accessedOrSelf.isVal ) if (settings.warnDelayedInit && isLikelyUninitialized) refchecksWarning(pos, s"Selecting ${sym} from ${sym.owner}, which extends scala.DelayedInit, is likely to yield an uninitialized value", WarningCategory.LintDelayedinitSelect) } private def lessAccessible(otherSym: Symbol, memberSym: Symbol): Boolean = ( (otherSym != NoSymbol) && !otherSym.isProtected && !otherSym.isTypeParameterOrSkolem && !otherSym.isExistentiallyBound && memberSym.ownersIterator.forall(otherSym.isLessAccessibleThan(_)) ) private def lessAccessibleSymsInType(other: Type, memberSym: Symbol): List[Symbol] = { val extras = other match { case TypeRef(pre, _, args) => // checking the prefix here gives us spurious errors on e.g. a private[process] // object which contains a type alias, which normalizes to a visible type. args.filterNot(_ eq NoPrefix).flatMap(lessAccessibleSymsInType(_, memberSym)) case _ => Nil } if (lessAccessible(other.typeSymbol, memberSym)) other.typeSymbol :: extras else extras } private def warnLessAccessible(otherSym: Symbol, memberSym: Symbol): Unit = { val comparison = accessFlagsToString(memberSym) match { case "" => "" case acc => " is " + acc + " but" } val cannot = if (memberSym.isDeferred) "may be unable to provide a concrete implementation of" else "may be unable to override" refchecksWarning(memberSym.pos, s"""|${memberSym.fullLocationString}${comparison} references ${accessFlagsToString(otherSym)} ${otherSym}. |Classes which cannot access ${otherSym.decodedName} ${cannot} ${memberSym.decodedName}.""".stripMargin, WarningCategory.LintInaccessible ) } /** Warn about situations where a method signature will include a type which * has more restrictive access than the method itself. */ private def checkAccessibilityOfReferencedTypes(tree: Tree): Unit = { val member = tree.symbol def checkAccessibilityOfType(tpe: Type): Unit = { val inaccessible = lessAccessibleSymsInType(tpe, member) // if the unnormalized type is accessible, that's good enough if (inaccessible.isEmpty) () // or if the normalized type is, that's good too else if ((tpe ne tpe.normalize) && lessAccessibleSymsInType(tpe.dealiasWiden, member).isEmpty) () // otherwise warn about the inaccessible syms in the unnormalized type else inaccessible.foreach(warnLessAccessible(_, member)) } // types of the value parameters foreachParamss(member)(p => checkAccessibilityOfType(p.tpe)) // upper bounds of type parameters member.typeParams.foreach(tp => checkAccessibilityOfType(tp.info.upperBound.widen)) } /** Check that a deprecated val or def does not override a * concrete, non-deprecated method. If it does, then * deprecation is meaningless. */ private def checkDeprecatedOvers(tree: Tree): Unit = { val symbol = tree.symbol if (symbol.isDeprecated) { val concrOvers = symbol.allOverriddenSymbols.filter(sym => !sym.isDeprecated && !sym.isDeferred && !sym.hasDeprecatedOverridingAnnotation && !sym.enclClass.hasDeprecatedInheritanceAnnotation) if(!concrOvers.isEmpty) runReporting.deprecationWarning( tree.pos, symbol, currentOwner, s"${symbol.toString} overrides concrete, non-deprecated symbol(s): ${concrOvers.map(_.name.decode).mkString(", ")}", "") } } private def checkRepeatedParamArg(tree: Tree): Unit = { val bailure = "such annotations are only allowed in arguments to *-parameters" val err = currentApplication match { case Apply(fn, args) => val ok = ( args.nonEmpty && (args.last eq tree) && (fn.tpe.params.length == args.length) && isRepeatedParamType(fn.tpe.params.last.tpe) ) if (ok) null else if (!args.exists(tree.eq)) bailure else { val i = args.indexWhere(tree.eq) val isLast = i == args.length - 1 val formal = if (i >= fn.tpe.params.length - 1) fn.tpe.params.last.tpe else fn.tpe.params(i).tpe val isRepeated = isRepeatedParamType(formal) val lastly = if (!isLast) ";\nsequence argument must be the last argument" else "" val solely = if (fn.tpe.params.length == 1) "single" else "corresponding" if (isRepeated) s"it is not the only argument to be passed to the $solely repeated parameter $formal$lastly" else s"the $solely parameter has type $formal which is not a repeated parameter type$lastly" } case _ => bailure } if (err != null) reporter.error(tree.pos, s"Sequence argument type annotation `: _*` cannot be used here:\n$err") } private object RefCheckTypeMap extends TypeMap { object UnboundExistential extends TypeMap { private[this] val bound = mutable.Set.empty[Symbol] def toWildcardIn(tpe: Type): Type = try apply(tpe) finally bound.clear() override def apply(tpe: Type): Type = tpe match { case ExistentialType(quantified, _) => bound ++= quantified tpe.mapOver(this) case tpe => val sym = tpe.typeSymbol if (sym.isExistential && !bound(sym)) WildcardType else tpe.mapOver(this) } } private[this] var inPattern = false private[this] var skipBounds = false private[this] var tree: Tree = EmptyTree def check(tpe: Type, tree: Tree, inPattern: Boolean = false): Type = { this.inPattern = inPattern this.tree = tree try apply(tpe) finally { this.inPattern = false this.skipBounds = false this.tree = EmptyTree } } // check all bounds, except those that are existential type parameters // or those within typed annotated with @uncheckedBounds override def apply(tpe: Type): Type = tpe match { case tpe: AnnotatedType if tpe.hasAnnotation(UncheckedBoundsClass) => // scala/bug#7694 Allow code synthesizers to disable checking of bounds for TypeTrees based on inferred LUBs // which might not conform to the constraints. val savedSkipBounds = skipBounds skipBounds = true try tpe.mapOver(this).filterAnnotations(_.symbol != UncheckedBoundsClass) finally skipBounds = savedSkipBounds case tpe: TypeRef => if (!inPattern) checkTypeRef(UnboundExistential.toWildcardIn(tpe)) checkUndesired(tpe.sym) tpe.mapOver(this) case tpe => tpe.mapOver(this) } private def checkTypeRef(tpe: Type): Unit = tpe match { case TypeRef(pre, sym, args) => if (sym.isJavaDefined) sym.typeParams.foreach(_.cookJavaRawInfo()) if (!tpe.isHigherKinded && !skipBounds) checkBounds(tree, pre, sym.owner, sym.typeParams, args) case _ => } private def checkUndesired(sym: Symbol): Unit = tree match { // scala/bug#7783 don't warn about inferred types // FIXME: reconcile this check with one in resetAttrs case tree: TypeTree if tree.original == null => case tree => checkUndesiredProperties(sym, tree.pos) } } private def applyRefchecksToAnnotations(tree: Tree): Unit = { def checkVarArgs(tp: Type, tree: Tree): Unit = tp match { case TypeRef(_, VarargsClass, _) => tree match { case tt: TypeTree if tt.original == null => // same exception as in checkTypeRef case _: DefDef => case _ => reporter.error(tree.pos, s"Only methods can be marked @varargs") } case _ => } def applyChecks(annots: List[AnnotationInfo]): List[AnnotationInfo] = if (annots.isEmpty) Nil else { annots.foreach { ann => checkVarArgs(ann.atp, tree) RefCheckTypeMap.check(ann.atp, tree) if (ann.original != null && ann.original.hasExistingSymbol) checkUndesiredProperties(ann.original.symbol, tree.pos) } val annotsBySymbol = new mutable.LinkedHashMap[Symbol, ListBuffer[AnnotationInfo]]() val transformedAnnots = { val saved = inAnnotation inAnnotation = true try annots.map(_.transformArgs(transformTrees)) finally inAnnotation = saved } for (transformedAnnot <- transformedAnnots) { val buffer = annotsBySymbol.getOrElseUpdate(transformedAnnot.symbol, new ListBuffer) buffer += transformedAnnot } annotsBySymbol.iterator.flatMap(x => groupRepeatableAnnotations(x._1, x._2.toList)).toList } // assumes non-empty `anns` def groupRepeatableAnnotations(sym: Symbol, anns: List[AnnotationInfo]): List[AnnotationInfo] = if (!sym.isJavaDefined) anns else anns match { case single :: Nil => anns case multiple => sym.getAnnotation(AnnotationRepeatableAttr) match { case Some(repeatable) => repeatable.assocs.collectFirst { case (nme.value, LiteralAnnotArg(Constant(c: Type))) => c } match { case Some(container) => val assocs = List( nme.value -> ArrayAnnotArg(multiple.map(NestedAnnotArg(_)).toArray) ) AnnotationInfo(container, args = Nil, assocs = assocs) :: Nil case None => devWarning(s"@Repeatable $sym had no containing class") multiple } case None => reporter.error(tree.pos, s"$sym may not appear multiple times on ${tree.symbol}") multiple } } def checkIsElidable(sym: Symbol): Unit = if (sym ne null) sym.elisionLevel.foreach { level => if (!sym.isMethod || sym.isAccessor || sym.isLazy || sym.isDeferred) { val rest = if (sym.isDeferred) " The annotation affects only the annotated method, not overriding methods in subclasses." else "" reporter.error(sym.pos, s"${sym.name}: Only concrete methods can be marked @elidable.$rest") } } checkIsElidable(tree.symbol) def checkMember(sym: Symbol): Unit = { sym.setAnnotations(applyChecks(sym.annotations)) // validate implicitNotFoundMessage and implicitAmbiguousMessage if (settings.lintImplicitNotFound) { def messageWarning(name: String)(warn: String) = refchecksWarning(tree.pos, s"Invalid $name message for ${sym}${sym.locationString}:\n$warn", WarningCategory.LintImplicitNotFound) analyzer.ImplicitNotFoundMsg.check(sym) foreach messageWarning("implicitNotFound") analyzer.ImplicitAmbiguousMsg.check(sym) foreach messageWarning("implicitAmbiguous") } if (settings.warnSerialization && sym.isClass && sym.hasAnnotation(SerialVersionUIDAttr)) { def warn(what: String) = refchecksWarning(tree.pos, s"@SerialVersionUID has no effect on $what", WarningCategory.LintSerial) if (sym.isTrait) warn("traits") else if (!sym.isSerializable) warn("non-serializable classes") } if (!sym.isMethod && !sym.isConstructor) checkNoThrows(sym.annotations) } def checkNoThrows(anns: List[AnnotationInfo]): Unit = if (anns.exists(_.symbol == ThrowsClass)) reporter.error(tree.pos, s"`@throws` only allowed for methods and constructors") tree match { case m: MemberDef => checkMember(m.symbol) case tpt@TypeTree() => if (tpt.original != null) tpt.original.foreach { case dc: TypeTreeWithDeferredRefCheck => applyRefchecksToAnnotations(dc.check()) // #2416 case _ => } if (!inPattern) tree.setType(tree.tpe.map { case AnnotatedType(anns, ul) => checkNoThrows(anns) AnnotatedType(applyChecks(anns), ul) case tp => tp }) case _ => } } private def isSimpleCaseApply(tree: Tree): Boolean = { val sym = tree.symbol def isClassTypeAccessible(tree: Tree): Boolean = tree match { case TypeApply(fun, targs) => isClassTypeAccessible(fun) case Select(module, apply) => // scala/bug#4859 `CaseClass1().InnerCaseClass2()` must not be rewritten to `new InnerCaseClass2()`; // {expr; Outer}.Inner() must not be rewritten to `new Outer.Inner()`. treeInfo.isQualifierSafeToElide(module) && // scala/bug#5626 Classes in refinement types cannot be constructed with `new`. !module.exists { case t @ Select(_, _) => t.symbol != null && t.symbol.isStructuralRefinementMember case _ => false } case x => throw new MatchError(x) } sym.name == nme.apply && !sym.hasStableFlag && // ??? sym.isCase && isClassTypeAccessible(tree) && !tree.tpe.finalResultType.typeSymbol.primaryConstructor.isLessAccessibleThan(tree.symbol) } private def transformCaseApply(tree: Tree) = { def loop(t: Tree): Unit = t match { case Ident(_) => checkUndesiredProperties(t.symbol, t.pos) case Select(qual, _) => checkUndesiredProperties(t.symbol, t.pos) loop(qual) case _ => } tree foreach { case i@Ident(_) => enterReference(i.pos, i.symbol) // scala/bug#5390 need to `enterReference` for `a` in `a.B()` case _ => } loop(tree) toConstructor(tree.pos, tree.tpe) } private def transformApply(tree: Apply): Tree = tree match { case Apply( Select(qual, nme.withFilter), List(Function( List(ValDef(_, pname, tpt, _)), Match(_, CaseDef(pat1, _, _) :: _)))) if ((pname startsWith nme.CHECK_IF_REFUTABLE_STRING) && isIrrefutable(pat1, tpt.tpe) && (qual.tpe <:< tree.tpe)) => transform(qual) case Apply(fn, args) => // sensicality should be subsumed by the unreachability/exhaustivity/irrefutability // analyses in the pattern matcher if (!inPattern) { checkImplicitViewOptionApply(tree.pos, fn, args) checkSensible(tree.pos, fn, args) // TODO: this should move to preEraseApply, as reasoning about runtime semantics makes more sense in the JVM type system checkNamedBooleanArgs(fn, args) } currentApplication = tree tree } /** Check that boolean literals are passed as named args. * The rule is enforced when the type of the parameter is `Boolean`. * The rule is relaxed when the method has exactly one boolean parameter * and it is the first parameter, such as `assert(false, msg)`. */ private def checkNamedBooleanArgs(fn: Tree, args: List[Tree]): Unit = { val sym = fn.symbol def applyDepth: Int = { def loop(t: Tree, d: Int): Int = t match { case Apply(f, _) => loop(f, d+1) case _ => d } loop(fn, 0) } def isAssertParadigm(params: List[Symbol]): Boolean = !sym.isConstructor && !sym.isCaseApplyOrUnapply && { params match { case h :: t => h.tpe == BooleanTpe && !t.exists(_.tpe == BooleanTpe) case _ => false } } if (settings.lintNamedBooleans && !sym.isJavaDefined && !args.isEmpty) { val params = sym.paramLists(applyDepth) if (!isAssertParadigm(params)) foreach2(args, params)((arg, param) => arg match { case Literal(Constant(_: Boolean)) if arg.hasAttachment[UnnamedArg.type] && param.tpe.typeSymbol == BooleanClass && !param.deprecatedParamName.contains(nme.NO_NAME) => runReporting.warning(arg.pos, s"Boolean literals should be passed using named argument syntax for parameter ${param.name}.", WarningCategory.LintNamedBooleans, sym) case _ => }) } } private def transformSelect(tree: Select): Tree = { val Select(qual, name) = tree val sym = tree.symbol checkUndesiredProperties(sym, tree.pos) checkDelayedInitSelect(qual, sym, tree.pos) if (!sym.exists) devWarning("Select node has NoSymbol! " + tree + " / " + tree.tpe) if (name == nme.synchronized_ && isBoxedValueClass(qual.tpe.typeSymbol)) refchecksWarning(tree.pos, s"Suspicious `synchronized` call involving boxed primitive `${qual.tpe.typeSymbol.name}`", WarningCategory.LintUniversalMethods) def checkSuper(mix: Name) = // term should have been eliminated by super accessors assert(!(qual.symbol.isTrait && sym.isTerm && mix == tpnme.EMPTY), (qual.symbol, sym, mix)) // Rewrite eligible calls to monomorphic case companion apply methods to the equivalent constructor call. // // Note: for generic case classes the rewrite needs to be handled at the enclosing `TypeApply` to transform // `TypeApply(Select(C, apply), targs)` to `Select(New(C[targs]), )`. In case such a `TypeApply` // was deemed ineligible for transformation (e.g. the case constructor was private), the refchecks transform // will recurse to this point with `Select(C, apply)`, which will have a type `[T](...)C[T]`. // // We don't need to perform the check on the Select node, and `!isHigherKinded will guard against this // redundant (and previously buggy, scala/bug#9546) consideration. if (!tree.tpe.isHigherKinded && isSimpleCaseApply(tree)) { transformCaseApply(tree) } else { qual match { case Super(_, mix) => checkSuper(mix) case _ => } tree } } private def transformIf(tree: If): Tree = { val If(cond, thenpart, elsepart) = tree def unitIfEmpty(t: Tree): Tree = if (t == EmptyTree) Literal(Constant(())).setPos(tree.pos).setType(UnitTpe) else t cond.tpe match { case FoldableConstantType(value) => val res = if (value.booleanValue) thenpart else elsepart unitIfEmpty(res) case _ => tree } } // Warning about nullary methods returning Unit. private def checkNullaryMethodReturnType(sym: Symbol) = sym.tpe match { case NullaryMethodType(restpe) if restpe.typeSymbol == UnitClass => // this may be the implementation of e.g. a generic method being parameterized // on Unit, in which case we had better let it slide. val isOk = ( sym.isGetter || sym.isDefaultGetter || sym.allOverriddenSymbols.exists(over => !(over.tpe.resultType =:= sym.tpe.resultType)) || sym.isArtifact ) if (!isOk) { val msg = s"side-effecting nullary methods are discouraged: suggest defining as `def ${sym.name.decode}()` instead" val namePos = sym.pos.focus.withEnd(sym.pos.point + sym.decodedName.length) val action = if (namePos.source.sourceAt(namePos) == sym.decodedName) runReporting.codeAction("add empty parameter list", namePos.focusEnd, "()", msg) else Nil refchecksWarning(sym.pos, msg, WarningCategory.LintNullaryUnit, action) } case _ => () } // Verify classes extending AnyVal meet the requirements private def checkAnyValSubclass(clazz: Symbol) = if (clazz.isDerivedValueClass) { if (clazz.isTrait) reporter.error(clazz.pos, "Only classes (not traits) are allowed to extend AnyVal") else if (clazz.hasAbstractFlag) reporter.error(clazz.pos, "`abstract` modifier cannot be used with value classes") } private def checkUnexpandedMacro(t: Tree) = if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) reporter.error(t.pos, "macro has not been expanded") // if expression in statement position (of template or block) // looks like a useful value that should not be ignored, warn and return true // User specifies that an expression is boring by ascribing `e: Unit`. // The subtree `e` will bear an attachment, but may be wrapped in adaptations. private def checkInterestingResultInStatement(t: Tree): Boolean = { def isUninterestingSymbol(sym: Symbol): Boolean = sym != null && ( sym.isConstructor || sym.hasPackageFlag || sym.isPackageObjectOrClass || sym == BoxedUnitClass || sym == AnyClass || sym == AnyRefClass || sym == AnyValClass ) def isUninterestingType(tpe: Type): Boolean = tpe != null && ( isUnitType(tpe) || tpe.typeSymbol.isBottomClass || tpe =:= UnitTpe || tpe =:= BoxedUnitTpe || isTrivialTopType(tpe) ) // java lacks this.type idiom to distinguish side-effecting method, so ignore result of invoking java method. def isJavaApplication(t: Tree): Boolean = t match { case Apply(f, _) => f.symbol.isJavaDefined && !isUniversalMember(f.symbol) case _ => false } // The quirk of typechecking if is that the LUB often results in boring types. // Parser adds suppressing attachment on `if (b) expr` when user has `-Wnonunit-if:false`. def checkInterestingShapes(t: Tree): Boolean = t match { case If(_, thenpart, elsepart) => checkInterestingShapes(thenpart) || checkInterestingShapes(elsepart) // either or //case Block(_, Apply(label, Nil)) if label.symbol != null && nme.isLoopHeaderLabel(label.symbol.name) => false case Block(_, res) => checkInterestingShapes(res) case Match(_, cases) => cases.exists(k => checkInterestingShapes(k.body)) case _ => checksForInterestingResult(t) } // tests for various flavors of blandness in expressions. def checksForInterestingResult(t: Tree): Boolean = ( !t.isDef && !treeInfo.isPureDef(t) // ignore defs && !isUninterestingSymbol(t.symbol) // ctors, package, Unit, Any && !isUninterestingType(t.tpe) // bottom types, Unit, Any && !treeInfo.isThisTypeResult(t) // buf += x && !treeInfo.isSuperConstrCall(t) // just a thing && !treeInfo.hasExplicitUnit(t) // suppressed by explicit expr: Unit && !isJavaApplication(t) // Java methods are inherently side-effecting ) // begin checkInterestingResultInStatement settings.warnNonUnitStatement.value && checkInterestingShapes(t) && { val where = t match { case Block(_, res) => res case If(_, thenpart, Literal(Constant(()))) => thenpart match { case Block(_, res) => res case _ => thenpart } case _ => t } def msg = s"unused value of type ${where.tpe} (add `: Unit` to discard silently)" refchecksWarning(where.pos, msg, WarningCategory.OtherPureStatement) true } } // end checkInterestingResultInStatement override def transform(tree: Tree): Tree = { val savedLocalTyper = localTyper val savedCurrentApplication = currentApplication try { val sym = tree.symbol // Apply RefChecks to annotations. Makes sure the annotations conform to // type bounds (bug #935), issues deprecation warnings for symbols used // inside annotations. applyRefchecksToAnnotations(tree) val result: Tree = tree match { // NOTE: a val in a trait is now a DefDef, with the RHS being moved to an Assign in Constructors case tree: ValOrDefDef => checkDeprecatedOvers(tree) if (!tree.isErroneous) checkInfiniteLoop(tree.symbol, tree.rhs) if (settings.warnNullaryUnit) checkNullaryMethodReturnType(sym) if (settings.warnInaccessible) { if (!sym.isConstructor && !sym.isEffectivelyFinalOrNotOverridden && !sym.owner.isSealed && !sym.isSynthetic) checkAccessibilityOfReferencedTypes(tree) } tree match { case dd: DefDef if sym.hasAnnotation(NativeAttr) => if (sym.owner.isTrait) { reporter.error(tree.pos, "A trait cannot define a native method.") tree } else if (dd.rhs == EmptyTree) { // pretend it had a stub implementation sym resetFlag DEFERRED deriveDefDef(dd)(_ => typed(gen.mkThrowNewRuntimeException("native method stub"))) } else tree case _ => tree } case Template(parents, self, body) => localTyper = localTyper.atOwner(tree, currentOwner) for (stat <- body) if (!checkInterestingResultInStatement(stat) && treeInfo.isPureExprForWarningPurposes(stat)) { val msg = "a pure expression does nothing in statement position" val clause = if (body.lengthCompare(1) > 0) "; multiline expressions may require enclosing parentheses" else "" refchecksWarning(stat.pos, s"$msg$clause", WarningCategory.OtherPureStatement) } validateBaseTypes(currentOwner) checkOverloadedRestrictions(currentOwner, currentOwner) // scala/bug#7870 default getters for constructors live in the companion module checkOverloadedRestrictions(currentOwner, currentOwner.companionModule) val bridges = addVarargBridges(currentOwner) // TODO: do this during uncurry? checkAllOverrides(currentOwner) checkAnyValSubclass(currentOwner) if (currentOwner.isDerivedValueClass) currentOwner.primaryConstructor makeNotPrivate NoSymbol // scala/bug#6601, must be done *after* pickler! if (bridges.nonEmpty) deriveTemplate(tree)(_ ::: bridges) else tree case _: TypeTreeWithDeferredRefCheck => abort("adapt should have turned dc: TypeTreeWithDeferredRefCheck into tpt: TypeTree, with tpt.original == dc") case tpt@TypeTree() => if(tpt.original != null) { tpt.original foreach { case dc: TypeTreeWithDeferredRefCheck => transform(dc.check()) // #2416 -- only call transform to do refchecks, but discard results // tpt has the right type if the deferred checks are ok case _ => } } tree.setType(RefCheckTypeMap.check(tree.tpe, tree, inPattern)) case TypeApply(fn, args) => checkBounds(tree, NoPrefix, NoSymbol, fn.tpe.typeParams, args map (_.tpe)) if (isSimpleCaseApply(tree)) transformCaseApply(tree) else tree case x @ Apply(_, _) => transformApply(x) case x @ If(_, _, _) => transformIf(x) case New(tpt) => enterReference(tree.pos, tpt.tpe.typeSymbol) tree case treeInfo.WildcardStarArg(_) => checkRepeatedParamArg(tree) tree case Ident(name) => checkUndesiredProperties(sym, tree.pos) if (name != nme.WILDCARD && name != tpnme.WILDCARD_STAR) { assert(sym != NoSymbol, "transformCaseApply: name = " + name.debugString + " tree = " + tree + " / " + tree.getClass) //debug enterReference(tree.pos, sym) } tree case x @ Select(_, _) => transformSelect(x) case Literal(Constant(tpe: Type)) => RefCheckTypeMap.check(tpe, tree) tree case UnApply(fun, args) => transform(fun) // just make sure we enterReference for unapply symbols, note that super.transform(tree) would not transform(fun) // transformTrees(args) // TODO: is this necessary? could there be forward references in the args?? // probably not, until we allow parameterised extractors tree case blk @ Block(stats, expr) => // diagnostic info val (count, result0, adapted) = expr match { case Block(expr :: Nil, Literal(Constant(()))) => (1, expr, true) case Literal(Constant(())) => (0, EmptyTree, false) case _ => (1, EmptyTree, false) } val isMultiline = stats.lengthCompare(1 - count) > 0 def checkPure(t: Tree, supple: Boolean): Unit = if (!treeInfo.hasExplicitUnit(t) && treeInfo.isPureExprForWarningPurposes(t)) { val msg = "a pure expression does nothing in statement position" val parens = if (isMultiline) "multiline expressions might require enclosing parentheses" else "" val discard = if (adapted) "; a value can be silently discarded when Unit is expected" else "" val text = if (supple) s"$parens$discard" else if (!parens.isEmpty) s"$msg; $parens" else msg refchecksWarning(t.pos, text, WarningCategory.OtherPureStatement) } // check block for unintended "expression in statement position" stats.foreach { t => if (!checkInterestingResultInStatement(t)) checkPure(t, supple = false) } if (result0.nonEmpty) checkPure(result0, supple = true) def checkImplicitlyAdaptedBlockResult(t: Tree): Unit = expr match { case treeInfo.Applied(f, _, _) if f.symbol != null && f.symbol.isImplicit => f.symbol.paramLists match { case (p :: Nil) :: _ if p.isByNameParam => refchecksWarning(t.pos, s"Block result was adapted via implicit conversion (${f.symbol}) taking a by-name parameter", WarningCategory.LintBynameImplicit) case _ => } case _ => } if (isMultiline && settings.warnByNameImplicit) checkImplicitlyAdaptedBlockResult(expr) tree case Match(selector, cases) => // only warn if it could be put in backticks in a pattern def isWarnable(sym: Symbol): Boolean = sym != null && sym.exists && !sym.hasPackageFlag && sym.isStable && !isByName(sym) && !sym.hasAttachment[PatVarDefAttachment.type] // val (_, v) = with one var is shadowed in desugaring //!toCheck.isSynthetic // self-type symbols are synthetic: value self (), do warn class CheckSelector extends InternalTraverser { var selectorSymbols: List[Symbol] = null override def traverse(t: Tree): Unit = { val include = t match { case _: This => true // !t.symbol.isStable case _: SymTree => isWarnable(t.symbol) case _ => false } if (include) selectorSymbols ::= t.symbol t.traverse(this) } // true if the shadowed toCheck appears in the selector expression def implicatesSelector(toCheck: Symbol): Boolean = { if (selectorSymbols == null) { selectorSymbols = Nil apply(selector) } selectorSymbols.exists(sym => sym.eq(toCheck) || sym.accessedOrSelf.eq(toCheck.accessedOrSelf) || toCheck.isThisSym && toCheck.owner == sym) // self match { case self: S => }, selector C.this is class symbol } } val checkSelector = new CheckSelector // true to warn about shadowed when selSym is the scrutinee def checkShadowed(shadowed: Symbol): Boolean = { def checkShadowedSymbol(toCheck: Symbol): Boolean = isWarnable(toCheck) && !checkSelector.implicatesSelector(toCheck) if (shadowed.isOverloaded) shadowed.alternatives.exists(checkShadowedSymbol) else checkShadowedSymbol(shadowed) } // warn if any checkable pattern var shadows, in the context of the selector, // or for `tree match case Apply(fun, args) =>` check whether names in args equal names of fun.params def checkPattern(p: Tree): Unit = { val traverser = new InternalTraverser { // names absolved of shadowing because it is a "current" parameter (of a case class, etc) var absolved: List[Name] = Nil override def traverse(t: Tree): Unit = t match { case Apply(_, args) => treeInfo.dissectApplied(t).core.tpe match { case MethodType(ps, _) => foreach2(ps, args) { (p, arg) => absolved ::= p.name try traverse(arg) finally absolved = absolved.tail } case _ => t.traverse(this) } case bind @ Bind(name, _) => def richLocation(sym: Symbol): String = sym.ownsString match { case "" => val n = sym.pos.line; if (n > 0) s"$sym at line $n" else sym.fullLocationString case owns => s"$sym in $owns" } for (shade <- bind.getAndRemoveAttachment[PatShadowAttachment]) { val shadowed = shade.shadowed if (!absolved.contains(name) && !bind.symbol.hasTransOwner(shadowed.accessedOrSelf) && checkShadowed(shadowed)) refchecksWarning(bind.pos, s"Name $name is already introduced in an enclosing scope as ${richLocation(shadowed)}. Did you intend to match it using backquoted `$name`?", WarningCategory.OtherShadowing) } case _ => t.traverse(this) } } traverser(p) } // check the patterns for unfriendly shadowing, patvars bearing PatShadowAttachment if (settings.warnPatternShadow) for (cdef <- cases) checkPattern(cdef.pat) tree case _ => tree } // skip refchecks in patterns.... val result1 = result match { case CaseDef(pat, guard, body) => val pat1 = savingInPattern { inPattern = true transform(pat) } treeCopy.CaseDef(tree, pat1, transform(guard), transform(body)) case _ => result.transform(this) } result1 match { case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) | ModuleDef(_, _, _) => if (result1.symbol.isLocalToBlock || result1.symbol.isTopLevel) varianceValidator.traverse(result1) case tt @ TypeTree() if tt.original != null => varianceValidator.validateVarianceOfPolyTypesIn(tt.tpe) case _ => } checkUnexpandedMacro(result1) result1 } catch { case ex: TypeError => if (settings.isDebug) ex.printStackTrace() reporter.error(tree.pos, ex.getMessage()) tree } finally { localTyper = savedLocalTyper currentApplication = savedCurrentApplication } } } } ================================================ FILE: examples/SyntaxAnalyzer.scala ================================================ /* NSC -- new Scala compiler * Copyright 2005-2013 LAMP/EPFL * @author Martin Odersky */ package scala.tools.nsc package ast.parser import javac._ /** An nsc sub-component. */ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParsers with Scanners with JavaParsers with JavaScanners { import global._ val phaseName = "parser" def newPhase(prev: Phase): StdPhase = new ParserPhase(prev) abstract class MemberDefTraverser extends Traverser { def onMember(defn: MemberDef): Unit private var depth: Int = 0 private def lower[T](body: => T): T = { depth += 1 try body finally depth -= 1 } def currentDepth = depth /** Prune this tree and all trees beneath it. Can be overridden. */ def prune(md: MemberDef): Boolean = ( md.mods.isSynthetic || md.mods.isParamAccessor || nme.isConstructorName(md.name) || (md.name containsName nme.ANON_CLASS_NAME) ) override def traverse(t: Tree): Unit = t match { case md: MemberDef if prune(md) => case md @ PackageDef(_, stats) => traverseTrees(stats) case md: ImplDef => onMember(md) ; lower(traverseTrees(md.impl.body)) case md: ValOrDefDef => onMember(md) ; lower(traverse(md.rhs)) case _ => super.traverse(t) } } class MemberPosReporter(unit: CompilationUnit) extends MemberDefTraverser { private var outputFn: MemberDef => String = outputForScreen val path = unit.source.file.path // If a single line, outputs the line; if it spans multiple lines // outputs NN,NN with start and end lines, e.g. 15,25. def outputPos(md: MemberDef): String = { val pos = md.pos val start = pos.focusStart.line val end = pos.focusEnd.line if (start == end) "" + start else s"$start,$end" } def outputForSed(md: MemberDef): String = { val pos_s = "%-12s" format outputPos(md) + "p" s"$pos_s $path # ${md.keyword} ${md.name}" } def outputForScreen(md: MemberDef): String = { val pos_s = "%-20s" format " " * currentDepth + outputPos(md) s"$pos_s ${md.keyword} ${md.name}" } def onMember(md: MemberDef) = println(outputFn(md)) // It recognizes "sed" and "anything else". def show(style: String) { if (style == "sed") { outputFn = outputForSed traverse(unit.body) } else { outputFn = outputForScreen println(path) traverse(unit.body) } println("") } } private def initialUnitBody(unit: CompilationUnit): Tree = { if (unit.isJava) newJavaUnitParser(unit).parse() else if (currentRun.parsing.incompleteHandled) newUnitParser(unit).parse() else newUnitParser(unit).smartParse() } class ParserPhase(prev: Phase) extends StdPhase(prev) { override val checkable = false override val keepsTypeParams = false def apply(unit: CompilationUnit) { informProgress("parsing " + unit) // if the body is already filled in, don't overwrite it // otherwise compileLate is going to overwrite bodies of synthetic source files if (unit.body == EmptyTree) unit.body = initialUnitBody(unit) if (settings.Yrangepos && !reporter.hasErrors) validatePositions(unit.body) if (settings.Ymemberpos.isSetByUser) new MemberPosReporter(unit) show (style = settings.Ymemberpos.value) } } } ================================================ FILE: examples/Variance.scala ================================================ class Function1[-T1, +R] ================================================ FILE: go.mod ================================================ module github.com/tree-sitter/tree-sitter-scala go 1.22 require github.com/tree-sitter/go-tree-sitter v0.24.0 require github.com/mattn/go-pointer v0.0.1 // indirect ================================================ FILE: go.sum ================================================ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tree-sitter/go-tree-sitter v0.24.0 h1:kRZb6aBNfcI/u0Qh8XEt3zjNVnmxTisDBN+kXK0xRYQ= github.com/tree-sitter/go-tree-sitter v0.24.0/go.mod h1:x681iFVoLMEwOSIHA1chaLkXlroXEN7WY+VHGFaoDbk= github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb h1:A8425heRM8mylnv4H58FPUiH+aYivyitre0PzxrfmWs= github.com/tree-sitter/tree-sitter-c v0.21.5-0.20240818205408-927da1f210eb/go.mod h1:dOF6gtQiF9UwNh995T5OphYmtIypkjsp3ap7r9AN/iA= github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148 h1:AfFPZwtwGN01BW1jDdqBVqscTwetvMpydqYZz57RSlc= github.com/tree-sitter/tree-sitter-cpp v0.22.4-0.20240818224355-b1a4e2b25148/go.mod h1:Bh6U3viD57rFXRYIQ+kmiYtr+1Bx0AceypDLJJSyi9s= github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33 h1:TwqSV3qLp3tKSqirGLRHnjFk9Tc2oy57LIl+FQ4GjI4= github.com/tree-sitter/tree-sitter-embedded-template v0.21.1-0.20240819044651-ffbf64942c33/go.mod h1:CvCKCt3v04Ufos1zZnNCelBDeCGRpPucaN8QczoUsN4= github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012 h1:Xvxck3tE5FW7F7bTS97iNM2ADMyCMJztVqn5HYKdJGo= github.com/tree-sitter/tree-sitter-go v0.21.3-0.20240818010209-8c0f0e7a6012/go.mod h1:T40D0O1cPvUU/+AmiXVXy1cncYQT6wem4Z0g4SfAYvY= github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0 h1:c46K6uh5Dz00zJeU9BfjXdb8I+E4RkUdfnWJpQADXFo= github.com/tree-sitter/tree-sitter-html v0.20.5-0.20240818004741-d11201a263d0/go.mod h1:hcNt/kOJHcIcuMvouE7LJcYdeFUFbVpBJ6d4wmOA+tU= github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495 h1:jrt4qbJVEFs4H93/ITxygHc6u0TGqAkkate7TQ4wFSA= github.com/tree-sitter/tree-sitter-java v0.21.1-0.20240824015150-576d8097e495/go.mod h1:oyaR7fLnRV0hT9z6qwE9GkaeTom/hTDwK3H2idcOJFc= github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5 h1:om4X9AVg3asL8gxNJDcz4e/Wp+VpQj1PY3uJXKr6EOg= github.com/tree-sitter/tree-sitter-javascript v0.21.5-0.20240818005344-15887341e5b5/go.mod h1:nNqgPoV/h9uYWk6kYEFdEAhNVOacpfpRW5SFmdaP4tU= github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5 h1:pfV3G3k7NCKqKk8THBmyuh2zA33lgYHS3GVrzRR8ry4= github.com/tree-sitter/tree-sitter-json v0.21.1-0.20240818005659-bdd69eb8c8a5/go.mod h1:GbMKRjLfk0H+PI7nLi1Sx5lHf5wCpLz9al8tQYSxpEk= github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1 h1:ZXZMDwE+IhUtGug4Brv6NjJWUU3rfkZBKpemf6RY8/g= github.com/tree-sitter/tree-sitter-php v0.22.9-0.20240819002312-a552625b56c1/go.mod h1:UKCLuYnJ312Mei+3cyTmGOHzn0YAnaPRECgJmHtzrqs= github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb h1:EXEM82lFM7JjJb6qiKZXkpIDaCcbV2obNn82ghwj9lw= github.com/tree-sitter/tree-sitter-python v0.21.1-0.20240818005537-55a9b8a4fbfb/go.mod h1:lXCF1nGG5Dr4J3BTS0ObN4xJCCICiSu/b+Xe/VqMV7g= github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d h1:fcYCvoXdcP1uRQYXqJHRy6Hec+uKScQdKVtMwK9JeCI= github.com/tree-sitter/tree-sitter-ruby v0.21.1-0.20240818211811-7dbc1e2d0e2d/go.mod h1:T1nShQ4v5AJtozZ8YyAS4uzUtDAJj/iv4YfwXSbUHzg= github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447 h1:o9alBu1J/WjrcTKEthYtXmdkDc5OVXD+PqlvnEZ0Lzc= github.com/tree-sitter/tree-sitter-rust v0.21.3-0.20240818005432-2b43eafe6447/go.mod h1:1Oh95COkkTn6Ezp0vcMbvfhRP5gLeqqljR0BYnBzWvc= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= ================================================ FILE: grammar.js ================================================ const PREC = { comment: 1, using_directive: 2, control: 1, stable_type_id: 2, type: 2, while: 2, assign: 3, case: 3, stable_id: 4, unit: 4, postfix: 5, colon_call: 5, infix: 6, prefix: 7, compound: 7, call: 8, field: 8, macro: 10, binding: 10, }; module.exports = grammar({ name: "scala", extras: $ => [/\s/, $.comment, $.block_comment], supertypes: $ => [$.expression, $._definition, $._pattern], externals: $ => [ $._automatic_semicolon, $._indent, $._outdent, $._comma_outdent, $._simple_string_start, $._simple_string_middle, $._simple_multiline_string_start, $._interpolated_string_middle, $._interpolated_multiline_string_middle, $._raw_string_start, $._raw_string_middle, $._raw_string_multiline_middle, $._single_line_string_end, $._multiline_string_end, "else", "catch", "finally", "extends", "derives", "with", $.error_sentinel, ], inline: $ => [ $._pattern, $._semicolon, $._definition, $._param_type, $._identifier, $._postfix_expression_choice, $._infix_type_choice, $._param_value_type, $._simple_type, $.literal, ], // Doc: https://tree-sitter.github.io/tree-sitter/creating-parsers, search "precedences" // These names can be used in the prec functions to define precedence relative only to other names in the array, rather than globally. precedences: $ => [ ["mod", "soft_id"], ["end", "soft_id"], ["new", "structural_type"], ["self_type", "lambda"], ["annotation", "applied_constructor_type"], ["constructor_application", "applied_constructor_type"], ], conflicts: $ => [ [$.tuple_type, $.parameter_types], [$.binding, $._simple_expression], [$.binding, $._type_identifier], [$.while_expression, $._simple_expression], [$.if_expression], [$.match_expression], [$._given_constructor, $._type_identifier], [$.instance_expression], // In case of: 'extension' _indent '{' 'case' operator_identifier 'if' operator_identifier • '=>' … // we treat `operator_identifier` as `simple_expression` [$._simple_expression, $.lambda_expression], // operator_identifier • ':' … [$._simple_expression, $._single_lambda_param], // 'class' _class_constructor • _automatic_semicolon … [$._class_definition], // 'class' operator_identifier • _automatic_semicolon … [$._class_constructor], // 'enum' _class_constructor '{' 'case' operator_identifier _full_enum_def_repeat1 • _automatic_semicolon … [$._full_enum_def], // _start_val identifier ',' identifier • ':' … [$.identifiers, $.val_declaration], // 'enum' operator_identifier _automatic_semicolon '(' ')' • ':' … [$.class_parameters], // 'for' operator_identifier ':' _annotated_type • ':' … [$._type, $.compound_type], // 'for' 'given' _annotated_type • '*' … [$._type, $.infix_type], // _simple_expression ':' _annotated_type • 'match' … [$._type, $.match_type], // 'given' '(' '[' _type_parameter • ',' … [$._variant_type_parameter, $.type_lambda], // 'given' '(' operator_identifier ':' _type • ',' … [$.name_and_type, $.parameter], [$._simple_expression, $.binding, $.tuple_pattern], [$._simple_expression, $.tuple_pattern], [$._simple_expression, $._type_identifier], // 'if' parenthesized_expression • '{' … [$._if_condition, $._simple_expression], [$.block, $._braced_template_body1], [$._simple_expression, $._type_identifier], // '[' operator_identifier ':' '{' operator_identifier • '=>' … [$._single_lambda_param, $.self_type, $._type_identifier], // '[' operator_identifier ':' '{' operator_identifier • '?=>' … [$._single_lambda_param, $._type_identifier], // '(' operator_identifier • ':' … [$._simple_expression, $._single_lambda_param, $.binding], // 'given' '{' operator_identifier • ':' … [$._simple_expression, $._single_lambda_param, $.self_type], // '[' operator_identifier ':' '{' operator_identifier • ':' … [ $._simple_expression, $._single_lambda_param, $.self_type, $._type_identifier, ], // 'given' '{' operator_identifier ':' _type • '=>' … [$._single_lambda_param, $._self_type_ascription], [$.binding, $._simple_expression, $._type_identifier], [$.class_parameter, $._type_identifier], // '{' _single_lambda_param '=>' expression • '}' … [$._block, $._indentable_expression], [$.match_expression, $._simple_expression], // _ : Type • '=>' … [$.self_type, $._simple_expression], // 'for' null_literal _asterisk • '*' … [$.repeat_pattern, $.operator_identifier], // _simple_expression '(' _simple_expression _asterisk • ')' … [$.vararg, $.operator_identifier], // _simple_expression '(' expression • ',' … [$._exprs_in_parens], // _simple_expression ':' '(' wildcard • ',' … [$._annotated_type, $.binding], // '[' identifier ':' '{' wildcard • ':' … [$.self_type, $._annotated_type, $._simple_expression], // '[' identifier ':' '{' '(' wildcard • ':' … [$.binding, $._annotated_type, $._simple_expression], // '[' identifier ':' '{' wildcard • '{' … [$._annotated_type, $._simple_expression], // '[' identifier ':' '{' wildcard • '[' … [$.generic_type, $._simple_expression], ], word: $ => $._alpha_identifier, rules: { // TopStats ::= TopStat {semi TopStat} compilation_unit: $ => seq( optional($._shebang), optional(trailingSep1($._semicolon, $._top_level_definition)), ), _top_level_definition: $ => choice($._definition, $._end_marker, $.expression), _definition: $ => choice( $.given_definition, $.extension_definition, $.class_definition, $.import_declaration, $.export_declaration, $.object_definition, $.enum_definition, $.trait_definition, $.val_definition, $.val_declaration, $.var_definition, $.var_declaration, $.type_definition, $.function_definition, $.function_declaration, $.package_clause, $.package_object, ), enum_definition: $ => seq( repeat($.annotation), optional($.modifiers), "enum", $._class_constructor, field("extend", optional($.extends_clause)), field("derive", optional($.derives_clause)), field("body", $.enum_body), ), _enum_block: $ => prec.left( seq( sep1( $._semicolon, choice($.enum_case_definitions, $.expression, $._definition), ), optional($._semicolon), ), ), enum_body: $ => choice( prec.left(PREC.control, seq(":", $._indent, $._enum_block, $._outdent)), seq( "{", // TODO: self type optional($._enum_block), "}", ), ), enum_case_definitions: $ => seq( repeat($.annotation), "case", choice(commaSep1($.simple_enum_case), $.full_enum_case), ), simple_enum_case: $ => prec.left( seq( field("name", $._identifier), field("extend", optional($.extends_clause)), ), ), full_enum_case: $ => seq(field("name", $._identifier), $._full_enum_def), _full_enum_def: $ => seq( field("type_parameters", optional($.type_parameters)), field("class_parameters", repeat1($.class_parameters)), field("extend", optional($.extends_clause)), ), package_clause: $ => prec.right( seq( "package", field("name", $.package_identifier), // This is slightly more permissive than the EBNF in that it allows any // kind of declaration inside of the package blocks. As we're more // concerned with the structure rather than the validity of the program // we'll allow it. field("body", optional($.template_body)), ), ), package_identifier: $ => prec.right(sep1(".", $._identifier)), package_object: $ => seq("package", "object", $._object_definition), import_declaration: $ => prec.left(seq("import", sep1(",", $._namespace_expression))), export_declaration: $ => prec.left(seq("export", sep1(",", $._namespace_expression))), /* ImportExpr ::= SimpleRef {‘.’ id} ‘.’ ImportSpec | SimpleRef ‘as’ id ImportSpec ::= NamedSelector | WildCardSelector | ‘{’ ImportSelectors) ‘}’ NamedSelector ::= id [‘as’ (id | ‘_’)] WildCardSelector ::= ‘*’ | ‘given’ [InfixType] */ _namespace_expression: $ => prec.left( choice( seq( field("path", sep1(".", $._identifier)), optional( seq( ".", choice( $.namespace_wildcard, $.namespace_selectors, // Only allowed in Scala 3 // ImportExpr ::= // SimpleRef {‘.’ id} ‘.’ ImportSpec | SimpleRef ‘as’ id $.as_renamed_identifier, ), ), ), ), $.as_renamed_identifier, ), ), namespace_wildcard: $ => prec.left(1, choice("*", "_", "given")), _namespace_given_by_type: $ => seq("given", $._type), namespace_selectors: $ => seq( "{", trailingCommaSep1( choice( $._namespace_given_by_type, $.namespace_wildcard, $._identifier, $.arrow_renamed_identifier, $.as_renamed_identifier, ), ), "}", ), // deprecated: Remove when highlight query is updated for Neovim _import_selectors: $ => alias($.namespace_selectors, $.import_selectors), arrow_renamed_identifier: $ => seq( field("name", $._identifier), "=>", field("alias", choice($._identifier, $.wildcard)), ), as_renamed_identifier: $ => seq( field("name", $._identifier), "as", field("alias", choice($._identifier, $.wildcard)), ), object_definition: $ => seq( repeat($.annotation), optional($.modifiers), optional("case"), "object", $._object_definition, ), _object_definition: $ => prec.left( seq( field("name", $._identifier), field("extend", optional($.extends_clause)), field("derive", optional($.derives_clause)), field("body", optional($._definition_body)), ), ), class_definition: $ => seq( repeat($.annotation), optional($.modifiers), optional("case"), "class", $._class_definition, ), _class_definition: $ => seq( $._class_constructor, field("extend", optional($.extends_clause)), field("derive", optional($.derives_clause)), field("body", optional($._definition_body)), ), _definition_body: $ => seq(optional($._automatic_semicolon), field("body", $.template_body)), /** * ClassConstr ::= [ClsTypeParamClause] [ConstrMods] ClsParamClauses * ConstrMods ::= {Annotation} [AccessModifier] */ _class_constructor: $ => seq( field("name", $._identifier), field("type_parameters", optional($.type_parameters)), optional(alias($._constructor_annotation, $.annotation)), optional($.access_modifier), field( "class_parameters", repeat(seq(optional($._automatic_semicolon), $.class_parameters)), ), ), trait_definition: $ => prec.left( seq( repeat($.annotation), optional($.modifiers), "trait", $._class_definition, ), ), // The EBNF makes a distinction between function type parameters and other // type parameters as you can't specify variance on function type // parameters. This isn't important to the structure of the AST so we don't // make that distinction. type_parameters: $ => seq("[", trailingCommaSep1($._variant_type_parameter), "]"), _variant_type_parameter: $ => seq( repeat($.annotation), choice( $.covariant_type_parameter, $.contravariant_type_parameter, $._type_parameter, // invariant type parameter $.type_lambda, ), ), covariant_type_parameter: $ => seq("+", $._type_parameter), contravariant_type_parameter: $ => seq("-", $._type_parameter), _type_parameter: $ => seq( field("name", choice($.wildcard, $._identifier)), field("type_parameters", optional($.type_parameters)), field("bound", optional($.lower_bound)), field("bound", optional($.upper_bound)), field("bound", optional(repeat($.view_bound))), field("bound", optional($._context_bounds)), ), upper_bound: $ => seq("<:", field("type", $._type)), lower_bound: $ => seq(">:", field("type", $._type)), view_bound: $ => seq("<%", field("type", $._type)), _context_bounds: $ => choice( repeat1(seq(":", $.context_bound)), seq(":", "{", trailingCommaSep1($.context_bound), "}"), ), context_bound: $ => seq( field("type", $._type), optional(seq("as", field("name", $._identifier))), ), /* * TemplateBody ::= :<<< [SelfType] TemplateStat {semi TemplateStat} >>> */ template_body: $ => choice($._indented_template_body, $._braced_template_body), _indented_template_body: $ => prec.left( PREC.control, seq(":", $._indent, optional($.self_type), $._block, $._outdent), ), _braced_template_body: $ => prec.left( PREC.control, seq( "{", optional(choice($._braced_template_body1, $._braced_template_body2)), "}", ), ), _braced_template_body1: $ => seq(optional($.self_type), $._block), _braced_template_body2: $ => seq( choice( seq($._indent, optional($.self_type)), seq(optional($.self_type), $._indent), ), optional($._block), $._outdent, ), /* * WithTemplateBody ::= <<< [SelfType] TemplateStat {semi TemplateStat} >>> */ with_template_body: $ => choice( prec.left( PREC.control, seq($._indent, optional($.self_type), $._block, $._outdent), ), seq("{", optional($._block), "}"), ), _extension_template_body: $ => choice( prec.left(PREC.control, seq($._indent, $._block, $._outdent)), seq("{", optional($._block), "}"), ), _end_marker: $ => prec.left( "end", seq( "end", choice( "if", "while", "for", "match", "try", "new", "this", "given", "extension", "val", alias($._identifier, "_end_ident"), ), ), ), // Dynamic precedences added here to win over $.call_expression self_type: $ => prec.dynamic( 1, prec( "self_type", seq( choice($._identifier, $.wildcard), optional($._self_type_ascription), "=>", ), ), ), _self_type_ascription: $ => seq(":", $._type), annotation: $ => prec.right( "annotation", seq( "@", field("name", $._simple_type), field("arguments", repeat(prec("annotation", $.arguments))), ), ), // Only allows 0 or 1 argument lists as these annotations // usually come from Java, where multiple argument lists are not allowed _constructor_annotation: $ => prec( "annotation", seq( "@", field("name", $._simple_type), optional( alias( seq( // token.immediate here carries an assumption that there are no spaces between // an annotation name and its argument list, otherwise this list should be // classified as a class constructor list token.immediate("("), optional($._exprs_in_parens), ")", ), $.arguments, ), ), ), ), val_definition: $ => seq( $._start_val, field("pattern", choice($._pattern, $.identifiers)), optional(seq(":", field("type", $._type))), "=", field("value", $._indentable_expression), ), val_declaration: $ => seq( $._start_val, commaSep1(field("name", $._identifier)), ":", field("type", $._type), ), _start_val: $ => seq(repeat($.annotation), optional($.modifiers), "val"), var_declaration: $ => seq( $._start_var, commaSep1(field("name", $._identifier)), ":", field("type", $._type), ), var_definition: $ => seq( $._start_var, field("pattern", choice($._pattern, $.identifiers)), optional(seq(":", field("type", $._type))), "=", field("value", $._indentable_expression), ), _start_var: $ => seq(repeat($.annotation), optional($.modifiers), "var"), type_definition: $ => prec.left( seq( repeat($.annotation), optional($.modifiers), optional($.opaque_modifier), "type", $._type_constructor, optional(seq("=", field("type", $._type))), ), ), // Created for memory-usage optimization during codegen. _type_constructor: $ => prec.left( seq( field("name", $._type_identifier), field("type_parameters", optional($.type_parameters)), field("bound", optional($.lower_bound)), field("bound", optional($.upper_bound)), field("bound", optional($._context_bounds)), ), ), function_definition: $ => seq( $._function_declaration, choice( seq("=", field("body", $._indentable_expression)), field("body", $.block), ), ), function_declaration: $ => $._function_declaration, _function_declaration: $ => prec.left( seq( repeat($.annotation), optional($.modifiers), "def", $._function_constructor, optional(seq(":", field("return_type", $._type))), ), ), // Created for memory-usage optimization during codegen. _function_constructor: $ => prec.right( seq( field("name", $._identifier), field( "parameters", repeat( seq( optional($._automatic_semicolon), choice($.parameters, $.type_parameters), ), ), ), optional($._automatic_semicolon), ), ), opaque_modifier: $ => prec("mod", "opaque"), /** * Extension ::= 'extension' [DefTypeParamClause] {UsingParamClause} * '(' DefParam ')' {UsingParamClause} ExtMethods */ extension_definition: $ => prec.left( seq( "extension", field("type_parameters", optional($.type_parameters)), field("parameters", repeat($.parameters)), field( "body", choice( $._extension_template_body, $.function_definition, $.function_declaration, ), ), ), ), /** * GivenDef ::= [GivenSig] (AnnotType ['=' Expr] | StructuralInstance) * GivenSig ::= [id] [DefTypeParamClause] {UsingParamClause} ':' */ given_definition: $ => prec.left( seq( repeat($.annotation), optional($.modifiers), "given", optional($._given_constructor), repeat($._given_sig), choice( field("return_type", $._structural_instance), seq( field("return_type", $._annotated_type), optional(seq("=", field("body", $._indentable_expression))), ), ), ), ), _given_sig: $ => seq($._given_conditional, "=>"), _given_conditional: $ => choice(alias($.parameters, $.given_conditional), $.type_parameters), _given_constructor: $ => prec.right( seq( field("name", optional($._identifier)), field("type_parameters", optional($.type_parameters)), field( "parameters", repeat(seq(optional($._automatic_semicolon), $.parameters)), ), optional($._automatic_semicolon), ":", ), ), /** * StructuralInstance ::= ConstrApp {'with' ConstrApp} ['with' WithTemplateBody] */ _structural_instance: $ => prec.left( PREC.compound, seq( $._constructor_application, choice(":", "with"), field("body", $.with_template_body), ), ), /** * ConstrApp ::= SimpleType1 {Annotation} {ParArgumentExprs} * * Note: It would look more elegant if we could make seq(choice(), optional(arguments)), * but that doesn't seem to work. */ _constructor_application: $ => prec.left( "constructor_application", choice( $._annotated_type, $.compound_type, // In theory structural_type should just be added to simple_type, // but doing so increases the state of template_body to 4000 $._structural_type, // This adds _simple_type, but not the above intentionally. seq($._simple_type, field("arguments", $.arguments)), seq($._annotated_type, field("arguments", $.arguments)), seq($.compound_type, field("arguments", $.arguments)), ), ), _constructor_applications: $ => prec.left( choice( commaSep1($._constructor_application), sep1("with", $._constructor_application), ), ), modifiers: $ => prec.left( repeat1( prec.left( choice( "abstract", "final", "sealed", "implicit", "lazy", "override", $.access_modifier, $.inline_modifier, $.infix_modifier, $.into_modifier, $.open_modifier, $.tracked_modifier, $.transparent_modifier, ), ), ), ), access_modifier: $ => prec.left( seq(choice("private", "protected"), optional($.access_qualifier)), ), access_qualifier: $ => seq("[", $._identifier, "]"), inline_modifier: $ => prec("mod", "inline"), infix_modifier: $ => prec("mod", "infix"), into_modifier: $ => prec("mod", "into"), open_modifier: $ => prec("mod", "open"), tracked_modifier: $ => prec("mod", "tracked"), transparent_modifier: $ => prec("mod", "transparent"), /** * InheritClauses ::= ['extends' ConstrApps] ['derives' QualId {',' QualId}] */ extends_clause: $ => prec.left( seq( "extends", field("type", $._constructor_applications), repeat($.arguments), ), ), derives_clause: $ => prec.left( seq( "derives", commaSep1( field("type", choice($._type_identifier, $.stable_type_identifier)), ), ), ), class_parameters: $ => prec( 1, seq( optional($._automatic_semicolon), "(", choice( seq( "using", choice( trailingCommaSep1($.class_parameter), trailingCommaSep1($._param_type), ), ), seq(optional("implicit"), trailingCommaSep($.class_parameter)), ), ")", ), ), /* * DefParamClauses ::= {DefParamClause} [[nl] ‘(’ [‘implicit’] DefParams ‘)’] * DefParamClause ::= [nl] ‘(’ DefParams ‘)’ | UsingParamClause * DefParams ::= DefParam {‘,’ DefParam} */ parameters: $ => choice( seq("(", optional("implicit"), trailingCommaSep($.parameter), ")"), $._using_parameters_clause, ), /* * UsingParamClause ::= [nl] ‘(’ ‘using’ (DefParams | FunArgTypes) ‘)’ * DefParams ::= DefParam {‘,’ DefParam} * FunArgTypes ::= FunArgType { ‘,’ FunArgType } */ _using_parameters_clause: $ => seq( "(", "using", choice( trailingCommaSep1($.parameter), trailingCommaSep1($._param_type), ), ")", ), class_parameter: $ => seq( repeat($.annotation), optional($.modifiers), optional(choice("val", "var")), field("name", $._identifier), optional(seq(":", field("type", $._param_type))), optional(seq("=", field("default_value", $.expression))), ), /* * DefParam ::= {Annotation} [‘inline’] Param * Param ::= id ‘:’ ParamType [‘=’ Expr] */ parameter: $ => prec.left( PREC.control, seq( repeat($.annotation), optional($.inline_modifier), field("name", $._identifier), ":", field("type", $._param_type), optional(seq("=", field("default_value", $.expression))), ), ), /* * NameAndType ::= id ':' Type */ name_and_type: $ => prec.left( PREC.control, seq(field("name", $._identifier), ":", field("type", $._param_type)), ), _block: $ => prec.left( seq( sep1( $._semicolon, choice($.expression, $._definition, $._end_marker, ";"), ), optional($._semicolon), ), ), _indentable_expression: $ => prec.right(choice($.indented_block, $.indented_cases, $.expression)), block: $ => seq( "{", optional( choice( $._block, alias($._block_lambda_expression, $.lambda_expression), ), ), "}", ), indented_block: $ => prec.left( PREC.control, seq( $._indent, $._block, choice($._outdent, $._comma_outdent), optional($._end_marker), ), ), indented_cases: $ => prec.left( seq( $._indent, repeat1($.case_clause), choice($._outdent, $._comma_outdent), ), ), // --------------------------------------------------------------- // Types _type: $ => choice( $.function_type, $.compound_type, $.infix_type, $.match_type, $._annotated_type, $.literal_type, $._structural_type, $.type_lambda, ), _annotated_type: $ => prec.right(choice($.annotated_type, $._simple_type)), annotated_type: $ => prec.right(seq($._simple_type, repeat1($.annotation))), _simple_type: $ => choice( $.generic_type, $.projected_type, $.tuple_type, $.named_tuple_type, $.singleton_type, $.stable_type_identifier, $._type_identifier, $.applied_constructor_type, $.wildcard, ), applied_constructor_type: $ => prec("applied_constructor_type", seq($._type_identifier, $.arguments)), compound_type: $ => choice( prec.left( PREC.compound, seq( field("base", $._annotated_type), repeat1(seq("with", field("extra", $._annotated_type))), ), ), prec.left(seq(field("base", $._annotated_type), $._refinement)), prec.left( -1, seq( prec.left( PREC.compound, seq( field("base", $._annotated_type), repeat1(seq("with", field("extra", $._annotated_type))), ), ), $._refinement, ), ), ), _structural_type: $ => prec("structural_type", alias($.template_body, $.structural_type)), _refinement: $ => alias($.template_body, $.refinement), // This does not include _simple_type since _annotated_type covers it. _infix_type_choice: $ => prec.left( choice( $.compound_type, $.infix_type, $._annotated_type, $.literal_type, ), ), infix_type: $ => prec.left( seq( field("left", $._infix_type_choice), field("operator", $._identifier), field("right", $._infix_type_choice), ), ), tuple_type: $ => seq("(", trailingCommaSep1($._type), ")"), named_tuple_type: $ => seq("(", trailingCommaSep1($.name_and_type), ")"), singleton_type: $ => prec.left( PREC.stable_type_id, seq(choice($._identifier, $.stable_identifier), ".", "type"), ), stable_type_identifier: $ => prec.left( PREC.stable_type_id, seq( choice($._identifier, $.stable_identifier), ".", $._type_identifier, ), ), stable_identifier: $ => prec.left( PREC.stable_id, seq(choice($._identifier, $.stable_identifier), ".", $._identifier), ), generic_type: $ => seq( field("type", $._simple_type), field("type_arguments", $.type_arguments), ), projected_type: $ => seq( field("type", $._simple_type), "#", field("selector", $._type_identifier), ), match_type: $ => prec.left( seq( $._infix_type_choice, "match", choice( seq($._indent, repeat1($.type_case_clause), $._outdent), seq("{", repeat1($.type_case_clause), "}"), ), ), ), type_case_clause: $ => prec.left( PREC.control, seq("case", $._infix_type_choice, field("body", $._arrow_then_type)), ), function_type: $ => prec.left( choice( seq(field("type_parameters", $.type_parameters), $._arrow_then_type), seq(field("parameter_types", $.parameter_types), $._arrow_then_type), ), ), _arrow_then_type: $ => prec.right(seq(choice("=>", "?=>"), field("return_type", $._type))), // Deprioritize against typed_pattern._type. parameter_types: $ => prec( -1, choice( $._annotated_type, // Prioritize a parenthesized param list over a single tuple_type. prec.dynamic(1, seq("(", trailingCommaSep($._param_type), ")")), $.compound_type, $.infix_type, ), ), _param_type: $ => choice($.lazy_parameter_type, $._param_value_type), _param_value_type: $ => choice(field("type", $._type), $.repeated_parameter_type), repeated_parameter_type: $ => seq(field("type", $._type), $._asterisk), lazy_parameter_type: $ => seq("=>", field("type", $._param_value_type)), _type_identifier: $ => alias($._identifier, $.type_identifier), type_lambda: $ => seq( "[", trailingCommaSep1($._type_parameter), "]", "=>>", field("return_type", $._type), ), // --------------------------------------------------------------- // Patterns _pattern: $ => choice( $._identifier, $.stable_identifier, $.interpolated_string_expression, $.capture_pattern, $.tuple_pattern, $.named_tuple_pattern, $.case_class_pattern, $.infix_pattern, $.alternative_pattern, $.typed_pattern, $.given_pattern, $.quote_expression, $.literal, $.wildcard, $.repeat_pattern, ), case_class_pattern: $ => seq( field("type", choice($._type_identifier, $.stable_type_identifier)), "(", choice( field("pattern", trailingCommaSep($._pattern)), field("pattern", trailingCommaSep($.named_pattern)), ), ")", ), infix_pattern: $ => prec.left( PREC.infix, seq( field("left", $._pattern), field("operator", $._identifier), field("right", $._pattern), ), ), capture_pattern: $ => prec.right( PREC.field, seq( field("name", choice($._identifier, $.wildcard)), "@", field("pattern", $._pattern), ), ), repeat_pattern: $ => prec.right(seq(field("pattern", $._pattern), $._asterisk)), typed_pattern: $ => prec.right( -1, seq(field("pattern", $._pattern), ":", field("type", $._type)), ), given_pattern: $ => seq("given", field("type", $._type)), // TODO: Flatten this. alternative_pattern: $ => prec.left(-2, seq($._pattern, "|", $._pattern)), tuple_pattern: $ => seq("(", trailingCommaSep1($._pattern), ")"), named_pattern: $ => prec.left(-1, seq($._identifier, "=", $._pattern)), named_tuple_pattern: $ => seq("(", trailingCommaSep1($.named_pattern), ")"), // --------------------------------------------------------------- // Expressions expression: $ => choice( $.if_expression, $.match_expression, $.try_expression, $.assignment_expression, $.lambda_expression, $.postfix_expression, $.ascription_expression, $.infix_expression, $.prefix_expression, $.return_expression, $.throw_expression, $.while_expression, $.do_while_expression, $.for_expression, $.macro_body, $._simple_expression, ), /** * SimpleExpr ::= SimpleRef * | Literal * | '_' * | BlockExpr * | ExprSplice * | Quoted * | quoteId * | 'new' ConstrApp {'with' ConstrApp} [TemplateBody] * | 'new' TemplateBody * | '(' ExprsInParens ')' * | SimpleExpr '.' id * | SimpleExpr '.' MatchClause * | SimpleExpr TypeArgs * | SimpleExpr ArgumentExprs * | SimpleExpr ColonArgument * TODO: ColonArgument */ _simple_expression: $ => choice( $.identifier, $.operator_identifier, $.literal, $.interpolated_string_expression, $.unit, $.tuple_expression, $.wildcard, $.block, $.splice_expression, $.case_block, $.quote_expression, $.instance_expression, $.parenthesized_expression, $.field_expression, $.generic_function, $.call_expression, alias($._dot_match_expression, $.match_expression), ), _single_lambda_param: $ => prec.right( seq(optional("implicit"), $._identifier, optional(seq(":", $._type))), ), lambda_expression: $ => prec.right( "lambda", seq( optional(seq(field("type_parameters", $.type_parameters), "=>")), field( "parameters", choice($.bindings, $.wildcard, $._single_lambda_param), ), choice("=>", "?=>"), $._indentable_expression, ), ), /* Special-case lambda expression to handle lambdas in braces (in $.block), e.g. * { (...) => val a = 1; val b = 2 * 3 * } * * It exists as a separate rule because grammar generation becomes unacceptably slow * if we include $._block right into $.lambda_expression as a viable option for the lambda body. */ _block_lambda_expression: $ => prec.right( "lambda", seq( field( "parameters", choice($.bindings, $.wildcard, $._single_lambda_param), ), choice("=>", "?=>"), $._block, ), ), /* * ::= [‘inline’] ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] ‘else’ Expr] * | [‘inline’] ‘if’ Expr ‘then’ Expr [[semi] ‘else’ Expr] */ if_expression: $ => seq( optional($.inline_modifier), "if", field("condition", $._if_condition), field("consequence", $._indentable_expression), optional( seq( optional(";"), "else", field("alternative", $._indentable_expression), ), ), ), // NOTE(susliko): _if_condition and its magic dynamic precedence were introduced as a fix to // https://github.com/tree-sitter/tree-sitter-scala/issues/263 and // https://github.com/tree-sitter/tree-sitter-scala/issues/342 // Neither do I understand why this works, nor have I found a better solution _if_condition: $ => prec.dynamic( 4, choice( $.parenthesized_expression, seq($._indentable_expression, "then"), ), ), /* * MatchClause ::= 'match' <<< CaseClauses >>> * * Handles: * InfixExpr MatchClause * ‘inline’ InfixExpr MatchClause * SimpleExpr ‘.’ MatchClause */ match_expression: $ => choice( seq( optional($.inline_modifier), field("value", $.expression), "match", field("body", choice($.case_block, $.indented_cases)), ), $._dot_match_expression, ), _dot_match_expression: $ => seq( field("value", $._simple_expression), ".", token.immediate("match"), field("body", choice($.case_block, $.indented_cases)), ), try_expression: $ => prec.right( PREC.control, seq( "try", field("body", $._indentable_expression), optional($.catch_clause), optional($.finally_clause), ), ), /* * Catches ::= 'catch' (Expr | ExprCaseClause) */ catch_clause: $ => prec.right( seq("catch", choice($._indentable_expression, $._expr_case_clause)), ), _expr_case_clause: $ => prec.left(seq("case", $._case_pattern, field("body", $.expression))), finally_clause: $ => prec.right(seq("finally", $._indentable_expression)), /* * Binding ::= (id | ‘_’) [‘:’ Type] */ binding: $ => seq( choice(field("name", $._identifier), $.wildcard), optional(seq(":", field("type", $._param_type))), ), bindings: $ => seq("(", trailingCommaSep($.binding), ")"), case_block: $ => choice(prec(-1, seq("{", "}")), seq("{", repeat1($.case_clause), "}")), case_clause: $ => prec.left( seq("case", $._case_pattern, field("body", optional($._block))), ), // Dynamic precedence to win over lambda_expression in complex contexts _case_pattern: $ => prec.dynamic( 1, seq(field("pattern", $._pattern), optional($.guard), "=>"), ), guard: $ => prec.left( PREC.control, seq("if", field("condition", $._postfix_expression_choice)), ), assignment_expression: $ => prec.right( PREC.assign, seq( field("left", choice($.prefix_expression, $._simple_expression)), "=", field("right", choice($.expression, $.indented_block)), ), ), generic_function: $ => prec( PREC.call, seq( field("function", $.expression), field("type_arguments", $.type_arguments), ), ), call_expression: $ => choice( prec.left( PREC.call, seq( field("function", $._simple_expression), field("arguments", choice($.arguments, $.case_block, $.block)), ), ), prec.right( PREC.colon_call, seq( field("function", $._postfix_expression_choice), ":", field("arguments", $.colon_argument), ), ), ), /** * ColonArgument ::= colon [LambdaStart] * (CaseClauses | Block) */ colon_argument: $ => prec.left( PREC.colon_call, seq( optional( field( "lambda_start", seq(choice($.bindings, $._identifier, $.wildcard), "=>"), ), ), choice($.indented_block, $.indented_cases), ), ), field_expression: $ => prec.left( PREC.field, seq( field("value", $._simple_expression), ".", field("field", $._identifier), ), ), /** * SimpleExpr ::= SimpleRef * | 'new' ConstrApp {'with' ConstrApp} [TemplateBody] * | 'new' TemplateBody */ instance_expression: $ => choice( // This is weakened so ascription wins for new Array: Array prec.dynamic( 0, seq("new", $._constructor_application, $.template_body), ), prec("new", seq("new", $.template_body)), seq("new", $._constructor_application), ), /** * PostfixExpr [Ascription] */ ascription_expression: $ => prec.left( seq( $._postfix_expression_choice, ":", choice($._param_type, $.annotation), ), ), infix_expression: $ => prec.left( PREC.infix, seq( field( "left", choice( $.infix_expression, $.prefix_expression, $._simple_expression, ), ), field("operator", $._identifier), field( "right", choice( $.prefix_expression, $._simple_expression, seq(":", $.colon_argument), ), ), ), ), /** * PostfixExpr ::= InfixExpr [id] */ postfix_expression: $ => prec.left( PREC.postfix, seq( choice($.infix_expression, $.prefix_expression, $._simple_expression), $._identifier, ), ), _postfix_expression_choice: $ => prec.left( PREC.postfix, choice( $.postfix_expression, $.infix_expression, $.prefix_expression, $._simple_expression, ), ), macro_body: $ => prec.left( PREC.macro, seq( "macro", choice($.infix_expression, $.prefix_expression, $._simple_expression), ), ), /** * PrefixExpr ::= [PrefixOperator] SimpleExpr */ prefix_expression: $ => prec(PREC.prefix, seq(choice("+", "-", "!", "~"), $._simple_expression)), tuple_expression: $ => seq( "(", $.expression, repeat1(seq(",", $.expression)), optional(","), ")", ), parenthesized_expression: $ => seq("(", $.expression, ")"), type_arguments: $ => seq("[", trailingCommaSep1($._type), "]"), arguments: $ => seq( "(", choice( $._vararg_arguments, optional($._exprs_in_parens), seq("using", $._exprs_in_parens), ), ")", ), _vararg_arguments: $ => seq(optional(seq($._exprs_in_parens, ",")), $.vararg), vararg: $ => choice( // Scala 3: `args*` seq($._simple_expression, $._asterisk), // Scala 2: `args: _*` seq($._simple_expression, ":", token(seq("_", token.immediate("*")))), ), // ExprsInParens ::= ExprInParens {‘,’ ExprInParens} _exprs_in_parens: $ => trailingCommaSep1($.expression), splice_expression: $ => prec.left( PREC.macro, seq( "$", choice( seq("{", $._block, "}"), seq("[", $._type, "]"), // TODO: This would never hit, since identifier permits $ sign $.identifier, ), ), ), quote_expression: $ => prec.left( PREC.macro, seq( "'", choice(seq("{", $._block, "}"), seq("[", $._type, "]"), $.identifier), ), ), /** * id ::= plainid * | ‘`’ { charNoBackQuoteOrNewline | UnicodeEscape | charEscapeSeq */ identifier: $ => choice($._alpha_identifier, $._backquoted_id, $._soft_identifier), // https://docs.scala-lang.org/scala3/reference/soft-modifier.html _soft_identifier: $ => prec( "soft_id", choice( "infix", "inline", "opaque", "open", "tracked", "transparent", "end", ), ), /** * alphaid ::= upper idrest * | varid * We approximate the above as: * /[A-Za-z\$_][A-Z\$_a-z0-9]*(_[\-!#%&*+\/\\:<=>?@\u005e\u007c~]+)?/, * * The following is more accurate, but the state count goes over the unsigned short int, and should be comparable. * /([\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\$][\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\$\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F0-9]*(_[\-!#%&*+\/\\:<=>?@\u005e\u007c~]+)?|[\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F_][\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\$\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F0-9]*(_[\-!#%&*+/\\:<=>?@\u005e\u007c~]+)?|[\-!#%&*+\/\\:<=>?@\u005e\u007c~]+)|[\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F_][\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\$\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F0-9]*(_[\-!#%&*+\/\\:<=>?@\u005e\u007c~]+)?/, */ _alpha_identifier: $ => /[\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\$\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F\$][\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\$\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F0-9\$_\p{Ll}]*(_[\-!#%&*+\/\\:<=>?@\u005e\u007c~\p{Sm}\p{So}]+)?/, /** * Despite what the lexical syntax suggests, the alphaid rule doesn't apply * to identifiers that aren't in blocks in interpolated strings (e.g. $foo). * A more accurate description is given in * https://www.scala-lang.org/files/archive/spec/2.13/01-lexical-syntax.html * where it states (regarding dollar sign escapes in interpolated strings) that * """ * The simpler form consists of a ‘$’-sign followed by an identifier starting * with a letter and followed only by letters, digits, and underscore characters * """ * where "letters" does not include the $ character. * * This rule is similar to the _alpha_identifier rule, with the differences * being that the $ character is excluded, along with the _(operator_chars) * suffix and can be approximated as * /[A-Za-z_][A-Z_a-z0-9]/; */ _interpolation_identifier: $ => /[\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F][\p{Lu}\p{Lt}\p{Nl}\p{Lo}\p{Lm}\p{Ll}_\u00AA\u00BB\u02B0-\u02B8\u02C0-\u02C1\u02E0-\u02E4\u037A\u1D78\u1D9B-\u1DBF\u2071\u207F\u2090-\u209C\u2C7C-\u2C7D\uA69C-\uA69D\uA770\uA7F8-\uA7F9\uAB5C-\uAB5F0-9_\p{Ll}]*/, _backquoted_id: $ => /`[^\n`]+`/, _identifier: $ => choice($.identifier, $.operator_identifier), identifiers: $ => seq($.identifier, ",", commaSep1($.identifier)), wildcard: $ => "_", // We have an asterisk as a separte rule to avoid premature choice of // $.vararg branch over $.operator_identifier. // Otherwise $.operator_identifier that is being declared as regexp // looses by a lexical precedence to an explicitly defined literal "*". _asterisk: $ => "*", /** * Regex patterns created to avoid matching // comments and /* comment starts. * This could technically match illegal tokens such as val ?// = 1 */ operator_identifier: $ => choice( $._asterisk, token( choice( // opchar minus colon, equal, at // Technically speaking, Sm (Math symbols https://www.compart.com/en/unicode/category/Sm) // should be allowed as a single-character opchar, however, it includes `=`, // so we should to avoid that to prevent bad parsing of `=` as infix term or type. /[\-!#%&*+\/\\<>?\u005e\u007c~\u00ac\u00b1\u00d7\u00f7\u2190-\u2194\p{So}]/, seq( // opchar minus slash /[\-!#%&*+\\:<=>?@\u005e\u007c~\p{Sm}\p{So}]/, // opchar* repeat1(/[\-!#%&*+\/\\:<=>?@\u005e\u007c~\p{Sm}\p{So}]/), ), seq( // opchar /[\-!#%&*+\/\\:<=>?@\u005e\u007c~\p{Sm}\p{So}]/, // opchar minus slash and asterisk /[\-!#%&+\\:<=>?@\u005e\u007c~\p{Sm}\p{So}]/, // opchar* repeat(/[\-!#%&*+\/\\:<=>?@\u005e\u007c~\p{Sm}\p{So}]/), ), ), ), ), _non_null_literal: $ => choice( $.integer_literal, $.floating_point_literal, $.boolean_literal, $.character_literal, $.string, ), literal_type: $ => prec.left(PREC.type, $._non_null_literal), literal: $ => choice($._non_null_literal, $.null_literal), integer_literal: $ => token( seq( optional(/[-]/), choice(/[\d](_?\d)*/, /0[xX][\da-fA-F](_?[\da-fA-F])*/), optional(/[lL]/), ), ), floating_point_literal: $ => token( seq( optional(/[-]/), choice( // digit {digit} ‘.’ digit {digit} [exponentPart] [floatType] seq(/[\d]+\.[\d]+/, optional(/[eE][+-]?[\d]+/), optional(/[dfDF]/)), // ‘.’ digit {digit} [exponentPart] [floatType] seq(/\.[\d]+/, optional(/[eE][+-]?[\d]+/), optional(/[dfDF]/)), // digit {digit} exponentPart [floatType] seq(/[\d]+/, /[eE][+-]?[\d]+/, optional(/[dfDF]/)), // digit {digit} [exponentPart] floatType seq(/[\d]+/, optional(/[eE][+-]?[\d]+/), /[dfDF]/), ), ), ), boolean_literal: $ => choice("true", "false"), character_literal: $ => token( seq( "'", optional( choice( seq( "\\", choice(/[^xu]/, /[uU]+[0-9a-fA-F]{4}/, /x[0-9a-fA-F]{2}/), ), /[^\\'\n]/, ), ), "'", ), ), interpolated_string_expression: $ => choice( seq( field("interpolator", alias($._raw_string_start, $.identifier)), alias($._raw_string, $.interpolated_string), ), seq(field("interpolator", $.identifier), $.interpolated_string), ), _dollar_escape: $ => alias(token(seq("$", choice("$", '"'))), $.escape_sequence), _aliased_interpolation_identifier: $ => alias($._interpolation_identifier, $.identifier), interpolation: $ => seq("$", choice($._aliased_interpolation_identifier, $.block)), interpolated_string: $ => choice( seq( token.immediate('"'), repeat( seq( $._interpolated_string_middle, choice($._dollar_escape, $.interpolation, $.escape_sequence), ), ), $._single_line_string_end, ), seq( token.immediate('"""'), repeat( seq( $._interpolated_multiline_string_middle, // Multiline strings ignore escape sequences choice($._dollar_escape, $.interpolation), ), ), $._multiline_string_end, ), ), // We need to handle single-line raw strings separately from interpolated strings, // because raw strings are not parsed for escape sequences. For example, raw strings // are often used for regular expressions, which contain backslashes that would // be invalid if parsed as escape sequences. We do not special case multiline // raw strings, because multiline strings do not parse escape sequences anyway. // Scala handles multiline raw strings identically to other multiline interpolated, // so we could parse them as interpolated strings, but I think the code is cleaner // if we maintain the distinction. _raw_string: $ => choice( seq( $._simple_string_start, seq( repeat( seq( $._raw_string_middle, choice($._dollar_escape, $.interpolation), ), ), $._single_line_string_end, ), ), seq( $._simple_multiline_string_start, repeat( seq( $._raw_string_multiline_middle, choice($._dollar_escape, $.interpolation), ), ), $._multiline_string_end, ), ), escape_sequence: _ => token.immediate( seq( "\\", choice( /[tbnrf"'\\]/, // The Java spec allows any number of u's and U's at the start of a unicode escape. /[uU]+[0-9a-fA-F]{4}/, // Octals are not allowed in Scala 3, but are allowed in Scala 2. tree-sitter // does not have a mechanism for distinguishing between different versions of a // language, so I think it makes sense to allow them. Maybe in the future we // should move them to a `deprecated` syntax node? /[0-3]?[0-7]{1,2}/, ), ), ), string: $ => choice( seq( $._simple_string_start, repeat(seq($._simple_string_middle, $.escape_sequence)), $._single_line_string_end, ), seq( $._simple_multiline_string_start, /// Multiline strings ignore escape sequences $._multiline_string_end, ), ), _semicolon: $ => choice(";", $._automatic_semicolon), null_literal: $ => "null", unit: $ => prec(PREC.unit, seq("(", ")")), return_expression: $ => prec.left(seq("return", optional($.expression))), throw_expression: $ => prec.left(seq("throw", $.expression)), /* * Expr1 ::= 'while' '(' Expr ')' {nl} Expr * | 'while' Expr 'do' Expr */ while_expression: $ => prec( PREC.while, choice( prec.right( seq( "while", field("condition", $.parenthesized_expression), field("body", $.expression), ), ), prec.right( seq( "while", field("condition", seq($._indentable_expression, "do")), field("body", $._indentable_expression), ), ), ), ), do_while_expression: $ => prec.right( seq( "do", field("body", $.expression), "while", field("condition", $.parenthesized_expression), ), ), /* * ForExpr ::= 'for' '(' Enumerators0 ')' {nl} ['do' | 'yield'] Expr * | 'for' '{' Enumerators0 '}' {nl} ['do' | 'yield'] Expr * | 'for' Enumerators0 ('do' | 'yield') Expr */ for_expression: $ => choice( prec.right( PREC.control, seq( "for", field( "enumerators", choice( seq("(", $.enumerators, ")"), seq("{", $.enumerators, "}"), ), ), choice( seq(field("body", $.expression)), seq("yield", field("body", $._indentable_expression)), ), ), ), prec.right( PREC.control, seq( "for", field("enumerators", $.enumerators), choice( seq("do", field("body", $._indentable_expression)), seq("yield", field("body", $._indentable_expression)), ), ), ), ), enumerators: $ => choice( seq(sep1($._semicolon, $.enumerator), optional($._automatic_semicolon)), seq( $._indent, sep1($._semicolon, $.enumerator), optional($._automatic_semicolon), $._outdent, ), ), /** * Enumerator ::= Generator * | Guard {Guard} * | Pattern1 '=' Expr */ enumerator: $ => choice( seq( optional("case"), $._pattern, choice("<-", "="), $.expression, optional($.guard), ), repeat1($.guard), ), _shebang: $ => alias(token(seq("#!", /.*/)), $.comment), comment: $ => seq(token("//"), choice($.using_directive, $._comment_text)), _comment_text: $ => token(prec(PREC.comment, /.*/)), using_directive: $ => seq( token.immediate(prec(PREC.using_directive, ">")), token("using"), $.using_directive_key, $.using_directive_value, ), using_directive_key: $ => token(/[^\s]+/), using_directive_value: $ => token(/.*/), block_comment: $ => seq(token("/*"), repeat(choice(token(/./), token("//"))), token("*/")), }, }); function commaSep(rule) { return optional(commaSep1(rule)); } function commaSep1(rule) { return sep1(",", rule); } function trailingCommaSep(rule) { return optional(trailingCommaSep1(rule)); } function trailingCommaSep1(rule) { return trailingSep1(",", rule); } function trailingSep1(delimiter, rule) { return seq(sep1(delimiter, rule), optional(delimiter)); } function sep1(delimiter, rule) { return seq(rule, repeat(seq(delimiter, rule))); } ================================================ FILE: package.json ================================================ { "name": "tree-sitter-scala", "version": "0.26.0", "description": "Scala grammar for tree-sitter", "repository": "https://github.com/tree-sitter/tree-sitter-scala", "license": "MIT", "author": { "name": "Max Brunsfeld", "email": "maxbrunsfeld@gmail.com" }, "main": "bindings/node", "types": "bindings/node", "keywords": [ "incremental", "parsing", "tree-sitter", "scala" ], "files": [ "grammar.js", "tree-sitter.json", "binding.gyp", "prebuilds/**", "bindings/node/*", "queries/*", "src/**", "*.wasm" ], "dependencies": { "node-addon-api": "^8.2.2", "node-gyp-build": "^4.8.2" }, "devDependencies": { "prebuildify": "^6.0.1", "tree-sitter-cli": "^0.26.8", "prettier": "3.3.3" }, "peerDependencies": { "tree-sitter": "^0.21.1" }, "peerDependenciesMeta": { "tree-sitter": { "optional": true } }, "scripts": { "install": "node-gyp-build", "prestart": "tree-sitter build --wasm", "start": "tree-sitter playground", "test": "node --test bindings/node/*_test.js", "prebuildify": "prebuildify --napi --strip" } } ================================================ FILE: pyproject.toml ================================================ [build-system] requires = ["setuptools>=42", "wheel"] build-backend = "setuptools.build_meta" [project] name = "tree-sitter-scala" description = "Scala grammar for tree-sitter" version = "0.26.0" keywords = ["incremental", "parsing", "tree-sitter", "scala"] classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Compilers", "Topic :: Text Processing :: Linguistic", "Typing :: Typed", ] authors = [{ name = "Max Brunsfeld", email = "maxbrunsfeld@gmail.com" }] requires-python = ">=3.9" license.text = "MIT" readme = "README.md" [project.urls] Homepage = "https://github.com/tree-sitter/tree-sitter-scala" [project.optional-dependencies] core = ["tree-sitter~=0.22"] [tool.cibuildwheel] build = "cp39-*" build-frontend = "build" ================================================ FILE: queries/highlights.scm ================================================ ; CREDITS @stumash (stuart.mashaal@gmail.com) (field_expression field: (identifier) @property) (field_expression value: (identifier) @type (#match? @type "^[A-Z]")) (type_identifier) @type (class_definition name: (identifier) @type) (enum_definition name: (identifier) @type) (object_definition name: (identifier) @type) (trait_definition name: (identifier) @type) (full_enum_case name: (identifier) @type) (simple_enum_case name: (identifier) @type) ;; variables (class_parameter name: (identifier) @parameter) (self_type (identifier) @parameter) (interpolation (identifier) @none) (interpolation (block) @none) ;; types (type_definition name: (type_identifier) @type.definition) ;; val/var definitions/declarations (val_definition pattern: (identifier) @variable) (var_definition pattern: (identifier) @variable) (val_declaration name: (identifier) @variable) (var_declaration name: (identifier) @variable) ; imports/exports (import_declaration path: (identifier) @namespace) ((stable_identifier (identifier) @namespace)) ((import_declaration path: (identifier) @type) (#match? @type "^[A-Z]")) ((stable_identifier (identifier) @type) (#match? @type "^[A-Z]")) (export_declaration path: (identifier) @namespace) ((stable_identifier (identifier) @namespace)) ((export_declaration path: (identifier) @type) (#match? @type "^[A-Z]")) ((stable_identifier (identifier) @type) (#match? @type "^[A-Z]")) ((namespace_selectors (identifier) @type) (#match? @type "^[A-Z]")) ; method invocation (call_expression function: (identifier) @function.call) (call_expression function: (operator_identifier) @function.call) (call_expression function: (field_expression field: (identifier) @method.call)) ((call_expression function: (identifier) @constructor) (#match? @constructor "^[A-Z]")) (generic_function function: (identifier) @function.call) (interpolated_string_expression interpolator: (identifier) @function.call) ; function definitions (function_definition name: (identifier) @function) (parameter name: (identifier) @parameter) (binding name: (identifier) @parameter) ; method definition (function_declaration name: (identifier) @method) (function_definition name: (identifier) @method) ; expressions (infix_expression operator: (identifier) @operator) (infix_expression operator: (operator_identifier) @operator) (infix_type operator: (operator_identifier) @operator) (infix_type operator: (operator_identifier) @operator) ; literals (boolean_literal) @boolean (integer_literal) @number (floating_point_literal) @float [ (string) (character_literal) (interpolated_string_expression) ] @string (interpolation "$" @punctuation.special) ;; keywords (opaque_modifier) @type.qualifier (infix_modifier) @keyword (transparent_modifier) @type.qualifier (open_modifier) @type.qualifier [ "case" "class" "enum" "extends" "derives" "finally" ;; `forSome` existential types not implemented yet ;; `macro` not implemented yet "object" "override" "package" "trait" "type" "val" "var" "with" "given" "using" "end" "implicit" "extension" "with" ] @keyword [ "abstract" "final" "lazy" "sealed" "private" "protected" ] @type.qualifier (inline_modifier) @storageclass (null_literal) @constant.builtin (wildcard) @parameter (annotation) @attribute ;; special keywords "new" @keyword.operator [ "else" "if" "match" "then" ] @conditional [ "(" ")" "[" "]" "{" "}" ] @punctuation.bracket [ "." "," ] @punctuation.delimiter [ "do" "for" "while" "yield" ] @repeat "def" @keyword.function [ "=>" "<-" "@" ] @operator ["import" "export"] @include [ "try" "catch" "throw" ] @exception "return" @keyword.return (comment) @spell @comment (block_comment) @spell @comment ;; `case` is a conditional keyword in case_block (case_block (case_clause ("case") @conditional)) (indented_cases (case_clause ("case") @conditional)) (operator_identifier) @operator ((identifier) @type (#match? @type "^[A-Z]")) ((identifier) @variable.builtin (#match? @variable.builtin "^this$")) ( (identifier) @function.builtin (#match? @function.builtin "^super$") ) ;; Scala CLI using directives (using_directive_key) @parameter (using_directive_value) @string ================================================ FILE: queries/indents.scm ================================================ ; These indent queries adhere to nvim-tree-sytter syntax. ; See `nvim-tree-sitter-indentation-mod` vim help page. [ (template_body) (block) (parameters) (arguments) (match_expression) (splice_expression) (import_declaration) (function_definition) (ERROR ":") (ERROR "=") ("match") (":") ("=") ] @indent.begin (arguments ")" @indent.end) "}" @indent.end "end" @indent.end [ ")" "]" "}" ] @indent.branch ================================================ FILE: queries/locals.scm ================================================ (template_body) @local.scope (lambda_expression) @local.scope (function_declaration name: (identifier) @local.definition) @local.scope (function_definition name: (identifier) @local.definition) (parameter name: (identifier) @local.definition) (binding name: (identifier) @local.definition) (val_definition pattern: (identifier) @local.definition) (var_definition pattern: (identifier) @local.definition) (val_declaration name: (identifier) @local.definition) (var_declaration name: (identifier) @local.definition) (identifier) @local.reference ================================================ FILE: queries/tags.scm ================================================ ; Definitions (package_clause name: (package_identifier) @name) @definition.module (trait_definition name: (identifier) @name) @definition.interface (enum_definition name: (identifier) @name) @definition.enum (simple_enum_case name: (identifier) @name) @definition.class (full_enum_case name: (identifier) @name) @definition.class (class_definition name: (identifier) @name) @definition.class (object_definition name: (identifier) @name) @definition.object (function_definition name: (identifier) @name) @definition.function (val_definition pattern: (identifier) @name) @definition.variable (given_definition name: (identifier) @name) @definition.variable (var_definition pattern: (identifier) @name) @definition.variable (val_declaration name: (identifier) @name) @definition.variable (var_declaration name: (identifier) @name) @definition.variable (type_definition name: (type_identifier) @name) @definition.type (class_parameter name: (identifier) @name) @definition.property ; References (call_expression (identifier) @name) @reference.call (instance_expression (type_identifier) @name) @reference.interface (instance_expression (generic_type (type_identifier) @name)) @reference.interface (extends_clause (type_identifier) @name) @reference.class (extends_clause (generic_type (type_identifier) @name)) @reference.class ================================================ FILE: script/parse-with-scalac ================================================ #!/bin/bash # scalac -Yshow-trees -Xprint:parser $@ scalac -Yshow-trees -Xprint:typer $@ ================================================ FILE: script/smoke_test.sh ================================================ #!/bin/bash -e # This is an integration test to generally check the quality of parsing. SCALA_SCALA_LIBRARY_EXPECTED=100 SCALA_SCALA_COMPILER_EXPECTED=100 DOTTY_COMPILER_EXPECTED=93 LILA_MODULES_EXPECTED=99 SYNTAX_COMPLEXITY_CEILING=1800 PARSER_MAX_SIZE_MB=33 if [ ! -d "$SCALA_SCALA_DIR" ]; then echo "\$SCALA_SCALA_DIR must be set" exit 1 fi if [ ! -d "$DOTTY_DIR" ]; then echo "\$DOTTY_DIR must be set" exit 1 fi check_parser_size () { local max_size_mb=$1 local max_size=$(($max_size_mb * 1024 * 1024)) local actual_size=$(stat -c%s src/parser.c) local actual_size_mb=$(echo "scale=2; $actual_size / 1024 / 1024" | bc) if [ "$actual_size" -gt "$max_size" ]; then echo -e "::error file=src/parser.c::Parser size (${actual_size_mb}M) exceeds maximum allowed size (${max_size_mb}M)" failed=$((failed + 1)) else echo -e "::notice file=src/parser.c::Parser size: ${actual_size_mb}M / ${max_size_mb}M" fi } failed=0 run_tree_sitter () { local source_dir=$1 local expected=$2 local name=$3 local files=$(find "$source_dir" -name '*.scala' -type f | tr '\n' ' ') cmd="npm exec -c 'tree-sitter parse $files --quiet --stat' | sort | sed 's%$source_dir%%g'" echo echo "Parse $source_dir: $cmd" out=$( (eval "$cmd") || true) if [ ! -e "$PRODUCE_REPORTS" ]; then local report_file="report-$name.txt" echo "$out" | sed G | sed -E 's/([0-9]+) ms//' | grep -v 'success percentage' > "report-$name.txt" echo "Report written to $report_file" fi actual=$(echo "$out" | grep 'success percentage:' | rev | cut -d' ' -f5 | rev | sed 's/;//g' | sed 's/%//g' ) echo "$actual" if (( $(echo "$actual >= $expected" |bc -l) )); then # See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#example-creating-an-annotation-for-an-error echo -e "::notice file=grammar.js,line=1::ok, ${source_dir}: ${actual}%, expected at least $expected%" else echo -e "::error file=grammar.js,line=1::${source_dir}: expected ${expected}, but got ${actual} instead" failed=$((failed + 1)) fi } check_complexity () { local expected=$1 name="complexity" cmd="npm exec -c 'tree-sitter generate --report-states-for-rule compilation_unit' 2>&1 >/dev/null" echo echo "Checking syntax complexity: $cmd" out=$( (eval "$cmd") || true) if [ ! -e "$PRODUCE_REPORTS" ]; then local report_file="report-$name.txt" echo "$out" > "report-$name.txt" echo "Report written to $report_file" fi out1=$(echo "$out" | grep -v "ExperimentalWarning" | grep -v "experimental" | grep -v "node") top=$(echo "$out1" | head -n 1 | sed 's/ \+/ /g') top_definition=$(echo "$top" | cut -d' ' -f1) top_definition_line=$(grep -n "$top_definition:" grammar.js | head -n 1 | cut -d : -f 1) actual=$(echo "$top" | cut -d' ' -f2) echo "$top_definition $actual" if (( $(echo "$actual < $expected" |bc -l) )); then # See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#example-creating-an-annotation-for-an-error echo -e "::notice file=grammar.js,line=$top_definition_line::ok, complexity of the most complex definition ${top_definition}: ${actual}, lower than the allowed ceiling $expected" else echo -e "::error file=grammar.js,line=$top_definition_line::complexity of the most complex definition ${top_definition}: ${actual}, higher than the allowed ceiling $expected" failed=$((failed + 1)) fi } check_parser_size $PARSER_MAX_SIZE_MB run_tree_sitter "$SCALA_SCALA_DIR/src/library/" $SCALA_SCALA_LIBRARY_EXPECTED scala2-library run_tree_sitter "$SCALA_SCALA_DIR/src/compiler/" $SCALA_SCALA_COMPILER_EXPECTED scala2-compiler run_tree_sitter "$DOTTY_DIR/compiler/" $DOTTY_COMPILER_EXPECTED dotty-compiler run_tree_sitter "$LILA_DIR/modules/" $LILA_MODULES_EXPECTED lila-modules check_complexity $SYNTAX_COMPLEXITY_CEILING if (( failed > 0 )); then exit 1 fi ================================================ FILE: setup.py ================================================ from os.path import isdir, join from platform import system from setuptools import Extension, find_packages, setup from setuptools.command.build import build from wheel.bdist_wheel import bdist_wheel class Build(build): def run(self): if isdir("queries"): dest = join(self.build_lib, "tree_sitter_scala", "queries") self.copy_tree("queries", dest) super().run() class BdistWheel(bdist_wheel): def get_tag(self): python, abi, platform = super().get_tag() if python.startswith("cp"): python, abi = "cp39", "abi3" return python, abi, platform setup( packages=find_packages("bindings/python"), package_dir={"": "bindings/python"}, package_data={ "tree_sitter_scala": ["*.pyi", "py.typed"], "tree_sitter_scala.queries": ["*.scm"], }, ext_package="tree_sitter_scala", ext_modules=[ Extension( name="_binding", sources=[ "bindings/python/tree_sitter_scala/binding.c", "src/parser.c", "src/scanner.c", ], extra_compile_args=[ "-std=c11", "-fvisibility=hidden", ] if system() != "Windows" else [ "/std:c11", "/utf-8", ], define_macros=[ ("Py_LIMITED_API", "0x03090000"), ("PY_SSIZE_T_CLEAN", None), ("TREE_SITTER_HIDE_SYMBOLS", None), ], include_dirs=["src"], py_limited_api=True, ) ], cmdclass={ "build": Build, "bdist_wheel": BdistWheel }, zip_safe=False ) ================================================ FILE: src/grammar.json ================================================ { "$schema": "https://tree-sitter.github.io/tree-sitter/assets/schemas/grammar.schema.json", "name": "scala", "word": "_alpha_identifier", "rules": { "compilation_unit": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_shebang" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_top_level_definition" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_semicolon" }, { "type": "SYMBOL", "name": "_top_level_definition" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_semicolon" }, { "type": "BLANK" } ] } ] }, { "type": "BLANK" } ] } ] }, "_top_level_definition": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_definition" }, { "type": "SYMBOL", "name": "_end_marker" }, { "type": "SYMBOL", "name": "expression" } ] }, "_definition": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "given_definition" }, { "type": "SYMBOL", "name": "extension_definition" }, { "type": "SYMBOL", "name": "class_definition" }, { "type": "SYMBOL", "name": "import_declaration" }, { "type": "SYMBOL", "name": "export_declaration" }, { "type": "SYMBOL", "name": "object_definition" }, { "type": "SYMBOL", "name": "enum_definition" }, { "type": "SYMBOL", "name": "trait_definition" }, { "type": "SYMBOL", "name": "val_definition" }, { "type": "SYMBOL", "name": "val_declaration" }, { "type": "SYMBOL", "name": "var_definition" }, { "type": "SYMBOL", "name": "var_declaration" }, { "type": "SYMBOL", "name": "type_definition" }, { "type": "SYMBOL", "name": "function_definition" }, { "type": "SYMBOL", "name": "function_declaration" }, { "type": "SYMBOL", "name": "package_clause" }, { "type": "SYMBOL", "name": "package_object" } ] }, "enum_definition": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "enum" }, { "type": "SYMBOL", "name": "_class_constructor" }, { "type": "FIELD", "name": "extend", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "extends_clause" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "derive", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "derives_clause" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "enum_body" } } ] }, "_enum_block": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "enum_case_definitions" }, { "type": "SYMBOL", "name": "expression" }, { "type": "SYMBOL", "name": "_definition" } ] }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_semicolon" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "enum_case_definitions" }, { "type": "SYMBOL", "name": "expression" }, { "type": "SYMBOL", "name": "_definition" } ] } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_semicolon" }, { "type": "BLANK" } ] } ] } }, "enum_body": { "type": "CHOICE", "members": [ { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "SYMBOL", "name": "_indent" }, { "type": "SYMBOL", "name": "_enum_block" }, { "type": "SYMBOL", "name": "_outdent" } ] } }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_enum_block" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] } ] }, "enum_case_definitions": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "STRING", "value": "case" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "simple_enum_case" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "simple_enum_case" } ] } } ] }, { "type": "SYMBOL", "name": "full_enum_case" } ] } ] }, "simple_enum_case": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "FIELD", "name": "extend", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "extends_clause" }, { "type": "BLANK" } ] } } ] } }, "full_enum_case": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "SYMBOL", "name": "_full_enum_def" } ] }, "_full_enum_def": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "type_parameters", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "type_parameters" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "class_parameters", "content": { "type": "REPEAT1", "content": { "type": "SYMBOL", "name": "class_parameters" } } }, { "type": "FIELD", "name": "extend", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "extends_clause" }, { "type": "BLANK" } ] } } ] }, "package_clause": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "package" }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "package_identifier" } }, { "type": "FIELD", "name": "body", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "template_body" }, { "type": "BLANK" } ] } } ] } }, "package_identifier": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "." }, { "type": "SYMBOL", "name": "_identifier" } ] } } ] } }, "package_object": { "type": "SEQ", "members": [ { "type": "STRING", "value": "package" }, { "type": "STRING", "value": "object" }, { "type": "SYMBOL", "name": "_object_definition" } ] }, "import_declaration": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "import" }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_namespace_expression" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_namespace_expression" } ] } } ] } ] } }, "export_declaration": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "export" }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_namespace_expression" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_namespace_expression" } ] } } ] } ] } }, "_namespace_expression": { "type": "PREC_LEFT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "path", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "." }, { "type": "SYMBOL", "name": "_identifier" } ] } } ] } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "." }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "namespace_wildcard" }, { "type": "SYMBOL", "name": "namespace_selectors" }, { "type": "SYMBOL", "name": "as_renamed_identifier" } ] } ] }, { "type": "BLANK" } ] } ] }, { "type": "SYMBOL", "name": "as_renamed_identifier" } ] } }, "namespace_wildcard": { "type": "PREC_LEFT", "value": 1, "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "*" }, { "type": "STRING", "value": "_" }, { "type": "STRING", "value": "given" } ] } }, "_namespace_given_by_type": { "type": "SEQ", "members": [ { "type": "STRING", "value": "given" }, { "type": "SYMBOL", "name": "_type" } ] }, "namespace_selectors": { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_namespace_given_by_type" }, { "type": "SYMBOL", "name": "namespace_wildcard" }, { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "arrow_renamed_identifier" }, { "type": "SYMBOL", "name": "as_renamed_identifier" } ] }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_namespace_given_by_type" }, { "type": "SYMBOL", "name": "namespace_wildcard" }, { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "arrow_renamed_identifier" }, { "type": "SYMBOL", "name": "as_renamed_identifier" } ] } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "STRING", "value": "}" } ] }, "_import_selectors": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "namespace_selectors" }, "named": true, "value": "import_selectors" }, "arrow_renamed_identifier": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "STRING", "value": "=>" }, { "type": "FIELD", "name": "alias", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "wildcard" } ] } } ] }, "as_renamed_identifier": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "STRING", "value": "as" }, { "type": "FIELD", "name": "alias", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "wildcard" } ] } } ] }, "object_definition": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "case" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "object" }, { "type": "SYMBOL", "name": "_object_definition" } ] }, "_object_definition": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "FIELD", "name": "extend", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "extends_clause" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "derive", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "derives_clause" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "body", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_definition_body" }, { "type": "BLANK" } ] } } ] } }, "class_definition": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "case" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "class" }, { "type": "SYMBOL", "name": "_class_definition" } ] }, "_class_definition": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_class_constructor" }, { "type": "FIELD", "name": "extend", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "extends_clause" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "derive", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "derives_clause" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "body", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_definition_body" }, { "type": "BLANK" } ] } } ] }, "_definition_body": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "BLANK" } ] }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "template_body" } } ] }, "_class_constructor": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "FIELD", "name": "type_parameters", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "type_parameters" }, { "type": "BLANK" } ] } }, { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_constructor_annotation" }, "named": true, "value": "annotation" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "access_modifier" }, { "type": "BLANK" } ] }, { "type": "FIELD", "name": "class_parameters", "content": { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "class_parameters" } ] } } } ] }, "trait_definition": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "trait" }, { "type": "SYMBOL", "name": "_class_definition" } ] } }, "type_parameters": { "type": "SEQ", "members": [ { "type": "STRING", "value": "[" }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_variant_type_parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_variant_type_parameter" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "STRING", "value": "]" } ] }, "_variant_type_parameter": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "covariant_type_parameter" }, { "type": "SYMBOL", "name": "contravariant_type_parameter" }, { "type": "SYMBOL", "name": "_type_parameter" }, { "type": "SYMBOL", "name": "type_lambda" } ] } ] }, "covariant_type_parameter": { "type": "SEQ", "members": [ { "type": "STRING", "value": "+" }, { "type": "SYMBOL", "name": "_type_parameter" } ] }, "contravariant_type_parameter": { "type": "SEQ", "members": [ { "type": "STRING", "value": "-" }, { "type": "SYMBOL", "name": "_type_parameter" } ] }, "_type_parameter": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "wildcard" }, { "type": "SYMBOL", "name": "_identifier" } ] } }, { "type": "FIELD", "name": "type_parameters", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "type_parameters" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "bound", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "lower_bound" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "bound", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "upper_bound" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "bound", "content": { "type": "CHOICE", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "view_bound" } }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "bound", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_context_bounds" }, { "type": "BLANK" } ] } } ] }, "upper_bound": { "type": "SEQ", "members": [ { "type": "STRING", "value": "<:" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, "lower_bound": { "type": "SEQ", "members": [ { "type": "STRING", "value": ">:" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, "view_bound": { "type": "SEQ", "members": [ { "type": "STRING", "value": "<%" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, "_context_bounds": { "type": "CHOICE", "members": [ { "type": "REPEAT1", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "SYMBOL", "name": "context_bound" } ] } }, { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "STRING", "value": "{" }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "context_bound" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "context_bound" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "STRING", "value": "}" } ] } ] }, "context_bound": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "as" }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } } ] }, { "type": "BLANK" } ] } ] }, "template_body": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_indented_template_body" }, { "type": "SYMBOL", "name": "_braced_template_body" } ] }, "_indented_template_body": { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "SYMBOL", "name": "_indent" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "self_type" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "_block" }, { "type": "SYMBOL", "name": "_outdent" } ] } }, "_braced_template_body": { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_braced_template_body1" }, { "type": "SYMBOL", "name": "_braced_template_body2" } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] } }, "_braced_template_body1": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "self_type" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "_block" } ] }, "_braced_template_body2": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_indent" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "self_type" }, { "type": "BLANK" } ] } ] }, { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "self_type" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "_indent" } ] } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_block" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "_outdent" } ] }, "with_template_body": { "type": "CHOICE", "members": [ { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_indent" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "self_type" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "_block" }, { "type": "SYMBOL", "name": "_outdent" } ] } }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_block" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] } ] }, "_extension_template_body": { "type": "CHOICE", "members": [ { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_indent" }, { "type": "SYMBOL", "name": "_block" }, { "type": "SYMBOL", "name": "_outdent" } ] } }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_block" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] } ] }, "_end_marker": { "type": "PREC_LEFT", "value": "end", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "end" }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "if" }, { "type": "STRING", "value": "while" }, { "type": "STRING", "value": "for" }, { "type": "STRING", "value": "match" }, { "type": "STRING", "value": "try" }, { "type": "STRING", "value": "new" }, { "type": "STRING", "value": "this" }, { "type": "STRING", "value": "given" }, { "type": "STRING", "value": "extension" }, { "type": "STRING", "value": "val" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_identifier" }, "named": false, "value": "_end_ident" } ] } ] } }, "self_type": { "type": "PREC_DYNAMIC", "value": 1, "content": { "type": "PREC", "value": "self_type", "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "wildcard" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_self_type_ascription" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "=>" } ] } } }, "_self_type_ascription": { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "SYMBOL", "name": "_type" } ] }, "annotation": { "type": "PREC_RIGHT", "value": "annotation", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "@" }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_simple_type" } }, { "type": "FIELD", "name": "arguments", "content": { "type": "REPEAT", "content": { "type": "PREC", "value": "annotation", "content": { "type": "SYMBOL", "name": "arguments" } } } } ] } }, "_constructor_annotation": { "type": "PREC", "value": "annotation", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "@" }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_simple_type" } }, { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SEQ", "members": [ { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "(" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_exprs_in_parens" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ")" } ] }, "named": true, "value": "arguments" }, { "type": "BLANK" } ] } ] } }, "val_definition": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_start_val" }, { "type": "FIELD", "name": "pattern", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_pattern" }, { "type": "SYMBOL", "name": "identifiers" } ] } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_indentable_expression" } } ] }, "val_declaration": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_start_val" }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } } ] } } ] }, { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, "_start_val": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "val" } ] }, "var_declaration": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_start_var" }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } } ] } } ] }, { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, "var_definition": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_start_var" }, { "type": "FIELD", "name": "pattern", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_pattern" }, { "type": "SYMBOL", "name": "identifiers" } ] } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_indentable_expression" } } ] }, "_start_var": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "var" } ] }, "type_definition": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "opaque_modifier" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "type" }, { "type": "SYMBOL", "name": "_type_constructor" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, { "type": "BLANK" } ] } ] } }, "_type_constructor": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_type_identifier" } }, { "type": "FIELD", "name": "type_parameters", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "type_parameters" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "bound", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "lower_bound" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "bound", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "upper_bound" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "bound", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_context_bounds" }, { "type": "BLANK" } ] } } ] } }, "function_definition": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_function_declaration" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_indentable_expression" } } ] }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "block" } } ] } ] }, "function_declaration": { "type": "SYMBOL", "name": "_function_declaration" }, "_function_declaration": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "def" }, { "type": "SYMBOL", "name": "_function_constructor" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "return_type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, { "type": "BLANK" } ] } ] } }, "_function_constructor": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "FIELD", "name": "parameters", "content": { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "parameters" }, { "type": "SYMBOL", "name": "type_parameters" } ] } ] } } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "BLANK" } ] } ] } }, "opaque_modifier": { "type": "PREC", "value": "mod", "content": { "type": "STRING", "value": "opaque" } }, "extension_definition": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "extension" }, { "type": "FIELD", "name": "type_parameters", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "type_parameters" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "parameters", "content": { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "parameters" } } }, { "type": "FIELD", "name": "body", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_extension_template_body" }, { "type": "SYMBOL", "name": "function_definition" }, { "type": "SYMBOL", "name": "function_declaration" } ] } } ] } }, "given_definition": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "given" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_given_constructor" }, { "type": "BLANK" } ] }, { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "_given_sig" } }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "return_type", "content": { "type": "SYMBOL", "name": "_structural_instance" } }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "return_type", "content": { "type": "SYMBOL", "name": "_annotated_type" } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_indentable_expression" } } ] }, { "type": "BLANK" } ] } ] } ] } ] } }, "_given_sig": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_given_conditional" }, { "type": "STRING", "value": "=>" } ] }, "_given_conditional": { "type": "CHOICE", "members": [ { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "parameters" }, "named": true, "value": "given_conditional" }, { "type": "SYMBOL", "name": "type_parameters" } ] }, "_given_constructor": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "type_parameters", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "type_parameters" }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "parameters", "content": { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "parameters" } ] } } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ":" } ] } }, "_structural_instance": { "type": "PREC_LEFT", "value": 7, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_constructor_application" }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": ":" }, { "type": "STRING", "value": "with" } ] }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "with_template_body" } } ] } }, "_constructor_application": { "type": "PREC_LEFT", "value": "constructor_application", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_annotated_type" }, { "type": "SYMBOL", "name": "compound_type" }, { "type": "SYMBOL", "name": "_structural_type" }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_type" }, { "type": "FIELD", "name": "arguments", "content": { "type": "SYMBOL", "name": "arguments" } } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_annotated_type" }, { "type": "FIELD", "name": "arguments", "content": { "type": "SYMBOL", "name": "arguments" } } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "compound_type" }, { "type": "FIELD", "name": "arguments", "content": { "type": "SYMBOL", "name": "arguments" } } ] } ] } }, "_constructor_applications": { "type": "PREC_LEFT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_constructor_application" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_constructor_application" } ] } } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_constructor_application" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "with" }, { "type": "SYMBOL", "name": "_constructor_application" } ] } } ] } ] } }, "modifiers": { "type": "PREC_LEFT", "value": 0, "content": { "type": "REPEAT1", "content": { "type": "PREC_LEFT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "abstract" }, { "type": "STRING", "value": "final" }, { "type": "STRING", "value": "sealed" }, { "type": "STRING", "value": "implicit" }, { "type": "STRING", "value": "lazy" }, { "type": "STRING", "value": "override" }, { "type": "SYMBOL", "name": "access_modifier" }, { "type": "SYMBOL", "name": "inline_modifier" }, { "type": "SYMBOL", "name": "infix_modifier" }, { "type": "SYMBOL", "name": "into_modifier" }, { "type": "SYMBOL", "name": "open_modifier" }, { "type": "SYMBOL", "name": "tracked_modifier" }, { "type": "SYMBOL", "name": "transparent_modifier" } ] } } } }, "access_modifier": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": "private" }, { "type": "STRING", "value": "protected" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "access_qualifier" }, { "type": "BLANK" } ] } ] } }, "access_qualifier": { "type": "SEQ", "members": [ { "type": "STRING", "value": "[" }, { "type": "SYMBOL", "name": "_identifier" }, { "type": "STRING", "value": "]" } ] }, "inline_modifier": { "type": "PREC", "value": "mod", "content": { "type": "STRING", "value": "inline" } }, "infix_modifier": { "type": "PREC", "value": "mod", "content": { "type": "STRING", "value": "infix" } }, "into_modifier": { "type": "PREC", "value": "mod", "content": { "type": "STRING", "value": "into" } }, "open_modifier": { "type": "PREC", "value": "mod", "content": { "type": "STRING", "value": "open" } }, "tracked_modifier": { "type": "PREC", "value": "mod", "content": { "type": "STRING", "value": "tracked" } }, "transparent_modifier": { "type": "PREC", "value": "mod", "content": { "type": "STRING", "value": "transparent" } }, "extends_clause": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "extends" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_constructor_applications" } }, { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "arguments" } } ] } }, "derives_clause": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "derives" }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "type", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_type_identifier" }, { "type": "SYMBOL", "name": "stable_type_identifier" } ] } }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "FIELD", "name": "type", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_type_identifier" }, { "type": "SYMBOL", "name": "stable_type_identifier" } ] } } ] } } ] } ] } }, "class_parameters": { "type": "PREC", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "(" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "using" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "class_parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "class_parameter" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_param_type" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_param_type" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] } ] } ] }, { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": "implicit" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "class_parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "class_parameter" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "BLANK" } ] } ] } ] }, { "type": "STRING", "value": ")" } ] } }, "parameters": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "implicit" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "parameter" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ")" } ] }, { "type": "SYMBOL", "name": "_using_parameters_clause" } ] }, "_using_parameters_clause": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "STRING", "value": "using" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "parameter" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_param_type" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_param_type" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] } ] }, { "type": "STRING", "value": ")" } ] }, "class_parameter": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "modifiers" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": "val" }, { "type": "STRING", "value": "var" } ] }, { "type": "BLANK" } ] }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_param_type" } } ] }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "default_value", "content": { "type": "SYMBOL", "name": "expression" } } ] }, { "type": "BLANK" } ] } ] }, "parameter": { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SYMBOL", "name": "annotation" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "inline_modifier" }, { "type": "BLANK" } ] }, { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_param_type" } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "default_value", "content": { "type": "SYMBOL", "name": "expression" } } ] }, { "type": "BLANK" } ] } ] } }, "name_and_type": { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_param_type" } } ] } }, "_block": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "expression" }, { "type": "SYMBOL", "name": "_definition" }, { "type": "SYMBOL", "name": "_end_marker" }, { "type": "STRING", "value": ";" } ] }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_semicolon" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "expression" }, { "type": "SYMBOL", "name": "_definition" }, { "type": "SYMBOL", "name": "_end_marker" }, { "type": "STRING", "value": ";" } ] } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_semicolon" }, { "type": "BLANK" } ] } ] } }, "_indentable_expression": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "indented_block" }, { "type": "SYMBOL", "name": "indented_cases" }, { "type": "SYMBOL", "name": "expression" } ] } }, "block": { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_block" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_block_lambda_expression" }, "named": true, "value": "lambda_expression" } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "}" } ] }, "indented_block": { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_indent" }, { "type": "SYMBOL", "name": "_block" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_outdent" }, { "type": "SYMBOL", "name": "_comma_outdent" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_end_marker" }, { "type": "BLANK" } ] } ] } }, "indented_cases": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_indent" }, { "type": "REPEAT1", "content": { "type": "SYMBOL", "name": "case_clause" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_outdent" }, { "type": "SYMBOL", "name": "_comma_outdent" } ] } ] } }, "_type": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "function_type" }, { "type": "SYMBOL", "name": "compound_type" }, { "type": "SYMBOL", "name": "infix_type" }, { "type": "SYMBOL", "name": "match_type" }, { "type": "SYMBOL", "name": "_annotated_type" }, { "type": "SYMBOL", "name": "literal_type" }, { "type": "SYMBOL", "name": "_structural_type" }, { "type": "SYMBOL", "name": "type_lambda" } ] }, "_annotated_type": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "annotated_type" }, { "type": "SYMBOL", "name": "_simple_type" } ] } }, "annotated_type": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_type" }, { "type": "REPEAT1", "content": { "type": "SYMBOL", "name": "annotation" } } ] } }, "_simple_type": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "generic_type" }, { "type": "SYMBOL", "name": "projected_type" }, { "type": "SYMBOL", "name": "tuple_type" }, { "type": "SYMBOL", "name": "named_tuple_type" }, { "type": "SYMBOL", "name": "singleton_type" }, { "type": "SYMBOL", "name": "stable_type_identifier" }, { "type": "SYMBOL", "name": "_type_identifier" }, { "type": "SYMBOL", "name": "applied_constructor_type" }, { "type": "SYMBOL", "name": "wildcard" } ] }, "applied_constructor_type": { "type": "PREC", "value": "applied_constructor_type", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_type_identifier" }, { "type": "SYMBOL", "name": "arguments" } ] } }, "compound_type": { "type": "CHOICE", "members": [ { "type": "PREC_LEFT", "value": 7, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "base", "content": { "type": "SYMBOL", "name": "_annotated_type" } }, { "type": "REPEAT1", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "with" }, { "type": "FIELD", "name": "extra", "content": { "type": "SYMBOL", "name": "_annotated_type" } } ] } } ] } }, { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "base", "content": { "type": "SYMBOL", "name": "_annotated_type" } }, { "type": "SYMBOL", "name": "_refinement" } ] } }, { "type": "PREC_LEFT", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "PREC_LEFT", "value": 7, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "base", "content": { "type": "SYMBOL", "name": "_annotated_type" } }, { "type": "REPEAT1", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "with" }, { "type": "FIELD", "name": "extra", "content": { "type": "SYMBOL", "name": "_annotated_type" } } ] } } ] } }, { "type": "SYMBOL", "name": "_refinement" } ] } } ] }, "_structural_type": { "type": "PREC", "value": "structural_type", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "template_body" }, "named": true, "value": "structural_type" } }, "_refinement": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "template_body" }, "named": true, "value": "refinement" }, "_infix_type_choice": { "type": "PREC_LEFT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "compound_type" }, { "type": "SYMBOL", "name": "infix_type" }, { "type": "SYMBOL", "name": "_annotated_type" }, { "type": "SYMBOL", "name": "literal_type" } ] } }, "infix_type": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_infix_type_choice" } }, { "type": "FIELD", "name": "operator", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_infix_type_choice" } } ] } }, "tuple_type": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_type" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_type" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "STRING", "value": ")" } ] }, "named_tuple_type": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "name_and_type" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "name_and_type" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "STRING", "value": ")" } ] }, "singleton_type": { "type": "PREC_LEFT", "value": 2, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "stable_identifier" } ] }, { "type": "STRING", "value": "." }, { "type": "STRING", "value": "type" } ] } }, "stable_type_identifier": { "type": "PREC_LEFT", "value": 2, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "stable_identifier" } ] }, { "type": "STRING", "value": "." }, { "type": "SYMBOL", "name": "_type_identifier" } ] } }, "stable_identifier": { "type": "PREC_LEFT", "value": 4, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "stable_identifier" } ] }, { "type": "STRING", "value": "." }, { "type": "SYMBOL", "name": "_identifier" } ] } }, "generic_type": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_simple_type" } }, { "type": "FIELD", "name": "type_arguments", "content": { "type": "SYMBOL", "name": "type_arguments" } } ] }, "projected_type": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_simple_type" } }, { "type": "STRING", "value": "#" }, { "type": "FIELD", "name": "selector", "content": { "type": "SYMBOL", "name": "_type_identifier" } } ] }, "match_type": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_infix_type_choice" }, { "type": "STRING", "value": "match" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_indent" }, { "type": "REPEAT1", "content": { "type": "SYMBOL", "name": "type_case_clause" } }, { "type": "SYMBOL", "name": "_outdent" } ] }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "REPEAT1", "content": { "type": "SYMBOL", "name": "type_case_clause" } }, { "type": "STRING", "value": "}" } ] } ] } ] } }, "type_case_clause": { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "case" }, { "type": "SYMBOL", "name": "_infix_type_choice" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_arrow_then_type" } } ] } }, "function_type": { "type": "PREC_LEFT", "value": 0, "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "type_parameters", "content": { "type": "SYMBOL", "name": "type_parameters" } }, { "type": "SYMBOL", "name": "_arrow_then_type" } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "parameter_types", "content": { "type": "SYMBOL", "name": "parameter_types" } }, { "type": "SYMBOL", "name": "_arrow_then_type" } ] } ] } }, "_arrow_then_type": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": "=>" }, { "type": "STRING", "value": "?=>" } ] }, { "type": "FIELD", "name": "return_type", "content": { "type": "SYMBOL", "name": "_type" } } ] } }, "parameter_types": { "type": "PREC", "value": -1, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_annotated_type" }, { "type": "PREC_DYNAMIC", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_param_type" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_param_type" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ")" } ] } }, { "type": "SYMBOL", "name": "compound_type" }, { "type": "SYMBOL", "name": "infix_type" } ] } }, "_param_type": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "lazy_parameter_type" }, { "type": "SYMBOL", "name": "_param_value_type" } ] }, "_param_value_type": { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } }, { "type": "SYMBOL", "name": "repeated_parameter_type" } ] }, "repeated_parameter_type": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } }, { "type": "SYMBOL", "name": "_asterisk" } ] }, "lazy_parameter_type": { "type": "SEQ", "members": [ { "type": "STRING", "value": "=>" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_param_value_type" } } ] }, "_type_identifier": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_identifier" }, "named": true, "value": "type_identifier" }, "type_lambda": { "type": "SEQ", "members": [ { "type": "STRING", "value": "[" }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_type_parameter" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_type_parameter" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "STRING", "value": "]" }, { "type": "STRING", "value": "=>>" }, { "type": "FIELD", "name": "return_type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, "_pattern": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "stable_identifier" }, { "type": "SYMBOL", "name": "interpolated_string_expression" }, { "type": "SYMBOL", "name": "capture_pattern" }, { "type": "SYMBOL", "name": "tuple_pattern" }, { "type": "SYMBOL", "name": "named_tuple_pattern" }, { "type": "SYMBOL", "name": "case_class_pattern" }, { "type": "SYMBOL", "name": "infix_pattern" }, { "type": "SYMBOL", "name": "alternative_pattern" }, { "type": "SYMBOL", "name": "typed_pattern" }, { "type": "SYMBOL", "name": "given_pattern" }, { "type": "SYMBOL", "name": "quote_expression" }, { "type": "SYMBOL", "name": "literal" }, { "type": "SYMBOL", "name": "wildcard" }, { "type": "SYMBOL", "name": "repeat_pattern" } ] }, "case_class_pattern": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "type", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_type_identifier" }, { "type": "SYMBOL", "name": "stable_type_identifier" } ] } }, { "type": "STRING", "value": "(" }, { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "pattern", "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_pattern" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_pattern" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "BLANK" } ] } }, { "type": "FIELD", "name": "pattern", "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "named_pattern" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "named_pattern" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "BLANK" } ] } } ] }, { "type": "STRING", "value": ")" } ] }, "infix_pattern": { "type": "PREC_LEFT", "value": 6, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "SYMBOL", "name": "_pattern" } }, { "type": "FIELD", "name": "operator", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "FIELD", "name": "right", "content": { "type": "SYMBOL", "name": "_pattern" } } ] } }, "capture_pattern": { "type": "PREC_RIGHT", "value": 8, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "wildcard" } ] } }, { "type": "STRING", "value": "@" }, { "type": "FIELD", "name": "pattern", "content": { "type": "SYMBOL", "name": "_pattern" } } ] } }, "repeat_pattern": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "pattern", "content": { "type": "SYMBOL", "name": "_pattern" } }, { "type": "SYMBOL", "name": "_asterisk" } ] } }, "typed_pattern": { "type": "PREC_RIGHT", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "pattern", "content": { "type": "SYMBOL", "name": "_pattern" } }, { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] } }, "given_pattern": { "type": "SEQ", "members": [ { "type": "STRING", "value": "given" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_type" } } ] }, "alternative_pattern": { "type": "PREC_LEFT", "value": -2, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_pattern" }, { "type": "STRING", "value": "|" }, { "type": "SYMBOL", "name": "_pattern" } ] } }, "tuple_pattern": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_pattern" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_pattern" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "STRING", "value": ")" } ] }, "named_pattern": { "type": "PREC_LEFT", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_identifier" }, { "type": "STRING", "value": "=" }, { "type": "SYMBOL", "name": "_pattern" } ] } }, "named_tuple_pattern": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "named_pattern" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "named_pattern" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "STRING", "value": ")" } ] }, "expression": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "if_expression" }, { "type": "SYMBOL", "name": "match_expression" }, { "type": "SYMBOL", "name": "try_expression" }, { "type": "SYMBOL", "name": "assignment_expression" }, { "type": "SYMBOL", "name": "lambda_expression" }, { "type": "SYMBOL", "name": "postfix_expression" }, { "type": "SYMBOL", "name": "ascription_expression" }, { "type": "SYMBOL", "name": "infix_expression" }, { "type": "SYMBOL", "name": "prefix_expression" }, { "type": "SYMBOL", "name": "return_expression" }, { "type": "SYMBOL", "name": "throw_expression" }, { "type": "SYMBOL", "name": "while_expression" }, { "type": "SYMBOL", "name": "do_while_expression" }, { "type": "SYMBOL", "name": "for_expression" }, { "type": "SYMBOL", "name": "macro_body" }, { "type": "SYMBOL", "name": "_simple_expression" } ] }, "_simple_expression": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "SYMBOL", "name": "operator_identifier" }, { "type": "SYMBOL", "name": "literal" }, { "type": "SYMBOL", "name": "interpolated_string_expression" }, { "type": "SYMBOL", "name": "unit" }, { "type": "SYMBOL", "name": "tuple_expression" }, { "type": "SYMBOL", "name": "wildcard" }, { "type": "SYMBOL", "name": "block" }, { "type": "SYMBOL", "name": "splice_expression" }, { "type": "SYMBOL", "name": "case_block" }, { "type": "SYMBOL", "name": "quote_expression" }, { "type": "SYMBOL", "name": "instance_expression" }, { "type": "SYMBOL", "name": "parenthesized_expression" }, { "type": "SYMBOL", "name": "field_expression" }, { "type": "SYMBOL", "name": "generic_function" }, { "type": "SYMBOL", "name": "call_expression" }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_dot_match_expression" }, "named": true, "value": "match_expression" } ] }, "_single_lambda_param": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": "implicit" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "_identifier" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "SYMBOL", "name": "_type" } ] }, { "type": "BLANK" } ] } ] } }, "lambda_expression": { "type": "PREC_RIGHT", "value": "lambda", "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "type_parameters", "content": { "type": "SYMBOL", "name": "type_parameters" } }, { "type": "STRING", "value": "=>" } ] }, { "type": "BLANK" } ] }, { "type": "FIELD", "name": "parameters", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "bindings" }, { "type": "SYMBOL", "name": "wildcard" }, { "type": "SYMBOL", "name": "_single_lambda_param" } ] } }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "=>" }, { "type": "STRING", "value": "?=>" } ] }, { "type": "SYMBOL", "name": "_indentable_expression" } ] } }, "_block_lambda_expression": { "type": "PREC_RIGHT", "value": "lambda", "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "parameters", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "bindings" }, { "type": "SYMBOL", "name": "wildcard" }, { "type": "SYMBOL", "name": "_single_lambda_param" } ] } }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "=>" }, { "type": "STRING", "value": "?=>" } ] }, { "type": "SYMBOL", "name": "_block" } ] } }, "if_expression": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "inline_modifier" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "if" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_if_condition" } }, { "type": "FIELD", "name": "consequence", "content": { "type": "SYMBOL", "name": "_indentable_expression" } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": ";" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "else" }, { "type": "FIELD", "name": "alternative", "content": { "type": "SYMBOL", "name": "_indentable_expression" } } ] }, { "type": "BLANK" } ] } ] }, "_if_condition": { "type": "PREC_DYNAMIC", "value": 4, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "parenthesized_expression" }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_indentable_expression" }, { "type": "STRING", "value": "then" } ] } ] } }, "match_expression": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "inline_modifier" }, { "type": "BLANK" } ] }, { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "expression" } }, { "type": "STRING", "value": "match" }, { "type": "FIELD", "name": "body", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "case_block" }, { "type": "SYMBOL", "name": "indented_cases" } ] } } ] }, { "type": "SYMBOL", "name": "_dot_match_expression" } ] }, "_dot_match_expression": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_simple_expression" } }, { "type": "STRING", "value": "." }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "match" } }, { "type": "FIELD", "name": "body", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "case_block" }, { "type": "SYMBOL", "name": "indented_cases" } ] } } ] }, "try_expression": { "type": "PREC_RIGHT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "try" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_indentable_expression" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "catch_clause" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "finally_clause" }, { "type": "BLANK" } ] } ] } }, "catch_clause": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "catch" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_indentable_expression" }, { "type": "SYMBOL", "name": "_expr_case_clause" } ] } ] } }, "_expr_case_clause": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "case" }, { "type": "SYMBOL", "name": "_case_pattern" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "expression" } } ] } }, "finally_clause": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "finally" }, { "type": "SYMBOL", "name": "_indentable_expression" } ] } }, "binding": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "name", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "SYMBOL", "name": "wildcard" } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "type", "content": { "type": "SYMBOL", "name": "_param_type" } } ] }, { "type": "BLANK" } ] } ] }, "bindings": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "binding" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "binding" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ")" } ] }, "case_block": { "type": "CHOICE", "members": [ { "type": "PREC", "value": -1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "STRING", "value": "}" } ] } }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "REPEAT1", "content": { "type": "SYMBOL", "name": "case_clause" } }, { "type": "STRING", "value": "}" } ] } ] }, "case_clause": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "case" }, { "type": "SYMBOL", "name": "_case_pattern" }, { "type": "FIELD", "name": "body", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_block" }, { "type": "BLANK" } ] } } ] } }, "_case_pattern": { "type": "PREC_DYNAMIC", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "pattern", "content": { "type": "SYMBOL", "name": "_pattern" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "guard" }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "=>" } ] } }, "guard": { "type": "PREC_LEFT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "if" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "_postfix_expression_choice" } } ] } }, "assignment_expression": { "type": "PREC_RIGHT", "value": 3, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "prefix_expression" }, { "type": "SYMBOL", "name": "_simple_expression" } ] } }, { "type": "STRING", "value": "=" }, { "type": "FIELD", "name": "right", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "expression" }, { "type": "SYMBOL", "name": "indented_block" } ] } } ] } }, "generic_function": { "type": "PREC", "value": 8, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "function", "content": { "type": "SYMBOL", "name": "expression" } }, { "type": "FIELD", "name": "type_arguments", "content": { "type": "SYMBOL", "name": "type_arguments" } } ] } }, "call_expression": { "type": "CHOICE", "members": [ { "type": "PREC_LEFT", "value": 8, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "function", "content": { "type": "SYMBOL", "name": "_simple_expression" } }, { "type": "FIELD", "name": "arguments", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "arguments" }, { "type": "SYMBOL", "name": "case_block" }, { "type": "SYMBOL", "name": "block" } ] } } ] } }, { "type": "PREC_RIGHT", "value": 5, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "function", "content": { "type": "SYMBOL", "name": "_postfix_expression_choice" } }, { "type": "STRING", "value": ":" }, { "type": "FIELD", "name": "arguments", "content": { "type": "SYMBOL", "name": "colon_argument" } } ] } } ] }, "colon_argument": { "type": "PREC_LEFT", "value": 5, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "FIELD", "name": "lambda_start", "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "bindings" }, { "type": "SYMBOL", "name": "_identifier" }, { "type": "SYMBOL", "name": "wildcard" } ] }, { "type": "STRING", "value": "=>" } ] } }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "indented_block" }, { "type": "SYMBOL", "name": "indented_cases" } ] } ] } }, "field_expression": { "type": "PREC_LEFT", "value": 8, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "value", "content": { "type": "SYMBOL", "name": "_simple_expression" } }, { "type": "STRING", "value": "." }, { "type": "FIELD", "name": "field", "content": { "type": "SYMBOL", "name": "_identifier" } } ] } }, "instance_expression": { "type": "CHOICE", "members": [ { "type": "PREC_DYNAMIC", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "new" }, { "type": "SYMBOL", "name": "_constructor_application" }, { "type": "SYMBOL", "name": "template_body" } ] } }, { "type": "PREC", "value": "new", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "new" }, { "type": "SYMBOL", "name": "template_body" } ] } }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "new" }, { "type": "SYMBOL", "name": "_constructor_application" } ] } ] }, "ascription_expression": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_postfix_expression_choice" }, { "type": "STRING", "value": ":" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_param_type" }, { "type": "SYMBOL", "name": "annotation" } ] } ] } }, "infix_expression": { "type": "PREC_LEFT", "value": 6, "content": { "type": "SEQ", "members": [ { "type": "FIELD", "name": "left", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "infix_expression" }, { "type": "SYMBOL", "name": "prefix_expression" }, { "type": "SYMBOL", "name": "_simple_expression" } ] } }, { "type": "FIELD", "name": "operator", "content": { "type": "SYMBOL", "name": "_identifier" } }, { "type": "FIELD", "name": "right", "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "prefix_expression" }, { "type": "SYMBOL", "name": "_simple_expression" }, { "type": "SEQ", "members": [ { "type": "STRING", "value": ":" }, { "type": "SYMBOL", "name": "colon_argument" } ] } ] } } ] } }, "postfix_expression": { "type": "PREC_LEFT", "value": 5, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "infix_expression" }, { "type": "SYMBOL", "name": "prefix_expression" }, { "type": "SYMBOL", "name": "_simple_expression" } ] }, { "type": "SYMBOL", "name": "_identifier" } ] } }, "_postfix_expression_choice": { "type": "PREC_LEFT", "value": 5, "content": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "postfix_expression" }, { "type": "SYMBOL", "name": "infix_expression" }, { "type": "SYMBOL", "name": "prefix_expression" }, { "type": "SYMBOL", "name": "_simple_expression" } ] } }, "macro_body": { "type": "PREC_LEFT", "value": 10, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "macro" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "infix_expression" }, { "type": "SYMBOL", "name": "prefix_expression" }, { "type": "SYMBOL", "name": "_simple_expression" } ] } ] } }, "prefix_expression": { "type": "PREC", "value": 7, "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": "+" }, { "type": "STRING", "value": "-" }, { "type": "STRING", "value": "!" }, { "type": "STRING", "value": "~" } ] }, { "type": "SYMBOL", "name": "_simple_expression" } ] } }, "tuple_expression": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "SYMBOL", "name": "expression" }, { "type": "REPEAT1", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "expression" } ] } }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] }, { "type": "STRING", "value": ")" } ] }, "parenthesized_expression": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "SYMBOL", "name": "expression" }, { "type": "STRING", "value": ")" } ] }, "type_arguments": { "type": "SEQ", "members": [ { "type": "STRING", "value": "[" }, { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_type" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "_type" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, { "type": "STRING", "value": "]" } ] }, "arguments": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_vararg_arguments" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_exprs_in_parens" }, { "type": "BLANK" } ] }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "using" }, { "type": "SYMBOL", "name": "_exprs_in_parens" } ] } ] }, { "type": "STRING", "value": ")" } ] }, "_vararg_arguments": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_exprs_in_parens" }, { "type": "STRING", "value": "," } ] }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "vararg" } ] }, "vararg": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_expression" }, { "type": "SYMBOL", "name": "_asterisk" } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_expression" }, { "type": "STRING", "value": ":" }, { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "_" }, { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "*" } } ] } } ] } ] }, "_exprs_in_parens": { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "expression" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "expression" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "," }, { "type": "BLANK" } ] } ] }, "splice_expression": { "type": "PREC_LEFT", "value": 10, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "$" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "SYMBOL", "name": "_block" }, { "type": "STRING", "value": "}" } ] }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "[" }, { "type": "SYMBOL", "name": "_type" }, { "type": "STRING", "value": "]" } ] }, { "type": "SYMBOL", "name": "identifier" } ] } ] } }, "quote_expression": { "type": "PREC_LEFT", "value": 10, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "'" }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "SYMBOL", "name": "_block" }, { "type": "STRING", "value": "}" } ] }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "[" }, { "type": "SYMBOL", "name": "_type" }, { "type": "STRING", "value": "]" } ] }, { "type": "SYMBOL", "name": "identifier" } ] } ] } }, "identifier": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_alpha_identifier" }, { "type": "SYMBOL", "name": "_backquoted_id" }, { "type": "SYMBOL", "name": "_soft_identifier" } ] }, "_soft_identifier": { "type": "PREC", "value": "soft_id", "content": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "infix" }, { "type": "STRING", "value": "inline" }, { "type": "STRING", "value": "opaque" }, { "type": "STRING", "value": "open" }, { "type": "STRING", "value": "tracked" }, { "type": "STRING", "value": "transparent" }, { "type": "STRING", "value": "end" } ] } }, "_alpha_identifier": { "type": "PATTERN", "value": "[\\p{Lu}\\p{Lt}\\p{Nl}\\p{Lo}\\p{Lm}\\$\\p{Ll}_\\u00AA\\u00BB\\u02B0-\\u02B8\\u02C0-\\u02C1\\u02E0-\\u02E4\\u037A\\u1D78\\u1D9B-\\u1DBF\\u2071\\u207F\\u2090-\\u209C\\u2C7C-\\u2C7D\\uA69C-\\uA69D\\uA770\\uA7F8-\\uA7F9\\uAB5C-\\uAB5F\\$][\\p{Lu}\\p{Lt}\\p{Nl}\\p{Lo}\\p{Lm}\\$\\p{Ll}_\\u00AA\\u00BB\\u02B0-\\u02B8\\u02C0-\\u02C1\\u02E0-\\u02E4\\u037A\\u1D78\\u1D9B-\\u1DBF\\u2071\\u207F\\u2090-\\u209C\\u2C7C-\\u2C7D\\uA69C-\\uA69D\\uA770\\uA7F8-\\uA7F9\\uAB5C-\\uAB5F0-9\\$_\\p{Ll}]*(_[\\-!#%&*+\\/\\\\:<=>?@\\u005e\\u007c~\\p{Sm}\\p{So}]+)?" }, "_interpolation_identifier": { "type": "PATTERN", "value": "[\\p{Lu}\\p{Lt}\\p{Nl}\\p{Lo}\\p{Lm}\\p{Ll}_\\u00AA\\u00BB\\u02B0-\\u02B8\\u02C0-\\u02C1\\u02E0-\\u02E4\\u037A\\u1D78\\u1D9B-\\u1DBF\\u2071\\u207F\\u2090-\\u209C\\u2C7C-\\u2C7D\\uA69C-\\uA69D\\uA770\\uA7F8-\\uA7F9\\uAB5C-\\uAB5F][\\p{Lu}\\p{Lt}\\p{Nl}\\p{Lo}\\p{Lm}\\p{Ll}_\\u00AA\\u00BB\\u02B0-\\u02B8\\u02C0-\\u02C1\\u02E0-\\u02E4\\u037A\\u1D78\\u1D9B-\\u1DBF\\u2071\\u207F\\u2090-\\u209C\\u2C7C-\\u2C7D\\uA69C-\\uA69D\\uA770\\uA7F8-\\uA7F9\\uAB5C-\\uAB5F0-9_\\p{Ll}]*" }, "_backquoted_id": { "type": "PATTERN", "value": "`[^\\n`]+`" }, "_identifier": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "SYMBOL", "name": "operator_identifier" } ] }, "identifiers": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "STRING", "value": "," }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "identifier" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "," }, { "type": "SYMBOL", "name": "identifier" } ] } } ] } ] }, "wildcard": { "type": "STRING", "value": "_" }, "_asterisk": { "type": "STRING", "value": "*" }, "operator_identifier": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_asterisk" }, { "type": "TOKEN", "content": { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[\\-!#%&*+\\/\\\\<>?\\u005e\\u007c~\\u00ac\\u00b1\\u00d7\\u00f7\\u2190-\\u2194\\p{So}]" }, { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "[\\-!#%&*+\\\\:<=>?@\\u005e\\u007c~\\p{Sm}\\p{So}]" }, { "type": "REPEAT1", "content": { "type": "PATTERN", "value": "[\\-!#%&*+\\/\\\\:<=>?@\\u005e\\u007c~\\p{Sm}\\p{So}]" } } ] }, { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "[\\-!#%&*+\\/\\\\:<=>?@\\u005e\\u007c~\\p{Sm}\\p{So}]" }, { "type": "PATTERN", "value": "[\\-!#%&+\\\\:<=>?@\\u005e\\u007c~\\p{Sm}\\p{So}]" }, { "type": "REPEAT", "content": { "type": "PATTERN", "value": "[\\-!#%&*+\\/\\\\:<=>?@\\u005e\\u007c~\\p{Sm}\\p{So}]" } } ] } ] } } ] }, "_non_null_literal": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "integer_literal" }, { "type": "SYMBOL", "name": "floating_point_literal" }, { "type": "SYMBOL", "name": "boolean_literal" }, { "type": "SYMBOL", "name": "character_literal" }, { "type": "SYMBOL", "name": "string" } ] }, "literal_type": { "type": "PREC_LEFT", "value": 2, "content": { "type": "SYMBOL", "name": "_non_null_literal" } }, "literal": { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_non_null_literal" }, { "type": "SYMBOL", "name": "null_literal" } ] }, "integer_literal": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[-]" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[\\d](_?\\d)*" }, { "type": "PATTERN", "value": "0[xX][\\da-fA-F](_?[\\da-fA-F])*" } ] }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[lL]" }, { "type": "BLANK" } ] } ] } }, "floating_point_literal": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[-]" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "[\\d]+\\.[\\d]+" }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[eE][+-]?[\\d]+" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[dfDF]" }, { "type": "BLANK" } ] } ] }, { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "\\.[\\d]+" }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[eE][+-]?[\\d]+" }, { "type": "BLANK" } ] }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[dfDF]" }, { "type": "BLANK" } ] } ] }, { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "[\\d]+" }, { "type": "PATTERN", "value": "[eE][+-]?[\\d]+" }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[dfDF]" }, { "type": "BLANK" } ] } ] }, { "type": "SEQ", "members": [ { "type": "PATTERN", "value": "[\\d]+" }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[eE][+-]?[\\d]+" }, { "type": "BLANK" } ] }, { "type": "PATTERN", "value": "[dfDF]" } ] } ] } ] } }, "boolean_literal": { "type": "CHOICE", "members": [ { "type": "STRING", "value": "true" }, { "type": "STRING", "value": "false" } ] }, "character_literal": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "'" }, { "type": "CHOICE", "members": [ { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "\\" }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[^xu]" }, { "type": "PATTERN", "value": "[uU]+[0-9a-fA-F]{4}" }, { "type": "PATTERN", "value": "x[0-9a-fA-F]{2}" } ] } ] }, { "type": "PATTERN", "value": "[^\\\\'\\n]" } ] }, { "type": "BLANK" } ] }, { "type": "STRING", "value": "'" } ] } }, "interpolated_string_expression": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "interpolator", "content": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_raw_string_start" }, "named": true, "value": "identifier" } }, { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_raw_string" }, "named": true, "value": "interpolated_string" } ] }, { "type": "SEQ", "members": [ { "type": "FIELD", "name": "interpolator", "content": { "type": "SYMBOL", "name": "identifier" } }, { "type": "SYMBOL", "name": "interpolated_string" } ] } ] }, "_dollar_escape": { "type": "ALIAS", "content": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "$" }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "$" }, { "type": "STRING", "value": "\"" } ] } ] } }, "named": true, "value": "escape_sequence" }, "_aliased_interpolation_identifier": { "type": "ALIAS", "content": { "type": "SYMBOL", "name": "_interpolation_identifier" }, "named": true, "value": "identifier" }, "interpolation": { "type": "SEQ", "members": [ { "type": "STRING", "value": "$" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_aliased_interpolation_identifier" }, { "type": "SYMBOL", "name": "block" } ] } ] }, "interpolated_string": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "\"" } }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_interpolated_string_middle" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_dollar_escape" }, { "type": "SYMBOL", "name": "interpolation" }, { "type": "SYMBOL", "name": "escape_sequence" } ] } ] } }, { "type": "SYMBOL", "name": "_single_line_string_end" } ] }, { "type": "SEQ", "members": [ { "type": "IMMEDIATE_TOKEN", "content": { "type": "STRING", "value": "\"\"\"" } }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_interpolated_multiline_string_middle" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_dollar_escape" }, { "type": "SYMBOL", "name": "interpolation" } ] } ] } }, { "type": "SYMBOL", "name": "_multiline_string_end" } ] } ] }, "_raw_string": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_string_start" }, { "type": "SEQ", "members": [ { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_raw_string_middle" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_dollar_escape" }, { "type": "SYMBOL", "name": "interpolation" } ] } ] } }, { "type": "SYMBOL", "name": "_single_line_string_end" } ] } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_multiline_string_start" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_raw_string_multiline_middle" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_dollar_escape" }, { "type": "SYMBOL", "name": "interpolation" } ] } ] } }, { "type": "SYMBOL", "name": "_multiline_string_end" } ] } ] }, "escape_sequence": { "type": "IMMEDIATE_TOKEN", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "\\" }, { "type": "CHOICE", "members": [ { "type": "PATTERN", "value": "[tbnrf\"'\\\\]" }, { "type": "PATTERN", "value": "[uU]+[0-9a-fA-F]{4}" }, { "type": "PATTERN", "value": "[0-3]?[0-7]{1,2}" } ] } ] } }, "string": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_string_start" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_string_middle" }, { "type": "SYMBOL", "name": "escape_sequence" } ] } }, { "type": "SYMBOL", "name": "_single_line_string_end" } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_simple_multiline_string_start" }, { "type": "SYMBOL", "name": "_multiline_string_end" } ] } ] }, "_semicolon": { "type": "CHOICE", "members": [ { "type": "STRING", "value": ";" }, { "type": "SYMBOL", "name": "_automatic_semicolon" } ] }, "null_literal": { "type": "STRING", "value": "null" }, "unit": { "type": "PREC", "value": 4, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "STRING", "value": ")" } ] } }, "return_expression": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "return" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "expression" }, { "type": "BLANK" } ] } ] } }, "throw_expression": { "type": "PREC_LEFT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "throw" }, { "type": "SYMBOL", "name": "expression" } ] } }, "while_expression": { "type": "PREC", "value": 2, "content": { "type": "CHOICE", "members": [ { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "while" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "parenthesized_expression" } }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "expression" } } ] } }, { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "while" }, { "type": "FIELD", "name": "condition", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_indentable_expression" }, { "type": "STRING", "value": "do" } ] } }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_indentable_expression" } } ] } } ] } }, "do_while_expression": { "type": "PREC_RIGHT", "value": 0, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "do" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "expression" } }, { "type": "STRING", "value": "while" }, { "type": "FIELD", "name": "condition", "content": { "type": "SYMBOL", "name": "parenthesized_expression" } } ] } }, "for_expression": { "type": "CHOICE", "members": [ { "type": "PREC_RIGHT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "for" }, { "type": "FIELD", "name": "enumerators", "content": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "(" }, { "type": "SYMBOL", "name": "enumerators" }, { "type": "STRING", "value": ")" } ] }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "{" }, { "type": "SYMBOL", "name": "enumerators" }, { "type": "STRING", "value": "}" } ] } ] } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "expression" } } ] }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "yield" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_indentable_expression" } } ] } ] } ] } }, { "type": "PREC_RIGHT", "value": 1, "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "for" }, { "type": "FIELD", "name": "enumerators", "content": { "type": "SYMBOL", "name": "enumerators" } }, { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "STRING", "value": "do" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_indentable_expression" } } ] }, { "type": "SEQ", "members": [ { "type": "STRING", "value": "yield" }, { "type": "FIELD", "name": "body", "content": { "type": "SYMBOL", "name": "_indentable_expression" } } ] } ] } ] } } ] }, "enumerators": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "enumerator" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_semicolon" }, { "type": "SYMBOL", "name": "enumerator" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "BLANK" } ] } ] }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_indent" }, { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "enumerator" }, { "type": "REPEAT", "content": { "type": "SEQ", "members": [ { "type": "SYMBOL", "name": "_semicolon" }, { "type": "SYMBOL", "name": "enumerator" } ] } } ] }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "_outdent" } ] } ] }, "enumerator": { "type": "CHOICE", "members": [ { "type": "SEQ", "members": [ { "type": "CHOICE", "members": [ { "type": "STRING", "value": "case" }, { "type": "BLANK" } ] }, { "type": "SYMBOL", "name": "_pattern" }, { "type": "CHOICE", "members": [ { "type": "STRING", "value": "<-" }, { "type": "STRING", "value": "=" } ] }, { "type": "SYMBOL", "name": "expression" }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "guard" }, { "type": "BLANK" } ] } ] }, { "type": "REPEAT1", "content": { "type": "SYMBOL", "name": "guard" } } ] }, "_shebang": { "type": "ALIAS", "content": { "type": "TOKEN", "content": { "type": "SEQ", "members": [ { "type": "STRING", "value": "#!" }, { "type": "PATTERN", "value": ".*" } ] } }, "named": true, "value": "comment" }, "comment": { "type": "SEQ", "members": [ { "type": "TOKEN", "content": { "type": "STRING", "value": "//" } }, { "type": "CHOICE", "members": [ { "type": "SYMBOL", "name": "using_directive" }, { "type": "SYMBOL", "name": "_comment_text" } ] } ] }, "_comment_text": { "type": "TOKEN", "content": { "type": "PREC", "value": 1, "content": { "type": "PATTERN", "value": ".*" } } }, "using_directive": { "type": "SEQ", "members": [ { "type": "IMMEDIATE_TOKEN", "content": { "type": "PREC", "value": 2, "content": { "type": "STRING", "value": ">" } } }, { "type": "TOKEN", "content": { "type": "STRING", "value": "using" } }, { "type": "SYMBOL", "name": "using_directive_key" }, { "type": "SYMBOL", "name": "using_directive_value" } ] }, "using_directive_key": { "type": "TOKEN", "content": { "type": "PATTERN", "value": "[^\\s]+" } }, "using_directive_value": { "type": "TOKEN", "content": { "type": "PATTERN", "value": ".*" } }, "block_comment": { "type": "SEQ", "members": [ { "type": "TOKEN", "content": { "type": "STRING", "value": "/*" } }, { "type": "REPEAT", "content": { "type": "CHOICE", "members": [ { "type": "TOKEN", "content": { "type": "PATTERN", "value": "." } }, { "type": "TOKEN", "content": { "type": "STRING", "value": "//" } } ] } }, { "type": "TOKEN", "content": { "type": "STRING", "value": "*/" } } ] } }, "extras": [ { "type": "PATTERN", "value": "\\s" }, { "type": "SYMBOL", "name": "comment" }, { "type": "SYMBOL", "name": "block_comment" } ], "conflicts": [ [ "tuple_type", "parameter_types" ], [ "binding", "_simple_expression" ], [ "binding", "_type_identifier" ], [ "while_expression", "_simple_expression" ], [ "if_expression" ], [ "match_expression" ], [ "_given_constructor", "_type_identifier" ], [ "instance_expression" ], [ "_simple_expression", "lambda_expression" ], [ "_simple_expression", "_single_lambda_param" ], [ "_class_definition" ], [ "_class_constructor" ], [ "_full_enum_def" ], [ "identifiers", "val_declaration" ], [ "class_parameters" ], [ "_type", "compound_type" ], [ "_type", "infix_type" ], [ "_type", "match_type" ], [ "_variant_type_parameter", "type_lambda" ], [ "name_and_type", "parameter" ], [ "_simple_expression", "binding", "tuple_pattern" ], [ "_simple_expression", "tuple_pattern" ], [ "_simple_expression", "_type_identifier" ], [ "_if_condition", "_simple_expression" ], [ "block", "_braced_template_body1" ], [ "_simple_expression", "_type_identifier" ], [ "_single_lambda_param", "self_type", "_type_identifier" ], [ "_single_lambda_param", "_type_identifier" ], [ "_simple_expression", "_single_lambda_param", "binding" ], [ "_simple_expression", "_single_lambda_param", "self_type" ], [ "_simple_expression", "_single_lambda_param", "self_type", "_type_identifier" ], [ "_single_lambda_param", "_self_type_ascription" ], [ "binding", "_simple_expression", "_type_identifier" ], [ "class_parameter", "_type_identifier" ], [ "_block", "_indentable_expression" ], [ "match_expression", "_simple_expression" ], [ "self_type", "_simple_expression" ], [ "repeat_pattern", "operator_identifier" ], [ "vararg", "operator_identifier" ], [ "_exprs_in_parens" ], [ "_annotated_type", "binding" ], [ "self_type", "_annotated_type", "_simple_expression" ], [ "binding", "_annotated_type", "_simple_expression" ], [ "_annotated_type", "_simple_expression" ], [ "generic_type", "_simple_expression" ] ], "precedences": [ [ { "type": "STRING", "value": "mod" }, { "type": "STRING", "value": "soft_id" } ], [ { "type": "STRING", "value": "end" }, { "type": "STRING", "value": "soft_id" } ], [ { "type": "STRING", "value": "new" }, { "type": "STRING", "value": "structural_type" } ], [ { "type": "STRING", "value": "self_type" }, { "type": "STRING", "value": "lambda" } ], [ { "type": "STRING", "value": "annotation" }, { "type": "STRING", "value": "applied_constructor_type" } ], [ { "type": "STRING", "value": "constructor_application" }, { "type": "STRING", "value": "applied_constructor_type" } ] ], "externals": [ { "type": "SYMBOL", "name": "_automatic_semicolon" }, { "type": "SYMBOL", "name": "_indent" }, { "type": "SYMBOL", "name": "_outdent" }, { "type": "SYMBOL", "name": "_comma_outdent" }, { "type": "SYMBOL", "name": "_simple_string_start" }, { "type": "SYMBOL", "name": "_simple_string_middle" }, { "type": "SYMBOL", "name": "_simple_multiline_string_start" }, { "type": "SYMBOL", "name": "_interpolated_string_middle" }, { "type": "SYMBOL", "name": "_interpolated_multiline_string_middle" }, { "type": "SYMBOL", "name": "_raw_string_start" }, { "type": "SYMBOL", "name": "_raw_string_middle" }, { "type": "SYMBOL", "name": "_raw_string_multiline_middle" }, { "type": "SYMBOL", "name": "_single_line_string_end" }, { "type": "SYMBOL", "name": "_multiline_string_end" }, { "type": "STRING", "value": "else" }, { "type": "STRING", "value": "catch" }, { "type": "STRING", "value": "finally" }, { "type": "STRING", "value": "extends" }, { "type": "STRING", "value": "derives" }, { "type": "STRING", "value": "with" }, { "type": "SYMBOL", "name": "error_sentinel" } ], "inline": [ "_pattern", "_semicolon", "_definition", "_param_type", "_identifier", "_postfix_expression_choice", "_infix_type_choice", "_param_value_type", "_simple_type", "literal" ], "supertypes": [ "expression", "_definition", "_pattern" ], "reserved": {} } ================================================ FILE: src/node-types.json ================================================ [ { "type": "_definition", "named": true, "subtypes": [ { "type": "class_definition", "named": true }, { "type": "enum_definition", "named": true }, { "type": "export_declaration", "named": true }, { "type": "extension_definition", "named": true }, { "type": "function_declaration", "named": true }, { "type": "function_definition", "named": true }, { "type": "given_definition", "named": true }, { "type": "import_declaration", "named": true }, { "type": "object_definition", "named": true }, { "type": "package_clause", "named": true }, { "type": "package_object", "named": true }, { "type": "trait_definition", "named": true }, { "type": "type_definition", "named": true }, { "type": "val_declaration", "named": true }, { "type": "val_definition", "named": true }, { "type": "var_declaration", "named": true }, { "type": "var_definition", "named": true } ] }, { "type": "_pattern", "named": true, "subtypes": [ { "type": "alternative_pattern", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "capture_pattern", "named": true }, { "type": "case_class_pattern", "named": true }, { "type": "character_literal", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "given_pattern", "named": true }, { "type": "identifier", "named": true }, { "type": "infix_pattern", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "named_tuple_pattern", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "quote_expression", "named": true }, { "type": "repeat_pattern", "named": true }, { "type": "stable_identifier", "named": true }, { "type": "string", "named": true }, { "type": "tuple_pattern", "named": true }, { "type": "typed_pattern", "named": true }, { "type": "wildcard", "named": true } ] }, { "type": "expression", "named": true, "subtypes": [ { "type": "ascription_expression", "named": true }, { "type": "assignment_expression", "named": true }, { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "do_while_expression", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "for_expression", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "if_expression", "named": true }, { "type": "infix_expression", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "lambda_expression", "named": true }, { "type": "macro_body", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "postfix_expression", "named": true }, { "type": "prefix_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "return_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "throw_expression", "named": true }, { "type": "try_expression", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "while_expression", "named": true }, { "type": "wildcard", "named": true } ] }, { "type": "access_modifier", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "access_qualifier", "named": true } ] } }, { "type": "access_qualifier", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] } }, { "type": "alternative_pattern", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_pattern", "named": true } ] } }, { "type": "annotated_type", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "annotation", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "annotation", "named": true, "fields": { "arguments": { "multiple": true, "required": false, "types": [ { "type": "arguments", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "applied_constructor_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "arguments", "named": true } ] } }, { "type": "applied_constructor_type", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "arguments", "named": true }, { "type": "type_identifier", "named": true } ] } }, { "type": "arguments", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "expression", "named": true }, { "type": "vararg", "named": true } ] } }, { "type": "arrow_renamed_identifier", "named": true, "fields": { "alias": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] } } }, { "type": "as_renamed_identifier", "named": true, "fields": { "alias": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] } } }, { "type": "ascription_expression", "named": true, "fields": { "type": { "multiple": false, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": true, "types": [ { "type": "annotation", "named": true }, { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "infix_expression", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "lazy_parameter_type", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "postfix_expression", "named": true }, { "type": "prefix_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "repeated_parameter_type", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "assignment_expression", "named": true, "fields": { "left": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "prefix_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] }, "right": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true } ] } } }, { "type": "binding", "named": true, "fields": { "name": { "multiple": false, "required": false, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type": { "multiple": true, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "lazy_parameter_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "repeated_parameter_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": false, "required": false, "types": [ { "type": "wildcard", "named": true } ] } }, { "type": "bindings", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "binding", "named": true } ] } }, { "type": "block", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "expression", "named": true } ] } }, { "type": "block_comment", "named": true, "extra": true, "fields": {} }, { "type": "boolean_literal", "named": true, "fields": {} }, { "type": "call_expression", "named": true, "fields": { "arguments": { "multiple": false, "required": true, "types": [ { "type": "arguments", "named": true }, { "type": "block", "named": true }, { "type": "case_block", "named": true }, { "type": "colon_argument", "named": true } ] }, "function": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "infix_expression", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "postfix_expression", "named": true }, { "type": "prefix_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "capture_pattern", "named": true, "fields": { "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "pattern": { "multiple": false, "required": true, "types": [ { "type": "_pattern", "named": true } ] } } }, { "type": "case_block", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "case_clause", "named": true } ] } }, { "type": "case_class_pattern", "named": true, "fields": { "pattern": { "multiple": true, "required": false, "types": [ { "type": ",", "named": false }, { "type": "_pattern", "named": true }, { "type": "named_pattern", "named": true } ] }, "type": { "multiple": false, "required": true, "types": [ { "type": "stable_type_identifier", "named": true }, { "type": "type_identifier", "named": true } ] } } }, { "type": "case_clause", "named": true, "fields": { "body": { "multiple": true, "required": false, "types": [ { "type": ";", "named": false }, { "type": "_definition", "named": true }, { "type": "_end_ident", "named": false }, { "type": "end", "named": false }, { "type": "expression", "named": true }, { "type": "extension", "named": false }, { "type": "for", "named": false }, { "type": "given", "named": false }, { "type": "if", "named": false }, { "type": "match", "named": false }, { "type": "new", "named": false }, { "type": "this", "named": false }, { "type": "try", "named": false }, { "type": "val", "named": false }, { "type": "while", "named": false } ] }, "pattern": { "multiple": false, "required": true, "types": [ { "type": "_pattern", "named": true } ] } }, "children": { "multiple": false, "required": false, "types": [ { "type": "guard", "named": true } ] } }, { "type": "catch_clause", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "expression", "named": true } ] }, "pattern": { "multiple": false, "required": false, "types": [ { "type": "_pattern", "named": true } ] } }, "children": { "multiple": false, "required": false, "types": [ { "type": "expression", "named": true }, { "type": "guard", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] } }, { "type": "class_definition", "named": true, "fields": { "body": { "multiple": true, "required": false, "types": [ { "type": "template_body", "named": true } ] }, "class_parameters": { "multiple": true, "required": false, "types": [ { "type": "class_parameters", "named": true } ] }, "derive": { "multiple": false, "required": false, "types": [ { "type": "derives_clause", "named": true } ] }, "extend": { "multiple": false, "required": false, "types": [ { "type": "extends_clause", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "access_modifier", "named": true }, { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "class_parameter", "named": true, "fields": { "default_value": { "multiple": false, "required": false, "types": [ { "type": "expression", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type": { "multiple": true, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "lazy_parameter_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "repeated_parameter_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "class_parameters", "named": true, "fields": { "type": { "multiple": true, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "class_parameter", "named": true }, { "type": "lazy_parameter_type", "named": true }, { "type": "repeated_parameter_type", "named": true } ] } }, { "type": "colon_argument", "named": true, "fields": { "lambda_start": { "multiple": true, "required": false, "types": [ { "type": "=>", "named": false }, { "type": "bindings", "named": true }, { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": false, "required": true, "types": [ { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] } }, { "type": "comment", "named": true, "extra": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "using_directive", "named": true } ] } }, { "type": "compilation_unit", "named": true, "root": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "comment", "named": true }, { "type": "expression", "named": true } ] } }, { "type": "compound_type", "named": true, "fields": { "base": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "extra": { "multiple": true, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": false, "required": false, "types": [ { "type": "refinement", "named": true } ] } }, { "type": "context_bound", "named": true, "fields": { "name": { "multiple": false, "required": false, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "contravariant_type_parameter", "named": true, "fields": { "bound": { "multiple": true, "required": false, "types": [ { "type": ",", "named": false }, { "type": ":", "named": false }, { "type": "context_bound", "named": true }, { "type": "lower_bound", "named": true }, { "type": "upper_bound", "named": true }, { "type": "view_bound", "named": true }, { "type": "{", "named": false }, { "type": "}", "named": false } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } } }, { "type": "covariant_type_parameter", "named": true, "fields": { "bound": { "multiple": true, "required": false, "types": [ { "type": ",", "named": false }, { "type": ":", "named": false }, { "type": "context_bound", "named": true }, { "type": "lower_bound", "named": true }, { "type": "upper_bound", "named": true }, { "type": "view_bound", "named": true }, { "type": "{", "named": false }, { "type": "}", "named": false } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } } }, { "type": "derives_clause", "named": true, "fields": { "type": { "multiple": true, "required": true, "types": [ { "type": "stable_type_identifier", "named": true }, { "type": "type_identifier", "named": true } ] } } }, { "type": "do_while_expression", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true } ] }, "condition": { "multiple": false, "required": true, "types": [ { "type": "parenthesized_expression", "named": true } ] } } }, { "type": "enum_body", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "enum_case_definitions", "named": true }, { "type": "expression", "named": true } ] } }, { "type": "enum_case_definitions", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "annotation", "named": true }, { "type": "full_enum_case", "named": true }, { "type": "simple_enum_case", "named": true } ] } }, { "type": "enum_definition", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "enum_body", "named": true } ] }, "class_parameters": { "multiple": true, "required": false, "types": [ { "type": "class_parameters", "named": true } ] }, "derive": { "multiple": false, "required": false, "types": [ { "type": "derives_clause", "named": true } ] }, "extend": { "multiple": false, "required": false, "types": [ { "type": "extends_clause", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "access_modifier", "named": true }, { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "enumerator", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_pattern", "named": true }, { "type": "expression", "named": true }, { "type": "guard", "named": true } ] } }, { "type": "enumerators", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "enumerator", "named": true } ] } }, { "type": "export_declaration", "named": true, "fields": { "path": { "multiple": true, "required": false, "types": [ { "type": ".", "named": false }, { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "as_renamed_identifier", "named": true }, { "type": "namespace_selectors", "named": true }, { "type": "namespace_wildcard", "named": true } ] } }, { "type": "extends_clause", "named": true, "fields": { "arguments": { "multiple": true, "required": false, "types": [ { "type": "arguments", "named": true } ] }, "type": { "multiple": true, "required": true, "types": [ { "type": ",", "named": false }, { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "arguments", "named": true }, { "type": "compound_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true }, { "type": "with", "named": false } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "arguments", "named": true } ] } }, { "type": "extension_definition", "named": true, "fields": { "body": { "multiple": true, "required": true, "types": [ { "type": ";", "named": false }, { "type": "_definition", "named": true }, { "type": "_end_ident", "named": false }, { "type": "end", "named": false }, { "type": "expression", "named": true }, { "type": "extension", "named": false }, { "type": "for", "named": false }, { "type": "given", "named": false }, { "type": "if", "named": false }, { "type": "match", "named": false }, { "type": "new", "named": false }, { "type": "this", "named": false }, { "type": "try", "named": false }, { "type": "val", "named": false }, { "type": "while", "named": false }, { "type": "{", "named": false }, { "type": "}", "named": false } ] }, "parameters": { "multiple": true, "required": false, "types": [ { "type": "parameters", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } } }, { "type": "field_expression", "named": true, "fields": { "field": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "finally_clause", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] } }, { "type": "for_expression", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] }, "enumerators": { "multiple": true, "required": true, "types": [ { "type": "(", "named": false }, { "type": ")", "named": false }, { "type": "enumerators", "named": true }, { "type": "{", "named": false }, { "type": "}", "named": false } ] } } }, { "type": "full_enum_case", "named": true, "fields": { "class_parameters": { "multiple": true, "required": true, "types": [ { "type": "class_parameters", "named": true } ] }, "extend": { "multiple": false, "required": false, "types": [ { "type": "extends_clause", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } } }, { "type": "function_declaration", "named": true, "fields": { "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "parameters": { "multiple": true, "required": false, "types": [ { "type": "parameters", "named": true }, { "type": "type_parameters", "named": true } ] }, "return_type": { "multiple": false, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "function_definition", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "parameters": { "multiple": true, "required": false, "types": [ { "type": "parameters", "named": true }, { "type": "type_parameters", "named": true } ] }, "return_type": { "multiple": false, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "function_type", "named": true, "fields": { "parameter_types": { "multiple": false, "required": false, "types": [ { "type": "parameter_types", "named": true } ] }, "return_type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } } }, { "type": "generic_function", "named": true, "fields": { "function": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true } ] }, "type_arguments": { "multiple": false, "required": true, "types": [ { "type": "type_arguments", "named": true } ] } } }, { "type": "generic_type", "named": true, "fields": { "type": { "multiple": false, "required": true, "types": [ { "type": "applied_constructor_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "type_arguments": { "multiple": false, "required": true, "types": [ { "type": "type_arguments", "named": true } ] } } }, { "type": "given_conditional", "named": true, "fields": { "type": { "multiple": true, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "lazy_parameter_type", "named": true }, { "type": "parameter", "named": true }, { "type": "repeated_parameter_type", "named": true } ] } }, { "type": "given_definition", "named": true, "fields": { "arguments": { "multiple": false, "required": false, "types": [ { "type": "arguments", "named": true } ] }, "body": { "multiple": false, "required": false, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true }, { "type": "with_template_body", "named": true } ] }, "name": { "multiple": false, "required": false, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "parameters": { "multiple": true, "required": false, "types": [ { "type": "parameters", "named": true } ] }, "return_type": { "multiple": true, "required": true, "types": [ { "type": ":", "named": false }, { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "arguments", "named": true }, { "type": "compound_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true }, { "type": "with", "named": false }, { "type": "with_template_body", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "given_conditional", "named": true }, { "type": "modifiers", "named": true }, { "type": "type_parameters", "named": true } ] } }, { "type": "given_pattern", "named": true, "fields": { "type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "guard", "named": true, "fields": { "condition": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "infix_expression", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "postfix_expression", "named": true }, { "type": "prefix_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "identifier", "named": true, "fields": {} }, { "type": "identifiers", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "identifier", "named": true } ] } }, { "type": "if_expression", "named": true, "fields": { "alternative": { "multiple": false, "required": false, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] }, "condition": { "multiple": true, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true }, { "type": "then", "named": false } ] }, "consequence": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] } }, "children": { "multiple": false, "required": false, "types": [ { "type": "inline_modifier", "named": true } ] } }, { "type": "import_declaration", "named": true, "fields": { "path": { "multiple": true, "required": false, "types": [ { "type": ".", "named": false }, { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "as_renamed_identifier", "named": true }, { "type": "namespace_selectors", "named": true }, { "type": "namespace_wildcard", "named": true } ] } }, { "type": "indented_block", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "expression", "named": true } ] } }, { "type": "indented_cases", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "case_clause", "named": true } ] } }, { "type": "infix_expression", "named": true, "fields": { "left": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "infix_expression", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "prefix_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] }, "operator": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "right": { "multiple": true, "required": true, "types": [ { "type": ":", "named": false }, { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "colon_argument", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "prefix_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "infix_modifier", "named": true, "fields": {} }, { "type": "infix_pattern", "named": true, "fields": { "left": { "multiple": false, "required": true, "types": [ { "type": "_pattern", "named": true } ] }, "operator": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "right": { "multiple": false, "required": true, "types": [ { "type": "_pattern", "named": true } ] } } }, { "type": "infix_type", "named": true, "fields": { "left": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "operator": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "right": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "inline_modifier", "named": true, "fields": {} }, { "type": "instance_expression", "named": true, "fields": { "arguments": { "multiple": false, "required": false, "types": [ { "type": "arguments", "named": true } ] } }, "children": { "multiple": true, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "template_body", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "interpolated_string", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "escape_sequence", "named": true }, { "type": "interpolation", "named": true } ] } }, { "type": "interpolated_string_expression", "named": true, "fields": { "interpolator": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true } ] } }, "children": { "multiple": false, "required": true, "types": [ { "type": "interpolated_string", "named": true } ] } }, { "type": "interpolation", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "identifier", "named": true } ] } }, { "type": "into_modifier", "named": true, "fields": {} }, { "type": "lambda_expression", "named": true, "fields": { "parameters": { "multiple": true, "required": true, "types": [ { "type": ":", "named": false }, { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "bindings", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "identifier", "named": true }, { "type": "implicit", "named": false }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] } }, { "type": "lazy_parameter_type", "named": true, "fields": { "type": { "multiple": true, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "repeated_parameter_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "literal_type", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "boolean_literal", "named": true }, { "type": "character_literal", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "integer_literal", "named": true }, { "type": "string", "named": true } ] } }, { "type": "lower_bound", "named": true, "fields": { "type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "macro_body", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "infix_expression", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "prefix_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "match_expression", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "case_block", "named": true }, { "type": "indented_cases", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true } ] } }, "children": { "multiple": false, "required": false, "types": [ { "type": "inline_modifier", "named": true } ] } }, { "type": "match_type", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_case_clause", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "modifiers", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "access_modifier", "named": true }, { "type": "infix_modifier", "named": true }, { "type": "inline_modifier", "named": true }, { "type": "into_modifier", "named": true }, { "type": "open_modifier", "named": true }, { "type": "tracked_modifier", "named": true }, { "type": "transparent_modifier", "named": true } ] } }, { "type": "name_and_type", "named": true, "fields": { "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type": { "multiple": true, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "lazy_parameter_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "repeated_parameter_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "named_pattern", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_pattern", "named": true } ] } }, { "type": "named_tuple_pattern", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "named_pattern", "named": true } ] } }, { "type": "named_tuple_type", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "name_and_type", "named": true } ] } }, { "type": "namespace_selectors", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "arrow_renamed_identifier", "named": true }, { "type": "as_renamed_identifier", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "identifier", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "namespace_wildcard", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "namespace_wildcard", "named": true, "fields": {} }, { "type": "object_definition", "named": true, "fields": { "body": { "multiple": true, "required": false, "types": [ { "type": "template_body", "named": true } ] }, "derive": { "multiple": false, "required": false, "types": [ { "type": "derives_clause", "named": true } ] }, "extend": { "multiple": false, "required": false, "types": [ { "type": "extends_clause", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "opaque_modifier", "named": true, "fields": {} }, { "type": "open_modifier", "named": true, "fields": {} }, { "type": "operator_identifier", "named": true, "fields": {} }, { "type": "package_clause", "named": true, "fields": { "body": { "multiple": false, "required": false, "types": [ { "type": "template_body", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "package_identifier", "named": true } ] } } }, { "type": "package_identifier", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] } }, { "type": "package_object", "named": true, "fields": { "body": { "multiple": true, "required": false, "types": [ { "type": "template_body", "named": true } ] }, "derive": { "multiple": false, "required": false, "types": [ { "type": "derives_clause", "named": true } ] }, "extend": { "multiple": false, "required": false, "types": [ { "type": "extends_clause", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] } } }, { "type": "parameter", "named": true, "fields": { "default_value": { "multiple": false, "required": false, "types": [ { "type": "expression", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type": { "multiple": true, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "lazy_parameter_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "repeated_parameter_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "inline_modifier", "named": true } ] } }, { "type": "parameter_types", "named": true, "fields": { "type": { "multiple": true, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "lazy_parameter_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "repeated_parameter_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "parameters", "named": true, "fields": { "type": { "multiple": true, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "lazy_parameter_type", "named": true }, { "type": "parameter", "named": true }, { "type": "repeated_parameter_type", "named": true } ] } }, { "type": "parenthesized_expression", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true } ] } }, { "type": "postfix_expression", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "infix_expression", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "prefix_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "prefix_expression", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "projected_type", "named": true, "fields": { "selector": { "multiple": false, "required": true, "types": [ { "type": "type_identifier", "named": true } ] }, "type": { "multiple": false, "required": true, "types": [ { "type": "applied_constructor_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "quote_expression", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "expression", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true } ] } }, { "type": "refinement", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "expression", "named": true }, { "type": "self_type", "named": true } ] } }, { "type": "repeat_pattern", "named": true, "fields": { "pattern": { "multiple": false, "required": true, "types": [ { "type": "_pattern", "named": true } ] } } }, { "type": "repeated_parameter_type", "named": true, "fields": { "type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "return_expression", "named": true, "fields": {}, "children": { "multiple": false, "required": false, "types": [ { "type": "expression", "named": true } ] } }, { "type": "self_type", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "identifier", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "simple_enum_case", "named": true, "fields": { "extend": { "multiple": false, "required": false, "types": [ { "type": "extends_clause", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] } } }, { "type": "singleton_type", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "stable_identifier", "named": true } ] } }, { "type": "splice_expression", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "expression", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true } ] } }, { "type": "stable_identifier", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "stable_identifier", "named": true } ] } }, { "type": "stable_type_identifier", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "stable_identifier", "named": true }, { "type": "type_identifier", "named": true } ] } }, { "type": "string", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "escape_sequence", "named": true } ] } }, { "type": "structural_type", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "expression", "named": true }, { "type": "self_type", "named": true } ] } }, { "type": "template_body", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "expression", "named": true }, { "type": "self_type", "named": true } ] } }, { "type": "throw_expression", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true } ] } }, { "type": "tracked_modifier", "named": true, "fields": {} }, { "type": "trait_definition", "named": true, "fields": { "body": { "multiple": true, "required": false, "types": [ { "type": "template_body", "named": true } ] }, "class_parameters": { "multiple": true, "required": false, "types": [ { "type": "class_parameters", "named": true } ] }, "derive": { "multiple": false, "required": false, "types": [ { "type": "derives_clause", "named": true } ] }, "extend": { "multiple": false, "required": false, "types": [ { "type": "extends_clause", "named": true } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "access_modifier", "named": true }, { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "transparent_modifier", "named": true, "fields": {} }, { "type": "try_expression", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "catch_clause", "named": true }, { "type": "finally_clause", "named": true } ] } }, { "type": "tuple_expression", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "expression", "named": true } ] } }, { "type": "tuple_pattern", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "_pattern", "named": true } ] } }, { "type": "tuple_type", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "type_arguments", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "type_case_clause", "named": true, "fields": { "body": { "multiple": true, "required": true, "types": [ { "type": "=>", "named": false }, { "type": "?=>", "named": false }, { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] }, "return_type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "type_definition", "named": true, "fields": { "bound": { "multiple": true, "required": false, "types": [ { "type": ",", "named": false }, { "type": ":", "named": false }, { "type": "context_bound", "named": true }, { "type": "lower_bound", "named": true }, { "type": "upper_bound", "named": true }, { "type": "{", "named": false }, { "type": "}", "named": false } ] }, "name": { "multiple": false, "required": true, "types": [ { "type": "type_identifier", "named": true } ] }, "type": { "multiple": false, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] }, "type_parameters": { "multiple": false, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "modifiers", "named": true }, { "type": "opaque_modifier", "named": true } ] } }, { "type": "type_lambda", "named": true, "fields": { "bound": { "multiple": true, "required": false, "types": [ { "type": ",", "named": false }, { "type": ":", "named": false }, { "type": "context_bound", "named": true }, { "type": "lower_bound", "named": true }, { "type": "upper_bound", "named": true }, { "type": "view_bound", "named": true }, { "type": "{", "named": false }, { "type": "}", "named": false } ] }, "name": { "multiple": true, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "return_type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] }, "type_parameters": { "multiple": true, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } } }, { "type": "type_parameters", "named": true, "fields": { "bound": { "multiple": true, "required": false, "types": [ { "type": ",", "named": false }, { "type": ":", "named": false }, { "type": "context_bound", "named": true }, { "type": "lower_bound", "named": true }, { "type": "upper_bound", "named": true }, { "type": "view_bound", "named": true }, { "type": "{", "named": false }, { "type": "}", "named": false } ] }, "name": { "multiple": true, "required": false, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "wildcard", "named": true } ] }, "type_parameters": { "multiple": true, "required": false, "types": [ { "type": "type_parameters", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "contravariant_type_parameter", "named": true }, { "type": "covariant_type_parameter", "named": true }, { "type": "type_lambda", "named": true } ] } }, { "type": "typed_pattern", "named": true, "fields": { "pattern": { "multiple": false, "required": true, "types": [ { "type": "_pattern", "named": true } ] }, "type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "unit", "named": true, "fields": {} }, { "type": "upper_bound", "named": true, "fields": { "type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "using_directive", "named": true, "fields": {}, "children": { "multiple": true, "required": true, "types": [ { "type": "using_directive_key", "named": true }, { "type": "using_directive_value", "named": true } ] } }, { "type": "val_declaration", "named": true, "fields": { "name": { "multiple": true, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "val_definition", "named": true, "fields": { "pattern": { "multiple": false, "required": true, "types": [ { "type": "_pattern", "named": true }, { "type": "identifiers", "named": true } ] }, "type": { "multiple": false, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "var_declaration", "named": true, "fields": { "name": { "multiple": true, "required": true, "types": [ { "type": "identifier", "named": true }, { "type": "operator_identifier", "named": true } ] }, "type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "var_definition", "named": true, "fields": { "pattern": { "multiple": false, "required": true, "types": [ { "type": "_pattern", "named": true }, { "type": "identifiers", "named": true } ] }, "type": { "multiple": false, "required": false, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] }, "value": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] } }, "children": { "multiple": true, "required": false, "types": [ { "type": "annotation", "named": true }, { "type": "modifiers", "named": true } ] } }, { "type": "vararg", "named": true, "fields": {}, "children": { "multiple": false, "required": true, "types": [ { "type": "block", "named": true }, { "type": "boolean_literal", "named": true }, { "type": "call_expression", "named": true }, { "type": "case_block", "named": true }, { "type": "character_literal", "named": true }, { "type": "field_expression", "named": true }, { "type": "floating_point_literal", "named": true }, { "type": "generic_function", "named": true }, { "type": "identifier", "named": true }, { "type": "instance_expression", "named": true }, { "type": "integer_literal", "named": true }, { "type": "interpolated_string_expression", "named": true }, { "type": "match_expression", "named": true }, { "type": "null_literal", "named": true }, { "type": "operator_identifier", "named": true }, { "type": "parenthesized_expression", "named": true }, { "type": "quote_expression", "named": true }, { "type": "splice_expression", "named": true }, { "type": "string", "named": true }, { "type": "tuple_expression", "named": true }, { "type": "unit", "named": true }, { "type": "wildcard", "named": true } ] } }, { "type": "view_bound", "named": true, "fields": { "type": { "multiple": false, "required": true, "types": [ { "type": "annotated_type", "named": true }, { "type": "applied_constructor_type", "named": true }, { "type": "compound_type", "named": true }, { "type": "function_type", "named": true }, { "type": "generic_type", "named": true }, { "type": "infix_type", "named": true }, { "type": "literal_type", "named": true }, { "type": "match_type", "named": true }, { "type": "named_tuple_type", "named": true }, { "type": "projected_type", "named": true }, { "type": "singleton_type", "named": true }, { "type": "stable_type_identifier", "named": true }, { "type": "structural_type", "named": true }, { "type": "tuple_type", "named": true }, { "type": "type_identifier", "named": true }, { "type": "type_lambda", "named": true }, { "type": "wildcard", "named": true } ] } } }, { "type": "while_expression", "named": true, "fields": { "body": { "multiple": false, "required": true, "types": [ { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] }, "condition": { "multiple": true, "required": true, "types": [ { "type": "do", "named": false }, { "type": "expression", "named": true }, { "type": "indented_block", "named": true }, { "type": "indented_cases", "named": true } ] } } }, { "type": "wildcard", "named": true, "fields": {} }, { "type": "with_template_body", "named": true, "fields": {}, "children": { "multiple": true, "required": false, "types": [ { "type": "_definition", "named": true }, { "type": "expression", "named": true }, { "type": "self_type", "named": true } ] } }, { "type": "!", "named": false }, { "type": "\"", "named": false }, { "type": "\"\"\"", "named": false }, { "type": "#", "named": false }, { "type": "$", "named": false }, { "type": "'", "named": false }, { "type": "(", "named": false }, { "type": ")", "named": false }, { "type": "*", "named": false }, { "type": "*/", "named": false }, { "type": "+", "named": false }, { "type": ",", "named": false }, { "type": "-", "named": false }, { "type": ".", "named": false }, { "type": "/*", "named": false }, { "type": "//", "named": false }, { "type": ":", "named": false }, { "type": ";", "named": false }, { "type": "<%", "named": false }, { "type": "<-", "named": false }, { "type": "<:", "named": false }, { "type": "=", "named": false }, { "type": "=>", "named": false }, { "type": "=>>", "named": false }, { "type": ">", "named": false }, { "type": ">:", "named": false }, { "type": "?=>", "named": false }, { "type": "@", "named": false }, { "type": "[", "named": false }, { "type": "]", "named": false }, { "type": "_", "named": false }, { "type": "abstract", "named": false }, { "type": "as", "named": false }, { "type": "case", "named": false }, { "type": "catch", "named": false }, { "type": "character_literal", "named": true }, { "type": "class", "named": false }, { "type": "def", "named": false }, { "type": "derives", "named": false }, { "type": "do", "named": false }, { "type": "else", "named": false }, { "type": "end", "named": false }, { "type": "enum", "named": false }, { "type": "escape_sequence", "named": true }, { "type": "export", "named": false }, { "type": "extends", "named": false }, { "type": "extension", "named": false }, { "type": "false", "named": false }, { "type": "final", "named": false }, { "type": "finally", "named": false }, { "type": "floating_point_literal", "named": true }, { "type": "for", "named": false }, { "type": "given", "named": false }, { "type": "if", "named": false }, { "type": "implicit", "named": false }, { "type": "import", "named": false }, { "type": "infix", "named": false }, { "type": "inline", "named": false }, { "type": "integer_literal", "named": true }, { "type": "into", "named": false }, { "type": "lazy", "named": false }, { "type": "macro", "named": false }, { "type": "match", "named": false }, { "type": "new", "named": false }, { "type": "null_literal", "named": true }, { "type": "object", "named": false }, { "type": "opaque", "named": false }, { "type": "open", "named": false }, { "type": "override", "named": false }, { "type": "package", "named": false }, { "type": "private", "named": false }, { "type": "protected", "named": false }, { "type": "return", "named": false }, { "type": "sealed", "named": false }, { "type": "then", "named": false }, { "type": "this", "named": false }, { "type": "throw", "named": false }, { "type": "tracked", "named": false }, { "type": "trait", "named": false }, { "type": "transparent", "named": false }, { "type": "true", "named": false }, { "type": "try", "named": false }, { "type": "type", "named": false }, { "type": "using", "named": false }, { "type": "using_directive_key", "named": true }, { "type": "using_directive_value", "named": true }, { "type": "val", "named": false }, { "type": "var", "named": false }, { "type": "while", "named": false }, { "type": "with", "named": false }, { "type": "yield", "named": false }, { "type": "{", "named": false }, { "type": "|", "named": false }, { "type": "}", "named": false }, { "type": "~", "named": false } ] ================================================ FILE: src/parser.c ================================================ [File too large to display: 30.9 MB] ================================================ FILE: src/scanner.c ================================================ #include "tree_sitter/alloc.h" #include "tree_sitter/array.h" #include "tree_sitter/parser.h" #include // #define DEBUG #ifdef DEBUG #define LOG(...) fprintf(stderr, __VA_ARGS__) #else #define LOG(...) #endif enum TokenType { AUTOMATIC_SEMICOLON, INDENT, OUTDENT, COMMA_OUTDENT, SIMPLE_STRING_START, SIMPLE_STRING_MIDDLE, SIMPLE_MULTILINE_STRING_START, INTERPOLATED_STRING_MIDDLE, INTERPOLATED_MULTILINE_STRING_MIDDLE, RAW_STRING_START, RAW_STRING_MIDDLE, RAW_STRING_MULTILINE_MIDDLE, SINGLE_LINE_STRING_END, MULTILINE_STRING_END, ELSE, CATCH, FINALLY, EXTENDS, DERIVES, WITH, ERROR_SENTINEL }; const char* token_name[] = { "AUTOMATIC_SEMICOLON", "INDENT", "OUTDENT", "COMMA_OUTDENT", "SIMPLE_STRING_START", "SIMPLE_STRING_MIDDLE", "SIMPLE_MULTILINE_STRING_START", "INTERPOLATED_STRING_MIDDLE", "INTERPOLATED_MULTILINE_STRING_MIDDLE", "RAW_STRING_MIDDLE", "RAW_STRING_MULTILINE_MIDDLE", "SINGLE_LINE_STRING_END", "MULTILINE_STRING_END", "ELSE", "CATCH", "FINALLY", "EXTENDS", "DERIVES", "WITH", "ERROR_SENTINEL" }; typedef struct { Array(int16_t) indents; int16_t last_indentation_size; int16_t last_newline_count; int16_t last_column; } Scanner; void *tree_sitter_scala_external_scanner_create() { Scanner *scanner = ts_calloc(1, sizeof(Scanner)); array_init(&scanner->indents); scanner->last_indentation_size = -1; scanner->last_column = -1; return scanner; } void tree_sitter_scala_external_scanner_destroy(void *payload) { Scanner *scanner = payload; array_delete(&scanner->indents); ts_free(scanner); } unsigned tree_sitter_scala_external_scanner_serialize(void *payload, char *buffer) { Scanner *scanner = (Scanner*)payload; if ((scanner->indents.size + 3) * sizeof(int16_t) > TREE_SITTER_SERIALIZATION_BUFFER_SIZE) { return 0; } size_t size = 0; memcpy(buffer + size, &scanner->last_indentation_size, sizeof(int16_t)); size += sizeof(int16_t); memcpy(buffer + size, &scanner->last_newline_count, sizeof(int16_t)); size += sizeof(int16_t); memcpy(buffer + size, &scanner->last_column, sizeof(int16_t)); size += sizeof(int16_t); for (unsigned i = 0; i < scanner->indents.size; i++) { memcpy(buffer + size, &scanner->indents.contents[i], sizeof(int16_t)); size += sizeof(int16_t); } return size; } void tree_sitter_scala_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) { Scanner *scanner = (Scanner*)payload; array_clear(&scanner->indents); scanner->last_indentation_size = -1; scanner->last_column = -1; scanner->last_newline_count = 0; if (length == 0) { return; } size_t size = 0; scanner->last_indentation_size = *(int16_t *)&buffer[size]; size += sizeof(int16_t); scanner->last_newline_count = *(int16_t *)&buffer[size]; size += sizeof(int16_t); scanner->last_column = *(int16_t *)&buffer[size]; size += sizeof(int16_t); while (size < length) { array_push(&scanner->indents, *(int16_t *)&buffer[size]); size += sizeof(int16_t); } assert(size == length); } static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); } static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); } // Used to detect leading infix operators on continuation lines. // See: https://www.scala-lang.org/api/3.x/docs/changed-features/operators.html static bool is_op_char(int32_t c) { switch (c) { case '!': case '#': case '%': case '&': case '*': case '+': case '-': case '<': case '=': case '>': case '?': case '@': case '\\': case '^': case '|': case '~': case ':': return true; default: return false; } } // We enumerate 3 types of strings that we need to handle differently: // 1. Simple strings, `"..."` or `"""..."""` // 2. Interpolated strings, `s"..."` or `f"..."` or `foo"..."` or foo"""...""". // 3. Raw strings, `raw"..."` typedef enum { STRING_MODE_SIMPLE, STRING_MODE_INTERPOLATED, STRING_MODE_RAW } StringMode; static bool scan_string_content(TSLexer *lexer, bool is_multiline, StringMode string_mode) { LOG("scan_string_content(%d, %d, %c)\n", is_multiline, string_mode, lexer->lookahead); unsigned closing_quote_count = 0; for (;;) { if (lexer->lookahead == '"') { advance(lexer); closing_quote_count++; if (!is_multiline) { lexer->result_symbol = SINGLE_LINE_STRING_END; lexer->mark_end(lexer); return true; } if (closing_quote_count >= 3 && lexer->lookahead != '"') { lexer->result_symbol = MULTILINE_STRING_END; lexer->mark_end(lexer); return true; } } else if (lexer->lookahead == '$' && string_mode != STRING_MODE_SIMPLE) { switch (string_mode) { case STRING_MODE_INTERPOLATED: lexer->result_symbol = is_multiline ? INTERPOLATED_MULTILINE_STRING_MIDDLE : INTERPOLATED_STRING_MIDDLE; break; case STRING_MODE_RAW: lexer->result_symbol = is_multiline ? RAW_STRING_MULTILINE_MIDDLE : RAW_STRING_MIDDLE; break; default: assert(false); } lexer->mark_end(lexer); return true; } else { closing_quote_count = 0; if (lexer->lookahead == '\\') { // Multiline strings ignore escape sequences if (is_multiline || string_mode == STRING_MODE_RAW) { // FIXME: In raw string mode, we have to jump over escaped quotes. advance(lexer); // In single-line raw strings, `\"` is not translated to `"`, but it also does // not close the string. Likewise, `\\` is not translated to `\`, but it does // stop the second `\` from stopping a double-quote from closing the string. if (!is_multiline && string_mode == STRING_MODE_RAW && (lexer->lookahead == '"' || lexer->lookahead == '\\')) { advance(lexer); } } else { lexer->result_symbol = string_mode == STRING_MODE_SIMPLE ? SIMPLE_STRING_MIDDLE : INTERPOLATED_STRING_MIDDLE; lexer->mark_end(lexer); return true; } // During error recovery and dynamic precedence resolution, the external // scanner will be invoked with all valid_symbols set to true, which means // we will be asked to scan a string token when we are not actually in a // string context. Here we detect these cases and return false. } else if (lexer->lookahead == '\n' && !is_multiline) { return false; } else if (lexer->eof(lexer)) { return false; } else { advance(lexer); } } } } static bool detect_comment_start(TSLexer *lexer) { lexer->mark_end(lexer); // Comments should not affect indentation if (lexer->lookahead == '/') { advance(lexer); if (lexer->lookahead == '/' || lexer -> lookahead == '*') { return true; } } return false; } static bool scan_word(TSLexer *lexer, const char* const word) { for (uint8_t i = 0; word[i] != '\0'; i++) { if (lexer->lookahead != word[i]) { return false; } advance(lexer); } return !iswalnum(lexer->lookahead); } // Returns true if the lookahead starts a leading infix operator — a symbolic // operator or back-ticked identifier followed by whitespace and then a // non-whitespace operand on the same line. Such a line is a continuation of // the previous expression, so neither AUTOMATIC_SEMICOLON nor OUTDENT should // fire ahead of it. Advances the lexer; the caller must not rely on position. static bool is_leading_infix_continuation(TSLexer *lexer) { if (is_op_char(lexer->lookahead)) { advance(lexer); while (is_op_char(lexer->lookahead)) { advance(lexer); } bool found_space = false; while (lexer->lookahead == ' ' || lexer->lookahead == '\t') { advance(lexer); found_space = true; } return found_space && !iswspace(lexer->lookahead) && !lexer->eof(lexer); } if (lexer->lookahead == '`') { advance(lexer); while (lexer->lookahead != '`' && !lexer->eof(lexer)) { advance(lexer); } if (lexer->lookahead != '`') { return false; } advance(lexer); bool found_space = false; while (lexer->lookahead == ' ' || lexer->lookahead == '\t') { advance(lexer); found_space = true; } return found_space && !iswspace(lexer->lookahead) && !lexer->eof(lexer); } return false; } static inline void debug_indents(Scanner *scanner) { LOG(" indents(%d): ", scanner->indents.size); for (unsigned i = 0; i < scanner->indents.size; i++) { LOG("%d ", scanner->indents.contents[i]); } LOG("\n"); } bool tree_sitter_scala_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) { #ifdef DEBUG { if (valid_symbols[ERROR_SENTINEL]) { LOG("entering tree_sitter_scala_external_scanner_scan. ERROR_SENTINEL is valid\n"); } else { char debug_str[1024] = "entering tree_sitter_scala_external_scanner_scan valid symbols: "; for (unsigned i = 0; i < ERROR_SENTINEL; i++) { if (valid_symbols[i]) { strcat(debug_str, token_name[i]); strcat(debug_str, ", "); } } strcat(debug_str, "\n"); LOG("%s", debug_str); } } #endif Scanner *scanner = (Scanner *)payload; int16_t prev = scanner->indents.size > 0 ? *array_back(&scanner->indents) : -1; int16_t newline_count = 0; int16_t indentation_size = 0; while (iswspace(lexer->lookahead)) { if (lexer->lookahead == '\n') { newline_count++; indentation_size = 0; } else { indentation_size++; } skip(lexer); } // Separate from OUTDENT because the scanner cannot distinguish a comma that // terminates an indented block (e.g. `map: x => f(x),`) from one that is // internal to it (e.g. `case EnumCase1, EnumCase2`). By using a distinct // token, tree-sitter only makes it valid in grammar contexts where comma // termination is expected (colon_argument, _indentable_expression). if (valid_symbols[COMMA_OUTDENT] && lexer->lookahead == ',' && prev != -1) { if (scanner->indents.size > 0) { array_pop(&scanner->indents); } lexer->mark_end(lexer); lexer->result_symbol = COMMA_OUTDENT; return true; } // Before advancing the lexer, check if we can double outdent if ( valid_symbols[OUTDENT] && ( lexer->lookahead == 0 || ( prev != -1 && ( lexer->lookahead == ')' || lexer->lookahead == ']' || lexer->lookahead == '}' ) ) || ( scanner->last_indentation_size != -1 && prev != -1 && scanner->last_indentation_size < prev ) ) ) { if (scanner->indents.size > 0) { array_pop(&scanner->indents); } LOG(" pop\n"); LOG(" OUTDENT\n"); lexer->result_symbol = OUTDENT; return true; } scanner->last_indentation_size = -1; if ( valid_symbols[INDENT] && newline_count > 0 && ( scanner->indents.size == 0 || indentation_size > *array_back(&scanner->indents) ) ) { if (detect_comment_start(lexer)) { return false; } array_push(&scanner->indents, indentation_size); lexer->result_symbol = INDENT; LOG(" INDENT\n"); return true; } // This saves the indentation_size and newline_count so it can be used // in subsequent calls for multiple outdent or auto-semicolon. if (valid_symbols[OUTDENT] && (lexer->lookahead == 0 || ( newline_count > 0 && prev != -1 && indentation_size < prev ) ) ) { lexer->mark_end(lexer); if (detect_comment_start(lexer)) { return false; } scanner->last_indentation_size = indentation_size; scanner->last_newline_count = newline_count; if (lexer->eof(lexer)) { scanner->last_column = -1; } else { scanner->last_column = (int16_t)lexer->get_column(lexer); } // Don't close the indented block when the next line starts with a leading // infix operator: that operator continues the previous expression. if (lexer->lookahead != 0 && is_leading_infix_continuation(lexer)) { return false; } if (scanner->indents.size > 0) { array_pop(&scanner->indents); } LOG(" pop\n"); LOG(" OUTDENT\n"); lexer->result_symbol = OUTDENT; return true; } // Recover newline_count from the outdent reset bool is_eof = lexer->eof(lexer); if ( ( scanner->last_newline_count > 0 && (is_eof && scanner->last_column == -1) ) || (!is_eof && lexer->get_column(lexer) == (uint32_t)scanner->last_column) ) { newline_count += scanner->last_newline_count; } scanner->last_newline_count = 0; if (valid_symbols[AUTOMATIC_SEMICOLON] && newline_count > 0) { // AUTOMATIC_SEMICOLON should not be issued in the middle of expressions // Thus, we exit this branch when encountering comments, else/catch clauses, etc. lexer->mark_end(lexer); lexer->result_symbol = AUTOMATIC_SEMICOLON; // Probably, a multi-line field expression, e.g. // a // .b // .c if (lexer->lookahead == '.') { return false; } // Single-line and multi-line comments if (lexer->lookahead == '/') { advance(lexer); if (lexer->lookahead == '/') { return false; } if (lexer->lookahead == '*') { advance(lexer); while (!lexer->eof(lexer)) { if (lexer->lookahead == '*') { advance(lexer); if (lexer->lookahead == '/') { advance(lexer); break; } } else { advance(lexer); } } while (iswspace(lexer->lookahead)) { if (lexer->lookahead == '\n' || lexer->lookahead == '\r') { return false; } skip(lexer); } // If some code is present at the same line after comment end, // we should still produce AUTOMATIC_SEMICOLON, e.g. in // val a = 1 // /* comment */ val b = 2 return true; } } if (valid_symbols[ELSE]) { return !scan_word(lexer, "else"); } if (valid_symbols[CATCH]) { if (scan_word(lexer, "catch")) { return false; } } if (valid_symbols[FINALLY]) { if (scan_word(lexer, "finally")) { return false; } } if (valid_symbols[EXTENDS]) { if (scan_word(lexer, "extends")) { return false; } } if (valid_symbols[WITH]) { if (scan_word(lexer, "with")) { return false; } } if (valid_symbols[DERIVES]) { if (scan_word(lexer, "derives")) { return false; } } if (newline_count > 1) { return true; } // Don't insert automatic semicolon before leading infix operators: // - symbolic, e.g. || or && // - back-ticked, e.g. `in` // Only suppress if the operator is followed by horizontal whitespace // and then non-newline content on the same line, meaning it has an operand. if (is_leading_infix_continuation(lexer)) { return false; } return true; } while (iswspace(lexer->lookahead)) { if (lexer->lookahead == '\n') { newline_count++; } skip(lexer); } if (valid_symbols[SIMPLE_STRING_START] && lexer->lookahead == '"') { advance(lexer); lexer->mark_end(lexer); if (lexer->lookahead == '"') { advance(lexer); if (lexer->lookahead == '"') { advance(lexer); lexer->result_symbol = SIMPLE_MULTILINE_STRING_START; lexer->mark_end(lexer); return true; } } lexer->result_symbol = SIMPLE_STRING_START; return true; } // We need two tokens of lookahead to determine if we are parsing a raw string, // the `raw` and the `"`, which is why we need to do it in the external scanner. if (valid_symbols[RAW_STRING_START] && lexer->lookahead == 'r') { advance(lexer); if (lexer->lookahead == 'a') { advance(lexer); if (lexer->lookahead == 'w') { advance(lexer); if (lexer->lookahead == '"') { lexer->mark_end(lexer); lexer->result_symbol = RAW_STRING_START; return true; } } } } if (valid_symbols[SIMPLE_STRING_MIDDLE]) { return scan_string_content(lexer, false, STRING_MODE_SIMPLE); } if (valid_symbols[INTERPOLATED_STRING_MIDDLE]) { return scan_string_content(lexer, false, STRING_MODE_INTERPOLATED); } if (valid_symbols[RAW_STRING_MIDDLE]) { return scan_string_content(lexer, false, STRING_MODE_RAW); } if (valid_symbols[RAW_STRING_MULTILINE_MIDDLE]) { return scan_string_content(lexer, true, STRING_MODE_RAW); } if (valid_symbols[INTERPOLATED_MULTILINE_STRING_MIDDLE]) { return scan_string_content(lexer, true, STRING_MODE_INTERPOLATED); } // We still need to handle the simple multiline string case, but there is // no `MULTILINE_STRING_MIDDLE` token, and `MULTILINE_STRING_END` is used // by all three of simple raw, and interpolated multiline strings. So this // check needs to come after the `INTERPOLATED_MULTILINE_STRING_MIDDLE` and // `RAW_STRING_MULTILINE_MIDDLE` check, so that we can be sure we are in a // simple multiline string context. if (valid_symbols[MULTILINE_STRING_END]) { return scan_string_content(lexer, true, STRING_MODE_SIMPLE); } return false; } // ================================================ FILE: src/tree_sitter/alloc.h ================================================ #ifndef TREE_SITTER_ALLOC_H_ #define TREE_SITTER_ALLOC_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include // Allow clients to override allocation functions #ifdef TREE_SITTER_REUSE_ALLOCATOR extern void *(*ts_current_malloc)(size_t size); extern void *(*ts_current_calloc)(size_t count, size_t size); extern void *(*ts_current_realloc)(void *ptr, size_t size); extern void (*ts_current_free)(void *ptr); #ifndef ts_malloc #define ts_malloc ts_current_malloc #endif #ifndef ts_calloc #define ts_calloc ts_current_calloc #endif #ifndef ts_realloc #define ts_realloc ts_current_realloc #endif #ifndef ts_free #define ts_free ts_current_free #endif #else #ifndef ts_malloc #define ts_malloc malloc #endif #ifndef ts_calloc #define ts_calloc calloc #endif #ifndef ts_realloc #define ts_realloc realloc #endif #ifndef ts_free #define ts_free free #endif #endif #ifdef __cplusplus } #endif #endif // TREE_SITTER_ALLOC_H_ ================================================ FILE: src/tree_sitter/array.h ================================================ #ifndef TREE_SITTER_ARRAY_H_ #define TREE_SITTER_ARRAY_H_ #ifdef __cplusplus extern "C" { #endif #include "./alloc.h" #include #include #include #include #include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4101) #elif defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" #endif #define Array(T) \ struct { \ T *contents; \ uint32_t size; \ uint32_t capacity; \ } /// Initialize an array. #define array_init(self) \ ((self)->size = 0, (self)->capacity = 0, (self)->contents = NULL) /// Create an empty array. #define array_new() \ { NULL, 0, 0 } /// Get a pointer to the element at a given `index` in the array. #define array_get(self, _index) \ (assert((uint32_t)(_index) < (self)->size), &(self)->contents[_index]) /// Get a pointer to the first element in the array. #define array_front(self) array_get(self, 0) /// Get a pointer to the last element in the array. #define array_back(self) array_get(self, (self)->size - 1) /// Clear the array, setting its size to zero. Note that this does not free any /// memory allocated for the array's contents. #define array_clear(self) ((self)->size = 0) /// Reserve `new_capacity` elements of space in the array. If `new_capacity` is /// less than the array's current capacity, this function has no effect. #define array_reserve(self, new_capacity) \ ((self)->contents = _array__reserve( \ (void *)(self)->contents, &(self)->capacity, \ array_elem_size(self), new_capacity) \ ) /// Free any memory allocated for this array. Note that this does not free any /// memory allocated for the array's contents. #define array_delete(self) \ do { \ if ((self)->contents) ts_free((self)->contents); \ (self)->contents = NULL; \ (self)->size = 0; \ (self)->capacity = 0; \ } while (0) /// Push a new `element` onto the end of the array. #define array_push(self, element) \ do { \ (self)->contents = _array__grow( \ (void *)(self)->contents, (self)->size, &(self)->capacity, \ 1, array_elem_size(self) \ ); \ (self)->contents[(self)->size++] = (element); \ } while(0) /// Increase the array's size by `count` elements. /// New elements are zero-initialized. #define array_grow_by(self, count) \ do { \ if ((count) == 0) break; \ (self)->contents = _array__grow( \ (self)->contents, (self)->size, &(self)->capacity, \ count, array_elem_size(self) \ ); \ memset((self)->contents + (self)->size, 0, (count) * array_elem_size(self)); \ (self)->size += (count); \ } while (0) /// Append all elements from one array to the end of another. #define array_push_all(self, other) \ array_extend((self), (other)->size, (other)->contents) /// Append `count` elements to the end of the array, reading their values from the /// `contents` pointer. #define array_extend(self, count, other_contents) \ (self)->contents = _array__splice( \ (void*)(self)->contents, &(self)->size, &(self)->capacity, \ array_elem_size(self), (self)->size, 0, count, other_contents \ ) /// Remove `old_count` elements from the array starting at the given `index`. At /// the same index, insert `new_count` new elements, reading their values from the /// `new_contents` pointer. #define array_splice(self, _index, old_count, new_count, new_contents) \ (self)->contents = _array__splice( \ (void *)(self)->contents, &(self)->size, &(self)->capacity, \ array_elem_size(self), _index, old_count, new_count, new_contents \ ) /// Insert one `element` into the array at the given `index`. #define array_insert(self, _index, element) \ (self)->contents = _array__splice( \ (void *)(self)->contents, &(self)->size, &(self)->capacity, \ array_elem_size(self), _index, 0, 1, &(element) \ ) /// Remove one element from the array at the given `index`. #define array_erase(self, _index) \ _array__erase((void *)(self)->contents, &(self)->size, array_elem_size(self), _index) /// Pop the last element off the array, returning the element by value. #define array_pop(self) ((self)->contents[--(self)->size]) /// Assign the contents of one array to another, reallocating if necessary. #define array_assign(self, other) \ (self)->contents = _array__assign( \ (void *)(self)->contents, &(self)->size, &(self)->capacity, \ (const void *)(other)->contents, (other)->size, array_elem_size(self) \ ) /// Swap one array with another #define array_swap(self, other) \ do { \ void *_array_swap_tmp = (void *)(self)->contents; \ (self)->contents = (other)->contents; \ (other)->contents = _array_swap_tmp; \ _array__swap(&(self)->size, &(self)->capacity, \ &(other)->size, &(other)->capacity); \ } while (0) /// Get the size of the array contents #define array_elem_size(self) (sizeof *(self)->contents) /// Search a sorted array for a given `needle` value, using the given `compare` /// callback to determine the order. /// /// If an existing element is found to be equal to `needle`, then the `index` /// out-parameter is set to the existing value's index, and the `exists` /// out-parameter is set to true. Otherwise, `index` is set to an index where /// `needle` should be inserted in order to preserve the sorting, and `exists` /// is set to false. #define array_search_sorted_with(self, compare, needle, _index, _exists) \ _array__search_sorted(self, 0, compare, , needle, _index, _exists) /// Search a sorted array for a given `needle` value, using integer comparisons /// of a given struct field (specified with a leading dot) to determine the order. /// /// See also `array_search_sorted_with`. #define array_search_sorted_by(self, field, needle, _index, _exists) \ _array__search_sorted(self, 0, _compare_int, field, needle, _index, _exists) /// Insert a given `value` into a sorted array, using the given `compare` /// callback to determine the order. #define array_insert_sorted_with(self, compare, value) \ do { \ unsigned _index, _exists; \ array_search_sorted_with(self, compare, &(value), &_index, &_exists); \ if (!_exists) array_insert(self, _index, value); \ } while (0) /// Insert a given `value` into a sorted array, using integer comparisons of /// a given struct field (specified with a leading dot) to determine the order. /// /// See also `array_search_sorted_by`. #define array_insert_sorted_by(self, field, value) \ do { \ unsigned _index, _exists; \ array_search_sorted_by(self, field, (value) field, &_index, &_exists); \ if (!_exists) array_insert(self, _index, value); \ } while (0) // Private // Pointers to individual `Array` fields (rather than the entire `Array` itself) // are passed to the various `_array__*` functions below to address strict aliasing // violations that arises when the _entire_ `Array` struct is passed as `Array(void)*`. // // The `Array` type itself was not altered as a solution in order to avoid breakage // with existing consumers (in particular, parsers with external scanners). /// This is not what you're looking for, see `array_erase`. static inline void _array__erase(void* self_contents, uint32_t *size, size_t element_size, uint32_t index) { assert(index < *size); char *contents = (char *)self_contents; memmove(contents + index * element_size, contents + (index + 1) * element_size, (*size - index - 1) * element_size); (*size)--; } /// This is not what you're looking for, see `array_reserve`. static inline void *_array__reserve(void *contents, uint32_t *capacity, size_t element_size, uint32_t new_capacity) { void *new_contents = contents; if (new_capacity > *capacity) { if (contents) { new_contents = ts_realloc(contents, new_capacity * element_size); } else { new_contents = ts_malloc(new_capacity * element_size); } *capacity = new_capacity; } return new_contents; } /// This is not what you're looking for, see `array_assign`. static inline void *_array__assign(void* self_contents, uint32_t *self_size, uint32_t *self_capacity, const void *other_contents, uint32_t other_size, size_t element_size) { void *new_contents = _array__reserve(self_contents, self_capacity, element_size, other_size); *self_size = other_size; memcpy(new_contents, other_contents, *self_size * element_size); return new_contents; } /// This is not what you're looking for, see `array_swap`. static inline void _array__swap(uint32_t *self_size, uint32_t *self_capacity, uint32_t *other_size, uint32_t *other_capacity) { uint32_t tmp_size = *self_size; uint32_t tmp_capacity = *self_capacity; *self_size = *other_size; *self_capacity = *other_capacity; *other_size = tmp_size; *other_capacity = tmp_capacity; } /// This is not what you're looking for, see `array_push` or `array_grow_by`. static inline void *_array__grow(void *contents, uint32_t size, uint32_t *capacity, uint32_t count, size_t element_size) { void *new_contents = contents; uint32_t new_size = size + count; if (new_size > *capacity) { uint32_t new_capacity = *capacity * 2; if (new_capacity < 8) new_capacity = 8; if (new_capacity < new_size) new_capacity = new_size; new_contents = _array__reserve(contents, capacity, element_size, new_capacity); } return new_contents; } /// This is not what you're looking for, see `array_splice`. static inline void *_array__splice(void *self_contents, uint32_t *size, uint32_t *capacity, size_t element_size, uint32_t index, uint32_t old_count, uint32_t new_count, const void *elements) { uint32_t new_size = *size + new_count - old_count; uint32_t old_end = index + old_count; uint32_t new_end = index + new_count; assert(old_end <= *size); void *new_contents = _array__reserve(self_contents, capacity, element_size, new_size); char *contents = (char *)new_contents; if (*size > old_end) { memmove( contents + new_end * element_size, contents + old_end * element_size, (*size - old_end) * element_size ); } if (new_count > 0) { if (elements) { memcpy( (contents + index * element_size), elements, new_count * element_size ); } else { memset( (contents + index * element_size), 0, new_count * element_size ); } } *size += new_count - old_count; return new_contents; } /// A binary search routine, based on Rust's `std::slice::binary_search_by`. /// This is not what you're looking for, see `array_search_sorted_with` or `array_search_sorted_by`. #define _array__search_sorted(self, start, compare, suffix, needle, _index, _exists) \ do { \ *(_index) = start; \ *(_exists) = false; \ uint32_t size = (self)->size - *(_index); \ if (size == 0) break; \ int comparison; \ while (size > 1) { \ uint32_t half_size = size / 2; \ uint32_t mid_index = *(_index) + half_size; \ comparison = compare(&((self)->contents[mid_index] suffix), (needle)); \ if (comparison <= 0) *(_index) = mid_index; \ size -= half_size; \ } \ comparison = compare(&((self)->contents[*(_index)] suffix), (needle)); \ if (comparison == 0) *(_exists) = true; \ else if (comparison < 0) *(_index) += 1; \ } while (0) /// Helper macro for the `_sorted_by` routines below. This takes the left (existing) /// parameter by reference in order to work with the generic sorting function above. #define _compare_int(a, b) ((int)*(a) - (int)(b)) #ifdef _MSC_VER #pragma warning(pop) #elif defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic pop #endif #ifdef __cplusplus } #endif #endif // TREE_SITTER_ARRAY_H_ ================================================ FILE: src/tree_sitter/parser.h ================================================ #ifndef TREE_SITTER_PARSER_H_ #define TREE_SITTER_PARSER_H_ #ifdef __cplusplus extern "C" { #endif #include #include #include #define ts_builtin_sym_error ((TSSymbol)-1) #define ts_builtin_sym_end 0 #define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024 #ifndef TREE_SITTER_API_H_ typedef uint16_t TSStateId; typedef uint16_t TSSymbol; typedef uint16_t TSFieldId; typedef struct TSLanguage TSLanguage; typedef struct TSLanguageMetadata { uint8_t major_version; uint8_t minor_version; uint8_t patch_version; } TSLanguageMetadata; #endif typedef struct { TSFieldId field_id; uint8_t child_index; bool inherited; } TSFieldMapEntry; // Used to index the field and supertype maps. typedef struct { uint16_t index; uint16_t length; } TSMapSlice; typedef struct { bool visible; bool named; bool supertype; } TSSymbolMetadata; typedef struct TSLexer TSLexer; struct TSLexer { int32_t lookahead; TSSymbol result_symbol; void (*advance)(TSLexer *, bool); void (*mark_end)(TSLexer *); uint32_t (*get_column)(TSLexer *); bool (*is_at_included_range_start)(const TSLexer *); bool (*eof)(const TSLexer *); void (*log)(const TSLexer *, const char *, ...); }; typedef enum { TSParseActionTypeShift, TSParseActionTypeReduce, TSParseActionTypeAccept, TSParseActionTypeRecover, } TSParseActionType; typedef union { struct { uint8_t type; TSStateId state; bool extra; bool repetition; } shift; struct { uint8_t type; uint8_t child_count; TSSymbol symbol; int16_t dynamic_precedence; uint16_t production_id; } reduce; uint8_t type; } TSParseAction; typedef struct { uint16_t lex_state; uint16_t external_lex_state; } TSLexMode; typedef struct { uint16_t lex_state; uint16_t external_lex_state; uint16_t reserved_word_set_id; } TSLexerMode; typedef union { TSParseAction action; struct { uint8_t count; bool reusable; } entry; } TSParseActionEntry; typedef struct { int32_t start; int32_t end; } TSCharacterRange; struct TSLanguage { uint32_t abi_version; uint32_t symbol_count; uint32_t alias_count; uint32_t token_count; uint32_t external_token_count; uint32_t state_count; uint32_t large_state_count; uint32_t production_id_count; uint32_t field_count; uint16_t max_alias_sequence_length; const uint16_t *parse_table; const uint16_t *small_parse_table; const uint32_t *small_parse_table_map; const TSParseActionEntry *parse_actions; const char * const *symbol_names; const char * const *field_names; const TSMapSlice *field_map_slices; const TSFieldMapEntry *field_map_entries; const TSSymbolMetadata *symbol_metadata; const TSSymbol *public_symbol_map; const uint16_t *alias_map; const TSSymbol *alias_sequences; const TSLexerMode *lex_modes; bool (*lex_fn)(TSLexer *, TSStateId); bool (*keyword_lex_fn)(TSLexer *, TSStateId); TSSymbol keyword_capture_token; struct { const bool *states; const TSSymbol *symbol_map; void *(*create)(void); void (*destroy)(void *); bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist); unsigned (*serialize)(void *, char *); void (*deserialize)(void *, const char *, unsigned); } external_scanner; const TSStateId *primary_state_ids; const char *name; const TSSymbol *reserved_words; uint16_t max_reserved_word_set_size; uint32_t supertype_count; const TSSymbol *supertype_symbols; const TSMapSlice *supertype_map_slices; const TSSymbol *supertype_map_entries; TSLanguageMetadata metadata; }; static inline bool set_contains(const TSCharacterRange *ranges, uint32_t len, int32_t lookahead) { uint32_t index = 0; uint32_t size = len - index; while (size > 1) { uint32_t half_size = size / 2; uint32_t mid_index = index + half_size; const TSCharacterRange *range = &ranges[mid_index]; if (lookahead >= range->start && lookahead <= range->end) { return true; } else if (lookahead > range->end) { index = mid_index; } size -= half_size; } const TSCharacterRange *range = &ranges[index]; return (lookahead >= range->start && lookahead <= range->end); } /* * Lexer Macros */ #ifdef _MSC_VER #define UNUSED __pragma(warning(suppress : 4101)) #else #define UNUSED __attribute__((unused)) #endif #define START_LEXER() \ bool result = false; \ bool skip = false; \ UNUSED \ bool eof = false; \ int32_t lookahead; \ goto start; \ next_state: \ lexer->advance(lexer, skip); \ start: \ skip = false; \ lookahead = lexer->lookahead; #define ADVANCE(state_value) \ { \ state = state_value; \ goto next_state; \ } #define ADVANCE_MAP(...) \ { \ static const uint16_t map[] = { __VA_ARGS__ }; \ for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ if (map[i] == lookahead) { \ state = map[i + 1]; \ goto next_state; \ } \ } \ } #define SKIP(state_value) \ { \ skip = true; \ state = state_value; \ goto next_state; \ } #define ACCEPT_TOKEN(symbol_value) \ result = true; \ lexer->result_symbol = symbol_value; \ lexer->mark_end(lexer); #define END_STATE() return result; /* * Parse Table Macros */ #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) #define STATE(id) id #define ACTIONS(id) id #define SHIFT(state_value) \ {{ \ .shift = { \ .type = TSParseActionTypeShift, \ .state = (state_value) \ } \ }} #define SHIFT_REPEAT(state_value) \ {{ \ .shift = { \ .type = TSParseActionTypeShift, \ .state = (state_value), \ .repetition = true \ } \ }} #define SHIFT_EXTRA() \ {{ \ .shift = { \ .type = TSParseActionTypeShift, \ .extra = true \ } \ }} #define REDUCE(symbol_name, children, precedence, prod_id) \ {{ \ .reduce = { \ .type = TSParseActionTypeReduce, \ .symbol = symbol_name, \ .child_count = children, \ .dynamic_precedence = precedence, \ .production_id = prod_id \ }, \ }} #define RECOVER() \ {{ \ .type = TSParseActionTypeRecover \ }} #define ACCEPT_INPUT() \ {{ \ .type = TSParseActionTypeAccept \ }} #ifdef __cplusplus } #endif #endif // TREE_SITTER_PARSER_H_ ================================================ FILE: test/corpus/annotations.txt ================================================ ================================ Classes ================================ @deprecated("Use D", "1.0") class C {} --- (compilation_unit (class_definition (annotation (type_identifier) (arguments (string) (string))) (identifier) (template_body))) ================================ Declarations and definitions ================================ class A(x: String) { @transient @volatile var y: Int @transient @volatile val z = x @throws(Error) @deprecated(message = "Don't use this", since = "1.0") def foo() {} } --- (compilation_unit (class_definition (identifier) (class_parameters (class_parameter (identifier) (type_identifier))) (template_body (var_declaration (annotation (type_identifier)) (annotation (type_identifier)) (identifier) (type_identifier)) (val_definition (annotation (type_identifier)) (annotation (type_identifier)) (identifier) (identifier)) (function_definition (annotation (type_identifier) (arguments (identifier))) (annotation (type_identifier) (arguments (assignment_expression (identifier) (string)) (assignment_expression (identifier) (string)))) (identifier) (parameters) (block))))) ================================ Parameters ================================ class A(@one x: String) { def foo(@another x: Int) {} } --- (compilation_unit (class_definition (identifier) (class_parameters (class_parameter (annotation (type_identifier)) (identifier) (type_identifier))) (template_body (function_definition (identifier) (parameters (parameter (annotation (type_identifier)) (identifier) (type_identifier))) (block))))) ================================ Types ================================ trait Function0[@specialized(Unit, Int, Double) T] { def apply: T } --- (compilation_unit (trait_definition (identifier) (type_parameters (annotation (type_identifier) (arguments (identifier) (identifier) (identifier))) (identifier)) (template_body (function_declaration (identifier) (type_identifier))))) ================================================ FILE: test/corpus/comments.txt ================================================ ================================================================================ Single line comments ================================================================================ // comment 1 // comment 2 -------------------------------------------------------------------------------- (compilation_unit (comment) (comment)) ================================================================================ Block comments ================================================================================ /**/ /** comment 1 * /* comment 2 * /* / * * /comment 3 */ // comment 4 * @param * */ */ -------------------------------------------------------------------------------- (compilation_unit (block_comment) (block_comment (block_comment (block_comment)))) ================================================================================ Single line comments with block comment ================================================================================ // /* // * This is awesome comment // */ -------------------------------------------------------------------------------- (compilation_unit (comment) (comment) (comment)) ================================================================================ Block comment with single-line comment inside ================================================================================ /* // */ -------------------------------------------------------------------------------- (compilation_unit (block_comment)) ================================================================================ Using directives ================================================================================ //> using jvm graalvm:21 //> using scala 3.3.0 //> using dep foo:bar:1,2,3,url=https://github.com //> using exclude "examples/*" "*/resources/*" // > just a comment -------------------------------------------------------------------------------- (compilation_unit (comment (using_directive (using_directive_key) (using_directive_value))) (comment (using_directive (using_directive_key) (using_directive_value))) (comment (using_directive (using_directive_key) (using_directive_value))) (comment (using_directive (using_directive_key) (using_directive_value))) (comment)) ================================================================================ Shebang ================================================================================ #!/usr/bin/env -S scala-cli shebang -S 3 "shebang" -------------------------------------------------------------------------------- (compilation_unit (comment) (string)) ================================================ FILE: test/corpus/definitions-pending.txt ================================================ ================================================================================ Function without parens :skip ================================================================================ // https://github.com/scala/scala3/blob/main/tests/pos/multiLineOps.scala#L15 send_! "!" -------------------------------------------------------------------------------- ================================================ FILE: test/corpus/definitions.txt ================================================ ================================================================================ Identifiers ================================================================================ def m = ??? def unary_! = true def a_-> = ??? def __symtem = ??? def empty_? = ??? def ひらがな = ??? def a_^ = ??? -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (operator_identifier)) (function_definition (identifier) (boolean_literal)) (function_definition (identifier) (operator_identifier)) (function_definition (identifier) (operator_identifier)) (function_definition (identifier) (operator_identifier)) (function_definition (identifier) (operator_identifier)) (function_definition (identifier) (operator_identifier))) ================================================================================ $ in identifier names ================================================================================ class $A$B$ { val b$, c$ : Int val d$ : String } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (val_declaration (identifier) (identifier) (type_identifier)) (val_declaration (identifier) (type_identifier))))) ================================================================================ Operator identifiers ================================================================================ type ::[+Ab] = scala.collection.immutable.::[Ab] val :: = scala.collection.immutable.:: val +: = scala.collection.+: val :+ = scala.collection.:+ def → = ??? val test = id.## val x = y ///////// // avoid matching slashes as operator ///////// -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (type_parameters (covariant_type_parameter (identifier))) (generic_type (stable_type_identifier (stable_identifier (stable_identifier (identifier) (identifier)) (identifier)) (type_identifier)) (type_arguments (type_identifier)))) (val_definition (operator_identifier) (field_expression (field_expression (field_expression (identifier) (identifier)) (identifier)) (operator_identifier))) (val_definition (operator_identifier) (field_expression (field_expression (identifier) (identifier)) (operator_identifier))) (val_definition (operator_identifier) (field_expression (field_expression (identifier) (identifier)) (operator_identifier))) (function_definition (operator_identifier) (operator_identifier)) (val_definition (identifier) (field_expression (identifier) (operator_identifier))) (val_definition (identifier) (identifier)) (comment) (comment) (comment)) ================================================================================ Package ================================================================================ package a.b package c { object A } package d { package e { object B } } -------------------------------------------------------------------------------- (compilation_unit (package_clause (package_identifier (identifier) (identifier))) (package_clause (package_identifier (identifier)) (template_body (object_definition (identifier)))) (package_clause (package_identifier (identifier)) (template_body (package_clause (package_identifier (identifier)) (template_body (object_definition (identifier))))))) ================================================================================ Package with comma ================================================================================ package a.b; -------------------------------------------------------------------------------- (compilation_unit (package_clause (package_identifier (identifier) (identifier)))) ================================================================================ Package (Scala 3 syntax) ================================================================================ package a.b package c: object A package d: object A end d -------------------------------------------------------------------------------- (compilation_unit (package_clause (package_identifier (identifier) (identifier))) (package_clause (package_identifier (identifier)) (template_body (object_definition (identifier)))) (package_clause (package_identifier (identifier)) (template_body (object_definition (identifier))))) ================================================================================ Package object ================================================================================ package object d extends A { val hello: String = "there" } package object p1 { package object p2 { val a = 1 } } -------------------------------------------------------------------------------- (compilation_unit (package_object (identifier) (extends_clause (type_identifier)) (template_body (val_definition (identifier) (type_identifier) (string)))) (package_object (identifier) (template_body (package_object (identifier) (template_body (val_definition (identifier) (integer_literal))))))) ================================================================================ Imports ================================================================================ import PartialFunction.condOpt import a.b, c.e import reflect.io.{Directory, File, Path} import a.{ b, } import Opts.+ import a.{ :: } -------------------------------------------------------------------------------- (compilation_unit (import_declaration (identifier) (identifier)) (import_declaration (identifier) (identifier) (identifier) (identifier)) (import_declaration (identifier) (identifier) (namespace_selectors (identifier) (identifier) (identifier))) (import_declaration (identifier) (namespace_selectors (identifier))) (import_declaration (identifier) (operator_identifier)) (import_declaration (identifier) (namespace_selectors (operator_identifier)))) ================================================================================ Imports: Wildcard ================================================================================ import tools.nsc.classpath._ -------------------------------------------------------------------------------- (compilation_unit (import_declaration (identifier) (identifier) (identifier) (namespace_wildcard))) ================================================================================ Imports: Wildcard (Scala 3 syntax) ================================================================================ import tools.nsc.classpath.* import a.b.*, b.c, c.* -------------------------------------------------------------------------------- (compilation_unit (import_declaration (identifier) (identifier) (identifier) (namespace_wildcard)) (import_declaration (identifier) (identifier) (namespace_wildcard) (identifier) (identifier) (identifier) (namespace_wildcard))) ================================================================================ Imports: Wildcard and wildcard givens (Scala 3 syntax) ================================================================================ import tools.nsc.classpath.{*, given} import tools.given -------------------------------------------------------------------------------- (compilation_unit (import_declaration (identifier) (identifier) (identifier) (namespace_selectors (namespace_wildcard) (namespace_wildcard))) (import_declaration (identifier) (namespace_wildcard))) ================================================================================ Imports: Givens by type (Scala 3 syntax) ================================================================================ import tools.nsc.classpath.{given Test, given Test2, Test3} -------------------------------------------------------------------------------- (compilation_unit (import_declaration (identifier) (identifier) (identifier) (namespace_selectors (type_identifier) (type_identifier) (identifier)))) ================================================================================ Imports: Rename (Scala 3 Syntax) ================================================================================ import lang.System.{lineSeparator as EOL} import lang.System.lineSeparator as EOL import lang.System.lineSeparator as _ import lineSeparator as ls -------------------------------------------------------------------------------- (compilation_unit (import_declaration (identifier) (identifier) (namespace_selectors (as_renamed_identifier (identifier) (identifier)))) (import_declaration (identifier) (identifier) (as_renamed_identifier (identifier) (identifier))) (import_declaration (identifier) (identifier) (as_renamed_identifier (identifier) (wildcard))) (import_declaration (as_renamed_identifier (identifier) (identifier)))) ================================================================================ Imports: Rename ================================================================================ import lang.System.{lineSeparator => EOL} import lang.System.{lineSeparator => _} -------------------------------------------------------------------------------- (compilation_unit (import_declaration (identifier) (identifier) (namespace_selectors (arrow_renamed_identifier (identifier) (identifier)))) (import_declaration (identifier) (identifier) (namespace_selectors (arrow_renamed_identifier (identifier) (wildcard))))) ================================================================================ Object definitions ================================================================================ // o1 object O1 { } case object O2 { } object O3 extends A { } object O4 extends { val a: A = b } object O5 { ;; ; ; } -------------------------------------------------------------------------------- (compilation_unit (comment) (object_definition (identifier) (template_body)) (object_definition (identifier) (template_body)) (object_definition (identifier) (extends_clause (type_identifier)) (template_body)) (object_definition (identifier) (extends_clause (structural_type (val_definition (identifier) (type_identifier) (identifier))))) (object_definition (identifier) (template_body))) ================================================================================ Object definitions ================================================================================ case object A extends B derives C, D {} -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (extends_clause (type_identifier)) (derives_clause (type_identifier) (type_identifier)) (template_body))) ================================================================================ Class definitions ================================================================================ class C[ T, U, ](a: => A, b: B, c: C*) { } class A () () {} -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (type_parameters (identifier) (identifier)) (class_parameters (class_parameter (identifier) (lazy_parameter_type (type_identifier))) (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (repeated_parameter_type (type_identifier)))) (template_body)) (class_definition (identifier) (class_parameters) (class_parameters) (template_body))) ================================================================================ Class definitions (Scala 3) ================================================================================ final case class C() extends A derives B, C.D -------------------------------------------------------------------------------- (compilation_unit (class_definition (modifiers) (identifier) (class_parameters) (extends_clause (type_identifier)) (derives_clause (type_identifier) (stable_type_identifier (identifier) (type_identifier))))) ================================================================================ Subclass definitions ================================================================================ class A extends B.C[D, E] { } class A(b: B) extends C(b || ok) { } object C { class A extends B[T] with C[T] } class D(c: String) extends E(c) with F class MyClass extends Potato() with Tomato class A extends B(c)(d)(e) -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (extends_clause (generic_type (stable_type_identifier (identifier) (type_identifier)) (type_arguments (type_identifier) (type_identifier)))) (template_body)) (class_definition (identifier) (class_parameters (class_parameter (identifier) (type_identifier))) (extends_clause (type_identifier) (arguments (infix_expression (identifier) (operator_identifier) (identifier)))) (template_body)) (object_definition (identifier) (template_body (class_definition (identifier) (extends_clause (generic_type (type_identifier) (type_arguments (type_identifier))) (generic_type (type_identifier) (type_arguments (type_identifier))))))) (class_definition (identifier) (class_parameters (class_parameter (identifier) (type_identifier))) (extends_clause (type_identifier) (arguments (identifier)) (type_identifier))) (class_definition (identifier) (extends_clause (type_identifier) (arguments) (type_identifier))) (class_definition (identifier) (extends_clause (type_identifier) (arguments (identifier)) (arguments (identifier)) (arguments (identifier))))) ================================================================================ Subclass definitions (Scala 3 syntax) ================================================================================ class A extends B, C: 1 end A -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (extends_clause (type_identifier) (type_identifier)) (template_body (integer_literal)))) ================================================================================ Class definitions with parameters ================================================================================ class Point( val x: Int, val y: Int, )(implicit coord: Coord) class A @Inject()(x: Int, y: Int) class A @ann() (x: Int, y: Int) class A @ann ()(x: Int, y: Int) -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (class_parameters (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (type_identifier))) (class_parameters (class_parameter (identifier) (type_identifier)))) (class_definition (identifier) (annotation (type_identifier) (arguments) (arguments)) (class_parameters (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (type_identifier)))) (class_definition (identifier) (annotation (type_identifier) (arguments) (arguments)) (class_parameters (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (type_identifier)))) (class_definition (identifier) (annotation (type_identifier)) (class_parameters) (class_parameters (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (type_identifier))))) ================================================================================ Class definitions with parameters (Scala 3 syntax) ================================================================================ class Point(val x: Int, val y: Int)(using coord: Coord) class A @ann (x: Int, y: Int) class A @ann(1) (x: Int, y: Int) -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (class_parameters (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (type_identifier))) (class_parameters (class_parameter (identifier) (type_identifier)))) (class_definition (identifier) (annotation (type_identifier)) (class_parameters (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (type_identifier)))) (class_definition (identifier) (annotation (type_identifier) (arguments) (arguments (integer_literal)) (arguments)) (class_parameters (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (type_identifier))))) ================================================================================ Modifiers ================================================================================ implicit final sealed class Point { private override def getX() = 1 } private[a] class D[T] private (x: T) { private[a] def b: Byte } -------------------------------------------------------------------------------- (compilation_unit (class_definition (modifiers) (identifier) (template_body (function_definition (modifiers (access_modifier)) (identifier) (parameters) (integer_literal)))) (class_definition (modifiers (access_modifier (access_qualifier (identifier)))) (identifier) (type_parameters (identifier)) (access_modifier) (class_parameters (class_parameter (identifier) (type_identifier))) (template_body (function_declaration (modifiers (access_modifier (access_qualifier (identifier)))) (identifier) (type_identifier))))) ================================================================================ Trait definitions ================================================================================ trait A extends B trait A extends B with C derives D trait T[U] { } trait T[U] extends V.W[U] { } -------------------------------------------------------------------------------- (compilation_unit (trait_definition (identifier) (extends_clause (type_identifier))) (trait_definition (identifier) (extends_clause (type_identifier) (type_identifier)) (derives_clause (type_identifier))) (trait_definition (identifier) (type_parameters (identifier)) (template_body)) (trait_definition (identifier) (type_parameters (identifier)) (extends_clause (generic_type (stable_type_identifier (identifier) (type_identifier)) (type_arguments (type_identifier)))) (template_body))) ================================================================================ Value declarations ================================================================================ class A { val b, c : Int val d : String } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (val_declaration (identifier) (identifier) (type_identifier)) (val_declaration (identifier) (type_identifier))))) ================================================================================ Value declarations (Scala 3 syntax) ================================================================================ class A: // Comments that should not // influence indentation val b, c : Int val d : String -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (comment) (comment) (val_declaration (identifier) (identifier) (type_identifier)) (val_declaration (identifier) (type_identifier))))) ================================================================================ Value definitions ================================================================================ class A { val b = 1 val c : String = "d" val a, b, c: T3 = triple var a, b, c = triple } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (val_definition (identifier) (integer_literal)) (val_definition (identifier) (type_identifier) (string)) (val_definition (identifiers (identifier) (identifier) (identifier)) (type_identifier) (identifier)) (var_definition (identifiers (identifier) (identifier) (identifier)) (identifier))))) ================================================================================ Variable declarations ================================================================================ class A { var b, c : Int var d : String } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (var_declaration (identifier) (identifier) (type_identifier)) (var_declaration (identifier) (type_identifier))))) ================================================================================ Variable definitions ================================================================================ class A { var b : Int = 1 } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (var_definition (identifier) (type_identifier) (integer_literal))))) ================================================================================ Variable definitions (Scala 3 syntax) ================================================================================ class A: var b: Int = 1 var c: Int = val d = 2 d -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (var_definition (identifier) (type_identifier) (integer_literal)) (var_definition (identifier) (type_identifier) (indented_block (val_definition (identifier) (integer_literal)) (identifier)))))) ================================================================================ Type definitions ================================================================================ class A { type B = C type D[E] = F type Abs type Beta[B] } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (type_definition (type_identifier) (type_identifier)) (type_definition (type_identifier) (type_parameters (identifier)) (type_identifier)) (type_definition (type_identifier)) (type_definition (type_identifier) (type_parameters (identifier)))))) ================================================================================ Type definitions (Scala 3 syntax) ================================================================================ class A: type Element: Order -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (type_definition (type_identifier) (context_bound (type_identifier)))))) ================================================================================ Function declarations ================================================================================ class A { def b(c: D) : E def <*[B](that: IO[B]): IO[A] def c (a: A): B } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_declaration (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier)) (function_declaration (operator_identifier) (type_parameters (identifier)) (parameters (parameter (identifier) (generic_type (type_identifier) (type_arguments (type_identifier))))) (generic_type (type_identifier) (type_arguments (type_identifier)))) (function_declaration (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier))))) ================================================================================ Function definitions ================================================================================ class A { def b( c: D, e: F, ) = 1 def l: Int = 1 def m = () def n(using a: A) (using B <:< B, C =:= C) = () def o() : Int = 42 } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters (parameter (identifier) (type_identifier)) (parameter (identifier) (type_identifier))) (integer_literal)) (function_definition (identifier) (type_identifier) (indented_block (integer_literal))) (function_definition (identifier) (unit)) (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (parameters (infix_type (type_identifier) (operator_identifier) (type_identifier)) (infix_type (type_identifier) (operator_identifier) (type_identifier))) (unit)) (function_definition (identifier) (parameters) (type_identifier) (integer_literal))))) ================================================================================ Function definitions (Scala 3 syntax) ================================================================================ class A: def foo(c: C): Int = val x = 1 val y = 2 x + y // SIP-47 - Clause Interleaving def getOrElse(k: Key)[V >: k.Value](default: V): V def aaa[A](using a: A)(b: List[A])[C <: a.type, D](cd: (C, D))[E]: Unit -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (indented_block (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal)) (infix_expression (identifier) (operator_identifier) (identifier)) (comment))) (function_declaration (identifier) (parameters (parameter (identifier) (type_identifier))) (type_parameters (identifier) (lower_bound (stable_type_identifier (identifier) (type_identifier)))) (parameters (parameter (identifier) (type_identifier))) (type_identifier)) (function_declaration (identifier) (type_parameters (identifier)) (parameters (parameter (identifier) (type_identifier))) (parameters (parameter (identifier) (generic_type (type_identifier) (type_arguments (type_identifier))))) (type_parameters (identifier) (upper_bound (singleton_type (identifier))) (identifier)) (parameters (parameter (identifier) (tuple_type (type_identifier) (type_identifier)))) (type_parameters (identifier)) (type_identifier))))) ================================================================================ Extension methods (Scala 3 syntax) ================================================================================ object A: extension (c: C) def foo: Int = 1 extension [A1](d: D) def foo = "foo" trait B: extension (x: Int) def bar: String -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (extension_definition (parameters (parameter (identifier) (type_identifier))) (function_definition (identifier) (type_identifier) (integer_literal))) (extension_definition (type_parameters (identifier)) (parameters (parameter (identifier) (type_identifier))) (function_definition (identifier) (string))))) (trait_definition (identifier) (template_body (extension_definition (parameters (parameter (identifier) (type_identifier))) (function_declaration (identifier) (type_identifier)))))) ================================================================================ Given instance definitions (Scala 3 syntax) ================================================================================ object A: given a: A = x given intFoo: CanFoo[Int] with def foo(x: Int): Int = 0 given intFoo: CanFoo[Int]: def foo(x: Int): Int = 0 given CanFoo[Int] with def foo(x: Int): Int = 0 private given listFoo[A1](using ev: CanFoo[A1]): CanFoo[List[A1]] with def foo(xs: List[A1]): Int = 0 given foo(using ev: Foo) : Foo = ev given Context = ctx given Context[T] = ctx given Foo[Int] = case n => "123" given (using a: Int): Int = a given [A: Foo]: Foo[List[A]] with def x = () given [A](using Foo[A]): Foo[List[A]] with def x = () trait B: given c: Context[T] given (config: Config) => Factory = ConcreteFactory() given lila.db.NoDbHandler[GoodPercent] with {} -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (given_definition (identifier) (type_identifier) (identifier)) (given_definition (identifier) (generic_type (type_identifier) (type_arguments (type_identifier))) (with_template_body (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (integer_literal)))) (given_definition (identifier) (generic_type (type_identifier) (type_arguments (type_identifier))) (with_template_body (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (integer_literal)))) (given_definition (generic_type (type_identifier) (type_arguments (type_identifier))) (with_template_body (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (integer_literal)))) (given_definition (modifiers (access_modifier)) (identifier) (type_parameters (identifier)) (parameters (parameter (identifier) (generic_type (type_identifier) (type_arguments (type_identifier))))) (generic_type (type_identifier) (type_arguments (generic_type (type_identifier) (type_arguments (type_identifier))))) (with_template_body (function_definition (identifier) (parameters (parameter (identifier) (generic_type (type_identifier) (type_arguments (type_identifier))))) (type_identifier) (integer_literal)))) (given_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (identifier)) (given_definition (type_identifier) (identifier)) (given_definition (generic_type (type_identifier) (type_arguments (type_identifier))) (identifier)) (given_definition (generic_type (type_identifier) (type_arguments (type_identifier))) (indented_cases (case_clause (identifier) (string)))) (given_definition (parameters (parameter (identifier) (type_identifier))) (type_identifier) (identifier)) (given_definition (type_parameters (identifier) (context_bound (type_identifier))) (generic_type (type_identifier) (type_arguments (generic_type (type_identifier) (type_arguments (type_identifier))))) (with_template_body (function_definition (identifier) (unit)))) (given_definition (type_parameters (identifier)) (parameters (generic_type (type_identifier) (type_arguments (type_identifier)))) (generic_type (type_identifier) (type_arguments (generic_type (type_identifier) (type_arguments (type_identifier))))) (with_template_body (function_definition (identifier) (unit)))) (trait_definition (identifier) (template_body (given_definition (identifier) (generic_type (type_identifier) (type_arguments (type_identifier)))))) (given_definition (given_conditional (parameter (identifier) (type_identifier))) (type_identifier) (call_expression (identifier) (arguments))) (given_definition (generic_type (stable_type_identifier (stable_identifier (identifier) (identifier)) (type_identifier)) (type_arguments (type_identifier))) (with_template_body))))) ================================================================================ Given with type parameters (Scala 3.4+ syntax) ================================================================================ object A: given [T: Foo as bar] => Serde[T] = x given [T <: M] => (config: K) => Serde[T] = x -------------------------------------------------------------------------------- (compilation_unit (object_definition name: (identifier) body: (template_body (given_definition (type_parameters name: (identifier) bound: (context_bound type: (type_identifier) name: (identifier))) return_type: (generic_type type: (type_identifier) type_arguments: (type_arguments (type_identifier))) body: (identifier)) (given_definition (type_parameters name: (identifier) bound: (upper_bound type: (type_identifier))) (given_conditional (parameter name: (identifier) type: (type_identifier))) return_type: (generic_type type: (type_identifier) type_arguments: (type_arguments (type_identifier))) body: (identifier))))) ================================================================================ Class with using type-only parameters (Scala 3 syntax) ================================================================================ class Foo(x: Int)(using A, B, Runtime[Any]) extends Bar -------------------------------------------------------------------------------- (compilation_unit (class_definition name: (identifier) class_parameters: (class_parameters (class_parameter name: (identifier) type: (type_identifier))) class_parameters: (class_parameters type: (type_identifier) type: (type_identifier) type: (generic_type type: (type_identifier) type_arguments: (type_arguments (type_identifier)))) extend: (extends_clause type: (type_identifier)))) ================================================================================ Top-level Definitions (Scala 3 syntax) ================================================================================ class A: def a() = () def a() = 1 -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters) (indented_block (unit))))) (function_definition (identifier) (parameters) (integer_literal))) ================================================================================ Initialization expressions ================================================================================ class A(val x: Int, val y: Int) { assert(x != 0) } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (class_parameters (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (type_identifier))) (template_body (call_expression (identifier) (arguments (infix_expression (identifier) (operator_identifier) (integer_literal))))))) ================================================================================ Optional parameters ================================================================================ def mkLines(header: String, indented: Boolean = false, repeated: Long = 0L): String = {} -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters (parameter (identifier) (type_identifier)) (parameter (identifier) (type_identifier) (boolean_literal)) (parameter (identifier) (type_identifier) (integer_literal))) (type_identifier) (block))) ================================================================================ Enums (Scala 3) ================================================================================ @A private enum Hello[Y] extends java.Enumeration derives Codec, Eq { @A("") @B case World, You @A case Test[A](bla: Int, yo: String) extends Hello[A] case T extends Hello[String](25) } -------------------------------------------------------------------------------- (compilation_unit (enum_definition (annotation (type_identifier)) (modifiers (access_modifier)) (identifier) (type_parameters (identifier)) (extends_clause (stable_type_identifier (identifier) (type_identifier))) (derives_clause (type_identifier) (type_identifier)) (enum_body (enum_case_definitions (annotation (type_identifier) (arguments (string))) (annotation (type_identifier)) (simple_enum_case (identifier)) (simple_enum_case (identifier))) (enum_case_definitions (annotation (type_identifier)) (full_enum_case (identifier) (type_parameters (identifier)) (class_parameters (class_parameter (identifier) (type_identifier)) (class_parameter (identifier) (type_identifier))) (extends_clause (generic_type (type_identifier) (type_arguments (type_identifier)))))) (enum_case_definitions (simple_enum_case (identifier) (extends_clause (generic_type (type_identifier) (type_arguments (type_identifier))) (arguments (integer_literal)))))))) ================================================================================ Self types ================================================================================ trait A { self => def f: Int } trait A { self => def f: Int } class B { self: Something[A] => case class Hello(a: Int) } trait C { _: Analyzer with StdAttachments => def a = 1 } -------------------------------------------------------------------------------- (compilation_unit (trait_definition (identifier) (template_body (self_type (identifier)) (function_declaration (identifier) (type_identifier)))) (trait_definition (identifier) (template_body (self_type (identifier)) (function_declaration (identifier) (type_identifier)))) (class_definition (identifier) (template_body (self_type (identifier) (generic_type (type_identifier) (type_arguments (type_identifier)))) (class_definition (identifier) (class_parameters (class_parameter (identifier) (type_identifier)))))) (trait_definition (identifier) (template_body (self_type (wildcard) (compound_type (type_identifier) (type_identifier))) (function_definition (identifier) (integer_literal))))) ================================================================================ Inline methods and parameters (Scala 3) ================================================================================ inline def mkLines(inline header: String, indented: Boolean = false): String = {} -------------------------------------------------------------------------------- (compilation_unit (function_definition (modifiers (inline_modifier)) (identifier) (parameters (parameter (inline_modifier) (identifier) (type_identifier)) (parameter (identifier) (type_identifier) (boolean_literal))) (type_identifier) (block))) ================================================================================ Inline val (Scala 3) ================================================================================ inline def test() = inline val x = true -------------------------------------------------------------------------------- (compilation_unit (function_definition (modifiers (inline_modifier)) (identifier) (parameters) (indented_block (val_definition (modifiers (inline_modifier)) (identifier) (boolean_literal))))) ================================================================================ Inline given (Scala 3) ================================================================================ inline given Test = new Test -------------------------------------------------------------------------------- (compilation_unit (given_definition (modifiers (inline_modifier)) (type_identifier) (indented_block (instance_expression (type_identifier))))) ================================================================================ Infix methods (Scala 3) ================================================================================ object Test: inline infix private def hello = 25 -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (function_definition (modifiers (inline_modifier) (infix_modifier) (access_modifier)) (identifier) (integer_literal))))) ================================================================================ Open classes (Scala 3) ================================================================================ open class Test(a: Int): def test = 25 end Test -------------------------------------------------------------------------------- (compilation_unit (class_definition (modifiers (open_modifier)) (identifier) (class_parameters (class_parameter (identifier) (type_identifier))) (template_body (function_definition (identifier) (integer_literal))))) ================================================================================ Traits (Scala 3) ================================================================================ transparent trait Kind: this: A => def test = 1 -------------------------------------------------------------------------------- (compilation_unit (trait_definition (modifiers (transparent_modifier)) (identifier) (template_body (self_type (identifier) (type_identifier)) (function_definition (identifier) (integer_literal))))) ================================================================================ Exports (Scala 3) ================================================================================ export scanUnit.scan export printUnit.{status as _, *} export printUnit.Test as Hello export printUnit.Test as _ -------------------------------------------------------------------------------- (compilation_unit (export_declaration (identifier) (identifier)) (export_declaration (identifier) (namespace_selectors (as_renamed_identifier (identifier) (wildcard)) (namespace_wildcard))) (export_declaration (identifier) (as_renamed_identifier (identifier) (identifier))) (export_declaration (identifier) (as_renamed_identifier (identifier) (wildcard)))) ================================================================================ 'into' soft modifier (Scala 3) ================================================================================ into trait Modifier: val into: Int -------------------------------------------------------------------------------- (compilation_unit (trait_definition (modifiers (into_modifier)) (identifier) (template_body (val_declaration (identifier) (type_identifier))))) ================================================================================ 'tracked' soft modifier (Scala 3) ================================================================================ class F(tracked val x: C): tracked val tracked: Int -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (class_parameters (class_parameter (modifiers (tracked_modifier)) (identifier) (type_identifier))) (template_body (val_declaration (modifiers (tracked_modifier)) (identifier) (type_identifier))))) ================================================ FILE: test/corpus/expressions.txt ================================================ ================================================================================ Call expressions ================================================================================ class C { def main() { a() a( 123, 234, ) ::(123) a(b, c) a.map(x => x + 1) a { 123 } a { b } a.map{ x => x + 1 } /* comment */ a.exists { case ((i, _)) => i } } } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters) (block (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments (integer_literal) (integer_literal))) (call_expression (operator_identifier) (arguments (integer_literal))) (call_expression (identifier) (arguments (identifier) (identifier))) (call_expression (field_expression (identifier) (identifier)) (arguments (lambda_expression (identifier) (infix_expression (identifier) (operator_identifier) (integer_literal))))) (call_expression (identifier) (block (integer_literal))) (call_expression (identifier) (block (identifier))) (call_expression (field_expression (identifier) (identifier)) (block (lambda_expression (identifier) (infix_expression (identifier) (operator_identifier) (integer_literal))))) (block_comment) (call_expression (field_expression (identifier) (identifier)) (case_block (case_clause (tuple_pattern (tuple_pattern (identifier) (wildcard))) (identifier))))))))) ================================================================================ Call expressions (Scala 3 syntax) ================================================================================ class C { a(b, c)(using A.B) foo(new A: def a = new B: def b = 1) } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (call_expression (call_expression (identifier) (arguments (identifier) (identifier))) (arguments (field_expression (identifier) (identifier)))) (call_expression (identifier) (arguments (instance_expression (type_identifier) (template_body (function_definition (identifier) (instance_expression (type_identifier) (template_body (function_definition (identifier) (integer_literal)))))))))))) ================================================================================ SIP-44 Fewer braces (Scala 3 syntax) ================================================================================ class C: xs.map: x => x + 1 xs.map: x => x + 1 xs.map: (_: Int, a) => a xs: println("") xs `++`: val x = 1 List(x) xs.map: case x => x // This is ascription xs: Int // This is call_expression xs: Int -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (call_expression (field_expression (identifier) (identifier)) (colon_argument (identifier) (indented_block (infix_expression (identifier) (operator_identifier) (integer_literal))))) (call_expression (field_expression (identifier) (identifier)) (colon_argument (indented_block (lambda_expression (identifier) (indented_block (infix_expression (identifier) (operator_identifier) (integer_literal))))))) (call_expression (field_expression (identifier) (identifier)) (colon_argument (bindings (binding (wildcard) (type_identifier)) (binding (identifier))) (indented_block (identifier)))) (call_expression (identifier) (colon_argument (indented_block (call_expression (identifier) (arguments (string)))))) (infix_expression (identifier) (identifier) (colon_argument (indented_block (val_definition (identifier) (integer_literal)) (call_expression (identifier) (arguments (identifier)))))) (call_expression (field_expression (identifier) (identifier)) (colon_argument (indented_cases (case_clause (identifier) (identifier)) (comment)))) (ascription_expression (identifier) (type_identifier)) (comment) (call_expression (identifier) (colon_argument (indented_block (identifier))))))) ================================================================================ Trailing comma after for comprehension in lambda parameter of a function ================================================================================ foo(o => for { a <- o } yield a, ) -------------------------------------------------------------------------------- (compilation_unit (call_expression function: (identifier) arguments: (arguments (lambda_expression parameters: (identifier) (indented_block (for_expression enumerators: (enumerators (enumerator (identifier) (identifier))) body: (identifier))))))) ================================================================================ Leading infix operator at lower indent continues the expression across dedent ================================================================================ xs.filter(x => a && b ) -------------------------------------------------------------------------------- (compilation_unit (call_expression function: (field_expression value: (identifier) field: (identifier)) arguments: (arguments (lambda_expression parameters: (identifier) (indented_block (infix_expression left: (identifier) operator: (operator_identifier) right: (identifier))))))) ================================================================================ Colon argument followed by comma ================================================================================ boxTop( back.map: url => a(b), title, x match case a => a, ) -------------------------------------------------------------------------------- (compilation_unit (call_expression (identifier) (arguments (call_expression (field_expression (identifier) (identifier)) (colon_argument (identifier) (indented_block (call_expression (identifier) (arguments (identifier)))))) (identifier) (match_expression (identifier) (indented_cases (case_clause (identifier) (identifier))))))) ================================================================================ Generic functions ================================================================================ class C { def main() { a[ A1, A2, ]() List[Traversable[ClassPath]]() } } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters) (block (call_expression (generic_function (identifier) (type_arguments (type_identifier) (type_identifier))) (arguments)) (call_expression (generic_function (identifier) (type_arguments (generic_type (type_identifier) (type_arguments (type_identifier))))) (arguments))))))) ================================================================================ Assignments ================================================================================ a = b a(1) = c views = val key = 1 key + 1 -------------------------------------------------------------------------------- (compilation_unit (assignment_expression (identifier) (identifier)) (assignment_expression (call_expression (identifier) (arguments (integer_literal))) (identifier)) (assignment_expression (identifier) (indented_block (val_definition (identifier) (integer_literal)) (infix_expression (identifier) (operator_identifier) (integer_literal))))) ================================================================================ If expressions ================================================================================ class C { def main() { if (a) b() if (c) { d() e() } else if (f) { g() } else { h() } } } def other() { if (a) { b }; else c() } def another() { if (a) b match { case _ => c } else d } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters) (block (if_expression (parenthesized_expression (identifier)) (call_expression (identifier) (arguments))) (if_expression (parenthesized_expression (identifier)) (block (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments))) (if_expression (parenthesized_expression (identifier)) (block (call_expression (identifier) (arguments))) (block (call_expression (identifier) (arguments))))))))) (function_definition (identifier) (parameters) (block (if_expression (parenthesized_expression (identifier)) (block (identifier)) (call_expression (identifier) (arguments))))) (function_definition (identifier) (parameters) (block (if_expression (parenthesized_expression (identifier)) (match_expression (identifier) (case_block (case_clause (wildcard) (identifier)))) (identifier))))) ================================================================================ If expressions (Scala 3 syntax) ================================================================================ class C: def main() = if a then b() end if if val c = false c then d() 1 else if f then g() else h() if true then () // comment else () if (a) || b(c) then return true if (a) && b.c then () -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters) (indented_block (if_expression (identifier) (call_expression (identifier) (arguments))) (if_expression (indented_block (val_definition (identifier) (boolean_literal)) (identifier)) (indented_block (call_expression (identifier) (arguments)) (integer_literal)) (if_expression (identifier) (indented_block (call_expression (identifier) (arguments))) (indented_block (call_expression (identifier) (arguments))))) (if_expression (boolean_literal) (indented_block (unit) (comment)) (indented_block (unit))) (if_expression (infix_expression (parenthesized_expression (identifier)) (operator_identifier) (call_expression (identifier) (arguments (identifier)))) (return_expression (boolean_literal))) (if_expression (infix_expression (parenthesized_expression (identifier)) (operator_identifier) (field_expression (identifier) (identifier))) (indented_block (unit)))))))) ================================================================================ Try expressions ================================================================================ def main() { try a() finally depth -= 1 try { doThing() } catch { case e: SomeException => prinlnt(e.message) case NonFatal(ex) => throw new SomeException(ex) } finally { tryAnotherThing() } try b() catch { case e => println(e) } finally doFinalThing() try a() finally b() } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters) (block (try_expression (call_expression (identifier) (arguments)) (finally_clause (infix_expression (identifier) (operator_identifier) (integer_literal)))) (try_expression (block (call_expression (identifier) (arguments))) (catch_clause (case_block (case_clause (typed_pattern (identifier) (type_identifier)) (call_expression (identifier) (arguments (field_expression (identifier) (identifier))))) (case_clause (case_class_pattern (type_identifier) (identifier)) (throw_expression (instance_expression (type_identifier) (arguments (identifier))))))) (finally_clause (block (call_expression (identifier) (arguments))))) (try_expression (call_expression (identifier) (arguments)) (catch_clause (case_block (case_clause (identifier) (call_expression (identifier) (arguments (identifier)))))) (finally_clause (call_expression (identifier) (arguments)))) (try_expression (call_expression (identifier) (arguments)) (finally_clause (call_expression (identifier) (arguments))))))) ================================================================================ Try expressions (Scala 3 syntax) ================================================================================ def main(): Unit = try a() finally depth -= 1 try a() b() catch case e: SomeException => prinlnt(e.message) case NonFatal(ex) => throw new SomeException(ex) finally tryAnotherThing() tryAnotherThing2() try a catch case b: C => e finally f try a catch case b: C => e -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters) (type_identifier) (indented_block (try_expression (call_expression (identifier) (arguments)) (finally_clause (infix_expression (identifier) (operator_identifier) (integer_literal)))) (try_expression (indented_block (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments))) (catch_clause (indented_cases (case_clause (typed_pattern (identifier) (type_identifier)) (call_expression (identifier) (arguments (field_expression (identifier) (identifier))))) (case_clause (case_class_pattern (type_identifier) (identifier)) (throw_expression (instance_expression (type_identifier) (arguments (identifier))))))) (finally_clause (indented_block (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments))))) (try_expression (identifier) (catch_clause (typed_pattern (identifier) (type_identifier)) (identifier)) (finally_clause (identifier))) (try_expression (identifier) (catch_clause (typed_pattern (identifier) (type_identifier)) (identifier)))))) ================================================================================ Match expressions ================================================================================ def matchTest(x: Int): String = x match { case 0 => case 1 => "one"; "uno" case 2 => "two" case 3 => { "3" } case 4 => ; case A if a == 1 => case A if a == 2 => 2 case ((i, _)) => i case s"$l1 -- $l2" => l1 + l2 case _ => val x = "many" "more" case a if b => c } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (match_expression (identifier) (case_block (case_clause (integer_literal)) (case_clause (integer_literal) (string) (string)) (case_clause (integer_literal) (string)) (case_clause (integer_literal) (block (string))) (case_clause (integer_literal)) (case_clause (identifier) (guard (infix_expression (identifier) (operator_identifier) (integer_literal)))) (case_clause (identifier) (guard (infix_expression (identifier) (operator_identifier) (integer_literal))) (integer_literal)) (case_clause (tuple_pattern (tuple_pattern (identifier) (wildcard))) (identifier)) (case_clause (interpolated_string_expression (identifier) (interpolated_string (interpolation (identifier)) (interpolation (identifier)))) (infix_expression (identifier) (operator_identifier) (identifier))) (case_clause (wildcard) (val_definition (identifier) (string)) (string)) (case_clause (identifier) (guard (identifier)) (identifier)))))) ================================================================================ Match expressions (Scala 3 syntax) ================================================================================ def matchTest(x: Int): String = x match case 0 => case 1 => "one"; "uno" case 2 => "two" case x if x == 3 => val x = "3" x case ((i, _)) => i case _ => val x = "many" "more" -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (indented_block (match_expression (identifier) (indented_cases (case_clause (integer_literal)) (case_clause (integer_literal) (string) (string)) (case_clause (integer_literal) (string)) (case_clause (identifier) (guard (infix_expression (identifier) (operator_identifier) (integer_literal))) (val_definition (identifier) (string)) (identifier)) (case_clause (tuple_pattern (tuple_pattern (identifier) (wildcard))) (identifier)) (case_clause (wildcard) (val_definition (identifier) (string)) (string))))))) ================================================================================ Dot-syntax for match expressions (Scala 3 syntax) ================================================================================ def matchTest(x: Int): String = x .find() .match case 0 => case 1 => .run() -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (indented_block (call_expression (field_expression (match_expression (call_expression (field_expression (identifier) (identifier)) (arguments)) (indented_cases (case_clause (integer_literal)) (case_clause (integer_literal)))) (identifier)) (arguments))))) ================================================================================ Field expressions ================================================================================ class C { def main() { a.b = c a.b.d a .b // comment1 /* comment2 */ .c } } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters) (block (assignment_expression (field_expression (identifier) (identifier)) (identifier)) (field_expression (field_expression (identifier) (identifier)) (identifier)) (field_expression (field_expression (identifier) (identifier)) (comment) (block_comment) (identifier))))))) ================================================================================ Instance expressions ================================================================================ class C { def main() { val a = new B val c = new D(e, f) val e = new E: def app = 1 val f = new: def app = 1 val g = new G {} val i = new { "ok" } new Array: Array } } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters) (block (val_definition (identifier) (instance_expression (type_identifier))) (val_definition (identifier) (instance_expression (type_identifier) (arguments (identifier) (identifier)))) (val_definition (identifier) (instance_expression (type_identifier) (template_body (function_definition (identifier) (integer_literal))))) (val_definition (identifier) (instance_expression (template_body (function_definition (identifier) (integer_literal))))) (val_definition (identifier) (instance_expression (type_identifier) (template_body))) (val_definition (identifier) (instance_expression (template_body (string)))) (ascription_expression (instance_expression (type_identifier)) (type_identifier))))))) ================================================================================ Infix expressions ================================================================================ class C { def main() { a = b max c d + e + f a ** b } } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters) (block (assignment_expression (identifier) (infix_expression (identifier) (identifier) (identifier))) (infix_expression (infix_expression (identifier) (operator_identifier) (identifier)) (operator_identifier) (identifier)) (infix_expression (identifier) (operator_identifier) (identifier))))))) ================================================================================ Multi-line infix expressions with leading infix operators ================================================================================ def foo = a || b && c `in` d -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (indented_block (infix_expression (infix_expression (infix_expression (identifier) (operator_identifier) (identifier)) (operator_identifier) (identifier)) (identifier) (identifier))))) ================================================================================ Prefix expressions ================================================================================ class C { def main() { !a +a + b } } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (parameters) (block (prefix_expression (identifier)) (infix_expression (prefix_expression (identifier)) (operator_identifier) (identifier))))))) ================================================================================ ??? as standalone statement ================================================================================ final def a = println(1) ??? -------------------------------------------------------------------------------- (compilation_unit (function_definition (modifiers) name: (identifier) body: (indented_block (call_expression function: (identifier) arguments: (arguments (integer_literal))) (operator_identifier)))) ================================================================================ Postfix expressions ================================================================================ object O { val v = "value" toUpperCase val c = 1 + 2 toString } -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (val_definition (identifier) (postfix_expression (string) (identifier))) (val_definition (identifier) (postfix_expression (infix_expression (integer_literal) (operator_identifier) (integer_literal)) (identifier)))))) ================================================================================ Ascription Expression ================================================================================ object O { val l = a: List val x = 2: Byte Nil: List[String] x: @unchecked } -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (val_definition (identifier) (ascription_expression (identifier) (type_identifier))) (val_definition (identifier) (ascription_expression (integer_literal) (type_identifier))) (ascription_expression (identifier) (generic_type (type_identifier) (type_arguments (type_identifier)))) (ascription_expression (identifier) (annotation (type_identifier)))))) ================================================================================ Lambda Expression ================================================================================ object O { val l = a => a + 1 val b = (x: Int, y: Int) => { x * y } val f = _ => 2 foo { i => val x = 2 + i x } { x => val y = 2 * x y * y } { b => if (c) d.e } { a => implicit b => b } { (_, a) => a } { x: Int => x + 1 } { () => val x = 1; 2 } { () => val tp = qual.tpe; val sym = tp.typeSymbolDirect 1 } } -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (val_definition (identifier) (lambda_expression (identifier) (infix_expression (identifier) (operator_identifier) (integer_literal)))) (val_definition (identifier) (lambda_expression (bindings (binding (identifier) (type_identifier)) (binding (identifier) (type_identifier))) (block (infix_expression (identifier) (operator_identifier) (identifier))))) (val_definition (identifier) (lambda_expression (wildcard) (integer_literal))) (call_expression (identifier) (block (lambda_expression (identifier) (indented_block (val_definition (identifier) (infix_expression (integer_literal) (operator_identifier) (identifier))) (identifier))))) (block (lambda_expression (identifier) (indented_block (val_definition (identifier) (infix_expression (integer_literal) (operator_identifier) (identifier))) (infix_expression (identifier) (operator_identifier) (identifier))))) (block (lambda_expression (identifier) (indented_block (if_expression (parenthesized_expression (identifier)) (field_expression (identifier) (identifier)))))) (block (lambda_expression (identifier) (lambda_expression (identifier) (identifier)))) (block (lambda_expression (bindings (binding (wildcard)) (binding (identifier))) (identifier))) (block (lambda_expression (identifier) (type_identifier) (infix_expression (identifier) (operator_identifier) (integer_literal)))) (block (lambda_expression (bindings) (val_definition (identifier) (integer_literal)) (integer_literal))) (block (lambda_expression (bindings) (val_definition (identifier) (field_expression (identifier) (identifier))) (val_definition (identifier) (field_expression (identifier) (identifier))) (integer_literal)))))) ================================================================================ Lambda Expression (Scala 3 syntax) ================================================================================ object O: val f = (a: Int) ?=> (b: Int) => b val less: Comparer = [X: Ord] => (x: X, y: X) => ??? -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (val_definition (identifier) (lambda_expression (bindings (binding (identifier) (type_identifier))) (lambda_expression (bindings (binding (identifier) (type_identifier))) (identifier)))) (val_definition (identifier) (type_identifier) (lambda_expression (type_parameters (identifier) (context_bound (type_identifier))) (bindings (binding (identifier) (type_identifier)) (binding (identifier) (type_identifier))) (operator_identifier)))))) ================================================================================ Unit expressions ================================================================================ val x = () def f(): Unit = { ( ); } -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (unit)) (function_definition (identifier) (parameters) (type_identifier) (block (unit)))) ================================================================================ Return expressions ================================================================================ def f: Unit = return def g(a: A): B = { f(); return null.asInstanceOf[B] } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (type_identifier) (return_expression)) (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (block (call_expression (identifier) (arguments)) (return_expression (generic_function (field_expression (null_literal) (identifier)) (type_arguments (type_identifier))))))) ================================================================================ While loops ================================================================================ def f = { while (a) g() while (b < c) { d } } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (block (while_expression (parenthesized_expression (identifier)) (call_expression (identifier) (arguments))) (while_expression (parenthesized_expression (infix_expression (identifier) (operator_identifier) (identifier))) (block (identifier)))))) ================================================================================ While loops (Scala 3 syntax) ================================================================================ def f: Unit = while a do g() while val x = 1 b < x do () -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (type_identifier) (indented_block (while_expression (identifier) (call_expression (identifier) (arguments))) (while_expression (indented_block (val_definition (identifier) (integer_literal)) (infix_expression (identifier) (operator_identifier) (identifier))) (indented_block (unit)))))) ================================================================================ Do-while loops ================================================================================ def f() = { do g(a, b) while(c && d) do { g(a, b) h(a, b) } while (c < d) } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters) (block (do_while_expression (call_expression (identifier) (arguments (identifier) (identifier))) (parenthesized_expression (infix_expression (identifier) (operator_identifier) (identifier)))) (do_while_expression (block (call_expression (identifier) (arguments (identifier) (identifier))) (call_expression (identifier) (arguments (identifier) (identifier)))) (parenthesized_expression (infix_expression (identifier) (operator_identifier) (identifier))))))) ================================================================================ For comprehensions ================================================================================ def f() = { for (n <- nums) yield n + 1 for (x <- xs; y <- ys) g(x, y) for { x <- xs a = b + c y <- g() if d (t, u) = y } yield { h(x, y) } } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters) (block (for_expression (enumerators (enumerator (identifier) (identifier))) (infix_expression (identifier) (operator_identifier) (integer_literal))) (for_expression (enumerators (enumerator (identifier) (identifier)) (enumerator (identifier) (identifier))) (call_expression (identifier) (arguments (identifier) (identifier)))) (for_expression (enumerators (enumerator (identifier) (identifier)) (enumerator (identifier) (infix_expression (identifier) (operator_identifier) (identifier))) (enumerator (identifier) (call_expression (identifier) (arguments)) (guard (identifier))) (enumerator (tuple_pattern (identifier) (identifier)) (identifier))) (block (call_expression (identifier) (arguments (identifier) (identifier)))))))) ================================================================================ For comprehensions (Scala 3 syntax) ================================================================================ def f(): Unit = for n <- nums yield n + 1 for a = 1 x <- xs y <- ys yield g(x, y) for annot <- annotations if shouldEmitAnnotation(annot) do () -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters) (type_identifier) (indented_block (for_expression (enumerators (enumerator (identifier) (identifier))) (infix_expression (identifier) (operator_identifier) (integer_literal))) (for_expression (enumerators (enumerator (identifier) (integer_literal)) (enumerator (identifier) (identifier)) (enumerator (identifier) (identifier))) (indented_block (call_expression (identifier) (arguments (identifier) (identifier))))) (for_expression (enumerators (enumerator (identifier) (identifier)) (enumerator (guard (call_expression (identifier) (arguments (identifier)))))) (indented_block (unit)))))) ================================================================================ Chained expressions ================================================================================ def main() { val myList = List(1, 2, 3) myList.map(_ * 2) myList .map(_ * 2) myList .length } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters) (block (val_definition (identifier) (call_expression (identifier) (arguments (integer_literal) (integer_literal) (integer_literal)))) (call_expression (field_expression (identifier) (identifier)) (arguments (infix_expression (wildcard) (operator_identifier) (integer_literal)))) (call_expression (field_expression (identifier) (identifier)) (arguments (infix_expression (wildcard) (operator_identifier) (integer_literal)))) (field_expression (identifier) (identifier))))) ================================================================================ Macros (Scala 2 syntax) ================================================================================ class Foo { def a: A = macro B.b } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (type_identifier) (indented_block (macro_body (field_expression (identifier) (identifier)))))))) ================================================================================ Macros (Scala 3 syntax) ================================================================================ class A: inline def inspect(inline a: Any): Any = ${ inspectCode('a) } def foo = '{ $b } -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (modifiers (inline_modifier)) (identifier) (parameters (parameter (inline_modifier) (identifier) (type_identifier))) (type_identifier) (indented_block (splice_expression (call_expression (identifier) (arguments (quote_expression (identifier))))))) (function_definition (identifier) (indented_block (quote_expression (identifier))))))) ================================================================================ Inline matches (Scala 3) ================================================================================ def hello = inline c match { case 1 => } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (indented_block (match_expression (inline_modifier) (identifier) (case_block (case_clause (integer_literal))))))) ================================================================================ Inline if (Scala 3) ================================================================================ def hello = inline if (x) {} else {} -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (indented_block (if_expression (inline_modifier) (parenthesized_expression (identifier)) (block) (block))))) ================================================================================ Nested inline if and match (Scala 3) ================================================================================ def hello = inline if (x) { inline x match { } } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (indented_block (if_expression (inline_modifier) (parenthesized_expression (identifier)) (block (match_expression (inline_modifier) (identifier) (case_block))))))) ================================================================================ Top-level expressions ================================================================================ var greeting = "Good bye" greeting = "Hello" val message = greeting + " from Scala script!" if true then println(message) addSbtPlugin("foo" % "bar" % "0.1") -------------------------------------------------------------------------------- (compilation_unit (var_definition (identifier) (string)) (assignment_expression (identifier) (string)) (val_definition (identifier) (infix_expression (identifier) (operator_identifier) (string))) (if_expression (boolean_literal) (indented_block (call_expression (identifier) (arguments (identifier))))) (call_expression (identifier) (arguments (infix_expression (infix_expression (string) (operator_identifier) (string)) (operator_identifier) (string))))) ================================================================================ Soft keywords used as identifiers (Scala 3) ================================================================================ infix() opaque() open() transparent() as() derives() end() throws() using() -------------------------------------------------------------------------------- (compilation_unit (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments))) ================================================================================ Compound expression with instance declaration, pattern matching with guards and if statement ================================================================================ new Foo { tree match { case Foo if foos contains foo => if (foo) bar } } -------------------------------------------------------------------------------- (compilation_unit (instance_expression (type_identifier) (template_body (match_expression (identifier) (case_block (case_clause (identifier) (guard (infix_expression (identifier) (identifier) (identifier))) (if_expression (parenthesized_expression (identifier)) (identifier)))))))) ================================================================================ Vararg expressions ================================================================================ foo(args*) bar(xs: _*) foo(a, args*) bar(a, xs: _*) -------------------------------------------------------------------------------- (compilation_unit (call_expression function: (identifier) arguments: (arguments (vararg (identifier)))) (call_expression function: (identifier) arguments: (arguments (vararg (identifier)))) (call_expression function: (identifier) arguments: (arguments (identifier) (vararg (identifier)))) (call_expression function: (identifier) arguments: (arguments (identifier) (vararg (identifier))))) ================================================ FILE: test/corpus/literals.txt ================================================ ================================================================================ Simple strings ================================================================================ val emptyString = "" val oneLineString = "I'm just on one line" val stringWithCommentLikeContent1 = "// not a comment" val stringWithCommentLikeContent2 = "/* not a comment */" val stringWithEscapeSequence = "first line\nsecond line" val multiLineString = """ a $thisIsntInterpolated ${thisEither} no escape codes in multiline strings \uD83D\uDE00 \n """ val emptyMultilineStringf = """""" val stringOfOneDoubleQuote = """"""" val multiLineString3 = """\{@inheritDoc\p{Zs}*\}""" val blackslashDoesNotEscapeClosingQuote = """\""" -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (string)) (val_definition (identifier) (string)) (val_definition (identifier) (string)) (val_definition (identifier) (string)) (val_definition (identifier) (string (escape_sequence))) (val_definition (identifier) (string)) (val_definition (identifier) (string)) (val_definition (identifier) (string)) (val_definition (identifier) (string)) (val_definition (identifier) (string))) ================================================================================ Escape sequences in strings ================================================================================ val singleEscapeCode = "\n" val singleCharacterEscapes = "\n\r\t\b\f\'\"\\" val unicodeEscape = "\uD83D\UDE00" val repeatedUs = "\uuuuD83D\UUDE00" -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (string (escape_sequence))) (val_definition (identifier) (string (escape_sequence) (escape_sequence) (escape_sequence) (escape_sequence) (escape_sequence) (escape_sequence) (escape_sequence) (escape_sequence))) (val_definition (identifier) (string (escape_sequence) (escape_sequence))) (val_definition (identifier) (string (escape_sequence) (escape_sequence)))) ================================================================================ Interpolated strings ================================================================================ val empty = s"" val emptyMultiline = s"""""" val string1 = s"a $b ${c}" val string2 = f"hi $name%s" val string3 = raw"Not a really a new line \n${ha}." val string4 = s""" works even in multiline strings, ${name} """ val string5 = s"$works${without}$spaces" val string6 = s"$a$b" val string7 = s"$$ $a" val string8 = s"$"$a" val string9 = s"$"$a\uD83D\UDE00\n" val multiline = raw""" $$ ${interp} \n \x \" \""" -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (interpolation (identifier)) (interpolation (block (identifier)))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (interpolation (identifier))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (interpolation (block (identifier)))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (interpolation (block (identifier)))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (interpolation (identifier)) (interpolation (block (identifier))) (interpolation (identifier))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (interpolation (identifier)) (interpolation (identifier))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (escape_sequence) (interpolation (identifier))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (escape_sequence) (interpolation (identifier))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (escape_sequence) (interpolation (identifier)) (escape_sequence) (escape_sequence) (escape_sequence)))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (escape_sequence) (interpolation (block (identifier))))))) ================================================================================ Raw strings ================================================================================ val emptyRaw = raw"" val emptyMultilineRaw = raw"""""" val invalidEscapeCodesAllowedAndValidEscapesIgnored = raw"\n\t\x\w\g\k" val ErasedFunctionN = raw"ErasedFunction(\d+)".r val escapedAndInterpolated = raw"Not a really a new line \n${ha}." val blackslashQuoteDoesNotCloseString = raw"\"" val doubleSlashQuoteDoesCloseString = raw"\\" val dollarEscapeInSingleLine = raw"$$" val slashDoesNotEscapeDollarSign = raw"\$$" val multiline = raw""" $$ ${interp} \n \x \" \""" val ensureIdentifierNamedRawStillWorks = someFunction(raw) val raw = raw(raw) -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string))) (val_definition (identifier) (field_expression (interpolated_string_expression (identifier) (interpolated_string)) (identifier))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (interpolation (block (identifier)))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (escape_sequence)))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (escape_sequence)))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (escape_sequence) (interpolation (block (identifier)))))) (val_definition (identifier) (call_expression (identifier) (arguments (identifier)))) (val_definition (identifier) (call_expression (identifier) (arguments (identifier))))) ================================================================================ Raw and interpolated strings have equivalent parse trees ================================================================================ val raw = raw"Foo $$ ${bar}" val raw = s"Foo $$ ${bar}" -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (escape_sequence) (interpolation (block (identifier)))))) (val_definition (identifier) (interpolated_string_expression (identifier) (interpolated_string (escape_sequence) (interpolation (block (identifier))))))) ================================================================================ Integer literals ================================================================================ val i1 = 0 val i2 = 1234 val i3 = -0xF2 val i4 = 0XA0 val l1 = -0l val l2 = 1234L val l3 = 0xF23l val l4 = 0XA03L val l5 = 150_000_000 val l6 = 0xFF_FF_FF -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal)) (val_definition (identifier) (integer_literal))) ================================================================================ Floating point literals ================================================================================ val f1 = 3.14 val f2 = -3f val f2 = 3E-1 val d1 = .314D -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (floating_point_literal)) (val_definition (identifier) (floating_point_literal)) (val_definition (identifier) (floating_point_literal)) (val_definition (identifier) (floating_point_literal))) ================================================================================ Boolean literals ================================================================================ val myBool = true def foo(a: Boolean = false) = a && true -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (boolean_literal)) (function_definition (identifier) (parameters (parameter (identifier) (type_identifier) (boolean_literal))) (infix_expression (identifier) (operator_identifier) (boolean_literal)))) ================================================================================ Character literals ================================================================================ val myChar = 'c' val otherChar = '\u0041' val otherChar2 = '\uu0041' val anotherChar = '\n' def foo(a: Char = 'c') = a + 'd' -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (character_literal)) (val_definition (identifier) (character_literal)) (val_definition (identifier) (character_literal)) (val_definition (identifier) (character_literal)) (function_definition (identifier) (parameters (parameter (identifier) (type_identifier) (character_literal))) (infix_expression (identifier) (operator_identifier) (character_literal)))) ================================================================================ Null ================================================================================ lazy val nullObject: String = null -------------------------------------------------------------------------------- (compilation_unit (val_definition (modifiers) (identifier) (type_identifier) (null_literal))) ================================================================================ Tuple literals ================================================================================ val x = ( 1, 2, 3, ) -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (tuple_expression (integer_literal) (integer_literal) (integer_literal)))) ================================================ FILE: test/corpus/patterns-pending.txt ================================================ ================================================ FILE: test/corpus/patterns.txt ================================================ ================================================================================ Alternative patterns ================================================================================ val x = y match { case 1 | a => b case "c" | "d" | "e" => f } -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (match_expression (identifier) (case_block (case_clause (alternative_pattern (integer_literal) (identifier)) (identifier)) (case_clause (alternative_pattern (alternative_pattern (string) (string)) (string)) (identifier)))))) ================================================================================ Typed patterns ================================================================================ val x = y match { case 1 : Int => 2 case a : B with C => d case _: B | _: C => 3 case Object.Constant => 3 } -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (match_expression (identifier) (case_block (case_clause (typed_pattern (integer_literal) (type_identifier)) (integer_literal)) (case_clause (typed_pattern (identifier) (compound_type (type_identifier) (type_identifier))) (identifier)) (case_clause (alternative_pattern (typed_pattern (wildcard) (type_identifier)) (typed_pattern (wildcard) (type_identifier))) (integer_literal)) (case_clause (stable_identifier (identifier) (identifier)) (integer_literal)))))) ================================================================================ Tuple patterns ================================================================================ val (a, b) = if (c) (d, e) else (f, g) val x = y match { case (A, B) => X } -------------------------------------------------------------------------------- (compilation_unit (val_definition (tuple_pattern (identifier) (identifier)) (if_expression (parenthesized_expression (identifier)) (tuple_expression (identifier) (identifier)) (tuple_expression (identifier) (identifier)))) (val_definition (identifier) (match_expression (identifier) (case_block (case_clause (tuple_pattern (identifier) (identifier)) (identifier)))))) ================================================================================ Name tuple patterns (Scala 3 syntax) ================================================================================ val x = y match case (a = A, b = B) => ??? -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (match_expression (identifier) (indented_cases (case_clause (named_tuple_pattern (named_pattern (identifier) (identifier)) (named_pattern (identifier) (identifier))) (operator_identifier)))))) ================================================================================ Case class patterns ================================================================================ def showNotification(notification: Notification): String = { notification match { case Email(email, title, _) => s"You got an email from $email with title: $title" case SMS(number, message) => s"You got an SMS from $number! Message: $message" case VoiceRecording(name, link) => s"you received a Voice Recording from $name! Click the link to hear it: $link" } } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters (parameter (identifier) (type_identifier))) (type_identifier) (block (match_expression (identifier) (case_block (case_clause (case_class_pattern (type_identifier) (identifier) (identifier) (wildcard)) (interpolated_string_expression (identifier) (interpolated_string (interpolation (identifier)) (interpolation (identifier))))) (case_clause (case_class_pattern (type_identifier) (identifier) (identifier)) (interpolated_string_expression (identifier) (interpolated_string (interpolation (identifier)) (interpolation (identifier))))) (case_clause (case_class_pattern (type_identifier) (identifier) (identifier)) (interpolated_string_expression (identifier) (interpolated_string (interpolation (identifier)) (interpolation (identifier)))))))))) ================================================================================ Case class patterns (Scala 3 syntax) ================================================================================ class A: c match case c @ City(name = "Hoboken") => c.population -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (match_expression (identifier) (indented_cases (case_clause (capture_pattern (identifier) (case_class_pattern (type_identifier) (named_pattern (identifier) (string)))) (field_expression (identifier) (identifier)))))))) ================================================================================ Infix patterns ================================================================================ def first(x: Seq[Int]) = x match { case e :+ _ => Some(e) case _ => None } -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters (parameter (identifier) (generic_type (type_identifier) (type_arguments (type_identifier))))) (match_expression (identifier) (case_block (case_clause (infix_pattern (identifier) (operator_identifier) (wildcard)) (call_expression (identifier) (arguments (identifier)))) (case_clause (wildcard) (identifier)))))) ================================================================================ Capture patterns ================================================================================ val x = y match { case a @ B(1) => a case b @ C(d @ (e @ X, _: Y)) => e case req @ (POST | GET) -> Root / "test" => 5 case Array(a: Type, _@_*) => y } -------------------------------------------------------------------------------- (compilation_unit (val_definition (identifier) (match_expression (identifier) (case_block (case_clause (capture_pattern (identifier) (case_class_pattern (type_identifier) (integer_literal))) (identifier)) (case_clause (capture_pattern (identifier) (case_class_pattern (type_identifier) (capture_pattern (identifier) (tuple_pattern (capture_pattern (identifier) (identifier)) (typed_pattern (wildcard) (type_identifier)))))) (identifier)) (case_clause (infix_pattern (infix_pattern (capture_pattern (identifier) (tuple_pattern (alternative_pattern (identifier) (identifier)))) (operator_identifier) (identifier)) (operator_identifier) (string)) (integer_literal)) (case_clause (case_class_pattern (type_identifier) (typed_pattern (identifier) (type_identifier)) (repeat_pattern (capture_pattern (wildcard) (wildcard)))) (identifier)))))) ================================================================================ Quoted patterns (Scala 3 syntax) ================================================================================ def foo = x match case '{ $boolExpr } => Some(true) case _ => None -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (indented_block (match_expression (identifier) (indented_cases (case_clause (quote_expression (identifier)) (call_expression (identifier) (arguments (boolean_literal)))) (case_clause (wildcard) (identifier))))))) ================================================================================ Given pattern (Scala 3 syntax) ================================================================================ for given Int <- Some(1) yield () -------------------------------------------------------------------------------- (compilation_unit (for_expression (enumerators (enumerator (given_pattern (type_identifier)) (call_expression (identifier) (arguments (integer_literal))))) (unit))) ================================================ FILE: test/corpus/types-pending.txt ================================================ ================================================================================ Subclass with multiline params and unnamed after named param :skip ================================================================================ // https://github.com/tree-sitter/tree-sitter-scala/issues/465 // https://github.com/scala/scala3/blob/main/tests/run/i14164.scala#L5-L9 class Child extends Base( param = for x <- Seq("a") yield x "param" ) -------------------------------------------------------------------------------- ================================================================================ case class nested in an object definition :skip ================================================================================ // https://github.com/tree-sitter/tree-sitter-scala/issues/329 object Merge: case class Location(runIndex: Int, locationInRun: String): end Location end Merge -------------------------------------------------------------------------------- ================================================ FILE: test/corpus/types.txt ================================================ ================================================================================ Stable type identifiers ================================================================================ object Main { type A = B.C type D = E.F.G type H = __root__.scala.Int } -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (type_definition (type_identifier) (stable_type_identifier (identifier) (type_identifier))) (type_definition (type_identifier) (stable_type_identifier (stable_identifier (identifier) (identifier)) (type_identifier))) (type_definition (type_identifier) (stable_type_identifier (stable_identifier (identifier) (identifier)) (type_identifier)))))) ================================================================================ Generic types ================================================================================ object Main { type A = B[ C, D, ] type E = F.G[H] } -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (type_definition (type_identifier) (generic_type (type_identifier) (type_arguments (type_identifier) (type_identifier)))) (type_definition (type_identifier) (generic_type (stable_type_identifier (identifier) (type_identifier)) (type_arguments (type_identifier))))))) ================================================================================ Tuple types ================================================================================ object Main { type A = (B, C) type A = ( B, C, ) } -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (type_definition (type_identifier) (tuple_type (type_identifier) (type_identifier))) (type_definition (type_identifier) (tuple_type (type_identifier) (type_identifier)))))) ================================================================================ Named tuple types (Scala 3 syntax) ================================================================================ object O: type A = (name: String, age: Int) -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (type_definition (type_identifier) (named_tuple_type (name_and_type (identifier) (type_identifier)) (name_and_type (identifier) (type_identifier))))))) ================================================================================ Function types ================================================================================ object Main { type A = (B, C) => D type A = (B, C) => (D, E) type A = B => (D, E) } -------------------------------------------------------------------------------- (compilation_unit (object_definition (identifier) (template_body (type_definition (type_identifier) (function_type (parameter_types (type_identifier) (type_identifier)) (type_identifier))) (type_definition (type_identifier) (function_type (parameter_types (type_identifier) (type_identifier)) (tuple_type (type_identifier) (type_identifier)))) (type_definition (type_identifier) (function_type (parameter_types (type_identifier)) (tuple_type (type_identifier) (type_identifier))))))) ================================================================================ Polymorphic function types (Scala 3 syntax) ================================================================================ class A: type Comparer = [X: Ord] => (X, X) => Boolean -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (type_definition (type_identifier) (function_type (type_parameters (identifier) (context_bound (type_identifier))) (function_type (parameter_types (type_identifier) (type_identifier)) (type_identifier))))))) ================================================================================ Context function types (Scala 3 syntax) ================================================================================ type Executable[A] = ExecutionContext ?=> A -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (type_parameters (identifier)) (function_type (parameter_types (type_identifier)) (type_identifier)))) ================================================================================ Match types (Scala 3 syntax) ================================================================================ type Elem[A] = A match case String => Char case Array[a] => a case t *: rest => t -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (type_parameters (identifier)) (match_type (type_identifier) (type_case_clause (type_identifier) (type_identifier)) (type_case_clause (generic_type (type_identifier) (type_arguments (type_identifier))) (type_identifier)) (type_case_clause (infix_type (type_identifier) (operator_identifier) (type_identifier)) (type_identifier))))) ================================================================================ Match types with braced syntax (Scala 3 syntax) ================================================================================ type Elem[A] = A match { case String => Char case Array[a] => a case t *: rest => t } -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (type_parameters (identifier)) (match_type (type_identifier) (type_case_clause (type_identifier) (type_identifier)) (type_case_clause (generic_type (type_identifier) (type_arguments (type_identifier))) (type_identifier)) (type_case_clause (infix_type (type_identifier) (operator_identifier) (type_identifier)) (type_identifier))))) ================================================================================ Compound types ================================================================================ def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { } class F extends Cloneable with Resetable with Serializable {} type G = H[A1] { def foo[A2 <: Stepper[_]]: A2 } type I = F1[A1: def foo: A2] def a: F { val x: Int } = ??? -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (parameters (parameter (identifier) (compound_type (type_identifier) (type_identifier)))) (type_identifier) (block)) (class_definition (identifier) (extends_clause (type_identifier) (type_identifier) (type_identifier)) (template_body)) (type_definition (type_identifier) (compound_type (generic_type (type_identifier) (type_arguments (type_identifier))) (refinement (function_declaration (identifier) (type_parameters (identifier) (upper_bound (generic_type (type_identifier) (type_arguments (wildcard))))) (type_identifier))))) (type_definition (type_identifier) (generic_type (type_identifier) (type_arguments (compound_type (type_identifier) (refinement (function_declaration (identifier) (type_identifier))))))) (function_definition (identifier) (compound_type (type_identifier) (refinement (val_declaration (identifier) (type_identifier)))) (operator_identifier))) ================================================================================ Infix types ================================================================================ type A = B Foo C type A = B ! C or D type A = (B, C) ~ D -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (infix_type (type_identifier) (identifier) (type_identifier))) (type_definition (type_identifier) (infix_type (infix_type (type_identifier) (operator_identifier) (type_identifier)) (identifier) (type_identifier))) (type_definition (type_identifier) (infix_type (tuple_type (type_identifier) (type_identifier)) (operator_identifier) (type_identifier)))) ================================================================================ Variant Types ================================================================================ class Function1[-T1, +R] -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (type_parameters (contravariant_type_parameter (identifier)) (covariant_type_parameter (identifier))))) ================================================================================ Upper bound ================================================================================ class A[B <: C] -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (type_parameters (identifier) (upper_bound (type_identifier))))) ================================================================================ Lower bound ================================================================================ class A[B >: C] -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (type_parameters (identifier) (lower_bound (type_identifier))))) ================================================================================ Lower and upper bounds ================================================================================ class A[B >: C <: D] -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (type_parameters (identifier) (lower_bound (type_identifier)) (upper_bound (type_identifier))))) ================================================================================ View bound ================================================================================ class A[B <% C <% D] -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (type_parameters (identifier) (view_bound (type_identifier)) (view_bound (type_identifier))))) ================================================================================ Context bound ================================================================================ class A[B : C : D] -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (type_parameters (identifier) (context_bound (type_identifier)) (context_bound (type_identifier))))) ================================================================================ Context bound (Scala 3 syntax) ================================================================================ def reduce[A : Monoid as m](xs: List[A]): A = () def showMax[X : {Ordering, Show}](x: X, y: X): String = () -------------------------------------------------------------------------------- (compilation_unit (function_definition (identifier) (type_parameters (identifier) (context_bound (type_identifier) (identifier))) (parameters (parameter (identifier) (generic_type (type_identifier) (type_arguments (type_identifier))))) (type_identifier) (unit)) (function_definition (identifier) (type_parameters (identifier) (context_bound (type_identifier)) (context_bound (type_identifier))) (parameters (parameter (identifier) (type_identifier)) (parameter (identifier) (type_identifier))) (type_identifier) (unit))) ================================================================================ Projections ================================================================================ type A = B[C]#D -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (projected_type (generic_type (type_identifier) (type_arguments (type_identifier))) (type_identifier)))) ================================================================================ Complex types ================================================================================ type A = B with B1 with B2 ! C with C1 -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (infix_type (compound_type (type_identifier) (type_identifier) (type_identifier)) (operator_identifier) (compound_type (type_identifier) (type_identifier))))) ================================================================================ Literal type aliases (Scala 2.13+) ================================================================================ type A = "hello" type B = 25 type C = false type D = 0.5f class Test(d: "hello", b: 25) -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (literal_type (string))) (type_definition (type_identifier) (literal_type (integer_literal))) (type_definition (type_identifier) (literal_type (boolean_literal))) (type_definition (type_identifier) (literal_type (floating_point_literal))) (class_definition (identifier) (class_parameters (class_parameter (identifier) (literal_type (string))) (class_parameter (identifier) (literal_type (integer_literal)))))) ================================================================================ Singleton Types ================================================================================ class A: def foobar: this.type = this type X = A.B.type -------------------------------------------------------------------------------- (compilation_unit (class_definition (identifier) (template_body (function_definition (identifier) (singleton_type (identifier)) (identifier)) (type_definition (type_identifier) (singleton_type (stable_identifier (identifier) (identifier))))))) ================================================================================ Opaque type aliases (Scala 3) ================================================================================ opaque type A = Int private opaque type B = String opaque type B >: Test <: Help = String -------------------------------------------------------------------------------- (compilation_unit (type_definition (opaque_modifier) (type_identifier) (type_identifier)) (type_definition (modifiers (access_modifier)) (opaque_modifier) (type_identifier) (type_identifier)) (type_definition (opaque_modifier) (type_identifier) (lower_bound (type_identifier)) (upper_bound (type_identifier)) (type_identifier))) ================================================================================ Structural type ================================================================================ type A = { def fly(): Unit } -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (structural_type (function_declaration (identifier) (parameters) (type_identifier))))) ================================================================================ Anonymous structural type with projection ================================================================================ type A = B[({ type f[x] = M[S, x] })#f] -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (generic_type (type_identifier) (type_arguments (projected_type (tuple_type (structural_type (type_definition (type_identifier) (type_parameters (identifier)) (generic_type (type_identifier) (type_arguments (type_identifier) (type_identifier)))))) (type_identifier)))))) ================================================================================ Type Lambdas (Scala 3) ================================================================================ type A = [B <: C] =>> D type Z = [X, Y] =>> Map[Y, X] class A[ [B <: C] =>> D ] -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (type_lambda (identifier) (upper_bound (type_identifier)) (type_identifier))) (type_definition (type_identifier) (type_lambda (identifier) (identifier) (generic_type (type_identifier) (type_arguments (type_identifier) (type_identifier))))) (class_definition (identifier) (type_parameters (type_lambda (identifier) (upper_bound (type_identifier)) (type_identifier))))) ================================================================================ Union and Intersection Types (Scala 3) ================================================================================ type A = Foo | Bar & Buz type B = "foo" | "bar" & "buz" -------------------------------------------------------------------------------- (compilation_unit (type_definition (type_identifier) (infix_type (infix_type (type_identifier) (operator_identifier) (type_identifier)) (operator_identifier) (type_identifier))) (type_definition (type_identifier) (infix_type (infix_type (literal_type (string)) (operator_identifier) (literal_type (string))) (operator_identifier) (literal_type (string))))) ================================================================================ Applied Constructor Types (Scala 3) ================================================================================ val c: C(42) -------------------------------------------------------------------------------- (compilation_unit (val_declaration (identifier) (applied_constructor_type (type_identifier) (arguments (integer_literal))))) ================================================ FILE: test/highlight/basics.scala ================================================ import java.time.Instant //^include // ^namespace // ^type object Hello { // ^ keyword // ^ type val x = if (true) (25 * 1.0) else "hello" // ^keyword // ^variable // ^conditional // ^boolean // ^number // ^float // ^string // ^conditional val y = new lower_case_intentionally // ^keyword.operator // ^type var mutation = "mutant" // ^keyword // ^variable trait Test { // ^ keyword // ^ type def meth(i: Int)(implicit x: Boolean) = ??? // ^keyword.function // ^keyword // ^type // ^method // ^parameter val anonFun: Int => Int = (a: Int) => a // ^variable // ^type // ^operator // ^type // ^parameter } protected abstract class Bla(test: String) // ^type.qualifier // ^keyword // ^type.qualifier // ^parameter // ^type type Hello = "25" // ^keyword // ^type.definition // ^string class A { // ^ keyword // ^ type self: X => // ^parameter // ^type } type A = { def fly(): Unit } // ^keyword.function // ^method // ^type type A = B[({ type f[x] = M[S, x] })#f] // ^keyword // ^type.definition val hello = c"some $mutation ${1}" // ^function.call // ^punctuation.special // ^variable // ^number def meth = ??? // ^method val hello2 = c"some $meth" // ^method val hello3 = s"$$$meth$hello2%" // ^string // ^punctuation.special // ^method // ^punctuation.special // ^variable // ^string val hello4 = s"$"$hello3" // ^string // ^punctuation.special // ^variable } ================================================ FILE: test/highlight/comments.scala ================================================ //> using scala 3.1.0 // ^keyword // ^parameter // ^string /* * Beep boop */ // <- comment // Single line comment // <- comment ================================================ FILE: test/highlight/scala3.scala ================================================ // Optional braces syntax class C: // ^keyword // ^type def test(aaaa: A): Int = //^keyword.function // ^method // no curly braces, but this is still in test method val bbb = 1 //^keyword // ^variable val ccc = 2 //^keyword // ^variable 1 object O1: //^keyword // ^type def test: Unit = () //^keyword.function // ^method object O2: type Elem[A] = A match //^keyword // ^type.definition case String => Char //^keyword // ^type ^type case Array[a] => a // ^type ^type // SIP-44 class C: // ^keyword // ^type fooooo.map: x => // ^method.call x + 1 xs.map: param1 => param1 + 1 foooo: // ^function.call println("") foooo `++`: // ^operator val x = 1 List(x) // This is an ascription val y = x: Int // ^type // This is SIP-44 val y = x: Int //^type // Ascription expression class C: foooo: Int // ^type enum Simple: //^keyword // ^type case A, B, C // ^type enum Test(a: Int) derives Codec: // ^keyword // ^type // ^type // ^keyword // ^type // ^type // ^parameter case Test(b: String) // ^keyword // ^type // ^type // ^parameter case Hello, Bla // ^type // ^type case Bla extends Test(256) // ^keyword opaque type Blow <: Int = 25 // ^type.qualifier // ^keyword // ^type // ^type.definition inline given Test = new Test { // ^ storageclass inline def hello(inline x: Boolean) = // ^ storageclass // ^ storageclass inline if x then "hi" else "bye" // ^storageclass // ^conditional inline x match // ^storageclass case true => 25 case false => 26 } object A: // ^ keyword // ^type ::(123) //^operator // ^number object bla: open class Hello(A: Int) // ^ type.qualifier transparent trait Hello // ^ type.qualifier infix def hello = 25 // ^ keyword extension (s: String) // ^keyword def test = 25 def test2 = 25 val extension = "hello" // ^variable - to test "soft" keywords given Test with // ^keyword // ^type // ^keyword def test = 1 // ^keyword.function val a = "hello" class Copier: private val printUnit = new Printer { type PrinterType = InkJet } private val scanUnit = new Scanner export scanUnit.scan // ^ include // ^variable export printUnit.{status as _, *} // ^ include // ^variable def status: List[String] = printUnit.status ++ scanUnit.status ================================================ FILE: test/tags/basics.scala ================================================ package com.example // ^definition.module enum Color: // ^definition.enum case Red // ^definition.class case Green // ^definition.class case Yellow // ^definition.class trait Fruit: // ^definition.interface val color: Color // ^definition.variable object Fruit: // ^definition.object case object Banana extends Fruit { // ^definition.object // ^reference.class val color = Color.Yellow // ^definition.variable } case class Apple(c: Color.Red | Color.Green) extends Fruit { // ^definition.class // ^definition.property // ^reference.class val color = c // ^definition.variable } given show: Show[Fruit] = new Show[Fruit] { } // ^definition.variable // ^reference.interface def color(fruit: Fruit): String = ??? // ^definition.function var flag: Boolean = true // ^definition.variable ================================================ FILE: tree-sitter.json ================================================ { "grammars": [ { "name": "scala", "camelcase": "Scala", "scope": "source.scala", "path": ".", "file-types": [ "scala", "sbt" ], "highlights": "queries/highlights.scm", "locals": "queries/locals.scm", "tags": "queries/tags.scm" } ], "metadata": { "version": "0.26.0", "license": "MIT", "description": "Scala grammar for tree-sitter", "authors": [ { "name": "Max Brunsfeld", "email": "maxbrunsfeld@gmail.com" } ], "links": { "repository": "https://github.com/tree-sitter/tree-sitter-scala" } }, "bindings": { "c": true, "go": true, "node": true, "python": true, "rust": true, "swift": true } }