Add 'vendor/tree-sitter-swift/' from commit '9b4350e513cb03fdd3e670069a30859ff82d532d'

git-subtree-dir: vendor/tree-sitter-swift
git-subtree-mainline: 6a404f51a8
git-subtree-split: 9b4350e513
pull/225/head
cherryblossom 2022-04-26 16:40:00 +07:00
commit 782b8f809e
No known key found for this signature in database
GPG Key ID: 03B34648D6DEB639
47 changed files with 11093 additions and 0 deletions

@ -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,14 @@
node_modules
/src/*
!/src/scanner.c
*.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,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 @@
![Parse rate badge](https://byob.yarr.is/alex-pinkus/tree-sitter-swift/parse_rate)
[![Crates.io badge](https://byob.yarr.is/alex-pinkus/tree-sitter-swift/crates_io_version)](https://crates.io/crates/tree-sitter-swift)
[![NPM badge](https://byob.yarr.is/alex-pinkus/tree-sitter-swift/npm_version)](https://www.npmjs.com/package/tree-sitter-swift)
[![Build](https://github.com/alex-pinkus/tree-sitter-swift/actions/workflows/top-repos.yml/badge.svg)](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))

@ -0,0 +1,95 @@
================================================================================
Emojis in variable names
================================================================================
let ⭐️ = "star"
let 🌙 = "moon"
let ☁️☀️☁️ = "clouds and sun"
--------------------------------------------------------------------------------
(source_file
(property_declaration
(value_binding_pattern
(non_binding_pattern
(simple_identifier)))
(line_string_literal
(line_str_text)))
(property_declaration
(value_binding_pattern
(non_binding_pattern
(simple_identifier)))
(line_string_literal
(line_str_text)))
(property_declaration
(value_binding_pattern
(non_binding_pattern
(simple_identifier)))
(line_string_literal
(line_str_text))))
================================================================================
Multi-codepoint emojis
================================================================================
func 🏃🏼‍♂️() {
}
🏃🏼‍♂️()
func 👨‍❤️‍💋‍👨(🙋🏼‍♂️ 🙋‍♂️: Man, 🙋🏻‍♂️ 🙋2: Man) {
}
👨‍❤️‍💋‍👨(🙋🏼‍♂️: a, 🙋🏻‍♂️: b)
--------------------------------------------------------------------------------
(source_file
(function_declaration
(simple_identifier)
(function_body))
(call_expression
(simple_identifier)
(call_suffix
(value_arguments)))
(function_declaration
(simple_identifier)
(parameter
(simple_identifier)
(simple_identifier)
(user_type
(type_identifier)))
(parameter
(simple_identifier)
(simple_identifier)
(user_type
(type_identifier)))
(function_body))
(call_expression
(simple_identifier)
(call_suffix
(value_arguments
(value_argument
(simple_identifier)
(simple_identifier))
(value_argument
(simple_identifier)
(simple_identifier))))))
================================================================================
Emojis with numbers in them
================================================================================
let number4⃣ = nummber2⃣ + number2
--------------------------------------------------------------------------------
(source_file
(property_declaration
(value_binding_pattern
(non_binding_pattern
(simple_identifier)))
(additive_expression
(simple_identifier)
(simple_identifier))))

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!"

@ -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,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:../"
}
}