mirror of https://github.com/Wilfred/difftastic/
Merge remote-tracking branch 'cherryblossom/swift'
commit
62e5b21d53
@ -0,0 +1,3 @@
|
|||||||
|
func f(_ x: Int) -> Int {
|
||||||
|
x * 3
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
func f(_ x: Int) -> Int {
|
||||||
|
x * 2
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
../tree-sitter-swift/queries/highlights.scm
|
||||||
@ -0,0 +1 @@
|
|||||||
|
tree-sitter-swift/src
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
name: Check compilation/bindings/style
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x, 14.x, 16.x]
|
||||||
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
cache: 'npm'
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run ci
|
||||||
|
- run: npm run test-ci
|
||||||
|
- run: make install
|
||||||
|
env:
|
||||||
|
PREFIX: /tmp
|
||||||
|
- run: cargo test
|
||||||
|
- run: cd ./test-npm-package && npm test; cd -
|
||||||
|
- run: npm pack && cd .. && npm install -g ./tree-sitter-swift/tree-sitter-swift-*.tgz; cd -
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
name: Check in static grammar files
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
generate_grammar:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- run: ./scripts/write-generated-grammar.sh ${{github.ref}}
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
name: Publish `grammar.json` and `parser.c`
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: 16.x
|
||||||
|
cache: 'npm'
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run test-ci
|
||||||
|
- name: Publish parser source
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: generated-parser-src
|
||||||
|
path: src
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
name: Publish to `npm` and `crates.io`
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ["Parse top repositories"]
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
npm_publish:
|
||||||
|
if: ${{ github.ref == 'refs/heads/main' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
type: ${{ steps.npm_publish.outputs.type }}
|
||||||
|
package_version: ${{ steps.npm_publish.outputs.version }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run test-ci
|
||||||
|
- run: cd ./test-npm-package && npm test; cd ..
|
||||||
|
- uses: JS-DevTools/npm-publish@v1
|
||||||
|
id: npm_publish
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.NPM_TOKEN }}
|
||||||
|
crates_io_publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: npm_publish
|
||||||
|
if: ${{ needs.npm_publish.outputs.type != 'none' }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
override: true
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run test-ci
|
||||||
|
- run: cargo test
|
||||||
|
- uses: katyo/publish-crates@v1
|
||||||
|
with:
|
||||||
|
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||||
|
args: --allow-dirty
|
||||||
|
badge_update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- npm_publish
|
||||||
|
- crates_io_publish
|
||||||
|
steps:
|
||||||
|
- name: Update crates.io badge
|
||||||
|
uses: RubbaBoy/BYOB@v1.3.0
|
||||||
|
with:
|
||||||
|
NAME: crates_io_version
|
||||||
|
LABEL: 'crates.io'
|
||||||
|
STATUS: ${{ needs.npm_publish.outputs.package_version }}
|
||||||
|
COLOR: green
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Update npm badge
|
||||||
|
uses: RubbaBoy/BYOB@v1.3.0
|
||||||
|
with:
|
||||||
|
NAME: npm_version
|
||||||
|
LABEL: 'npm'
|
||||||
|
STATUS: ${{ needs.npm_publish.outputs.package_version }}
|
||||||
|
COLOR: green
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
name: Parse top repositories
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
repo:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
- 4
|
||||||
|
- 5
|
||||||
|
- 6
|
||||||
|
- 7
|
||||||
|
- 8
|
||||||
|
- 9
|
||||||
|
- 10
|
||||||
|
- 11
|
||||||
|
- 12
|
||||||
|
- 13
|
||||||
|
- 14
|
||||||
|
- 15
|
||||||
|
- 16
|
||||||
|
- 17
|
||||||
|
- 18
|
||||||
|
- 19
|
||||||
|
- 20
|
||||||
|
- 21
|
||||||
|
- 22
|
||||||
|
- 23
|
||||||
|
- 24
|
||||||
|
- 25
|
||||||
|
- 26
|
||||||
|
- 27
|
||||||
|
- 28
|
||||||
|
- 29
|
||||||
|
- 30
|
||||||
|
- 31
|
||||||
|
- 32
|
||||||
|
- 33
|
||||||
|
- 34
|
||||||
|
- 35
|
||||||
|
- 36
|
||||||
|
- 37
|
||||||
|
- 38
|
||||||
|
- 39
|
||||||
|
- 40
|
||||||
|
- 41
|
||||||
|
- 42
|
||||||
|
- 43
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: '16.x'
|
||||||
|
cache: 'npm'
|
||||||
|
- run: npm install
|
||||||
|
- run: ./scripts/top-repos.sh ${{matrix.repo}}
|
||||||
|
badge_gen:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- id: parse_rate
|
||||||
|
run: echo "##[set-output name=parse_rate;]$(./scripts/calculate-parse-rate.sh)"
|
||||||
|
- name: BYOB
|
||||||
|
if: ${{ github.event_name == 'push' }}
|
||||||
|
uses: RubbaBoy/BYOB@v1.3.0
|
||||||
|
with:
|
||||||
|
NAME: parse_rate
|
||||||
|
LABEL: 'Parse rate'
|
||||||
|
STATUS: ${{ steps.parse_rate.outputs.parse_rate }}
|
||||||
|
COLOR: blue
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
name: Update corpus repository versions
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '12 4 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update_repository_versions:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- run: ./scripts/update-top-repos.sh
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
node_modules
|
||||||
|
/src/*
|
||||||
|
!/src/scanner.c
|
||||||
|
!/src/parser.c
|
||||||
|
!/src/tree_sitter
|
||||||
|
*.swp
|
||||||
|
/build
|
||||||
|
/test
|
||||||
|
Cargo.lock
|
||||||
|
/target/*
|
||||||
|
*.a
|
||||||
|
*.dylib
|
||||||
|
*.so
|
||||||
|
*.o
|
||||||
|
bindings/c/*.h
|
||||||
|
bindings/c/tree-sitter-*.pc
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
build
|
||||||
|
coverage
|
||||||
|
src
|
||||||
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
[package]
|
||||||
|
name = "tree-sitter-swift"
|
||||||
|
description = "swift grammar for the tree-sitter parsing library"
|
||||||
|
version = "0.2.0"
|
||||||
|
keywords = ["incremental", "parsing", "swift"]
|
||||||
|
categories = ["parsing", "text-editors"]
|
||||||
|
repository = "https://github.com/alex-pinkus/tree-sitter-swift"
|
||||||
|
edition = "2018"
|
||||||
|
license = "MIT"
|
||||||
|
|
||||||
|
build = "bindings/rust/build.rs"
|
||||||
|
include = [
|
||||||
|
"bindings/rust/*",
|
||||||
|
"grammar.ts",
|
||||||
|
"queries/*",
|
||||||
|
"src/*",
|
||||||
|
]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "bindings/rust/lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tree-sitter = "~0.20.0"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
cc = "1.0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 alex-pinkus
|
||||||
|
|
||||||
|
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.
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
VERSION := 0.2.0
|
||||||
|
|
||||||
|
# Repository
|
||||||
|
SRC_DIR := src
|
||||||
|
|
||||||
|
PARSER_REPO_URL := $(shell git -C $(SRC_DIR) remote get-url origin )
|
||||||
|
|
||||||
|
ifeq (, $(PARSER_NAME))
|
||||||
|
PARSER_NAME := $(shell basename $(PARSER_REPO_URL))
|
||||||
|
PARSER_NAME := $(subst tree-sitter-,,$(PARSER_NAME))
|
||||||
|
PARSER_NAME := $(subst .git,,$(PARSER_NAME))
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq (, $(PARSER_URL))
|
||||||
|
PARSER_URL := $(subst :,/,$(PARSER_REPO_URL))
|
||||||
|
PARSER_URL := $(subst git@,https://,$(PARSER_URL))
|
||||||
|
PARSER_URL := $(subst .git,,$(PARSER_URL))
|
||||||
|
endif
|
||||||
|
|
||||||
|
UPPER_PARSER_NAME := $(shell echo $(PARSER_NAME) | tr a-z A-Z )
|
||||||
|
|
||||||
|
# install directory layout
|
||||||
|
PREFIX ?= /usr/local
|
||||||
|
INCLUDEDIR ?= $(PREFIX)/include
|
||||||
|
LIBDIR ?= $(PREFIX)/lib
|
||||||
|
PCLIBDIR ?= $(LIBDIR)/pkgconfig
|
||||||
|
|
||||||
|
# collect C++ sources, and link if necessary
|
||||||
|
CPPSRC := $(wildcard $(SRC_DIR)/*.cc)
|
||||||
|
|
||||||
|
ifeq (, $(CPPSRC))
|
||||||
|
ADDITIONALLIBS :=
|
||||||
|
else
|
||||||
|
ADDITIONALLIBS := -lc++
|
||||||
|
endif
|
||||||
|
|
||||||
|
# collect sources
|
||||||
|
SRC := $(wildcard $(SRC_DIR)/*.c)
|
||||||
|
SRC += $(CPPSRC)
|
||||||
|
OBJ := $(addsuffix .o,$(basename $(SRC)))
|
||||||
|
|
||||||
|
# ABI versioning
|
||||||
|
SONAME_MAJOR := 0
|
||||||
|
SONAME_MINOR := 0
|
||||||
|
|
||||||
|
CFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR)
|
||||||
|
CXXFLAGS ?= -O3 -Wall -Wextra -I$(SRC_DIR)
|
||||||
|
override CFLAGS += -std=gnu99 -fPIC
|
||||||
|
override CXXFLAGS += -fPIC
|
||||||
|
|
||||||
|
# OS-specific bits
|
||||||
|
ifeq ($(shell uname),Darwin)
|
||||||
|
SOEXT = dylib
|
||||||
|
SOEXTVER_MAJOR = $(SONAME_MAJOR).dylib
|
||||||
|
SOEXTVER = $(SONAME_MAJOR).$(SONAME_MINOR).dylib
|
||||||
|
LINKSHARED := $(LINKSHARED)-dynamiclib -Wl,
|
||||||
|
ifneq ($(ADDITIONALLIBS),)
|
||||||
|
LINKSHARED := $(LINKSHARED)$(ADDITIONALLIBS),
|
||||||
|
endif
|
||||||
|
LINKSHARED := $(LINKSHARED)-install_name,$(LIBDIR)/libtree-sitter-$(PARSER_NAME).$(SONAME_MAJOR).dylib,-rpath,@executable_path/../Frameworks
|
||||||
|
else
|
||||||
|
SOEXT = so
|
||||||
|
SOEXTVER_MAJOR = so.$(SONAME_MAJOR)
|
||||||
|
SOEXTVER = so.$(SONAME_MAJOR).$(SONAME_MINOR)
|
||||||
|
LINKSHARED := $(LINKSHARED)-shared -Wl,
|
||||||
|
ifneq ($(ADDITIONALLIBS),)
|
||||||
|
LINKSHARED := $(LINKSHARED)$(ADDITIONALLIBS)
|
||||||
|
endif
|
||||||
|
LINKSHARED := $(LINKSHARED)-soname,libtree-sitter-$(PARSER_NAME).so.$(SONAME_MAJOR)
|
||||||
|
endif
|
||||||
|
ifneq (,$(filter $(shell uname),FreeBSD NetBSD DragonFly))
|
||||||
|
PCLIBDIR := $(PREFIX)/libdata/pkgconfig
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: libtree-sitter-$(PARSER_NAME).a libtree-sitter-$(PARSER_NAME).$(SOEXTVER) bindings/c/$(PARSER_NAME).h bindings/c/tree-sitter-$(PARSER_NAME).pc
|
||||||
|
|
||||||
|
libtree-sitter-$(PARSER_NAME).a: $(OBJ)
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
|
libtree-sitter-$(PARSER_NAME).$(SOEXTVER): $(OBJ)
|
||||||
|
$(CC) $(LDFLAGS) $(LINKSHARED) $^ $(LDLIBS) -o $@
|
||||||
|
ln -sf $@ libtree-sitter-$(PARSER_NAME).$(SOEXT)
|
||||||
|
ln -sf $@ libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR)
|
||||||
|
|
||||||
|
bindings/c/$(PARSER_NAME).h:
|
||||||
|
sed -e 's|@UPPER_PARSERNAME@|$(UPPER_PARSER_NAME)|' \
|
||||||
|
-e 's|@PARSERNAME@|$(PARSER_NAME)|' \
|
||||||
|
bindings/c/tree-sitter.h.in > $@
|
||||||
|
|
||||||
|
bindings/c/tree-sitter-$(PARSER_NAME).pc:
|
||||||
|
sed -e 's|@LIBDIR@|$(LIBDIR)|;s|@INCLUDEDIR@|$(INCLUDEDIR)|;s|@VERSION@|$(VERSION)|' \
|
||||||
|
-e 's|=$(PREFIX)|=$${prefix}|' \
|
||||||
|
-e 's|@PREFIX@|$(PREFIX)|' \
|
||||||
|
-e 's|@ADDITIONALLIBS@|$(ADDITIONALLIBS)|' \
|
||||||
|
-e 's|@PARSERNAME@|$(PARSER_NAME)|' \
|
||||||
|
-e 's|@PARSERURL@|$(PARSER_URL)|' \
|
||||||
|
bindings/c/tree-sitter.pc.in > $@
|
||||||
|
|
||||||
|
install: all
|
||||||
|
install -d '$(DESTDIR)$(LIBDIR)'
|
||||||
|
install -m755 libtree-sitter-$(PARSER_NAME).a '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).a
|
||||||
|
install -m755 libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXTVER)
|
||||||
|
ln -sf libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR)
|
||||||
|
ln -sf libtree-sitter-$(PARSER_NAME).$(SOEXTVER) '$(DESTDIR)$(LIBDIR)'/libtree-sitter-$(PARSER_NAME).$(SOEXT)
|
||||||
|
install -d '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter
|
||||||
|
install -m644 bindings/c/$(PARSER_NAME).h '$(DESTDIR)$(INCLUDEDIR)'/tree_sitter/
|
||||||
|
install -d '$(DESTDIR)$(PCLIBDIR)'
|
||||||
|
install -m644 bindings/c/tree-sitter-$(PARSER_NAME).pc '$(DESTDIR)$(PCLIBDIR)'/
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJ) libtree-sitter-$(PARSER_NAME).a libtree-sitter-$(PARSER_NAME).$(SOEXT) libtree-sitter-$(PARSER_NAME).$(SOEXTVER_MAJOR) libtree-sitter-$(PARSER_NAME).$(SOEXTVER)
|
||||||
|
rm -f bindings/c/$(PARSER_NAME).h bindings/c/tree-sitter-$(PARSER_NAME).pc
|
||||||
|
|
||||||
|
.PHONY: all install clean
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|

|
||||||
|
[](https://crates.io/crates/tree-sitter-swift)
|
||||||
|
[](https://www.npmjs.com/package/tree-sitter-swift)
|
||||||
|
[](https://github.com/alex-pinkus/tree-sitter-swift/actions/workflows/top-repos.yml)
|
||||||
|
|
||||||
|
# tree-sitter-swift
|
||||||
|
|
||||||
|
This contains a [`tree-sitter`](https://tree-sitter.github.io/tree-sitter) grammar for the Swift programming language.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
To use this parser to parse Swift code, you'll want to depend on either the Rust crate or the NPM package.
|
||||||
|
|
||||||
|
### Rust
|
||||||
|
To use the Rust crate, you'll add this to your `Cargo.toml`:
|
||||||
|
```
|
||||||
|
tree-sitter = "0.20.0"
|
||||||
|
tree-sitter-swift = "=0.2.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can use a `tree-sitter` parser with the language declared here:
|
||||||
|
|
||||||
|
```
|
||||||
|
let mut parser = tree_sitter::Parser::new();
|
||||||
|
parser.set_language(tree_sitter_swift::language())?;
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
let tree = parser.parse(&my_source_code, None)
|
||||||
|
.ok_or_else(|| /* error handling code */)?;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Javascript
|
||||||
|
|
||||||
|
To use this from NPM, you'll add similar dependencies to `package.json`:
|
||||||
|
```
|
||||||
|
"dependencies: {
|
||||||
|
"tree-sitter-swift": "0.2.0",
|
||||||
|
"tree-sitter": "^0.20.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Your usage of the parser will look like:
|
||||||
|
```
|
||||||
|
const Parser = require("tree-sitter");
|
||||||
|
const Swift = require("tree-sitter-swift");
|
||||||
|
|
||||||
|
const parser = new Parser();
|
||||||
|
parser.setLanguage(Swift);
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const tree = parser.parse(mySourceCode);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Editing the grammar
|
||||||
|
|
||||||
|
With this package checked out, a common workflow for editing the grammar will look something like:
|
||||||
|
|
||||||
|
1. Make a change to `grammar.ts`.
|
||||||
|
2. Run `npm install && npm test` to see whether the change has had impact on existing parsing behavior. The default
|
||||||
|
`npm test` target requires `valgrind` to be installed; if you do not have it installed, and do not wish to, you can
|
||||||
|
substitute `tree-sitter test` directly.
|
||||||
|
3. Run `tree-sitter parse` on some real Swift codebase and see whether (or where) it fails.
|
||||||
|
4. Use any failures to create new corpus test cases.
|
||||||
|
|
||||||
|
## Contributions
|
||||||
|
|
||||||
|
If you have a change to make to this parser, and the change is a net positive, please submit a pull request. I mostly
|
||||||
|
started this parser to teach myself how `tree-sitter` works, and how to write a grammar, so I welcome improvements. If
|
||||||
|
you have an issue with the parser, please file a bug and include a test case to put in the `corpus`. I can't promise any
|
||||||
|
level of support, but having the test case makes it more likely that I want to tinker with it.
|
||||||
|
|
||||||
|
## Frequently asked questions
|
||||||
|
|
||||||
|
### Where is your `parser.c`?
|
||||||
|
|
||||||
|
This repository currently omits most of the code that is autogenerated during a build. This means, for instance, that
|
||||||
|
`grammar.json` and `parser.c` are both only available following a build. It also significantly reduces noise during
|
||||||
|
diffs.
|
||||||
|
|
||||||
|
The side benefit of not checking in `parser.c` is that you can guarantee backwards compatibility. Parsers generated by
|
||||||
|
the tree-sitter CLI aren't always backwards compatible. If you need a parser, generate it yourself using the CLI; all
|
||||||
|
the information to do so is available in this package. By doing that, you'll also know for sure that your parser version
|
||||||
|
and your library version are compatible.
|
||||||
|
|
||||||
|
If you need a `parser.c`, and you don't care about the tree-sitter version, but you don't have a local setup that would
|
||||||
|
allow you to obtain the parser, you can just download one from a recent workflow run in this package. To do so:
|
||||||
|
* Go to the [GitHub actions page](https://github.com/alex-pinkus/tree-sitter-swift/actions) for this
|
||||||
|
repository.
|
||||||
|
* Click on the "Publish `grammar.json` and `parser.c`" action for the appropriate commit.
|
||||||
|
* Go down to `Artifacts` and click on `generated-parser-src`. All the relevant parser files will be available in your
|
||||||
|
download.
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"target_name": "tree_sitter_swift_binding",
|
||||||
|
"include_dirs": [
|
||||||
|
"<!(node -e \"require('nan')\")",
|
||||||
|
"src"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
"bindings/node/binding.cc",
|
||||||
|
"src/parser.c",
|
||||||
|
"src/scanner.c"
|
||||||
|
],
|
||||||
|
"cflags_c": [
|
||||||
|
"-std=c99",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef TREE_SITTER_@UPPER_PARSERNAME@_H_
|
||||||
|
#define TREE_SITTER_@UPPER_PARSERNAME@_H_
|
||||||
|
|
||||||
|
#include <tree_sitter/parser.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern TSLanguage *tree_sitter_@PARSERNAME@();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // TREE_SITTER_@UPPER_PARSERNAME@_H_
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
prefix=@PREFIX@
|
||||||
|
libdir=@LIBDIR@
|
||||||
|
includedir=@INCLUDEDIR@
|
||||||
|
additionallibs=@ADDITIONALLIBS@
|
||||||
|
|
||||||
|
Name: tree-sitter-@PARSERNAME@
|
||||||
|
Description: A tree-sitter grammar for the @PARSERNAME@ programming language.
|
||||||
|
URL: @PARSERURL@
|
||||||
|
Version: @VERSION@
|
||||||
|
Libs: -L${libdir} ${additionallibs} -ltree-sitter-@PARSERNAME@
|
||||||
|
Cflags: -I${includedir}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
#include "tree_sitter/parser.h"
|
||||||
|
#include <node.h>
|
||||||
|
#include "nan.h"
|
||||||
|
|
||||||
|
using namespace v8;
|
||||||
|
|
||||||
|
extern "C" TSLanguage * tree_sitter_swift();
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
NAN_METHOD(New) {}
|
||||||
|
|
||||||
|
void Init(Local<Object> exports, Local<Object> module) {
|
||||||
|
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
|
||||||
|
tpl->SetClassName(Nan::New("Language").ToLocalChecked());
|
||||||
|
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
|
|
||||||
|
Local<Function> constructor = Nan::GetFunction(tpl).ToLocalChecked();
|
||||||
|
Local<Object> instance = constructor->NewInstance(Nan::GetCurrentContext()).ToLocalChecked();
|
||||||
|
Nan::SetInternalFieldPointer(instance, 0, tree_sitter_swift());
|
||||||
|
|
||||||
|
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("swift").ToLocalChecked());
|
||||||
|
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
NODE_MODULE(tree_sitter_swift_binding, Init)
|
||||||
|
|
||||||
|
} // namespace
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
try {
|
||||||
|
module.exports = require("../../build/Release/tree_sitter_swift_binding");
|
||||||
|
} catch (error1) {
|
||||||
|
if (error1.code !== "MODULE_NOT_FOUND") {
|
||||||
|
throw error1;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
module.exports = require("../../build/Debug/tree_sitter_swift_binding");
|
||||||
|
} catch (error2) {
|
||||||
|
if (error2.code !== "MODULE_NOT_FOUND") {
|
||||||
|
throw error2;
|
||||||
|
}
|
||||||
|
throw error1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
module.exports.nodeTypeInfo = require("../../src/node-types.json");
|
||||||
|
} catch (_) {}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
fn main() {
|
||||||
|
let src_dir = std::path::Path::new("src");
|
||||||
|
|
||||||
|
let mut c_config = cc::Build::new();
|
||||||
|
c_config.include(&src_dir);
|
||||||
|
c_config
|
||||||
|
.flag_if_supported("-Wno-unused-parameter")
|
||||||
|
.flag_if_supported("-Wno-unused-but-set-variable")
|
||||||
|
.flag_if_supported("-Wno-trigraphs");
|
||||||
|
let parser_path = src_dir.join("parser.c");
|
||||||
|
c_config.file(&parser_path);
|
||||||
|
|
||||||
|
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("parser");
|
||||||
|
println!("cargo:rerun-if-changed={}", parser_path.to_str().unwrap());
|
||||||
|
}
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
//! This crate provides swift language support for the [tree-sitter][] parsing library.
|
||||||
|
//!
|
||||||
|
//! Typically, you will use the [language][language func] function to add this language to a
|
||||||
|
//! tree-sitter [Parser][], and then use the parser to parse some code:
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! let code = "";
|
||||||
|
//! let mut parser = tree_sitter::Parser::new();
|
||||||
|
//! parser.set_language(tree_sitter_swift::language()).expect("Error loading swift grammar");
|
||||||
|
//! let tree = parser.parse(code, None).unwrap();
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
|
||||||
|
//! [language func]: fn.language.html
|
||||||
|
//! [Parser]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html
|
||||||
|
//! [tree-sitter]: https://tree-sitter.github.io/
|
||||||
|
|
||||||
|
use tree_sitter::Language;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn tree_sitter_swift() -> Language;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the tree-sitter [Language][] for this grammar.
|
||||||
|
///
|
||||||
|
/// [Language]: https://docs.rs/tree-sitter/*/tree_sitter/struct.Language.html
|
||||||
|
pub fn language() -> Language {
|
||||||
|
unsafe { tree_sitter_swift() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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: &'static str = include_str!("../../src/node-types.json");
|
||||||
|
|
||||||
|
// Uncomment these to include any queries that this grammar contains
|
||||||
|
|
||||||
|
// pub const HIGHLIGHTS_QUERY: &'static str = include_str!("../../queries/highlights.scm");
|
||||||
|
// pub const INJECTIONS_QUERY: &'static str = include_str!("../../queries/injections.scm");
|
||||||
|
// pub const LOCALS_QUERY: &'static str = include_str!("../../queries/locals.scm");
|
||||||
|
// pub const TAGS_QUERY: &'static str = include_str!("../../queries/tags.scm");
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_can_load_grammar() -> Result<()> {
|
||||||
|
let mut parser = tree_sitter::Parser::new();
|
||||||
|
parser.set_language(super::language())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_can_parse_basic_file() -> Result<()> {
|
||||||
|
let mut parser = tree_sitter::Parser::new();
|
||||||
|
parser.set_language(super::language())?;
|
||||||
|
|
||||||
|
let tree = parser.parse("_ = \"Hello!\"\n", None)
|
||||||
|
.ok_or_else(|| anyhow!("Unable to parse!"))?;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
"(source_file (assignment target: (directly_assignable_expression (simple_identifier)) result: (line_string_literal text: (line_str_text))))",
|
||||||
|
tree.root_node().to_sexp(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
==================
|
||||||
|
Annotations
|
||||||
|
==================
|
||||||
|
|
||||||
|
@Test
|
||||||
|
class Empty { }
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(class_declaration
|
||||||
|
(modifiers (attribute (user_type (type_identifier))))
|
||||||
|
(type_identifier)
|
||||||
|
(class_body)))
|
||||||
|
|
||||||
|
==================
|
||||||
|
Multiple annotations on a variable
|
||||||
|
==================
|
||||||
|
|
||||||
|
class X {
|
||||||
|
@A @B
|
||||||
|
override let s: String
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(class_declaration
|
||||||
|
(type_identifier)
|
||||||
|
(class_body
|
||||||
|
(property_declaration
|
||||||
|
(modifiers
|
||||||
|
(attribute (user_type (type_identifier)))
|
||||||
|
(attribute (user_type (type_identifier)))
|
||||||
|
(member_modifier))
|
||||||
|
(value_binding_pattern (non_binding_pattern (simple_identifier)))
|
||||||
|
(type_annotation (user_type (type_identifier)))))))
|
||||||
|
|
||||||
|
|
||||||
|
==================
|
||||||
|
Multiple annotations on a function
|
||||||
|
==================
|
||||||
|
|
||||||
|
class X {
|
||||||
|
@A @B
|
||||||
|
func s() -> String { }
|
||||||
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(class_declaration
|
||||||
|
(type_identifier)
|
||||||
|
(class_body
|
||||||
|
(function_declaration
|
||||||
|
(modifiers
|
||||||
|
(attribute (user_type (type_identifier)))
|
||||||
|
(attribute (user_type (type_identifier))))
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type (type_identifier))
|
||||||
|
(function_body)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,103 @@
|
|||||||
|
================================================================================
|
||||||
|
Comments
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
1 + 2
|
||||||
|
// 1 + 2
|
||||||
|
/* Hello world */
|
||||||
|
/** I am a doc comment */
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(additive_expression
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal))
|
||||||
|
(comment)
|
||||||
|
(multiline_comment)
|
||||||
|
(multiline_comment))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Nested Comments
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is how comments work: //
|
||||||
|
Also like this: /* */
|
||||||
|
|
||||||
|
func doesNotExist() {
|
||||||
|
// This should not show up in the AST
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is the same but with different whitespace: /*
|
||||||
|
*/
|
||||||
|
|
||||||
|
func alsoDoesNotExist() { }
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// /*
|
||||||
|
/* * */
|
||||||
|
func doesExist() { }
|
||||||
|
|
||||||
|
/*/*/* triple nested */*/*/
|
||||||
|
|
||||||
|
/****
|
||||||
|
/****
|
||||||
|
nested with extra stars
|
||||||
|
****/
|
||||||
|
****/
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(multiline_comment)
|
||||||
|
(multiline_comment)
|
||||||
|
(comment)
|
||||||
|
(multiline_comment)
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(function_body))
|
||||||
|
(multiline_comment)
|
||||||
|
(multiline_comment))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Almost nested comments
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is allowed in a comment but does not nest: /
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Same with this: *
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
And even this: / *
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(multiline_comment)
|
||||||
|
(multiline_comment)
|
||||||
|
(multiline_comment))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Single line comment at the end of a non-empty file
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
class SwiftExamples {
|
||||||
|
}
|
||||||
|
// Some comment
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(class_declaration
|
||||||
|
(type_identifier)
|
||||||
|
(class_body))
|
||||||
|
(comment))
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,820 @@
|
|||||||
|
================================================================================
|
||||||
|
Top-level functions
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(function_body)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Generic functions
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func test<T>(t: T) {}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(type_parameters
|
||||||
|
(type_parameter
|
||||||
|
(type_identifier)))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(function_body)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Static functions
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
static func help() {}
|
||||||
|
static func === (lhs: MyType, rhs: MyType) { }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(modifiers
|
||||||
|
(property_modifier))
|
||||||
|
(simple_identifier)
|
||||||
|
(function_body))
|
||||||
|
(function_declaration
|
||||||
|
(modifiers
|
||||||
|
(property_modifier))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(function_body)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Functions with parameters
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func main(args: [String]) {}
|
||||||
|
|
||||||
|
func maybe_main(args: Maybe<String>) {}
|
||||||
|
|
||||||
|
func convert(@Arg args: [String: Int]) {}
|
||||||
|
|
||||||
|
func sum(a: Int, b: Int!) { return a + b }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(array_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(function_body))
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))
|
||||||
|
(function_body))
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(attribute
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(dictionary_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(function_body))
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(additive_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Functions with renamed parameters
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func sum(_ a: Int, with b: Int) { return a + b }
|
||||||
|
|
||||||
|
sum(1, with: 2)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(additive_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier))))))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments
|
||||||
|
(value_argument
|
||||||
|
(integer_literal))
|
||||||
|
(value_argument
|
||||||
|
(simple_identifier)
|
||||||
|
(integer_literal))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Functions with return types
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func answerToTheUltimateQuestionOfLifeTheUniverseAndEverything() -> Int { return 42 }
|
||||||
|
func getConfig() -> [String: Int] {
|
||||||
|
return [
|
||||||
|
"TimeoutMillis": 1000,
|
||||||
|
"RetryCount": 5,
|
||||||
|
"RetryBackoffMillis": 5000
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
func returnGetsImplicitlyUnwrapped() -> String! {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(integer_literal)))))
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(dictionary_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(dictionary_literal
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(integer_literal)
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(integer_literal)
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(integer_literal))))))
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Variadic functions
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func toUpperCaseAll(strings: String ...) -> [String] { }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(array_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(function_body)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Operator overrides
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
public static func < (lhs: Wrapped<F>, rhs: Wrapped<F>) -> Bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
public func ??<V : Value>(optional: Expression<V?>, defaultValue: V) -> Expression<V> {
|
||||||
|
return Expression(optional.inner() ?? defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
public prefix func ! (value: Wrapped<F>) -> Bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(modifiers
|
||||||
|
(visibility_modifier)
|
||||||
|
(property_modifier))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(boolean_literal)))))
|
||||||
|
(function_declaration
|
||||||
|
(modifiers
|
||||||
|
(visibility_modifier))
|
||||||
|
(custom_operator)
|
||||||
|
(type_parameters
|
||||||
|
(type_parameter
|
||||||
|
(type_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(optional_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))))
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments
|
||||||
|
(value_argument
|
||||||
|
(nil_coalescing_expression
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(simple_identifier))))))))))
|
||||||
|
(function_declaration
|
||||||
|
(modifiers
|
||||||
|
(visibility_modifier)
|
||||||
|
(function_modifier))
|
||||||
|
(bang)
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(boolean_literal))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Custom operators
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
precedencegroup MyPrecedence {
|
||||||
|
associativity: left
|
||||||
|
assignment: true
|
||||||
|
lowerThan: AdditionPrecedence
|
||||||
|
}
|
||||||
|
|
||||||
|
infix operator -=- : MyPrecedence
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(precedence_group_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(precedence_group_attributes
|
||||||
|
(precedence_group_attribute
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier))
|
||||||
|
(precedence_group_attribute
|
||||||
|
(simple_identifier)
|
||||||
|
(boolean_literal))
|
||||||
|
(precedence_group_attribute
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier))))
|
||||||
|
(operator_declaration
|
||||||
|
(custom_operator)
|
||||||
|
(simple_identifier)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Custom operator with another operator as a prefix
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
let messageCoerced = error ??? "nil"
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(infix_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(custom_operator)
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Functions that throw
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func anythingYouCanDo() throws -> Int { return -1 }
|
||||||
|
func iCanDoBetter()
|
||||||
|
throws
|
||||||
|
-> Int { return -2 }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(throws)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(prefix_expression
|
||||||
|
(integer_literal))))))
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(throws)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(prefix_expression
|
||||||
|
(integer_literal)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Async functions
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func eventually() async -> Int { return -1 }
|
||||||
|
func maybe()
|
||||||
|
async
|
||||||
|
throws
|
||||||
|
-> Int { return -2 }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(async)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(prefix_expression
|
||||||
|
(integer_literal))))))
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(async)
|
||||||
|
(throws)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(prefix_expression
|
||||||
|
(integer_literal)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 1
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func test(i: Int = 0, block: (Int) throws -> Void) {}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(integer_literal)
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(function_type
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(throws)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(function_body)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 2
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
test { value in /* does nothing */ }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(lambda_function_type
|
||||||
|
(lambda_function_type_parameters
|
||||||
|
(lambda_parameter
|
||||||
|
(simple_identifier))))
|
||||||
|
(multiline_comment)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 3
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
test(2) { $0.doSomething() }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments
|
||||||
|
(value_argument
|
||||||
|
(integer_literal)))))
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(statements
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 4
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
test { (a) -> Void in }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(lambda_function_type
|
||||||
|
(lambda_function_type_parameters
|
||||||
|
(lambda_parameter
|
||||||
|
(simple_identifier)))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 5
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
test { (a: inout Int) in }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(lambda_function_type
|
||||||
|
(lambda_function_type_parameters
|
||||||
|
(lambda_parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(parameter_modifiers
|
||||||
|
(parameter_modifier))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 6
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
test { @Special [weak self, otherSelf] (a) in }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(capture_list
|
||||||
|
(attribute
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(capture_list_item
|
||||||
|
(ownership_modifier)
|
||||||
|
(simple_identifier))
|
||||||
|
(capture_list_item
|
||||||
|
(simple_identifier)))
|
||||||
|
(lambda_function_type
|
||||||
|
(lambda_function_type_parameters
|
||||||
|
(lambda_parameter
|
||||||
|
(simple_identifier))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 7
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
test(block: ===)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments
|
||||||
|
(value_argument
|
||||||
|
(simple_identifier))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 8
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
test { ($0, someVariable) }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(statements
|
||||||
|
(tuple_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 9
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
test { (self, a) -> Void in }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(lambda_function_type
|
||||||
|
(lambda_function_type_parameters
|
||||||
|
(lambda_parameter
|
||||||
|
(self_expression))
|
||||||
|
(lambda_parameter
|
||||||
|
(simple_identifier)))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 10
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
test { (a: Any?) in foo(a) }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(lambda_function_type
|
||||||
|
(lambda_function_type_parameters
|
||||||
|
(lambda_parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(optional_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))))
|
||||||
|
(statements
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments
|
||||||
|
(value_argument
|
||||||
|
(simple_identifier))))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Higher-order functions - pt 11
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
types.flatMap { [abc, 1] }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(statements
|
||||||
|
(array_literal
|
||||||
|
(simple_identifier)
|
||||||
|
(integer_literal)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Function type with wildcard
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
private lazy var onCatClosure: (_ cat: Cat) throws -> Void = { _ in
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(modifiers
|
||||||
|
(visibility_modifier)
|
||||||
|
(property_behavior_modifier))
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(type_annotation
|
||||||
|
(function_type
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(wildcard_pattern)
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(throws)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(lambda_literal
|
||||||
|
(lambda_function_type
|
||||||
|
(lambda_function_type_parameters
|
||||||
|
(lambda_parameter
|
||||||
|
(simple_identifier)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Multiple trailing lambdas
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
myInstance.registerCallbacks { } onCancelled: { }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal)
|
||||||
|
(simple_identifier)
|
||||||
|
(lambda_literal))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Return type fun
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func opaqueType() -> some Equatable { return "" }
|
||||||
|
func multipleType() -> Foo & Bar { return Foo() }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(opaque_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(line_string_literal)))))
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(protocol_composition_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Annotated function parameters in lambdas
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
types.flatMap { @Sendable _ in }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(lambda_literal
|
||||||
|
(lambda_function_type
|
||||||
|
(lambda_function_type_parameters
|
||||||
|
(lambda_parameter
|
||||||
|
(attribute
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(simple_identifier))))))))
|
||||||
@ -0,0 +1,433 @@
|
|||||||
|
================================================================================
|
||||||
|
Simple identifiers
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
helloWorld
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(simple_identifier))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Boolean literals
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
true
|
||||||
|
false
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(boolean_literal)
|
||||||
|
(boolean_literal))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
String literals
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
"Hello World!"
|
||||||
|
"""
|
||||||
|
This is a "multiline"
|
||||||
|
string.
|
||||||
|
"""
|
||||||
|
"This string has a // comment (except not!)"
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(multi_line_string_literal
|
||||||
|
(multi_line_str_text)
|
||||||
|
(multi_line_str_text)
|
||||||
|
(multi_line_str_text))
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
String interpolation
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
"Sample \("string.interpolation") literal"
|
||||||
|
"""
|
||||||
|
Multiline
|
||||||
|
\("""string interpolation""") literal
|
||||||
|
"""
|
||||||
|
"This is a string with // a comment in it"
|
||||||
|
"""
|
||||||
|
And so is this! /*
|
||||||
|
#if qwertyuiop
|
||||||
|
And yet neither of those comments should register
|
||||||
|
""" // This comment is valid
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)
|
||||||
|
(interpolated_expression
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))
|
||||||
|
(line_str_text))
|
||||||
|
(multi_line_string_literal
|
||||||
|
(multi_line_str_text)
|
||||||
|
(interpolated_expression
|
||||||
|
(multi_line_string_literal
|
||||||
|
(multi_line_str_text)))
|
||||||
|
(multi_line_str_text))
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(multi_line_string_literal
|
||||||
|
(multi_line_str_text))
|
||||||
|
(comment))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Custom interpolation
|
||||||
|
================================================================================
|
||||||
|
"Hi, I'm \(format: age)"
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)
|
||||||
|
(interpolated_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Strings with newline escaping
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
"""
|
||||||
|
This is a string that acts as though it \
|
||||||
|
is all on one line
|
||||||
|
"""
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(multi_line_string_literal
|
||||||
|
(multi_line_str_text)
|
||||||
|
(str_escaped_char)
|
||||||
|
(multi_line_str_text)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Integer literals
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
0
|
||||||
|
8
|
||||||
|
23
|
||||||
|
9847
|
||||||
|
0xf00
|
||||||
|
0o774
|
||||||
|
0b01
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)
|
||||||
|
(hex_literal)
|
||||||
|
(oct_literal)
|
||||||
|
(bin_literal))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Real literals
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
0.0
|
||||||
|
-23.434
|
||||||
|
1e-10
|
||||||
|
4.3
|
||||||
|
+53.9e-3
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(real_literal)
|
||||||
|
(prefix_expression
|
||||||
|
(real_literal))
|
||||||
|
(real_literal)
|
||||||
|
(real_literal)
|
||||||
|
(prefix_expression
|
||||||
|
(real_literal)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Collections
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
let numbers = [1, 2, 3]
|
||||||
|
let numerals = [1: "I", 4: "IV", 5: "V", 10: "X"]
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(array_literal
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(dictionary_literal
|
||||||
|
(integer_literal)
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(integer_literal)
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(integer_literal)
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(integer_literal)
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Trailing commas
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
[
|
||||||
|
"Time": Date.now(),
|
||||||
|
"Success": true,
|
||||||
|
]
|
||||||
|
|
||||||
|
[1, 2, 3, 4, 5,]
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(dictionary_literal
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))
|
||||||
|
(boolean_literal))
|
||||||
|
(array_literal
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Nil
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
let _ = nil
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(wildcard_pattern)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Raw strings
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
let _ = #"Hello, world!"#
|
||||||
|
let _ = ##"Hello, so-called "world"!"##
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(wildcard_pattern)))
|
||||||
|
(raw_string_literal
|
||||||
|
(raw_str_end_part)))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(wildcard_pattern)))
|
||||||
|
(raw_string_literal
|
||||||
|
(raw_str_end_part))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Doesn't hang for incomplete raw strings (issue #146)
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
let _ = #"Foo"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(wildcard_pattern)))
|
||||||
|
(ERROR
|
||||||
|
(UNEXPECTED '"'))
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Raw strings with interpolation
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
extension URL {
|
||||||
|
func html(withTitle title: String) -> String {
|
||||||
|
return #"<a href="\#(absoluteString)">\#(title)</a>"#
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(class_declaration
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(class_body
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(parameter
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(raw_string_literal
|
||||||
|
(raw_str_part)
|
||||||
|
(raw_str_interpolation
|
||||||
|
(raw_str_interpolation_start)
|
||||||
|
(interpolated_expression
|
||||||
|
(simple_identifier)))
|
||||||
|
(raw_str_part)
|
||||||
|
(raw_str_interpolation
|
||||||
|
(raw_str_interpolation_start)
|
||||||
|
(interpolated_expression
|
||||||
|
(simple_identifier)))
|
||||||
|
(raw_str_end_part)))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Raw strings interpolation edge cases
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
print(#"Hello \#(world /* commented out)"#) */ )"#)
|
||||||
|
|
||||||
|
let _ = ##"Multiple pound signs \##(interpolated): still one part "# not done yet "##
|
||||||
|
let _ = ##"Fake \#(interpolation) and unused # pound signs "##
|
||||||
|
let _ = ##"\##(a)\#(b)\##(c)\#(d)"# ##"##
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments
|
||||||
|
(value_argument
|
||||||
|
(raw_string_literal
|
||||||
|
(raw_str_part)
|
||||||
|
(raw_str_interpolation
|
||||||
|
(raw_str_interpolation_start)
|
||||||
|
(interpolated_expression
|
||||||
|
(simple_identifier))
|
||||||
|
(multiline_comment))
|
||||||
|
(raw_str_end_part))))))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(wildcard_pattern)))
|
||||||
|
(raw_string_literal
|
||||||
|
(raw_str_part)
|
||||||
|
(raw_str_interpolation
|
||||||
|
(raw_str_interpolation_start)
|
||||||
|
(interpolated_expression
|
||||||
|
(simple_identifier)))
|
||||||
|
(raw_str_end_part)))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(wildcard_pattern)))
|
||||||
|
(raw_string_literal
|
||||||
|
(raw_str_end_part)))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(wildcard_pattern)))
|
||||||
|
(raw_string_literal
|
||||||
|
(raw_str_part)
|
||||||
|
(raw_str_interpolation
|
||||||
|
(raw_str_interpolation_start)
|
||||||
|
(interpolated_expression
|
||||||
|
(simple_identifier)))
|
||||||
|
(raw_str_part)
|
||||||
|
(raw_str_interpolation
|
||||||
|
(raw_str_interpolation_start)
|
||||||
|
(interpolated_expression
|
||||||
|
(simple_identifier)))
|
||||||
|
(raw_str_end_part))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Unicode escape sequences
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
let unicodeEscaping = "\u{8}"
|
||||||
|
let anotherUnicode = "…\u{2060}"
|
||||||
|
let infinity = "\u{221E}"
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(line_string_literal
|
||||||
|
(str_escaped_char)))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)
|
||||||
|
(str_escaped_char)))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(line_string_literal
|
||||||
|
(str_escaped_char))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Playground literals
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
let playgroundLiteral = #imageLiteral(resourceName: "heart")
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(simple_identifier)
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))))
|
||||||
@ -0,0 +1,988 @@
|
|||||||
|
================================================================================
|
||||||
|
Let statements
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
let singleVariable = 1
|
||||||
|
let (tuple1, tuple2) = (2, 3)
|
||||||
|
let `default` = 0
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier))
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier))))
|
||||||
|
(tuple_expression
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
C-style compound declaration
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
var one = 1, two = 2, four = 4, eight = 8
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal)
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal)
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal)
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
For statements
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
for value: MyType in values {
|
||||||
|
print(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
for case .some(value) in valuesMaybe { }
|
||||||
|
|
||||||
|
for case .some((.some(0), .some(1))) in crazyValues {
|
||||||
|
}
|
||||||
|
|
||||||
|
for var value in values where value.isExcellent() {
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(for_statement
|
||||||
|
(simple_identifier)
|
||||||
|
(type_annotation
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(simple_identifier)
|
||||||
|
(statements
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments
|
||||||
|
(value_argument
|
||||||
|
(simple_identifier)))))))
|
||||||
|
(for_statement
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier))
|
||||||
|
(for_statement
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)
|
||||||
|
(integer_literal)
|
||||||
|
(simple_identifier)
|
||||||
|
(integer_literal)
|
||||||
|
(simple_identifier))
|
||||||
|
(for_statement
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier))
|
||||||
|
(simple_identifier)
|
||||||
|
(where_clause
|
||||||
|
(where_keyword)
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Weird for statements
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
for case let fileUrl as URL in directory {
|
||||||
|
}
|
||||||
|
|
||||||
|
for case let (a, b?) in tuples {
|
||||||
|
}
|
||||||
|
|
||||||
|
outerLoop: for outerObject in dataArray {
|
||||||
|
for innerObject in comparisonArray {
|
||||||
|
if outerObject == innerObject {
|
||||||
|
isValid = true
|
||||||
|
break outerLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(for_statement
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(simple_identifier))
|
||||||
|
(for_statement
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier))
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(simple_identifier))
|
||||||
|
(statement_label)
|
||||||
|
(for_statement
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)
|
||||||
|
(statements
|
||||||
|
(for_statement
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)
|
||||||
|
(statements
|
||||||
|
(if_statement
|
||||||
|
(equality_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier))
|
||||||
|
(statements
|
||||||
|
(assignment
|
||||||
|
(directly_assignable_expression
|
||||||
|
(simple_identifier))
|
||||||
|
(boolean_literal))
|
||||||
|
(control_transfer_statement
|
||||||
|
(simple_identifier)))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
While and friends
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
while idx > 0, input.count > 0 {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
while let .ok(data) = doWork() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
repeat {
|
||||||
|
// ...
|
||||||
|
} while something()
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(while_statement
|
||||||
|
(comparison_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(integer_literal))
|
||||||
|
(comparison_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal))
|
||||||
|
(comment))
|
||||||
|
(while_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(comment))
|
||||||
|
(repeat_while_statement
|
||||||
|
(comment)
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Switch statements
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
switch something {
|
||||||
|
case .pattern: return "Hello"
|
||||||
|
case expression: return "and"
|
||||||
|
case "Literal": return "Goodbye"
|
||||||
|
default: return ":)"
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(switch_statement
|
||||||
|
(simple_identifier)
|
||||||
|
(switch_entry
|
||||||
|
(switch_pattern
|
||||||
|
(simple_identifier))
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))))
|
||||||
|
(switch_entry
|
||||||
|
(switch_pattern
|
||||||
|
(simple_identifier))
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))))
|
||||||
|
(switch_entry
|
||||||
|
(switch_pattern
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))))
|
||||||
|
(switch_entry
|
||||||
|
(default_keyword)
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Weird switch statements
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
switch something {
|
||||||
|
case let .pattern2(_, bound): fallthrough
|
||||||
|
case .ident where someCondition, ident2: fallthrough
|
||||||
|
@unknown default: return "Goodbye"
|
||||||
|
}
|
||||||
|
|
||||||
|
switch self {
|
||||||
|
case .notExecutable(let path?):
|
||||||
|
return "File not executable: \(path)"
|
||||||
|
case let .isExecutable(path?):
|
||||||
|
return "File is executable: \(path)"
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(switch_statement
|
||||||
|
(simple_identifier)
|
||||||
|
(switch_entry
|
||||||
|
(switch_pattern
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)
|
||||||
|
(wildcard_pattern)
|
||||||
|
(simple_identifier)))
|
||||||
|
(statements
|
||||||
|
(simple_identifier)))
|
||||||
|
(switch_entry
|
||||||
|
(switch_pattern
|
||||||
|
(simple_identifier))
|
||||||
|
(where_keyword)
|
||||||
|
(simple_identifier)
|
||||||
|
(switch_pattern
|
||||||
|
(simple_identifier))
|
||||||
|
(statements
|
||||||
|
(simple_identifier)))
|
||||||
|
(switch_entry
|
||||||
|
(modifiers
|
||||||
|
(attribute
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(default_keyword)
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text))))))
|
||||||
|
(switch_statement
|
||||||
|
(self_expression)
|
||||||
|
(switch_entry
|
||||||
|
(switch_pattern
|
||||||
|
(simple_identifier)
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)
|
||||||
|
(interpolated_expression
|
||||||
|
(simple_identifier))))))
|
||||||
|
(switch_entry
|
||||||
|
(switch_pattern
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)))
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)
|
||||||
|
(interpolated_expression
|
||||||
|
(simple_identifier))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Imports
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import class SomeModule.SomeClass
|
||||||
|
|
||||||
|
class Foo { }
|
||||||
|
|
||||||
|
import SomethingElse
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(import_declaration
|
||||||
|
(identifier
|
||||||
|
(simple_identifier)))
|
||||||
|
(import_declaration
|
||||||
|
(identifier
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)))
|
||||||
|
(class_declaration
|
||||||
|
(type_identifier)
|
||||||
|
(class_body))
|
||||||
|
(import_declaration
|
||||||
|
(identifier
|
||||||
|
(simple_identifier))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Do-catch
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
do {
|
||||||
|
let b = 1
|
||||||
|
} catch let error as MyError {
|
||||||
|
} catch SomeError.specificError {
|
||||||
|
} catch let error as MyOtherError where error.code == 2 {
|
||||||
|
} catch let MyEnumError.missingField(fieldName) {
|
||||||
|
} catch MyEnumError.missingField(fieldName: let fieldName) {
|
||||||
|
} catch {
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let c = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(do_statement
|
||||||
|
(statements
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal)))
|
||||||
|
(catch_block
|
||||||
|
(catch_keyword)
|
||||||
|
(binding_pattern
|
||||||
|
(binding_pattern
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(catch_block
|
||||||
|
(catch_keyword)
|
||||||
|
(binding_pattern
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(simple_identifier)))
|
||||||
|
(catch_block
|
||||||
|
(catch_keyword)
|
||||||
|
(binding_pattern
|
||||||
|
(binding_pattern
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(where_clause
|
||||||
|
(where_keyword)
|
||||||
|
(equality_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal))))
|
||||||
|
(catch_block
|
||||||
|
(catch_keyword)
|
||||||
|
(binding_pattern
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier))))
|
||||||
|
(catch_block
|
||||||
|
(catch_keyword)
|
||||||
|
(binding_pattern
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier))))
|
||||||
|
(catch_block
|
||||||
|
(catch_keyword)))
|
||||||
|
(do_statement
|
||||||
|
(statements
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
If let statements
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
if let something = doThing() {
|
||||||
|
anotherThing()
|
||||||
|
}
|
||||||
|
|
||||||
|
if case .someCase(_) = otherThing() {
|
||||||
|
}
|
||||||
|
|
||||||
|
if let something: MyType = doThing() {
|
||||||
|
}
|
||||||
|
|
||||||
|
someLabel: if a.isEmpty, let b = getB() {
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(if_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(statements
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))))
|
||||||
|
(if_statement
|
||||||
|
(binding_pattern
|
||||||
|
(simple_identifier)
|
||||||
|
(wildcard_pattern))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments))))
|
||||||
|
(if_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(type_annotation
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments))))
|
||||||
|
(statement_label)
|
||||||
|
(if_statement
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
If let with function call
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
func doSomething() {
|
||||||
|
if let a = try? Foo.getValue("key") {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(function_body
|
||||||
|
(statements
|
||||||
|
(if_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(try_expression
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments
|
||||||
|
(value_argument
|
||||||
|
(line_string_literal
|
||||||
|
(line_str_text)))))))
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(simple_identifier))))
|
||||||
|
(control_transfer_statement
|
||||||
|
(simple_identifier))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Compound if let
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
if let something = doThing(), something.isSpecial() {
|
||||||
|
anotherThing()
|
||||||
|
}
|
||||||
|
|
||||||
|
if let something = doThing(), let somethingElse = something.somethingElse() {
|
||||||
|
// Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(if_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(statements
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))))
|
||||||
|
(if_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(comment)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Else if...
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
if let aPrime = a {
|
||||||
|
} else if let bPrime = b {
|
||||||
|
}
|
||||||
|
|
||||||
|
if a == b {
|
||||||
|
}
|
||||||
|
else if let cPrime = c {
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(if_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(simple_identifier)
|
||||||
|
(else)
|
||||||
|
(if_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(simple_identifier)))
|
||||||
|
(if_statement
|
||||||
|
(equality_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier))
|
||||||
|
(else)
|
||||||
|
(if_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(simple_identifier))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Else interacts with comments
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
if foo {
|
||||||
|
fooVal = 0; // A comment
|
||||||
|
}
|
||||||
|
// Another comment
|
||||||
|
else if bar {
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(if_statement
|
||||||
|
(simple_identifier)
|
||||||
|
(statements
|
||||||
|
(assignment
|
||||||
|
(directly_assignable_expression
|
||||||
|
(simple_identifier))
|
||||||
|
(integer_literal)))
|
||||||
|
(comment)
|
||||||
|
(comment)
|
||||||
|
(else)
|
||||||
|
(if_statement
|
||||||
|
(simple_identifier))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
If try
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
if try limit == nil && singleResult && !expectsSingleResult {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(if_statement
|
||||||
|
(conjunction_expression
|
||||||
|
(try_expression
|
||||||
|
(equality_expression
|
||||||
|
(simple_identifier)))
|
||||||
|
(conjunction_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(prefix_expression
|
||||||
|
(bang)
|
||||||
|
(simple_identifier))))
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(simple_identifier)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Guard statements
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
guard let something = doThing() else {
|
||||||
|
anotherThing()
|
||||||
|
}
|
||||||
|
|
||||||
|
guard someGuard() else {
|
||||||
|
anotherThing()
|
||||||
|
}
|
||||||
|
|
||||||
|
guard case .someCase(ident: let foo)? = otherThing() else {
|
||||||
|
}
|
||||||
|
|
||||||
|
guard case justIdentifier = bound else { }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(guard_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(else)
|
||||||
|
(statements
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))))
|
||||||
|
(guard_statement
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(else)
|
||||||
|
(statements
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))))
|
||||||
|
(guard_statement
|
||||||
|
(binding_pattern
|
||||||
|
(simple_identifier)
|
||||||
|
(simple_identifier)
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(else))
|
||||||
|
(guard_statement
|
||||||
|
(binding_pattern
|
||||||
|
(simple_identifier))
|
||||||
|
(simple_identifier)
|
||||||
|
(else)))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Compound guard
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
guard let something = doThing(), something.isSpecial() else {
|
||||||
|
anotherThing()
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(guard_statement
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(call_expression
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))
|
||||||
|
(else)
|
||||||
|
(statements
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Type annotation on `guard case let`
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
guard case let size: Int = variable.size else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(guard_statement
|
||||||
|
(binding_pattern
|
||||||
|
(binding_pattern_kind)
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(type_annotation
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(navigation_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier)))
|
||||||
|
(else)
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Availability conditions
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
if #available(iOS 14.0, *) {
|
||||||
|
doSomething()
|
||||||
|
}
|
||||||
|
|
||||||
|
if #available(macOS 10.12.0, *) {
|
||||||
|
return 3
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(if_statement
|
||||||
|
(availability_condition
|
||||||
|
(identifier
|
||||||
|
(simple_identifier))
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal))
|
||||||
|
(statements
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))))
|
||||||
|
(if_statement
|
||||||
|
(availability_condition
|
||||||
|
(identifier
|
||||||
|
(simple_identifier))
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal)
|
||||||
|
(integer_literal))
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(integer_literal)))
|
||||||
|
(else)
|
||||||
|
(statements
|
||||||
|
(control_transfer_statement
|
||||||
|
(integer_literal)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Unicode identifiers
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
let ø = unicode()
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(call_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(call_suffix
|
||||||
|
(value_arguments)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Contextual keywords are usable as identifiers
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
// `prefix` doesn't work as a function modifier here, so it's legal as an identifier
|
||||||
|
prefix = prefixToJSON
|
||||||
|
|
||||||
|
// But some modifiers are legal!
|
||||||
|
weak var weakPrefix = prefix
|
||||||
|
final class LocalClass { }
|
||||||
|
|
||||||
|
// Annotations are legal too!
|
||||||
|
@someAnnotation
|
||||||
|
func innerFunc() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(function_declaration
|
||||||
|
(modifiers
|
||||||
|
(visibility_modifier))
|
||||||
|
(function_body
|
||||||
|
(comment)
|
||||||
|
(statements
|
||||||
|
(assignment
|
||||||
|
(directly_assignable_expression
|
||||||
|
(simple_identifier))
|
||||||
|
(simple_identifier))
|
||||||
|
(comment)
|
||||||
|
(property_declaration
|
||||||
|
(ownership_modifier)
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(simple_identifier))
|
||||||
|
(class_declaration
|
||||||
|
(inheritance_modifier)
|
||||||
|
(type_identifier)
|
||||||
|
(class_body))
|
||||||
|
(comment)
|
||||||
|
(function_declaration
|
||||||
|
(attribute
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(simple_identifier)
|
||||||
|
(function_body))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Compiler diagnostics
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
#if SOME_FLAG
|
||||||
|
#error("SOME_FLAG must not be enabled!")
|
||||||
|
#elseif OTHER_FLAG
|
||||||
|
#warning("OTHER_FLAG is deprecated!")
|
||||||
|
#else
|
||||||
|
#sourceLocation(file: "SomeFile.swift", line: 99)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(directive)
|
||||||
|
(diagnostic)
|
||||||
|
(directive)
|
||||||
|
(diagnostic)
|
||||||
|
(directive)
|
||||||
|
(directive)
|
||||||
|
(directive))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Async let
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
async let foo = 64
|
||||||
|
async let bar = 66
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(integer_literal)))
|
||||||
@ -0,0 +1,332 @@
|
|||||||
|
================================================================================
|
||||||
|
Type references
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
something as Int
|
||||||
|
something as? A
|
||||||
|
something as! A
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Nested types
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
something as Some.NestedType
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_identifier))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Deeply nested types
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
somethingElse as A.Deeply.Nested.Type
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_identifier)
|
||||||
|
(type_identifier)
|
||||||
|
(type_identifier))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Generic parameterized types
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
something as Generic<T>
|
||||||
|
something as Generic<A, Type>
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Function types
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
unitFunction as () -> Unit
|
||||||
|
consumer as (Int) -> Unit
|
||||||
|
configurator as (inout Config) -> Unit
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(function_type
|
||||||
|
(tuple_type)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(function_type
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(function_type
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(parameter_modifiers
|
||||||
|
(parameter_modifier))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Function types with multiple parameters
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
a as (Int, Generic<T>, Boolean) -> Unit
|
||||||
|
b as (Nested.Type, (Int)) -> Unit
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(function_type
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(tuple_type_item
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))
|
||||||
|
(tuple_type_item
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(function_type
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_identifier)))
|
||||||
|
(tuple_type_item
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))))
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Types with named parameters (function or tuple)
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
a as (first: A, second: B)
|
||||||
|
-> Unit
|
||||||
|
let c: (third: C, fourth: D)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(function_type
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(tuple_type_item
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(property_declaration
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(type_annotation
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))
|
||||||
|
(tuple_type_item
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Nested optional types
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
private var dictionary: [String: Any?]?
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(modifiers
|
||||||
|
(visibility_modifier))
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(type_annotation
|
||||||
|
(optional_type
|
||||||
|
(dictionary_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(optional_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Implicitly unwrapped optional types
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
private var dictionary: [String: Any?]!
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(property_declaration
|
||||||
|
(modifiers
|
||||||
|
(visibility_modifier))
|
||||||
|
(value_binding_pattern
|
||||||
|
(non_binding_pattern
|
||||||
|
(simple_identifier)))
|
||||||
|
(type_annotation
|
||||||
|
(dictionary_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))
|
||||||
|
(optional_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier)))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Type aliases
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
public typealias Callback<T> = (T) -> Void
|
||||||
|
public typealias IntCallback = Callback<T>
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(typealias_declaration
|
||||||
|
(modifiers
|
||||||
|
(visibility_modifier))
|
||||||
|
(type_identifier)
|
||||||
|
(type_parameters
|
||||||
|
(type_parameter
|
||||||
|
(type_identifier)))
|
||||||
|
(function_type
|
||||||
|
(tuple_type
|
||||||
|
(tuple_type_item
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(typealias_declaration
|
||||||
|
(modifiers
|
||||||
|
(visibility_modifier))
|
||||||
|
(type_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_arguments
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))))
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
Metatypes
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
_ = foo as [String].Type
|
||||||
|
|
||||||
|
protocol GetType {
|
||||||
|
func getType() -> AnyObject.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(source_file
|
||||||
|
(assignment
|
||||||
|
(directly_assignable_expression
|
||||||
|
(simple_identifier))
|
||||||
|
(navigation_expression
|
||||||
|
(as_expression
|
||||||
|
(simple_identifier)
|
||||||
|
(as_operator)
|
||||||
|
(array_type
|
||||||
|
(user_type
|
||||||
|
(type_identifier))))
|
||||||
|
(navigation_suffix
|
||||||
|
(simple_identifier))))
|
||||||
|
(protocol_declaration
|
||||||
|
(type_identifier)
|
||||||
|
(protocol_body
|
||||||
|
(protocol_function_declaration
|
||||||
|
(simple_identifier)
|
||||||
|
(user_type
|
||||||
|
(type_identifier)
|
||||||
|
(type_identifier))))))
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,794 @@
|
|||||||
|
{
|
||||||
|
"name": "tree-sitter-swift",
|
||||||
|
"version": "0.2.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@gar/promisify": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@npmcli/fs": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-VhP1qZLXcrXRIaPoqb4YA55JQxLNF3jNR4T55IdOJa3+IFJKNYHtPvtXx8slmeMavj37vCzCfrqQM1vWLsYKLA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@gar/promisify": "^1.0.1",
|
||||||
|
"semver": "^7.3.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@npmcli/move-file": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"mkdirp": "^1.0.4",
|
||||||
|
"rimraf": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tootallnate/once": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"abbrev": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"agent-base": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"debug": "4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"agentkeepalive": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"depd": "^1.1.2",
|
||||||
|
"humanize-ms": "^1.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"aggregate-error": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"clean-stack": "^2.0.0",
|
||||||
|
"indent-string": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ansi-regex": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"aproba": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"are-we-there-yet": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"delegates": "^1.0.0",
|
||||||
|
"readable-stream": "^3.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"brace-expansion": {
|
||||||
|
"version": "1.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cacache": {
|
||||||
|
"version": "15.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
|
||||||
|
"integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@npmcli/fs": "^1.0.0",
|
||||||
|
"@npmcli/move-file": "^1.0.1",
|
||||||
|
"chownr": "^2.0.0",
|
||||||
|
"fs-minipass": "^2.0.0",
|
||||||
|
"glob": "^7.1.4",
|
||||||
|
"infer-owner": "^1.0.4",
|
||||||
|
"lru-cache": "^6.0.0",
|
||||||
|
"minipass": "^3.1.1",
|
||||||
|
"minipass-collect": "^1.0.2",
|
||||||
|
"minipass-flush": "^1.0.5",
|
||||||
|
"minipass-pipeline": "^1.2.2",
|
||||||
|
"mkdirp": "^1.0.3",
|
||||||
|
"p-map": "^4.0.0",
|
||||||
|
"promise-inflight": "^1.0.1",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"ssri": "^8.0.1",
|
||||||
|
"tar": "^6.0.2",
|
||||||
|
"unique-filename": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chownr": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"clean-stack": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"color-support": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"console-control-strings": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||||
|
"integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delegates": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"depd": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||||
|
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"encoding": {
|
||||||
|
"version": "0.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
||||||
|
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"iconv-lite": "^0.6.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"env-paths": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"err-code": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"fs-minipass": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fs.realpath": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"gauge": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-F8sU45yQpjQjxKkm1UOAhf0U/O0aFt//Fl7hsrNVto+patMHjs7dPI9mFOGUKbhrgKm0S3EjW3scMFuQmWSROw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-regex": "^5.0.1",
|
||||||
|
"aproba": "^1.0.3 || ^2.0.0",
|
||||||
|
"color-support": "^1.1.2",
|
||||||
|
"console-control-strings": "^1.0.0",
|
||||||
|
"has-unicode": "^2.0.1",
|
||||||
|
"signal-exit": "^3.0.0",
|
||||||
|
"string-width": "^4.2.3",
|
||||||
|
"strip-ansi": "^6.0.1",
|
||||||
|
"wide-align": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glob": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fs.realpath": "^1.0.0",
|
||||||
|
"inflight": "^1.0.4",
|
||||||
|
"inherits": "2",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"path-is-absolute": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"graceful-fs": {
|
||||||
|
"version": "4.2.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
|
||||||
|
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"has-unicode": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"http-cache-semantics": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"http-proxy-agent": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@tootallnate/once": "1",
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https-proxy-agent": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"humanize-ms": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
|
||||||
|
"integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"iconv-lite": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"imurmurhash": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||||
|
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"indent-string": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"infer-owner": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"inflight": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||||
|
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"is-lambda": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"isexe": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||||
|
},
|
||||||
|
"lru-cache": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"make-fetch-happen": {
|
||||||
|
"version": "9.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
|
||||||
|
"integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"agentkeepalive": "^4.1.3",
|
||||||
|
"cacache": "^15.2.0",
|
||||||
|
"http-cache-semantics": "^4.1.0",
|
||||||
|
"http-proxy-agent": "^4.0.1",
|
||||||
|
"https-proxy-agent": "^5.0.0",
|
||||||
|
"is-lambda": "^1.0.1",
|
||||||
|
"lru-cache": "^6.0.0",
|
||||||
|
"minipass": "^3.1.3",
|
||||||
|
"minipass-collect": "^1.0.2",
|
||||||
|
"minipass-fetch": "^1.3.2",
|
||||||
|
"minipass-flush": "^1.0.5",
|
||||||
|
"minipass-pipeline": "^1.2.4",
|
||||||
|
"negotiator": "^0.6.2",
|
||||||
|
"promise-retry": "^2.0.1",
|
||||||
|
"socks-proxy-agent": "^6.0.0",
|
||||||
|
"ssri": "^8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minimatch": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minipass": {
|
||||||
|
"version": "3.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
|
||||||
|
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minipass-collect": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minipass-fetch": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"encoding": "^0.1.12",
|
||||||
|
"minipass": "^3.1.0",
|
||||||
|
"minipass-sized": "^1.0.3",
|
||||||
|
"minizlib": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minipass-flush": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minipass-pipeline": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minipass-sized": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minizlib": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^3.0.0",
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mkdirp": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"nan": {
|
||||||
|
"version": "2.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
|
||||||
|
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
|
||||||
|
},
|
||||||
|
"negotiator": {
|
||||||
|
"version": "0.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||||
|
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node-gyp": {
|
||||||
|
"version": "8.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz",
|
||||||
|
"integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"env-paths": "^2.2.0",
|
||||||
|
"glob": "^7.1.4",
|
||||||
|
"graceful-fs": "^4.2.6",
|
||||||
|
"make-fetch-happen": "^9.1.0",
|
||||||
|
"nopt": "^5.0.0",
|
||||||
|
"npmlog": "^6.0.0",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"semver": "^7.3.5",
|
||||||
|
"tar": "^6.1.2",
|
||||||
|
"which": "^2.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nopt": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"abbrev": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"npmlog": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-03ppFRGlsyUaQFbGC2C8QWJN/C/K7PsfyD9aQdhVKAQIH4sQBc8WASqFBP7O+Ut4d2oo5LoeoboB3cGdBZSp6Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"are-we-there-yet": "^2.0.0",
|
||||||
|
"console-control-strings": "^1.1.0",
|
||||||
|
"gauge": "^4.0.0",
|
||||||
|
"set-blocking": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"p-map": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"aggregate-error": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-is-absolute": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"version": "2.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz",
|
||||||
|
"integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"promise-inflight": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"promise-retry": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"err-code": "^2.0.2",
|
||||||
|
"retry": "^0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"retry": {
|
||||||
|
"version": "0.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
||||||
|
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"rimraf": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"glob": "^7.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "7.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
||||||
|
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"lru-cache": "^6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"set-blocking": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"signal-exit": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"smart-buffer": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"socks": {
|
||||||
|
"version": "2.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz",
|
||||||
|
"integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ip": "^1.1.5",
|
||||||
|
"smart-buffer": "^4.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"socks-proxy-agent": {
|
||||||
|
"version": "6.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz",
|
||||||
|
"integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"agent-base": "^6.0.2",
|
||||||
|
"debug": "^4.3.1",
|
||||||
|
"socks": "^2.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ssri": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
|
||||||
|
"integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"string-width": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
|
"strip-ansi": "^6.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"strip-ansi": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-regex": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tar": {
|
||||||
|
"version": "6.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
|
||||||
|
"integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chownr": "^2.0.0",
|
||||||
|
"fs-minipass": "^2.0.0",
|
||||||
|
"minipass": "^3.0.0",
|
||||||
|
"minizlib": "^2.1.1",
|
||||||
|
"mkdirp": "^1.0.3",
|
||||||
|
"yallist": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tree-sitter-cli": {
|
||||||
|
"version": "0.20.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.6.tgz",
|
||||||
|
"integrity": "sha512-tjbAeuGSMhco/EnsThjWkQbDIYMDmdkWsTPsa/NJAW7bjaki9P7oM9TkLxfdlnm4LXd1wR5wVSM2/RTLtZbm6A=="
|
||||||
|
},
|
||||||
|
"unique-filename": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"unique-slug": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unique-slug": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"imurmurhash": "^0.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"which": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||||
|
"requires": {
|
||||||
|
"isexe": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wide-align": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
|
||||||
|
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"yallist": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "tree-sitter-swift",
|
||||||
|
"version": "0.2.0",
|
||||||
|
"description": "A tree-sitter grammar for the Swift programming language.",
|
||||||
|
"main": "bindings/node/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"install": "node scripts/wait-for-tree-sitter.js && tree-sitter generate",
|
||||||
|
"postinstall": "node-gyp configure && node-gyp build",
|
||||||
|
"ci": "prettier --check grammar.js",
|
||||||
|
"test-ci": "./scripts/test-with-memcheck.sh --install-valgrind",
|
||||||
|
"test": "./scripts/test-with-memcheck.sh"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/alex-pinkus/tree-sitter-swift.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"parser",
|
||||||
|
"swift"
|
||||||
|
],
|
||||||
|
"author": "Alex Pinkus <alex.pinkus@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/alex-pinkus/tree-sitter-swift/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/alex-pinkus/tree-sitter-swift#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"nan": "^2.15.0",
|
||||||
|
"tree-sitter-cli": "^0.20.6",
|
||||||
|
"which": "2.0.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"node-gyp": "^8.4.1",
|
||||||
|
"prettier": "2.3.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,158 @@
|
|||||||
|
[ "." ";" ":" "," ] @punctuation.delimiter
|
||||||
|
[ "\\(" "(" ")" "[" "]" "{" "}"] @punctuation.bracket ; TODO: "\\(" ")" in interpolations should be @punctuation.special
|
||||||
|
|
||||||
|
; Identifiers
|
||||||
|
(attribute) @variable
|
||||||
|
(type_identifier) @type
|
||||||
|
(self_expression) @variable.builtin
|
||||||
|
|
||||||
|
; Declarations
|
||||||
|
"func" @keyword.function
|
||||||
|
[
|
||||||
|
(visibility_modifier)
|
||||||
|
(member_modifier)
|
||||||
|
(function_modifier)
|
||||||
|
(property_modifier)
|
||||||
|
(parameter_modifier)
|
||||||
|
(inheritance_modifier)
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
(function_declaration (simple_identifier) @method)
|
||||||
|
(function_declaration ["init" @constructor])
|
||||||
|
(throws) @keyword
|
||||||
|
"async" @keyword
|
||||||
|
(where_keyword) @keyword
|
||||||
|
(parameter external_name: (simple_identifier) @parameter)
|
||||||
|
(parameter name: (simple_identifier) @parameter)
|
||||||
|
(type_parameter (type_identifier) @parameter)
|
||||||
|
(inheritance_constraint (identifier (simple_identifier) @parameter))
|
||||||
|
(equality_constraint (identifier (simple_identifier) @parameter))
|
||||||
|
(non_binding_pattern bound_identifier: (simple_identifier)) @variable
|
||||||
|
|
||||||
|
[
|
||||||
|
"typealias"
|
||||||
|
"struct"
|
||||||
|
"class"
|
||||||
|
"enum"
|
||||||
|
"protocol"
|
||||||
|
"extension"
|
||||||
|
"indirect"
|
||||||
|
"some"
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
[
|
||||||
|
(getter_specifier)
|
||||||
|
(setter_specifier)
|
||||||
|
(modify_specifier)
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
(class_body (property_declaration (value_binding_pattern (non_binding_pattern (simple_identifier) @property))))
|
||||||
|
(protocol_property_declaration (value_binding_pattern (non_binding_pattern (simple_identifier) @property)))
|
||||||
|
|
||||||
|
(import_declaration ["import" @include])
|
||||||
|
|
||||||
|
(enum_entry ["case" @keyword])
|
||||||
|
|
||||||
|
; Function calls
|
||||||
|
(call_expression (simple_identifier) @function) ; foo()
|
||||||
|
(call_expression ; foo.bar.baz(): highlight the baz()
|
||||||
|
(navigation_expression
|
||||||
|
(navigation_suffix (simple_identifier) @function)))
|
||||||
|
((navigation_expression
|
||||||
|
(simple_identifier) @type) ; SomeType.method(): highlight SomeType as a type
|
||||||
|
(#match? @type "^[A-Z]"))
|
||||||
|
|
||||||
|
(directive) @function.macro
|
||||||
|
(diagnostic) @function.macro
|
||||||
|
|
||||||
|
; Statements
|
||||||
|
(for_statement ["for" @repeat])
|
||||||
|
(for_statement ["in" @repeat])
|
||||||
|
(for_statement item: (simple_identifier) @variable)
|
||||||
|
(else) @keyword
|
||||||
|
(as_operator) @keyword
|
||||||
|
|
||||||
|
["while" "repeat" "continue" "break"] @repeat
|
||||||
|
|
||||||
|
["let" "var"] @keyword
|
||||||
|
(non_binding_pattern (simple_identifier) @variable)
|
||||||
|
|
||||||
|
(guard_statement ["guard" @conditional])
|
||||||
|
(if_statement ["if" @conditional])
|
||||||
|
(switch_statement ["switch" @conditional])
|
||||||
|
(switch_entry ["case" @keyword])
|
||||||
|
(switch_entry ["fallthrough" @keyword])
|
||||||
|
(switch_entry (default_keyword) @keyword)
|
||||||
|
"return" @keyword.return
|
||||||
|
(ternary_expression
|
||||||
|
["?" ":"] @conditional)
|
||||||
|
|
||||||
|
["do" (throw_keyword) (catch_keyword)] @keyword
|
||||||
|
|
||||||
|
(statement_label) @label
|
||||||
|
|
||||||
|
; Comments
|
||||||
|
(comment) @comment
|
||||||
|
(multiline_comment) @comment
|
||||||
|
|
||||||
|
; String literals
|
||||||
|
(line_str_text) @string
|
||||||
|
(str_escaped_char) @string
|
||||||
|
(multi_line_str_text) @string
|
||||||
|
(raw_str_part) @string
|
||||||
|
(raw_str_end_part) @string
|
||||||
|
(raw_str_interpolation_start) @punctuation.special
|
||||||
|
["\"" "\"\"\""] @string
|
||||||
|
|
||||||
|
; Lambda literals
|
||||||
|
(lambda_literal ["in" @keyword.operator])
|
||||||
|
|
||||||
|
; Basic literals
|
||||||
|
[
|
||||||
|
(integer_literal)
|
||||||
|
(hex_literal)
|
||||||
|
(oct_literal)
|
||||||
|
(bin_literal)
|
||||||
|
] @number
|
||||||
|
(real_literal) @float
|
||||||
|
(boolean_literal) @boolean
|
||||||
|
"nil" @variable.builtin
|
||||||
|
|
||||||
|
; Operators
|
||||||
|
(custom_operator) @operator
|
||||||
|
[
|
||||||
|
"try"
|
||||||
|
"try?"
|
||||||
|
"try!"
|
||||||
|
"!"
|
||||||
|
"+"
|
||||||
|
"-"
|
||||||
|
"*"
|
||||||
|
"/"
|
||||||
|
"%"
|
||||||
|
"="
|
||||||
|
"+="
|
||||||
|
"-="
|
||||||
|
"*="
|
||||||
|
"/="
|
||||||
|
"<"
|
||||||
|
">"
|
||||||
|
"<="
|
||||||
|
">="
|
||||||
|
"++"
|
||||||
|
"--"
|
||||||
|
"&"
|
||||||
|
"~"
|
||||||
|
"%="
|
||||||
|
"!="
|
||||||
|
"!=="
|
||||||
|
"=="
|
||||||
|
"==="
|
||||||
|
"??"
|
||||||
|
|
||||||
|
"->"
|
||||||
|
|
||||||
|
"..<"
|
||||||
|
"..."
|
||||||
|
] @operator
|
||||||
|
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
(import_declaration (identifier) @definition.import)
|
||||||
|
(function_declaration name: (simple_identifier) @definition.function)
|
||||||
|
|
||||||
|
; Scopes
|
||||||
|
[
|
||||||
|
(statements)
|
||||||
|
(for_statement)
|
||||||
|
(while_statement)
|
||||||
|
(repeat_while_statement)
|
||||||
|
(do_statement)
|
||||||
|
(if_statement)
|
||||||
|
(guard_statement)
|
||||||
|
(switch_statement)
|
||||||
|
(property_declaration)
|
||||||
|
(function_declaration)
|
||||||
|
(class_declaration)
|
||||||
|
(protocol_declaration)
|
||||||
|
] @scope
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
firefox-ios/Shared/Functions.swift
|
||||||
|
RxSwift/RxExample/RxExample/Examples/GitHubSearchRepositories/GitHubSearchRepositories.swift
|
||||||
|
SwiftLint/Source/SwiftLintFramework/Rules/Lint/ExpiringTodoRule.swift
|
||||||
|
GRDB/GRDB/Core/Row.swift
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
Alamofire Alamofire/Alamofire 5.6.1
|
||||||
|
iina iina/iina v1.2.0
|
||||||
|
Charts danielgindi/Charts v4.0.2
|
||||||
|
lottie-ios airbnb/lottie-ios 3.3.0
|
||||||
|
vapor vapor/vapor 3.3.3
|
||||||
|
SwiftyJSON SwiftyJSON/SwiftyJSON 5.0.1
|
||||||
|
RxSwift ReactiveX/RxSwift 6.5.0 0 9
|
||||||
|
RxSwift ReactiveX/RxSwift 6.5.0 1 9
|
||||||
|
RxSwift ReactiveX/RxSwift 6.5.0 2 9
|
||||||
|
RxSwift ReactiveX/RxSwift 6.5.0 3 9
|
||||||
|
RxSwift ReactiveX/RxSwift 6.5.0 4 9
|
||||||
|
RxSwift ReactiveX/RxSwift 6.5.0 5 9
|
||||||
|
RxSwift ReactiveX/RxSwift 6.5.0 6 9
|
||||||
|
RxSwift ReactiveX/RxSwift 6.5.0 7 9
|
||||||
|
RxSwift ReactiveX/RxSwift 6.5.0 8 9
|
||||||
|
HeroTransitions HeroTransitions/Hero 1.6.1
|
||||||
|
Kingfisher onevcat/Kingfisher 7.2.1
|
||||||
|
shadowsocks shadowsocks/ShadowsocksX-NG v1.9.4
|
||||||
|
SnapKit SnapKit/SnapKit 5.0.1
|
||||||
|
SwiftLint realm/SwiftLint 0.47.0 0 2
|
||||||
|
SwiftLint realm/SwiftLint 0.47.0 1 2
|
||||||
|
ClashX yichengchen/clashX 1.91.1
|
||||||
|
Carthage Carthage/Carthage 0.38.0
|
||||||
|
Rectangle rxhanson/Rectangle v0.53
|
||||||
|
PromiseKit mxcl/PromiseKit 6.17.0
|
||||||
|
Moya Moya/Moya 15.0.0
|
||||||
|
MonitorControl MonitorControl/MonitorControl v4.0.2
|
||||||
|
ObjectMapper tristanhimmelman/ObjectMapper 4.2.0
|
||||||
|
SkeletonView Juanpe/SkeletonView 1.29.2
|
||||||
|
firefox-ios mozilla-mobile/firefox-ios v39.0 0 6
|
||||||
|
firefox-ios mozilla-mobile/firefox-ios v39.0 1 6
|
||||||
|
firefox-ios mozilla-mobile/firefox-ios v39.0 2 6
|
||||||
|
firefox-ios mozilla-mobile/firefox-ios v39.0 3 6
|
||||||
|
firefox-ios mozilla-mobile/firefox-ios v39.0 4 6
|
||||||
|
firefox-ios mozilla-mobile/firefox-ios v39.0 5 6
|
||||||
|
AudioKit AudioKit/AudioKit 5.4.0
|
||||||
|
Starscream daltoniam/Starscream 4.0.4
|
||||||
|
MessageKit MessageKit/MessageKit 3.7.0
|
||||||
|
KeychainAccess kishikawakatsumi/KeychainAccess v4.2.2
|
||||||
|
Nuke kean/Nuke 10.8.0
|
||||||
|
Swinject Swinject/Swinject 2.8.1
|
||||||
|
GRDB groue/GRDB.swift v5.23.0 0 2
|
||||||
|
GRDB groue/GRDB.swift v5.23.0 1 2
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
parser_dir="$(pwd)"
|
||||||
|
|
||||||
|
. $parser_dir/scripts/common.sh
|
||||||
|
|
||||||
|
# Check out every repository to figure out how many files they contain.
|
||||||
|
cd $tmpdir
|
||||||
|
while read line ; do
|
||||||
|
checkout $line
|
||||||
|
done < $top_repositories
|
||||||
|
|
||||||
|
file_count=$(find "$tmpdir" -name *.swift -not -path '*/Pods/*' | wc -l)
|
||||||
|
error_count=$(wc -l < $known_failures)
|
||||||
|
|
||||||
|
# Now, since we can assume that the "top-repos" workflow ran, our parse rate is the number of
|
||||||
|
# successful files over the number of total files. Pretty print that to two decimal places.
|
||||||
|
printf '%.2f%%\n' $(bc -l <<< "($file_count - $error_count) / $file_count * 100")
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
known_failures="$parser_dir/script-data/known_failures.txt"
|
||||||
|
top_repositories="$parser_dir/script-data/top-repositories.txt"
|
||||||
|
|
||||||
|
# Run all this logic in a temporary directory that we delete on exit
|
||||||
|
tmpdir="$(mktemp -d -t top-10-XXXXXX)"
|
||||||
|
trap 'rm -rf "$tmpdir"' EXIT
|
||||||
|
|
||||||
|
# Function to check out a git repository at a given tag.
|
||||||
|
#
|
||||||
|
# We use tags so that the source code is deterministic - tags are immutable and reasonable people
|
||||||
|
# don't delete and recreate them. The tree-sitter-python script this is based on uses raw SHA hashes
|
||||||
|
# for this, but that would require us to checkout the code at HEAD first and switch to the code at
|
||||||
|
# the given hash. Using tags means we can do this in one command and include `--depth 1` to reduce
|
||||||
|
# the number of extra objects we have to fetch.
|
||||||
|
function checkout() {
|
||||||
|
repo=$1; url=$2; tag=$3
|
||||||
|
|
||||||
|
if [ ! -d "$repo" ]; then
|
||||||
|
git clone --quiet --branch $tag --depth 1 "https://github.com/$url" "$repo" >/dev/null 2>/dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Locates all the swift source code files that exist in the source tree under the passed-in
|
||||||
|
# directory.
|
||||||
|
#
|
||||||
|
# Does not include code that gets included from dependencies of this repository, to avoid
|
||||||
|
# overcounting those files.
|
||||||
|
function swift_files_under() {
|
||||||
|
find "$1" -name *.swift -not -path '*/Pods/*'
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ "$1" == "--install-valgrind" ]]; then
|
||||||
|
sudo apt-get update # See https://github.com/facebook/zstd/pull/3082
|
||||||
|
sudo apt install -y valgrind
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Query tests hang forever when run with valgrind, so move them out of
|
||||||
|
# the way.
|
||||||
|
mv ./queries ./queries.bak
|
||||||
|
trap "mv ./queries.bak ./queries || true" EXIT
|
||||||
|
|
||||||
|
valgrind tree-sitter test
|
||||||
|
|
||||||
|
# Now move the query tests back, and move the corpus tests out of the
|
||||||
|
# way.
|
||||||
|
mv ./queries.bak ./queries
|
||||||
|
mv ./corpus ./corpus.bak
|
||||||
|
trap "mv ./corpus.bak ./corpus || true" EXIT
|
||||||
|
|
||||||
|
tree-sitter test
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
parser_dir="$(pwd)"
|
||||||
|
|
||||||
|
. $parser_dir/scripts/common.sh
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
repos=$(cat $top_repositories)
|
||||||
|
echo "Running on all top repositories."
|
||||||
|
else
|
||||||
|
repos=$(sed "$1q;d" $top_repositories)
|
||||||
|
echo "Running on single repository $repos."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Function to validate that a passed-in git repository can be parsed using this parser.
|
||||||
|
#
|
||||||
|
# If the passed-in repository fails to parse in ways that do not match the `known_failures` script
|
||||||
|
# data, this prints info about the failure and exits the script with a nonzero status code.
|
||||||
|
function validate() {
|
||||||
|
repo=$1; url=$2; tag=$3; part=$4; total=$5
|
||||||
|
|
||||||
|
if [ -z "$part" ] || [ -z "$total" ]; then
|
||||||
|
part=0
|
||||||
|
total=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
data_dir=$tmpdir/.$repo-data-$part
|
||||||
|
mkdir -p $data_dir || true
|
||||||
|
|
||||||
|
# Find the start and end of this section based on the passed-in `part` and `total`.
|
||||||
|
all_files=$data_dir/all_files.txt
|
||||||
|
swift_files_under "$tmpdir/$repo" > $all_files
|
||||||
|
file_count=$(wc -l < $all_files | tr -d ' ')
|
||||||
|
|
||||||
|
one_past_the_end=$((file_count + 1))
|
||||||
|
start=$(($((one_past_the_end * part)) / total))
|
||||||
|
next_part=$((part + 1))
|
||||||
|
next_start=$(($((one_past_the_end * next_part)) / total))
|
||||||
|
end=$((next_start - 1))
|
||||||
|
len=$((end - start))
|
||||||
|
|
||||||
|
failed_files=$(
|
||||||
|
IFS=$'\n'
|
||||||
|
for file in $(head -$end < $all_files | tail -$len); do
|
||||||
|
npx tree-sitter parse -q "$file" 2>/dev/null
|
||||||
|
done | { grep -v -f "$known_failures" || true; }
|
||||||
|
unset IFS
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ "$failed_files" = *[![:space:]]* ]]; then
|
||||||
|
echo -en "Unexpected parse failure found in $repo "
|
||||||
|
if [ -z $4 ]; then
|
||||||
|
echo ":"
|
||||||
|
else
|
||||||
|
echo "block $start-$end:"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat <<<"$failed_files"
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
elif [ -z $4 ]; then
|
||||||
|
echo "Parsed $repo successfully!"
|
||||||
|
else
|
||||||
|
echo "Parsed $repo files $start-$end of $file_count successfully!"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# It's really easy to add a blank line to `known_failures.txt`, which will make everything pass.
|
||||||
|
# This echoes some string from random.org to prove that the grp isn't excluding everything. If we
|
||||||
|
# added a blank line, this would have zero items, which results in a nonzero exit code from grep.
|
||||||
|
if ! echo "vkDSrg8n" | grep -v -f "$known_failures" > /dev/null; then
|
||||||
|
echo "You added a blank line to known_failures!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run `validate` on every repository in `top-repositories` sequentially.
|
||||||
|
while read line ; do
|
||||||
|
cd $tmpdir
|
||||||
|
checkout $line
|
||||||
|
|
||||||
|
cd $parser_dir
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
validate $line &
|
||||||
|
pids+=($!)
|
||||||
|
else
|
||||||
|
validate $line
|
||||||
|
fi
|
||||||
|
done <<<"$repos"
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
for pid in "${pids[@]}" ; do
|
||||||
|
wait $pid
|
||||||
|
done
|
||||||
|
fi
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
parser_dir="$(pwd)"
|
||||||
|
|
||||||
|
. $parser_dir/scripts/common.sh
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
repo=$1
|
||||||
|
cd $tmpdir/$repo
|
||||||
|
|
||||||
|
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||||
|
git fetch origin --unshallow 2>/dev/null || git fetch origin
|
||||||
|
remote_head_commit=$(git ls-remote | grep HEAD | awk '{ print $1 }')
|
||||||
|
# Find the oldest branch that contains the remote HEAD commit, which will correspond to the remote HEAD branch (i.e.
|
||||||
|
# what's sometimes called `main` or `master`. Other branches may be newer than this one if they are a fast-forward
|
||||||
|
# of `main`, but it's not possible for an _older_ branch to have the commit unless it's literally equivalent. If it
|
||||||
|
# is equivalent, it doesn't matter.
|
||||||
|
remote_head_branch=$(git branch -r --contains $remote_head_commit --sort=-committerdate | tac | head -1)
|
||||||
|
|
||||||
|
# Figure out which branch the passed-in tag was tracking. We prefer the main branch, if possible, but can fall back
|
||||||
|
# to another if needed.
|
||||||
|
if git branch -r --contains HEAD | grep -q $remote_head_branch; then
|
||||||
|
# Our tag was on `main` (or equivalent), so use that branch directly.
|
||||||
|
branch=$remote_head_branch
|
||||||
|
else
|
||||||
|
# Our tag was not on `main`, so use the newest branch that it _was_ on.
|
||||||
|
branch=$(git branch -r --contains HEAD --sort=-committerdate | head -1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find the latest tag on this branch, and print it along with the other fields that we were given.
|
||||||
|
new_tag=$(git describe --tags $branch | sed 's/\(.*\)-.*-.*/\1/')
|
||||||
|
echo $1 $2 $new_tag $4 $5
|
||||||
|
}
|
||||||
|
|
||||||
|
while read line ; do
|
||||||
|
cd $tmpdir
|
||||||
|
checkout $line
|
||||||
|
update $line
|
||||||
|
done < $top_repositories > $top_repositories.new
|
||||||
|
|
||||||
|
mv $top_repositories.new $top_repositories
|
||||||
|
|
||||||
|
# If the repository is now dirty, we have new versions available. Commit them and publish a PR.
|
||||||
|
cd $parser_dir
|
||||||
|
if ! git diff --quiet; then
|
||||||
|
git config --local user.email alex.pinkus@gmail.com
|
||||||
|
git config --local user.name "Alex Pinkus (Bot)"
|
||||||
|
git add ./script-data
|
||||||
|
git commit -m "Updating top repository version"
|
||||||
|
branch_name=repo-update-$(date +%Y-%m-%d)
|
||||||
|
git checkout -b $branch_name
|
||||||
|
echo "Creating pull request..."
|
||||||
|
gh auth setup-git
|
||||||
|
git remote add dest "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git"
|
||||||
|
git push dest HEAD:$branch_name
|
||||||
|
git fetch origin
|
||||||
|
gh pr create --fill
|
||||||
|
echo "Pull request created!"
|
||||||
|
else
|
||||||
|
echo "No repositories have been updated, so there's nothing more to do!"
|
||||||
|
fi
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const os = require("os");
|
||||||
|
const path = require("path");
|
||||||
|
const which = require("which");
|
||||||
|
const { promisify } = require("util");
|
||||||
|
const stat = promisify(fs.stat);
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const treeSitterExecutable = await which("tree-sitter");
|
||||||
|
if (!treeSitterExecutable.includes("node_modules")) {
|
||||||
|
// Not installed through npm, so should be safe.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const realTreeSitterDir = path.join(
|
||||||
|
treeSitterExecutable,
|
||||||
|
"..",
|
||||||
|
"..",
|
||||||
|
"tree-sitter-cli"
|
||||||
|
);
|
||||||
|
let timeout = undefined;
|
||||||
|
let timeoutResolve = undefined;
|
||||||
|
Promise.race([
|
||||||
|
waitForOneOf(realTreeSitterDir, ["tree-sitter", "tree-sitter.exe"]).then(
|
||||||
|
() => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeoutResolve();
|
||||||
|
}
|
||||||
|
),
|
||||||
|
new Promise((resolve) => {
|
||||||
|
timeoutResolve = resolve;
|
||||||
|
timeout = setTimeout(resolve, 10000);
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitForOneOf(dir, files) {
|
||||||
|
for (const file of files) {
|
||||||
|
try {
|
||||||
|
if (await canExecute(path.join(dir, file))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// File doesn't yet exist -- we must wait for it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
try {
|
||||||
|
fs.watch(dir, { persistent: false }, (eventType, filename) => {
|
||||||
|
if (
|
||||||
|
(eventType !== "rename" || os.platform() !== "win32") &&
|
||||||
|
files.includes(filename)
|
||||||
|
) {
|
||||||
|
let resolved = false;
|
||||||
|
canExecute(path.join(dir, filename)).then((canExec) => {
|
||||||
|
if (canExec && !resolved) {
|
||||||
|
resolve();
|
||||||
|
resolved = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
if (err.name !== "AbortError") {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function canExecute(filePath) {
|
||||||
|
const fileStat = await stat(filePath);
|
||||||
|
return fileStat.mode & 0111 || os.platform() === "win32";
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
ref=$1
|
||||||
|
branch_name=with-generated-files
|
||||||
|
|
||||||
|
# Load the branch that contains generated grammar files.
|
||||||
|
git checkout $branch_name
|
||||||
|
|
||||||
|
# Update our local directory to match the $ref, but then put the HEAD back at the previous commit.
|
||||||
|
# This will blow away the existing generated grammar. That's OK because this branch is only ever
|
||||||
|
# updated using this script.
|
||||||
|
git reset $ref --hard
|
||||||
|
git reset HEAD@{1}
|
||||||
|
|
||||||
|
# Now generate the grammar and validate that it works. Hopefully no one ever creates a tag to a
|
||||||
|
# commit with a non-working grammar, but the `npm test` protects us against that ever happening.
|
||||||
|
npm install
|
||||||
|
npm run test-ci
|
||||||
|
|
||||||
|
# Commit specific generated files, attributing the changes to the primary maintainer of this
|
||||||
|
# grammar. Notably, we do not commit the `.o` files generated during the build, just the source.
|
||||||
|
git config --local user.email alex.pinkus@gmail.com
|
||||||
|
git config --local user.name "Alex Pinkus (Bot)"
|
||||||
|
git add ./src/*.c --force
|
||||||
|
git add ./src/tree_sitter/* --force
|
||||||
|
git add ./src/*.json --force
|
||||||
|
git add grammar.js
|
||||||
|
git add package.json
|
||||||
|
git add corpus
|
||||||
|
git add queries
|
||||||
|
git commit -m "Updating grammar files for version ${ref/refs\/tags\//}"
|
||||||
|
echo "Committing new generated grammar"
|
||||||
|
|
||||||
|
# Push the change to github using the secrets from our environment.
|
||||||
|
gh auth setup-git
|
||||||
|
git remote add dest "https://$GITHUB_ACTOR:$GITHUB_TOKEN@github.com/$GITHUB_REPOSITORY.git"
|
||||||
|
git push dest HEAD:$branch_name
|
||||||
|
echo "Checkin complete!"
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,617 @@
|
|||||||
|
#include <tree_sitter/parser.h>
|
||||||
|
#include <wctype.h>
|
||||||
|
|
||||||
|
enum TokenType {
|
||||||
|
BLOCK_COMMENT,
|
||||||
|
RAW_STR_PART,
|
||||||
|
RAW_STR_CONTINUING_INDICATOR,
|
||||||
|
RAW_STR_END_PART,
|
||||||
|
SEMI,
|
||||||
|
ARROW_OPERATOR,
|
||||||
|
DOT_OPERATOR,
|
||||||
|
THREE_DOT_OPERATOR,
|
||||||
|
OPEN_ENDED_RANGE_OPERATOR,
|
||||||
|
CONJUNCTION_OPERATOR,
|
||||||
|
DISJUNCTION_OPERATOR,
|
||||||
|
NIL_COALESCING_OPERATOR,
|
||||||
|
EQUAL_SIGN,
|
||||||
|
EQ_EQ,
|
||||||
|
PLUS_THEN_WS,
|
||||||
|
MINUS_THEN_WS,
|
||||||
|
BANG,
|
||||||
|
THROWS_KEYWORD,
|
||||||
|
RETHROWS_KEYWORD,
|
||||||
|
DEFAULT_KEYWORD,
|
||||||
|
WHERE_KEYWORD,
|
||||||
|
ELSE_KEYWORD,
|
||||||
|
CATCH_KEYWORD,
|
||||||
|
AS_KEYWORD,
|
||||||
|
AS_QUEST,
|
||||||
|
AS_BANG,
|
||||||
|
ASYNC_KEYWORD
|
||||||
|
};
|
||||||
|
|
||||||
|
#define OPERATOR_COUNT 22
|
||||||
|
|
||||||
|
const char* OPERATORS[OPERATOR_COUNT] = {
|
||||||
|
"->",
|
||||||
|
".",
|
||||||
|
"...",
|
||||||
|
"..<",
|
||||||
|
"&&",
|
||||||
|
"||",
|
||||||
|
"??",
|
||||||
|
"=",
|
||||||
|
"==",
|
||||||
|
"+",
|
||||||
|
"-",
|
||||||
|
"!",
|
||||||
|
"throws",
|
||||||
|
"rethrows",
|
||||||
|
"default",
|
||||||
|
"where",
|
||||||
|
"else",
|
||||||
|
"catch",
|
||||||
|
"as",
|
||||||
|
"as?",
|
||||||
|
"as!",
|
||||||
|
"async"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum IllegalTerminatorGroup {
|
||||||
|
ALPHANUMERIC,
|
||||||
|
OPERATOR_SYMBOLS,
|
||||||
|
OPERATOR_OR_DOT,
|
||||||
|
NON_WHITESPACE
|
||||||
|
};
|
||||||
|
|
||||||
|
const enum IllegalTerminatorGroup OP_ILLEGAL_TERMINATORS[OPERATOR_COUNT] = {
|
||||||
|
OPERATOR_SYMBOLS, // ->
|
||||||
|
OPERATOR_OR_DOT, // .
|
||||||
|
OPERATOR_OR_DOT, // ...
|
||||||
|
OPERATOR_OR_DOT, // ..<
|
||||||
|
OPERATOR_SYMBOLS, // &&
|
||||||
|
OPERATOR_SYMBOLS, // ||
|
||||||
|
OPERATOR_SYMBOLS, // ??
|
||||||
|
OPERATOR_SYMBOLS, // =
|
||||||
|
OPERATOR_SYMBOLS, // ==
|
||||||
|
NON_WHITESPACE, // +
|
||||||
|
NON_WHITESPACE, // -
|
||||||
|
OPERATOR_SYMBOLS, // !
|
||||||
|
ALPHANUMERIC, // throws
|
||||||
|
ALPHANUMERIC, // rethrows
|
||||||
|
ALPHANUMERIC, // default
|
||||||
|
ALPHANUMERIC, // where
|
||||||
|
ALPHANUMERIC, // else
|
||||||
|
ALPHANUMERIC, // catch
|
||||||
|
ALPHANUMERIC, // as
|
||||||
|
OPERATOR_SYMBOLS, // as?
|
||||||
|
OPERATOR_SYMBOLS, // as!
|
||||||
|
ALPHANUMERIC // async
|
||||||
|
};
|
||||||
|
|
||||||
|
const enum TokenType OP_SYMBOLS[OPERATOR_COUNT] = {
|
||||||
|
ARROW_OPERATOR,
|
||||||
|
DOT_OPERATOR,
|
||||||
|
THREE_DOT_OPERATOR,
|
||||||
|
OPEN_ENDED_RANGE_OPERATOR,
|
||||||
|
CONJUNCTION_OPERATOR,
|
||||||
|
DISJUNCTION_OPERATOR,
|
||||||
|
NIL_COALESCING_OPERATOR,
|
||||||
|
EQUAL_SIGN,
|
||||||
|
EQ_EQ,
|
||||||
|
PLUS_THEN_WS,
|
||||||
|
MINUS_THEN_WS,
|
||||||
|
BANG,
|
||||||
|
THROWS_KEYWORD,
|
||||||
|
RETHROWS_KEYWORD,
|
||||||
|
DEFAULT_KEYWORD,
|
||||||
|
WHERE_KEYWORD,
|
||||||
|
ELSE_KEYWORD,
|
||||||
|
CATCH_KEYWORD,
|
||||||
|
AS_KEYWORD,
|
||||||
|
AS_QUEST,
|
||||||
|
AS_BANG,
|
||||||
|
ASYNC_KEYWORD
|
||||||
|
};
|
||||||
|
|
||||||
|
bool is_cross_semi_token(enum TokenType op) {
|
||||||
|
switch(op) {
|
||||||
|
case ARROW_OPERATOR:
|
||||||
|
case DOT_OPERATOR:
|
||||||
|
case THREE_DOT_OPERATOR:
|
||||||
|
case OPEN_ENDED_RANGE_OPERATOR:
|
||||||
|
case CONJUNCTION_OPERATOR:
|
||||||
|
case DISJUNCTION_OPERATOR:
|
||||||
|
case NIL_COALESCING_OPERATOR:
|
||||||
|
case EQUAL_SIGN:
|
||||||
|
case EQ_EQ:
|
||||||
|
case PLUS_THEN_WS:
|
||||||
|
case MINUS_THEN_WS:
|
||||||
|
case THROWS_KEYWORD:
|
||||||
|
case RETHROWS_KEYWORD:
|
||||||
|
case DEFAULT_KEYWORD:
|
||||||
|
case WHERE_KEYWORD:
|
||||||
|
case ELSE_KEYWORD:
|
||||||
|
case CATCH_KEYWORD:
|
||||||
|
case AS_KEYWORD:
|
||||||
|
case AS_QUEST:
|
||||||
|
case AS_BANG:
|
||||||
|
case ASYNC_KEYWORD:
|
||||||
|
return true;
|
||||||
|
case BANG:
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NON_CONSUMING_CROSS_SEMI_CHAR_COUNT 3
|
||||||
|
const uint32_t NON_CONSUMING_CROSS_SEMI_CHARS[NON_CONSUMING_CROSS_SEMI_CHAR_COUNT] = { '?', ':', '{' };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All possible results of having performed some sort of parsing.
|
||||||
|
*
|
||||||
|
* A parser can return a result along two dimensions:
|
||||||
|
* 1. Should the scanner continue trying to find another result?
|
||||||
|
* 2. Was some result produced by this parsing attempt?
|
||||||
|
*
|
||||||
|
* These are flattened into a single enum together. When the function returns one of the `TOKEN_FOUND` cases, it
|
||||||
|
* will always populate its `symbol_result` field. When it returns one of the `STOP_PARSING` cases, callers should
|
||||||
|
* immediately return (with the value, if there is one).
|
||||||
|
*/
|
||||||
|
enum ParseDirective {
|
||||||
|
CONTINUE_PARSING_NOTHING_FOUND,
|
||||||
|
CONTINUE_PARSING_TOKEN_FOUND,
|
||||||
|
STOP_PARSING_NOTHING_FOUND,
|
||||||
|
STOP_PARSING_TOKEN_FOUND
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ScannerState {
|
||||||
|
uint32_t ongoing_raw_str_hash_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *tree_sitter_swift_external_scanner_create() {
|
||||||
|
return calloc(0, sizeof(struct ScannerState));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tree_sitter_swift_external_scanner_destroy(void *payload) {
|
||||||
|
free(payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tree_sitter_swift_external_scanner_reset(void *payload) {
|
||||||
|
struct ScannerState *state = (struct ScannerState *)payload;
|
||||||
|
state->ongoing_raw_str_hash_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned tree_sitter_swift_external_scanner_serialize(void *payload, char *buffer) {
|
||||||
|
struct ScannerState *state = (struct ScannerState *)payload;
|
||||||
|
uint32_t hash_count = state->ongoing_raw_str_hash_count;
|
||||||
|
buffer[0] = (hash_count >> 24) & 0xff;
|
||||||
|
buffer[1] = (hash_count >> 16) & 0xff;
|
||||||
|
buffer[2] = (hash_count >> 8) & 0xff;
|
||||||
|
buffer[3] = (hash_count) & 0xff;
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tree_sitter_swift_external_scanner_deserialize(
|
||||||
|
void *payload,
|
||||||
|
const char *buffer,
|
||||||
|
unsigned length
|
||||||
|
) {
|
||||||
|
if (length < 4) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t hash_count = (
|
||||||
|
(((uint32_t) buffer[0]) << 24) |
|
||||||
|
(((uint32_t) buffer[1]) << 16) |
|
||||||
|
(((uint32_t) buffer[2]) << 8) |
|
||||||
|
(((uint32_t) buffer[3]))
|
||||||
|
);
|
||||||
|
struct ScannerState *state = (struct ScannerState *)payload;
|
||||||
|
state->ongoing_raw_str_hash_count = hash_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void advance(TSLexer *lexer) {
|
||||||
|
lexer->advance(lexer, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool should_treat_as_wspace(int32_t character) {
|
||||||
|
return iswspace(character) || (((int32_t) ';') == character);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t encountered_op_count(bool *encountered_operator) {
|
||||||
|
int32_t encountered = 0;
|
||||||
|
for (int op_idx = 0; op_idx < OPERATOR_COUNT; op_idx++) {
|
||||||
|
if (encountered_operator[op_idx]) {
|
||||||
|
encountered++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return encountered;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool eat_operators(
|
||||||
|
TSLexer *lexer,
|
||||||
|
const bool *valid_symbols,
|
||||||
|
bool mark_end,
|
||||||
|
enum TokenType *symbol_result
|
||||||
|
) {
|
||||||
|
bool possible_operators[OPERATOR_COUNT];
|
||||||
|
for (int op_idx = 0; op_idx < OPERATOR_COUNT; op_idx++) {
|
||||||
|
possible_operators[op_idx] = valid_symbols[OP_SYMBOLS[op_idx]];
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t str_idx = 0;
|
||||||
|
int32_t full_match = -1;
|
||||||
|
while(true) {
|
||||||
|
for (int op_idx = 0; op_idx < OPERATOR_COUNT; op_idx++) {
|
||||||
|
if (!possible_operators[op_idx]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OPERATORS[op_idx][str_idx] == '\0') {
|
||||||
|
// Make sure that the operator is allowed to have the next character as its lookahead.
|
||||||
|
enum IllegalTerminatorGroup illegal_terminators = OP_ILLEGAL_TERMINATORS[op_idx];
|
||||||
|
switch (lexer->lookahead) {
|
||||||
|
// See "Operators":
|
||||||
|
// https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID418
|
||||||
|
case '/':
|
||||||
|
case '=':
|
||||||
|
case '-':
|
||||||
|
case '+':
|
||||||
|
case '!':
|
||||||
|
case '*':
|
||||||
|
case '%':
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case '&':
|
||||||
|
case '|':
|
||||||
|
case '^':
|
||||||
|
case '?':
|
||||||
|
case '~':
|
||||||
|
if (illegal_terminators == OPERATOR_SYMBOLS) {
|
||||||
|
break;
|
||||||
|
} // Otherwise, intentionally fall through to the OPERATOR_OR_DOT case
|
||||||
|
// fall through
|
||||||
|
case '.':
|
||||||
|
if (illegal_terminators == OPERATOR_OR_DOT) {
|
||||||
|
break;
|
||||||
|
} // Otherwise, fall through to DEFAULT which checks its groups directly
|
||||||
|
// fall through
|
||||||
|
default:
|
||||||
|
if (iswalnum(lexer->lookahead) && illegal_terminators == ALPHANUMERIC) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iswspace(lexer->lookahead) && illegal_terminators == NON_WHITESPACE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
full_match = op_idx;
|
||||||
|
if (mark_end) {
|
||||||
|
lexer->mark_end(lexer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
possible_operators[op_idx] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OPERATORS[op_idx][str_idx] != lexer->lookahead) {
|
||||||
|
possible_operators[op_idx] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encountered_op_count(possible_operators) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lexer->advance(lexer, false);
|
||||||
|
str_idx += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (full_match != -1) {
|
||||||
|
*symbol_result = OP_SYMBOLS[full_match];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool eat_comment(
|
||||||
|
TSLexer *lexer,
|
||||||
|
const bool *valid_symbols,
|
||||||
|
bool mark_end,
|
||||||
|
enum TokenType *symbol_result
|
||||||
|
) {
|
||||||
|
// This is from https://github.com/tree-sitter/tree-sitter-rust/blob/f1c5c4b1d7b98a0288c1e4e6094cfcc3f6213cc0/src/scanner.c
|
||||||
|
if (lexer->lookahead == '/') {
|
||||||
|
advance(lexer);
|
||||||
|
if (lexer->lookahead != '*') return false;
|
||||||
|
advance(lexer);
|
||||||
|
|
||||||
|
bool after_star = false;
|
||||||
|
unsigned nesting_depth = 1;
|
||||||
|
for (;;) {
|
||||||
|
switch (lexer->lookahead) {
|
||||||
|
case '\0':
|
||||||
|
return false;
|
||||||
|
case '*':
|
||||||
|
advance(lexer);
|
||||||
|
after_star = true;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
if (after_star) {
|
||||||
|
advance(lexer);
|
||||||
|
after_star = false;
|
||||||
|
nesting_depth--;
|
||||||
|
if (nesting_depth == 0) {
|
||||||
|
if (mark_end) {
|
||||||
|
lexer->mark_end(lexer);
|
||||||
|
}
|
||||||
|
*symbol_result = BLOCK_COMMENT;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
advance(lexer);
|
||||||
|
after_star = false;
|
||||||
|
if (lexer->lookahead == '*') {
|
||||||
|
nesting_depth++;
|
||||||
|
advance(lexer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
advance(lexer);
|
||||||
|
after_star = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum ParseDirective eat_whitespace(
|
||||||
|
TSLexer *lexer,
|
||||||
|
const bool *valid_symbols,
|
||||||
|
enum TokenType *symbol_result
|
||||||
|
) {
|
||||||
|
enum ParseDirective ws_directive = CONTINUE_PARSING_NOTHING_FOUND;
|
||||||
|
bool semi_is_valid = valid_symbols[SEMI];
|
||||||
|
uint32_t lookahead;
|
||||||
|
while (should_treat_as_wspace(lookahead = lexer->lookahead)) {
|
||||||
|
if (lookahead == ';') {
|
||||||
|
if (!semi_is_valid) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ws_directive = STOP_PARSING_TOKEN_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
lexer->advance(lexer, true);
|
||||||
|
if (ws_directive == CONTINUE_PARSING_NOTHING_FOUND && (lookahead == '\n' || lookahead == '\r')) {
|
||||||
|
ws_directive = CONTINUE_PARSING_TOKEN_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lexer->mark_end(lexer);
|
||||||
|
|
||||||
|
if (true && ws_directive == CONTINUE_PARSING_TOKEN_FOUND && lookahead == '/') {
|
||||||
|
bool has_seen_single_comment = false;
|
||||||
|
while (lexer->lookahead == '/') {
|
||||||
|
// It's possible that this is a comment - start an exploratory mission to find out, and if it is, look for what
|
||||||
|
// comes after it. We care about what comes after it for the purpose of suppressing the newline.
|
||||||
|
|
||||||
|
enum TokenType multiline_comment_result;
|
||||||
|
bool saw_multiline_comment = eat_comment(lexer, valid_symbols, /* mark_end */ false, &multiline_comment_result);
|
||||||
|
if (saw_multiline_comment) {
|
||||||
|
// This is a multiline comment. This scanner should be parsing those, so we might want to bail out and
|
||||||
|
// emit it instead. However, we only want to do that if we haven't advanced through a _single_ line
|
||||||
|
// comment on the way - otherwise that will get lumped into this.
|
||||||
|
if (!has_seen_single_comment) {
|
||||||
|
lexer->mark_end(lexer);
|
||||||
|
*symbol_result = multiline_comment_result;
|
||||||
|
return STOP_PARSING_TOKEN_FOUND;
|
||||||
|
}
|
||||||
|
} else if (lexer->lookahead == '/') {
|
||||||
|
// There wasn't a multiline comment, which we know means that the comment parser ate its `/` and then
|
||||||
|
// bailed out. If it had seen anything comment-like after that first `/` it would have continued going
|
||||||
|
// and eventually had a well-formed comment or an EOF. Thus, if we're currently looking at a `/`, it's
|
||||||
|
// the second one of those and it means we have a single-line comment.
|
||||||
|
has_seen_single_comment = true;
|
||||||
|
while (lexer->lookahead != '\n' && lexer->lookahead != '\0') {
|
||||||
|
lexer->advance(lexer, true);
|
||||||
|
}
|
||||||
|
} else if (iswspace(lexer->lookahead)) {
|
||||||
|
// We didn't see any type of comment - in fact, we saw an operator that we don't normally treat as an
|
||||||
|
// operator. Still, this is a reason to stop parsing.
|
||||||
|
return STOP_PARSING_NOTHING_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we skipped through some comment, we're at whitespace now, so advance.
|
||||||
|
while(iswspace(lexer->lookahead)) {
|
||||||
|
lexer->advance(lexer, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TokenType operator_result;
|
||||||
|
bool saw_operator = eat_operators(lexer, valid_symbols, /* mark_end */ false, &operator_result);
|
||||||
|
if (saw_operator) {
|
||||||
|
// The operator we saw should suppress the newline, so bail out.
|
||||||
|
return STOP_PARSING_NOTHING_FOUND;
|
||||||
|
} else {
|
||||||
|
// Promote the implicit newline to an explicit one so we don't check for operators again.
|
||||||
|
*symbol_result = SEMI;
|
||||||
|
ws_directive = STOP_PARSING_TOKEN_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's consume operators that can live after a "semicolon" style newline. Before we do that, though, we want to
|
||||||
|
// check for a set of characters that we do not consume, but that still suppress the semi.
|
||||||
|
if (ws_directive == CONTINUE_PARSING_TOKEN_FOUND) {
|
||||||
|
for (int i = 0; i < NON_CONSUMING_CROSS_SEMI_CHAR_COUNT; i++) {
|
||||||
|
if (NON_CONSUMING_CROSS_SEMI_CHARS[i] == lookahead) {
|
||||||
|
return CONTINUE_PARSING_NOTHING_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semi_is_valid && ws_directive != CONTINUE_PARSING_NOTHING_FOUND) {
|
||||||
|
*symbol_result = SEMI;
|
||||||
|
return ws_directive;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CONTINUE_PARSING_NOTHING_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool eat_raw_str_part(
|
||||||
|
struct ScannerState *state,
|
||||||
|
TSLexer *lexer,
|
||||||
|
const bool *valid_symbols,
|
||||||
|
enum TokenType *symbol_result
|
||||||
|
) {
|
||||||
|
uint32_t hash_count = state->ongoing_raw_str_hash_count;
|
||||||
|
if (!valid_symbols[RAW_STR_PART]) {
|
||||||
|
return false;
|
||||||
|
} else if (hash_count == 0) {
|
||||||
|
// If this is a raw_str_part, it's the first one - look for hashes
|
||||||
|
while (lexer->lookahead == '#') {
|
||||||
|
hash_count += 1;
|
||||||
|
advance(lexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash_count == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lexer->lookahead == '"') {
|
||||||
|
advance(lexer);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (valid_symbols[RAW_STR_CONTINUING_INDICATOR]) {
|
||||||
|
// This is the end of an interpolation - now it's another raw_str_part. This is a synthetic
|
||||||
|
// marker to tell us that the grammar just consumed a `(` symbol to close a raw
|
||||||
|
// interpolation (since we don't want to fire on every `(` in existence). We don't have
|
||||||
|
// anything to do except continue.
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're in a state where anything other than `hash_count` hash symbols in a row should be eaten
|
||||||
|
// and is part of a string.
|
||||||
|
// The last character _before_ the hashes will tell us what happens next.
|
||||||
|
// Matters are also complicated by the fact that we don't want to consume every character we
|
||||||
|
// visit; if we see a `\#(`, for instance, with the appropriate number of hash symbols, we want
|
||||||
|
// to end our parsing _before_ that sequence. This allows highlighting tools to treat that as a
|
||||||
|
// separate token.
|
||||||
|
while (lexer->lookahead != '\0') {
|
||||||
|
uint8_t last_char = '\0';
|
||||||
|
lexer->mark_end(lexer); // We always want to parse thru the start of the string so far
|
||||||
|
// Advance through anything that isn't a hash symbol, because we want to count those.
|
||||||
|
while (lexer->lookahead != '#' && lexer->lookahead != '\0') {
|
||||||
|
last_char = lexer->lookahead;
|
||||||
|
advance(lexer);
|
||||||
|
if (last_char != '\\') {
|
||||||
|
// Mark a new end, but only if we didn't just advance past a `\` symbol, since we
|
||||||
|
// don't want to consume that.
|
||||||
|
lexer->mark_end(lexer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We hit at least one hash - count them and see if they match.
|
||||||
|
uint32_t current_hash_count = 0;
|
||||||
|
while (lexer->lookahead == '#' && current_hash_count < hash_count) {
|
||||||
|
current_hash_count += 1;
|
||||||
|
advance(lexer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we saw exactly the right number of hashes, one of three things is true:
|
||||||
|
// 1. We're trying to interpolate into this string.
|
||||||
|
// 2. The string just ended.
|
||||||
|
// 3. This was just some hash characters doing nothing important.
|
||||||
|
if (current_hash_count == hash_count) {
|
||||||
|
if (last_char == '\\' && lexer->lookahead == '(') {
|
||||||
|
// Interpolation case! Don't consume those chars; they get saved for grammar.js.
|
||||||
|
*symbol_result = RAW_STR_PART;
|
||||||
|
state->ongoing_raw_str_hash_count = hash_count;
|
||||||
|
return true;
|
||||||
|
} else if (last_char == '"') {
|
||||||
|
// The string is finished! Mark the end here, on the very last hash symbol.
|
||||||
|
lexer->mark_end(lexer);
|
||||||
|
*symbol_result = RAW_STR_END_PART;
|
||||||
|
state->ongoing_raw_str_hash_count = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Nothing special happened - let the string continue.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tree_sitter_swift_external_scanner_scan(
|
||||||
|
void *payload,
|
||||||
|
TSLexer *lexer,
|
||||||
|
const bool *valid_symbols
|
||||||
|
) {
|
||||||
|
// Figure out our scanner state
|
||||||
|
struct ScannerState *state = (struct ScannerState *)payload;
|
||||||
|
|
||||||
|
// Consume any whitespace at the start.
|
||||||
|
enum TokenType ws_result;
|
||||||
|
enum ParseDirective ws_directive = eat_whitespace(lexer, valid_symbols, &ws_result);
|
||||||
|
if (ws_directive == STOP_PARSING_TOKEN_FOUND) {
|
||||||
|
lexer->result_symbol = ws_result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ws_directive == STOP_PARSING_NOTHING_FOUND) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_ws_result = (ws_directive != CONTINUE_PARSING_NOTHING_FOUND);
|
||||||
|
|
||||||
|
// Now consume any operators that might cause our whitespace to be suppressed.
|
||||||
|
enum TokenType operator_result;
|
||||||
|
bool saw_operator = eat_operators(
|
||||||
|
lexer,
|
||||||
|
valid_symbols,
|
||||||
|
/* mark_end */ true,
|
||||||
|
&operator_result
|
||||||
|
);
|
||||||
|
|
||||||
|
if (saw_operator && (!has_ws_result || is_cross_semi_token(operator_result))) {
|
||||||
|
lexer->result_symbol = operator_result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_ws_result) {
|
||||||
|
// Don't `mark_end`, since we may have advanced through some operators.
|
||||||
|
lexer->result_symbol = ws_result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TokenType comment_result;
|
||||||
|
bool saw_comment = eat_comment(lexer, valid_symbols, /* mark_end */ true, &comment_result);
|
||||||
|
if (saw_comment) {
|
||||||
|
lexer->mark_end(lexer);
|
||||||
|
lexer->result_symbol = comment_result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: this will consume any `#` characters it sees, even if it does not find a result. Keep
|
||||||
|
// it at the end so that it doesn't interfere with special literals or selectors!
|
||||||
|
enum TokenType raw_str_result;
|
||||||
|
bool saw_raw_str_part = eat_raw_str_part(state, lexer, valid_symbols, &raw_str_result);
|
||||||
|
if (saw_raw_str_part) {
|
||||||
|
lexer->result_symbol = raw_str_result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,224 @@
|
|||||||
|
#ifndef TREE_SITTER_PARSER_H_
|
||||||
|
#define TREE_SITTER_PARSER_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define ts_builtin_sym_error ((TSSymbol)-1)
|
||||||
|
#define ts_builtin_sym_end 0
|
||||||
|
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
typedef uint16_t TSStateId;
|
||||||
|
|
||||||
|
#ifndef TREE_SITTER_API_H_
|
||||||
|
typedef uint16_t TSSymbol;
|
||||||
|
typedef uint16_t TSFieldId;
|
||||||
|
typedef struct TSLanguage TSLanguage;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
TSFieldId field_id;
|
||||||
|
uint8_t child_index;
|
||||||
|
bool inherited;
|
||||||
|
} TSFieldMapEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t index;
|
||||||
|
uint16_t length;
|
||||||
|
} TSFieldMapSlice;
|
||||||
|
|
||||||
|
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 *);
|
||||||
|
};
|
||||||
|
|
||||||
|
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 union {
|
||||||
|
TSParseAction action;
|
||||||
|
struct {
|
||||||
|
uint8_t count;
|
||||||
|
bool reusable;
|
||||||
|
} entry;
|
||||||
|
} TSParseActionEntry;
|
||||||
|
|
||||||
|
struct TSLanguage {
|
||||||
|
uint32_t 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 TSFieldMapSlice *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 TSLexMode *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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lexer Macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define START_LEXER() \
|
||||||
|
bool result = false; \
|
||||||
|
bool skip = false; \
|
||||||
|
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 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_val, child_count_val, ...) \
|
||||||
|
{{ \
|
||||||
|
.reduce = { \
|
||||||
|
.type = TSParseActionTypeReduce, \
|
||||||
|
.symbol = symbol_val, \
|
||||||
|
.child_count = child_count_val, \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
}, \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#define RECOVER() \
|
||||||
|
{{ \
|
||||||
|
.type = TSParseActionTypeRecover \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#define ACCEPT_INPUT() \
|
||||||
|
{{ \
|
||||||
|
.type = TSParseActionTypeAccept \
|
||||||
|
}}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // TREE_SITTER_PARSER_H_
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
const Parser = require("tree-sitter");
|
||||||
|
const Swift = require("tree-sitter-swift");
|
||||||
|
|
||||||
|
const parser = new Parser();
|
||||||
|
parser.setLanguage(Swift);
|
||||||
|
|
||||||
|
const sourceCode = `
|
||||||
|
struct HelloWorld {
|
||||||
|
func a() {
|
||||||
|
print("Hello, world!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HelloWorld().a()
|
||||||
|
`;
|
||||||
|
|
||||||
|
const tree = parser.parse(sourceCode);
|
||||||
|
console.log(tree.rootNode.toString());
|
||||||
|
|
||||||
|
const assert = require("assert");
|
||||||
|
const smallTree = parser.parse(`_ = "Hello!"\n`);
|
||||||
|
assert.equal(
|
||||||
|
`(source_file (assignment target: (directly_assignable_expression (simple_identifier)) result: (line_string_literal text: (line_str_text))))`,
|
||||||
|
smallTree.rootNode.toString()
|
||||||
|
);
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "npm-tree-sitter-test",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "npm install && node index.js"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tree-sitter": "^0.20.0",
|
||||||
|
"tree-sitter-swift": "file:../"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue