Add 'vendor/tree-sitter-kotlin/' from commit 'a4f71eb9b8c9b19ded3e0e9470be4b1b77c2b569'

git-subtree-dir: vendor/tree-sitter-kotlin
git-subtree-mainline: cbd93bc2ea
git-subtree-split: a4f71eb9b8
pull/261/head
Wilfred Hughes 2022-04-14 00:05:02 +07:00
commit 600a4fb039
41 changed files with 630665 additions and 0 deletions

@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = true

@ -0,0 +1 @@
src/** linguist-vendored

@ -0,0 +1,27 @@
name: Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: '12'
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Compile grammar
run: npm run generate
- name: Run tests
run: npm test
- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Build and test crate
uses: actions-rs/cargo@v1
with:
command: test

@ -0,0 +1,29 @@
name: Deploy to crates.io
on:
push:
tags:
- '*'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: '12'
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Compile grammar
run: npm run generate
- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: Publish to crates.io
uses: actions-rs/cargo@v1
with:
command: publish
args: --token ${{ secrets.CRATES_IO_TOKEN }}

@ -0,0 +1,39 @@
name: Deploy to GitHub
on:
push:
tags:
- '*'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: '12'
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Compile grammar
run: npm run generate
- name: Build WASM binary
run: npm run build-wasm
- name: Deploy to GitHub Releases
uses: ncipollo/release-action@v1
with:
artifacts: tree-sitter-kotlin.wasm
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up folder for GitHub Pages deployment
run: |
mkdir public
cp tree-sitter-kotlin.wasm public/tree-sitter-parser.wasm
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
keep_files: true
user_name: 'github-actions[bot]'
user_email: 'github-actions[bot]@users.noreply.github.com'

@ -0,0 +1,25 @@
name: Deploy to NPM
on:
push:
tags:
- '*'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: '12'
registry-url: 'https://registry.npmjs.org'
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Compile grammar
run: npm run generate
- name: Publish to npm
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

@ -0,0 +1,23 @@
.DS_Store
.vscode
.idea
bin
build
local
public
node_modules
*.swp
*.wasm
# Windows compiler
*.exp
*.lib
*.obj
# WASM
*.asm.js
*.wasm
*.wasm.mem
# Rust build artifacts
target

@ -0,0 +1,57 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "cc"
version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
[[package]]
name = "memchr"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "tree-sitter"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63ec02a07a782abef91279b72fe8fd2bee4c168a22112cedec5d3b0d49b9e4f9"
dependencies = [
"cc",
"regex",
]
[[package]]
name = "tree-sitter-kotlin"
version = "0.2.11"
dependencies = [
"cc",
"tree-sitter",
]

@ -0,0 +1,27 @@
[package]
name = "tree-sitter-kotlin"
description = "Kotlin grammar for the tree-sitter parsing library"
version = "0.2.11"
keywords = ["incremental", "parsing", "kotlin"]
categories = ["parsing", "text-editors"]
repository = "https://github.com/fwcd/tree-sitter-kotlin"
edition = "2018"
license = "MIT"
readme = "bindings/rust/README.md"
build = "bindings/rust/build.rs"
include = [
"bindings/rust/*",
"grammar.js",
"queries/*",
"src/*",
]
[lib]
path = "bindings/rust/lib.rs"
[dependencies]
tree-sitter = "0.20"
[build-dependencies]
cc = "1.0"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -0,0 +1,9 @@
The MIT License (MIT)
Copyright (c) 2019 fwcd
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,64 @@
# Kotlin Grammar for Tree-Sitter
[![Build](https://github.com/fwcd/tree-sitter-kotlin/actions/workflows/build.yml/badge.svg)](https://github.com/fwcd/tree-sitter-kotlin/actions/workflows/build.yml)
[Kotlin](https://kotlinlang.org) language grammar for [Tree-Sitter](http://tree-sitter.github.io/tree-sitter/). You can try it out directly [on the web](https://fwcd.github.io/tree-sitter-kotlin).
![Icon](Icon128.png)
The grammar is based on the [official language grammar](https://kotlinlang.org/docs/reference/grammar.html).
## Project Structure
| File | Description |
| ---- | ----------- |
| grammar.js | The Tree-Sitter grammar |
| grammar-reference.js | A direct translation of the Kotlin language grammar that is, however, ambiguous to Tree-Sitter |
| src | The generated parser |
## Setup
>`npm install`
## Development
### Compilation
To (re-)compile the grammar, run:
>`npm run generate`
Note that the grammar is written completely in JavaScript (`grammar.js`), the other source files are generated by `tree-sitter`.
### Testing
To run the unit tests, run:
>`npm run test`
## WebAssembly
### Compilation
First make sure to have [Emscripten](https://emscripten.org/) installed. If you use Homebrew, you can `brew install emscripten`. Then run:
>`npm run build-wasm`
### Playground
After compiling the grammar to WebAssembly, you can invoke
>`npm run playground`
to launch an interactive editing environment that displays the parsed syntax tree on-the-fly in the browser. You can also view a deployed version of this playground [on the web](https://fwcd.github.io/tree-sitter-kotlin).
![Screenshot](playground-screenshot.png)
## Documentation
More documentation on how to create Tree-Sitter grammars [can be found here](https://tree-sitter.github.io/tree-sitter/creating-parsers).
## See also
* [Kotlin Language Server](https://github.com/fwcd/kotlin-language-server) for code completion, diagnostics and more
* [Kotlin Debug Adapter](https://github.com/fwcd/kotlin-debug-adapter) for JVM debugging support

@ -0,0 +1,19 @@
{
"targets": [
{
"target_name": "tree_sitter_kotlin_binding",
"include_dirs": [
"<!(node -e \"require('nan')\")",
"src"
],
"sources": [
"src/parser.c",
"src/scanner.c",
"bindings/node/binding.cc"
],
"cflags_c": [
"-std=c99",
]
}
]
}

@ -0,0 +1,28 @@
#include "tree_sitter/parser.h"
#include <node.h>
#include "nan.h"
using namespace v8;
extern "C" TSLanguage * tree_sitter_kotlin();
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_kotlin());
Nan::Set(instance, Nan::New("name").ToLocalChecked(), Nan::New("kotlin").ToLocalChecked());
Nan::Set(module, Nan::New("exports").ToLocalChecked(), instance);
}
NODE_MODULE(tree_sitter_kotlin_binding, Init)
} // namespace

@ -0,0 +1,19 @@
try {
module.exports = require("../../build/Release/tree_sitter_kotlin_binding");
} catch (error1) {
if (error1.code !== 'MODULE_NOT_FOUND') {
throw error1;
}
try {
module.exports = require("../../build/Debug/tree_sitter_kotlin_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,22 @@
# Kotlin Grammar for Tree-Sitter
This crate provides a Kotlin grammar for the [tree-sitter](https://tree-sitter.github.io/tree-sitter/) parsing library. To use this crate, add it to the `[dependencies]` section of your `Cargo.toml` file:
```toml
tree-sitter = "0.20"
tree-sitter-kotlin = "0.2.11"
```
Typically, you will use the `language` function to add this grammar to a tree-sitter [`Parser`](https://docs.rs/tree-sitter/*/tree_sitter/struct.Parser.html), and then use the parser to parse some code:
```rust
let code = r#"
data class Point(
val x: Int,
val y: Int
)
"#;
let mut parser = Parser::new();
parser.set_language(tree_sitter_kotlin::language()).expect("Error loading Kotlin grammar");
let parsed = parser.parse(code, None);
```

@ -0,0 +1,35 @@
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());
// If your language uses an external scanner written in C++,
// then include this block of code:
/*
let mut cpp_config = cc::Build::new();
cpp_config.cpp(true);
cpp_config.include(&src_dir);
cpp_config
.flag_if_supported("-Wno-unused-parameter")
.flag_if_supported("-Wno-unused-but-set-variable");
let scanner_path = src_dir.join("scanner.cc");
cpp_config.file(&scanner_path);
cpp_config.compile("scanner");
println!("cargo:rerun-if-changed={}", scanner_path.to_str().unwrap());
*/
}

@ -0,0 +1,52 @@
//! This crate provides kotlin 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_kotlin::language()).expect("Error loading kotlin 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_kotlin() -> 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_kotlin() }
}
/// 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 {
#[test]
fn test_can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(super::language())
.expect("Error loading kotlin language");
}
}

@ -0,0 +1,165 @@
package org.javacs.kt
import java.io.PrintWriter
import java.io.StringWriter
import java.util.*
import java.util.logging.Formatter
import java.util.logging.LogRecord
import java.util.logging.Handler
import java.util.logging.Level
import java.time.Instant
val LOG = Logger()
private class JULRedirector(private val downstream: Logger): Handler() {
override fun publish(record: LogRecord) {
when (record.level) {
Level.SEVERE -> downstream.error(record.message)
Level.WARNING -> downstream.warn(record.message)
Level.INFO -> downstream.info(record.message)
Level.CONFIG -> downstream.debug(record.message)
Level.FINE -> downstream.trace(record.message)
else -> downstream.deepTrace(record.message)
}
}
override fun flush() {}
override fun close() {}
}
enum class LogLevel(val value: Int) {
NONE(100),
ERROR(2),
WARN(1),
INFO(0),
DEBUG(-1),
TRACE(-2),
DEEP_TRACE(-3),
ALL(-100)
}
class LogMessage(
val level: LogLevel,
val message: String
) {
val formatted: String
get() = "[$level] $message"
}
class Logger {
private var outBackend: ((LogMessage) -> Unit)? = null
private var errBackend: ((LogMessage) -> Unit)? = null
private val outQueue: Queue<LogMessage> = ArrayDeque()
private val errQueue: Queue<LogMessage> = ArrayDeque()
private val newline = System.lineSeparator()
val logTime = false
var level = LogLevel.INFO
private fun outputError(msg: LogMessage) {
if (errBackend == null) {
errQueue.offer(msg)
} else {
errBackend?.invoke(msg)
}
}
private fun output(msg: LogMessage) {
if (outBackend == null) {
outQueue.offer(msg)
} else {
outBackend?.invoke(msg)
}
}
private fun log(msgLevel: LogLevel, msg: String, placeholders: Array<out Any?>) {
if (level.value <= msgLevel.value) {
output(LogMessage(msgLevel, format(insertPlaceholders(msg, placeholders))))
}
}
fun error(msg: String, vararg placeholders: Any?) = log(LogLevel.ERROR, msg, placeholders)
fun warn(msg: String, vararg placeholders: Any?) = log(LogLevel.WARN, msg, placeholders)
fun info(msg: String, vararg placeholders: Any?) = log(LogLevel.INFO, msg, placeholders)
fun debug(msg: String, vararg placeholders: Any?) = log(LogLevel.DEBUG, msg, placeholders)
fun trace(msg: String, vararg placeholders: Any?) = log(LogLevel.TRACE, msg, placeholders)
fun deepTrace(msg: String, vararg placeholders: Any?) = log(LogLevel.DEEP_TRACE, msg, placeholders)
fun connectJULFrontend() {
val rootLogger = java.util.logging.Logger.getLogger("")
rootLogger.addHandler(JULRedirector(this))
}
fun connectOutputBackend(outBackend: (LogMessage) -> Unit) {
this.outBackend = outBackend
flushOutQueue()
}
fun connectErrorBackend(errBackend: (LogMessage) -> Unit) {
this.errBackend = errBackend
flushErrQueue()
}
fun connectStdioBackend() {
connectOutputBackend { println(it.formatted) }
connectOutputBackend { System.err.println(it.formatted) }
}
private fun insertPlaceholders(msg: String, placeholders: Array<out Any?>): String {
val msgLength = msg.length
val lastIndex = msgLength - 1
var charIndex = 0
var placeholderIndex = 0
var result = StringBuilder()
while (charIndex < msgLength) {
val currentChar = msg.get(charIndex)
val nextChar = if (charIndex != lastIndex) msg.get(charIndex + 1) else '?'
if ((currentChar == '{') && (nextChar == '}')) {
if (placeholderIndex >= placeholders.size) {
return "ERROR: Tried to log more '{}' placeholders than there are values"
}
result.append(placeholders[placeholderIndex] ?: "null")
placeholderIndex += 1
charIndex += 2
} else {
result.append(currentChar)
charIndex += 1
}
}
return result.toString()
}
private fun flushOutQueue() {
while (outQueue.isNotEmpty()) {
outBackend?.invoke(outQueue.poll())
}
}
private fun flushErrQueue() {
while (errQueue.isNotEmpty()) {
errBackend?.invoke(errQueue.poll())
}
}
private fun format(msg: String): String {
val time = if (logTime) "${Instant.now()} " else ""
var thread = Thread.currentThread().name
return time + shortenOrPad(thread, 10) + msg
}
private fun shortenOrPad(str: String, length: Int): String =
if (str.length <= length) {
str.padEnd(length, ' ')
} else {
".." + str.substring(str.length - length + 2)
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,48 @@
{
"name": "tree-sitter-kotlin",
"version": "0.2.11",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "tree-sitter-kotlin",
"version": "0.2.11",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"nan": "^2.15.0"
},
"devDependencies": {
"tree-sitter-cli": "^0.20.0"
}
},
"node_modules/nan": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"node_modules/tree-sitter-cli": {
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.0.tgz",
"integrity": "sha512-4D1qapWbJXZ5rrSUGM5rcw5Vuq/smzn9KbiFRhlON6KeuuXjra+KAtDYVrDgAoLIG4ku+jbEEGrJxCptUGi3dg==",
"dev": true,
"hasInstallScript": true,
"bin": {
"tree-sitter": "cli.js"
}
}
},
"dependencies": {
"nan": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
"integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
},
"tree-sitter-cli": {
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/tree-sitter-cli/-/tree-sitter-cli-0.20.0.tgz",
"integrity": "sha512-4D1qapWbJXZ5rrSUGM5rcw5Vuq/smzn9KbiFRhlON6KeuuXjra+KAtDYVrDgAoLIG4ku+jbEEGrJxCptUGi3dg==",
"dev": true
}
}
}

@ -0,0 +1,36 @@
{
"name": "tree-sitter-kotlin",
"version": "0.2.11",
"description": "Tree-Sitter grammar for Kotlin",
"main": "bindings/node",
"scripts": {
"test": "tree-sitter test",
"install": "node-gyp rebuild",
"generate": "tree-sitter generate",
"parse": "tree-sitter parse",
"build-wasm": "tree-sitter build-wasm",
"playground": "tree-sitter playground"
},
"repository": {
"type": "git",
"url": "git+https://github.com/fwcd/tree-sitter-kotlin.git"
},
"keywords": [
"tree-sitter",
"kotlin",
"grammar"
],
"author": "fwcd",
"license": "MIT",
"gypfile": true,
"bugs": {
"url": "https://github.com/fwcd/tree-sitter-kotlin/issues"
},
"homepage": "https://github.com/fwcd/tree-sitter-kotlin#readme",
"dependencies": {
"nan": "^2.15.0"
},
"devDependencies": {
"tree-sitter-cli": "^0.20.0"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,308 @@
#include <tree_sitter/parser.h>
#include <wctype.h>
// Mostly a copy paste of tree-sitter-javascript/src/scanner.c
enum TokenType {
AUTOMATIC_SEMICOLON,
IMPORT_LIST_DELIMITER,
SAFE_NAV,
};
void *tree_sitter_kotlin_external_scanner_create() { return NULL; }
void tree_sitter_kotlin_external_scanner_destroy(void *p) {}
void tree_sitter_kotlin_external_scanner_reset(void *p) {}
unsigned tree_sitter_kotlin_external_scanner_serialize(void *p, char *buffer) { return 0; }
void tree_sitter_kotlin_external_scanner_deserialize(void *p, const char *b, unsigned n) {}
static void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
static void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
static bool scan_whitespace_and_comments(TSLexer *lexer) {
for (;;) {
while (iswspace(lexer->lookahead)) {
skip(lexer);
}
if (lexer->lookahead == '/') {
skip(lexer);
if (lexer->lookahead == '/') {
skip(lexer);
while (lexer->lookahead != 0 && lexer->lookahead != '\n') {
skip(lexer);
}
} else if (lexer->lookahead == '*') {
skip(lexer);
while (lexer->lookahead != 0) {
if (lexer->lookahead == '*') {
skip(lexer);
if (lexer->lookahead == '/') {
skip(lexer);
break;
}
} else {
skip(lexer);
}
}
} else {
return false;
}
} else {
return true;
}
}
}
bool scan_for_word(TSLexer *lexer, char* word, unsigned len) {
skip(lexer);
for (unsigned i = 0; i < len; i++) {
if (lexer->lookahead != word[i]) return false;
skip(lexer);
}
return true;
}
bool scan_automatic_semicolon(TSLexer *lexer) {
lexer->result_symbol = AUTOMATIC_SEMICOLON;
lexer->mark_end(lexer);
bool sameline = true;
for (;;) {
if (lexer->eof(lexer))
return true;
if (lexer->lookahead == ';') {
advance(lexer);
lexer->mark_end(lexer);
return true;
}
if (!iswspace(lexer->lookahead)) {
break;
}
if (lexer->lookahead == '\n') {
skip(lexer);
sameline = false;
break;
}
if (lexer->lookahead == '\r') {
skip(lexer);
if (lexer->lookahead == '\n') {
skip(lexer);
}
sameline = false;
break;
}
skip(lexer);
}
// Skip whitespace and comments
if (!scan_whitespace_and_comments(lexer))
return false;
if (sameline) {
switch (lexer->lookahead) {
// Don't insert a semicolon before an else
case 'e':
return !scan_for_word(lexer, "lse", 3);
case 'i':
return scan_for_word(lexer, "mport", 5);
case ';':
advance(lexer);
lexer->mark_end(lexer);
return true;
default:
return false;
}
}
switch (lexer->lookahead) {
case ',':
case '.':
case ':':
case '*':
case '%':
case '>':
case '<':
case '=':
case '{':
case '[':
case '(':
case '?':
case '|':
case '&':
case '/':
return false;
// Insert a semicolon before `--` and `++`, but not before binary `+` or `-`.
// Insert before +/-Float
case '+':
skip(lexer);
if (lexer->lookahead == '+')
return true;
return iswdigit(lexer->lookahead);
case '-':
skip(lexer);
if (lexer->lookahead == '-')
return true;
return iswdigit(lexer->lookahead);
// Don't insert a semicolon before `!=`, but do insert one before a unary `!`.
case '!':
skip(lexer);
return lexer->lookahead != '=';
// Don't insert a semicolon before an else
case 'e':
return !scan_for_word(lexer, "lse", 3);
// Don't insert a semicolon before `in` or `instanceof`, but do insert one
// before an identifier or an import.
case 'i':
skip(lexer);
if (lexer->lookahead != 'n')
return true;
skip(lexer);
if (!iswalpha(lexer->lookahead))
return false;
return !scan_for_word(lexer, "stanceof", 8);
case ';':
advance(lexer);
lexer->mark_end(lexer);
return true;
default:
return true;
}
}
bool scan_safe_nav(TSLexer *lexer) {
lexer->result_symbol = SAFE_NAV;
lexer->mark_end(lexer);
// skip white space
if (!scan_whitespace_and_comments(lexer))
return false;
if (lexer->lookahead != '?')
return false;
advance(lexer);
if (!scan_whitespace_and_comments(lexer))
return false;
if (lexer->lookahead != '.')
return false;
advance(lexer);
lexer->mark_end(lexer);
return true;
}
bool scan_line_sep(TSLexer *lexer) {
// Line Seps: [ CR, LF, CRLF ]
int state = 0;
while (true) {
switch(lexer->lookahead) {
case ' ':
case '\t':
case '\v':
// Skip whitespace
advance(lexer);
break;
case '\n':
advance(lexer);
return true;
case '\r':
if (state == 1)
return true;
state = 1;
advance(lexer);
break;
default:
// We read a CR
if (state == 1)
return true;
return false;
}
}
}
bool scan_import_list_delimiter(TSLexer *lexer) {
// Import lists are terminated either by an empty line or a non import statement
lexer->result_symbol = IMPORT_LIST_DELIMITER;
lexer->mark_end(lexer);
// if eof; return true
if (lexer->eof(lexer))
return true;
// Scan for the first line seperator
if (!scan_line_sep(lexer))
return false;
// if line.sep line.sep; return true
if (scan_line_sep(lexer)) {
lexer->mark_end(lexer);
return true;
}
// if line.sep [^import]; return true
while (true) {
switch (lexer->lookahead) {
case ' ':
case '\t':
case '\v':
// Skip whitespace
advance(lexer);
break;
case 'i':
return !scan_for_word(lexer, "mport", 5);
default:
return true;
}
return false;
}
}
bool tree_sitter_kotlin_external_scanner_scan(void *payload, TSLexer *lexer,
const bool *valid_symbols) {
if (valid_symbols[AUTOMATIC_SEMICOLON]) {
bool ret = scan_automatic_semicolon(lexer);
if (!ret && valid_symbols[SAFE_NAV] && lexer->lookahead == '?')
return scan_safe_nav(lexer);
return ret;
}
if (valid_symbols[SAFE_NAV]) {
return scan_safe_nav(lexer);
}
if (valid_symbols[IMPORT_LIST_DELIMITER])
return scan_import_list_delimiter(lexer);
return false;
}

@ -0,0 +1,223 @@
#ifndef TREE_SITTER_PARSER_H_
#define TREE_SITTER_PARSER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#define ts_builtin_sym_error ((TSSymbol)-1)
#define ts_builtin_sym_end 0
#define TREE_SITTER_SERIALIZATION_BUFFER_SIZE 1024
typedef uint16_t TSStateId;
#ifndef TREE_SITTER_API_H_
typedef uint16_t TSSymbol;
typedef uint16_t TSFieldId;
typedef struct TSLanguage TSLanguage;
#endif
typedef struct {
TSFieldId field_id;
uint8_t child_index;
bool inherited;
} TSFieldMapEntry;
typedef struct {
uint16_t index;
uint16_t length;
} TSFieldMapSlice;
typedef struct {
bool visible;
bool named;
bool supertype;
} TSSymbolMetadata;
typedef struct TSLexer TSLexer;
struct TSLexer {
int32_t lookahead;
TSSymbol result_symbol;
void (*advance)(TSLexer *, bool);
void (*mark_end)(TSLexer *);
uint32_t (*get_column)(TSLexer *);
bool (*is_at_included_range_start)(const TSLexer *);
bool (*eof)(const TSLexer *);
};
typedef enum {
TSParseActionTypeShift,
TSParseActionTypeReduce,
TSParseActionTypeAccept,
TSParseActionTypeRecover,
} TSParseActionType;
typedef union {
struct {
uint8_t type;
TSStateId state;
bool extra;
bool repetition;
} shift;
struct {
uint8_t type;
uint8_t child_count;
TSSymbol symbol;
int16_t dynamic_precedence;
uint16_t production_id;
} reduce;
uint8_t type;
} TSParseAction;
typedef struct {
uint16_t lex_state;
uint16_t external_lex_state;
} TSLexMode;
typedef union {
TSParseAction action;
struct {
uint8_t count;
bool reusable;
} entry;
} TSParseActionEntry;
struct TSLanguage {
uint32_t version;
uint32_t symbol_count;
uint32_t alias_count;
uint32_t token_count;
uint32_t external_token_count;
uint32_t state_count;
uint32_t large_state_count;
uint32_t production_id_count;
uint32_t field_count;
uint16_t max_alias_sequence_length;
const uint16_t *parse_table;
const uint16_t *small_parse_table;
const uint32_t *small_parse_table_map;
const TSParseActionEntry *parse_actions;
const char * const *symbol_names;
const char * const *field_names;
const TSFieldMapSlice *field_map_slices;
const TSFieldMapEntry *field_map_entries;
const TSSymbolMetadata *symbol_metadata;
const TSSymbol *public_symbol_map;
const uint16_t *alias_map;
const TSSymbol *alias_sequences;
const TSLexMode *lex_modes;
bool (*lex_fn)(TSLexer *, TSStateId);
bool (*keyword_lex_fn)(TSLexer *, TSStateId);
TSSymbol keyword_capture_token;
struct {
const bool *states;
const TSSymbol *symbol_map;
void *(*create)(void);
void (*destroy)(void *);
bool (*scan)(void *, TSLexer *, const bool *symbol_whitelist);
unsigned (*serialize)(void *, char *);
void (*deserialize)(void *, const char *, unsigned);
} external_scanner;
};
/*
* Lexer Macros
*/
#define START_LEXER() \
bool result = false; \
bool skip = false; \
bool eof = false; \
int32_t lookahead; \
goto start; \
next_state: \
lexer->advance(lexer, skip); \
start: \
skip = false; \
lookahead = lexer->lookahead;
#define ADVANCE(state_value) \
{ \
state = state_value; \
goto next_state; \
}
#define SKIP(state_value) \
{ \
skip = true; \
state = state_value; \
goto next_state; \
}
#define ACCEPT_TOKEN(symbol_value) \
result = true; \
lexer->result_symbol = symbol_value; \
lexer->mark_end(lexer);
#define END_STATE() return result;
/*
* Parse Table Macros
*/
#define SMALL_STATE(id) id - LARGE_STATE_COUNT
#define STATE(id) id
#define ACTIONS(id) id
#define SHIFT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value \
} \
}}
#define SHIFT_REPEAT(state_value) \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.state = state_value, \
.repetition = true \
} \
}}
#define SHIFT_EXTRA() \
{{ \
.shift = { \
.type = TSParseActionTypeShift, \
.extra = true \
} \
}}
#define REDUCE(symbol_val, child_count_val, ...) \
{{ \
.reduce = { \
.type = TSParseActionTypeReduce, \
.symbol = symbol_val, \
.child_count = child_count_val, \
__VA_ARGS__ \
}, \
}}
#define RECOVER() \
{{ \
.type = TSParseActionTypeRecover \
}}
#define ACCEPT_INPUT() \
{{ \
.type = TSParseActionTypeAccept \
}}
#ifdef __cplusplus
}
#endif
#endif // TREE_SITTER_PARSER_H_

@ -0,0 +1,121 @@
==================
Annotations
==================
@Test
class Empty
---
(source_file
(class_declaration
(modifiers (annotation (user_type (type_identifier))))
(type_identifier)))
==================
Annotations with use-site-target
==================
class Empty(@field:Test val x: Boolean)
---
(source_file
(class_declaration
(type_identifier)
(primary_constructor (class_parameter
(modifiers (annotation (use_site_target) (user_type (type_identifier))))
(simple_identifier)
(user_type (type_identifier))))))
==================
Multi-annotations
==================
@set:[Inject VisibleForTesting]
var x: Int
---
(source_file
(property_declaration
(modifiers (annotation (use_site_target) (user_type (type_identifier)) (user_type (type_identifier))))
(variable_declaration (simple_identifier) (user_type (type_identifier)))))
==================
Multiple annotations on a variable
==================
class X {
@A @B
override val s: String
}
---
(source_file
(class_declaration
(type_identifier)
(class_body
(property_declaration
(modifiers
(annotation (user_type (type_identifier)))
(annotation (user_type (type_identifier)))
(member_modifier))
(variable_declaration (simple_identifier) (user_type (type_identifier)))
)
)
)
)
==================
Multiple annotations on a function
==================
class X {
@A @B
fun s(): String
}
---
(source_file
(class_declaration
(type_identifier)
(class_body
(function_declaration
(modifiers
(annotation (user_type (type_identifier)))
(annotation (user_type (type_identifier))))
(simple_identifier)
(user_type (type_identifier))
)
)
)
)
=====================
Annotated functions
======================
@Test
fun foo() = bar {}
---
(source_file
(function_declaration
(modifiers
(annotation
(user_type
(type_identifier))))
(simple_identifier)
(function_body
(call_expression
(simple_identifier)
(call_suffix
(annotated_lambda
(lambda_literal)))))))

@ -0,0 +1,64 @@
==================
This Assignment
==================
class Foo(){
var foo = null
constructor(bar:Int) {
this.foo = bar
}
}
---
(source_file
(class_declaration
(type_identifier)
(primary_constructor)
(class_body
(property_declaration
(variable_declaration
(simple_identifier)))
(secondary_constructor
(parameter
(simple_identifier)
(user_type
(type_identifier)))
(statements
(assignment
(directly_assignable_expression
(this_expression)
(navigation_suffix
(simple_identifier)))
(simple_identifier)))))))
==================
Index Assignment
==================
fun main(){
var listOfPets:Array<String>
listOfPets[0] = "foo"
}
---
(source_file
(function_declaration
(simple_identifier)
(function_body
(statements
(property_declaration
(variable_declaration
(simple_identifier)
(user_type
(type_identifier)
(type_arguments
(type_projection
(user_type
(type_identifier)))))))
(assignment
(directly_assignable_expression
(simple_identifier)
(indexing_suffix
(integer_literal)))
(line_string_literal))))))

@ -0,0 +1,329 @@
==================
Classes
==================
class Empty
class Empty2 {}
---
(source_file
(class_declaration (type_identifier))
(class_declaration (type_identifier) (class_body)))
==================
Class with methods
==================
class HelloWorld {
fun a() {}
fun b() {}
}
---
(source_file
(class_declaration (type_identifier)
(class_body
(function_declaration (simple_identifier) (function_body))
(function_declaration (simple_identifier) (function_body)))))
==================
Generic class
==================
class Container<T> {}
---
(source_file
(class_declaration (type_identifier)
(type_parameters (type_parameter (type_identifier)))
(class_body)))
==================
Class with methods and expressions
==================
class Strings {
fun aString() = "Hello World!"
fun anotherString() = "Hello" + " " + "World"
}
---
(source_file
(class_declaration (type_identifier)
(class_body
(function_declaration (simple_identifier) (function_body
(line_string_literal)))
(function_declaration (simple_identifier) (function_body
(additive_expression
(additive_expression
(line_string_literal)
(line_string_literal))
(line_string_literal)))))))
==================
Class with modifiers
==================
internal open class Test {
private abstract inline fun test()
}
---
(source_file
(class_declaration
(modifiers (visibility_modifier) (inheritance_modifier))
(type_identifier)
(class_body
(function_declaration
(modifiers (visibility_modifier) (inheritance_modifier) (function_modifier))
(simple_identifier)))))
==================
Objects
==================
object Singleton {
fun test()
}
---
(source_file
(object_declaration (type_identifier)
(class_body
(function_declaration (simple_identifier)))))
==================
Primary constructors
==================
data class Vector2D(
val x: Int,
val y: Int
)
---
(source_file
(class_declaration
(modifiers (class_modifier))
(type_identifier)
(primary_constructor
(class_parameter
(simple_identifier)
(user_type (type_identifier)))
(class_parameter
(simple_identifier)
(user_type (type_identifier))))))
==================
Inheritance
==================
class A : B() {}
class C(param: Int) : D(param)
class D : SomeInterface
---
(source_file
(class_declaration
(type_identifier)
(delegation_specifier (constructor_invocation (user_type (type_identifier))
(value_arguments)))
(class_body))
(class_declaration
(type_identifier)
(primary_constructor
(class_parameter
(simple_identifier)
(user_type (type_identifier))))
(delegation_specifier (constructor_invocation (user_type (type_identifier))
(value_arguments (value_argument (simple_identifier))))))
(class_declaration
(type_identifier)
(delegation_specifier (user_type (type_identifier)))))
==================
Properties
==================
class Something {
val x: Int = 4
var y: Int?
val z: Int get() = x
}
---
(source_file
(class_declaration
(type_identifier)
(class_body
(property_declaration
(variable_declaration
(simple_identifier)
(user_type (type_identifier)))
(integer_literal))
(property_declaration
(variable_declaration
(simple_identifier)
(nullable_type (user_type (type_identifier)))))
(property_declaration
(variable_declaration
(simple_identifier)
(user_type (type_identifier)))
(getter (function_body (simple_identifier)))))))
==================
Constructor delegation calls
==================
class Test(x: Int, y: Int) {
constructor() : this(0, 0)
}
---
(source_file
(class_declaration
(type_identifier)
(primary_constructor
(class_parameter
(simple_identifier)
(user_type (type_identifier)))
(class_parameter
(simple_identifier)
(user_type (type_identifier))))
(class_body
(secondary_constructor
(constructor_delegation_call
(value_arguments
(value_argument (integer_literal))
(value_argument (integer_literal))))))))
==================
Enum classes
==================
enum class Suit {
DIAMONDS, CLOVERS, HEARTS, SPADES
}
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF);
override fun toString() = rgb.toString(16)
}
---
(source_file
(class_declaration
(type_identifier)
(enum_class_body
(enum_entry
(simple_identifier))
(enum_entry
(simple_identifier))
(enum_entry
(simple_identifier))
(enum_entry
(simple_identifier))))
(class_declaration
(type_identifier)
(primary_constructor
(class_parameter
(simple_identifier)
(user_type (type_identifier))))
(enum_class_body
(enum_entry
(simple_identifier)
(value_arguments
(value_argument (hex_literal))))
(enum_entry
(simple_identifier)
(value_arguments
(value_argument (hex_literal))))
(enum_entry
(simple_identifier)
(value_arguments
(value_argument (hex_literal))))
(function_declaration
(modifiers (member_modifier))
(simple_identifier)
(function_body
(call_expression
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(call_suffix
(value_arguments
(value_argument (integer_literal))))))))))
==================
Type alias declaration
==================
@Suppress("ACTUAL_WITHOUT_EXPECT")
internal actual typealias CoroutineStackFrame = kotlin.coroutines.jvm.internal.CoroutineStackFrame
---
(source_file
(type_alias
(modifiers
(annotation
(constructor_invocation
(user_type
(type_identifier))
(value_arguments
(value_argument
(line_string_literal)))))
(visibility_modifier)
(platform_modifier))
(type_identifier)
(user_type
(type_identifier)
(type_identifier)
(type_identifier)
(type_identifier)
(type_identifier))))
==================
Data class with hanging comma
==================
data class JwtConfiguration(
val audience: String,
val realm: String,
)
---
(source_file
(class_declaration
(modifiers
(class_modifier))
(type_identifier)
(primary_constructor
(class_parameter
(simple_identifier)
(user_type
(type_identifier)))
(class_parameter
(simple_identifier)
(user_type
(type_identifier))))))

@ -0,0 +1,15 @@
==================
Comments
==================
1 + 2
// 1 + 2
/*
/* Hello world */
---
(source_file
(additive_expression (integer_literal) (integer_literal))
(comment)
(comment))

@ -0,0 +1,330 @@
==================
Multiplication expression
==================
45 * 3
---
(source_file (multiplicative_expression (integer_literal) (integer_literal)))
==================
Safe Navigation
==================
a?.bar()
a? .bar()
a? . bar()
a?
.bar()
a ? . bar()
---
(source_file
(call_expression
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(call_suffix
(value_arguments)))
(call_expression
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(call_suffix
(value_arguments)))
(call_expression
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(call_suffix
(value_arguments)))
(call_expression
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(call_suffix
(value_arguments)))
(call_expression
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(call_suffix
(value_arguments))))
==================
Function calls
==================
print("Hello World!")
sum(1, 2)
---
(source_file
(call_expression (simple_identifier)
(call_suffix (value_arguments
(value_argument (line_string_literal)))))
(call_expression (simple_identifier)
(call_suffix (value_arguments
(value_argument (integer_literal))
(value_argument (integer_literal))))))
==================
When expression
==================
val x = 1
val y = when(x){
1 -> true
2 -> false
}
---
(source_file
(property_declaration
(variable_declaration (simple_identifier))
(integer_literal))
(property_declaration
(variable_declaration (simple_identifier))
(when_expression
(when_subject (simple_identifier))
(when_entry (when_condition (integer_literal))
(control_structure_body (boolean_literal)))
(when_entry (when_condition (integer_literal))
(control_structure_body (boolean_literal))))))
=================
When expression with type arguments
================
when (this) {
is DispatchedCoroutine<*> -> return null
}
---
(source_file
(when_expression
(when_subject
(this_expression))
(when_entry
(when_condition
(type_test
(user_type
(type_identifier)
(type_arguments
(type_projection)))))
(control_structure_body
(jump_expression)))))
==================
Value declaration with receiver type
==================
val MyDate.s: String get() = "hello"
---
(source_file
(property_declaration
(user_type
(type_identifier))
(variable_declaration
(simple_identifier)
(user_type
(type_identifier)))
(getter
(function_body
(line_string_literal)))))
==================
Expect as an expression
==================
val x = expect(1)
---
(source_file
(property_declaration
(variable_declaration (simple_identifier))
(call_expression (simple_identifier)
(call_suffix (value_arguments (value_argument (integer_literal)))))))
==================
Expect as a top-level expression
==================
expect(1)
---
(source_file
(call_expression (simple_identifier)
(call_suffix (value_arguments (value_argument (integer_literal))))))
==================
Expect as a platform modifier
==================
expect fun randomUUID(): String
---
(source_file
(function_declaration
(modifiers (platform_modifier))
(simple_identifier)
(user_type (type_identifier))))
==================
Less than for generics
==================
foo<Int>(1,2)
foo<Int>(1)
---
(source_file
(call_expression (simple_identifier)
(call_suffix
(type_arguments (type_projection (user_type (type_identifier))))
(value_arguments (value_argument (integer_literal))
(value_argument (integer_literal)))))
(call_expression (simple_identifier)
(call_suffix
(type_arguments (type_projection (user_type (type_identifier))))
(value_arguments (value_argument (integer_literal))))))
==================
Less than for comparison
==================
val x = a<b
val y = a>b
val z = a<b>c
// this is parsed as a generic, but could also be parsed as a comparison
val w = a<b>(c)
val a = a<2>(3)
---
(source_file
(property_declaration (variable_declaration (simple_identifier))
(comparison_expression (simple_identifier) (simple_identifier)))
(property_declaration (variable_declaration (simple_identifier))
(comparison_expression (simple_identifier) (simple_identifier)))
(property_declaration (variable_declaration (simple_identifier))
(comparison_expression
(comparison_expression (simple_identifier) (simple_identifier))
(simple_identifier)))
(comment)
(property_declaration (variable_declaration (simple_identifier))
(call_expression (simple_identifier)
(call_suffix
(type_arguments (type_projection (user_type (type_identifier))))
(value_arguments (value_argument (simple_identifier))))))
(property_declaration (variable_declaration (simple_identifier))
(comparison_expression
(comparison_expression (simple_identifier) (integer_literal))
(parenthesized_expression (integer_literal)))))
==================
Lambda Expressions
==================
foo.forEach { (index, value) -> 2 }
---
(source_file
(call_expression
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(call_suffix
(annotated_lambda
(lambda_literal
(lambda_parameters
(multi_variable_declaration
(variable_declaration
(simple_identifier))
(variable_declaration
(simple_identifier))))
(statements
(integer_literal)))))))
==================
Multiple Statements on a Single Line
==================
fun main() { val temp = b.y; b.y = b.z; b.z = temp }
when (dir) {
1 -> { val temp = b.y; b.y = b.z; b.z = temp }
}
---
(source_file
(function_declaration
(simple_identifier)
(function_body
(statements
(property_declaration
(variable_declaration
(simple_identifier))
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier))))
(assignment
(directly_assignable_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier))))
(assignment
(directly_assignable_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(simple_identifier)))))
(when_expression
(when_subject
(simple_identifier))
(when_entry
(when_condition
(integer_literal))
(control_structure_body
(statements
(property_declaration
(variable_declaration
(simple_identifier))
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier))))
(assignment
(directly_assignable_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier))))
(assignment
(directly_assignable_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(simple_identifier)))))))

@ -0,0 +1,276 @@
==================
Top-level functions
==================
fun main() {}
---
(source_file
(function_declaration
(simple_identifier)
(function_body)))
==================
Generic functions
==================
fun <T> test() {}
---
(source_file
(function_declaration
(type_parameters (type_parameter (type_identifier)))
(simple_identifier)
(function_body)))
==================
Generic functions with parameters
=================
fun <T: Int> bar(foo: Int): T {}
---
(source_file
(function_declaration
(type_parameters
(type_parameter
(type_identifier)
(user_type
(type_identifier))))
(simple_identifier)
(parameter
(simple_identifier)
(user_type
(type_identifier)))
(user_type
(type_identifier))
(function_body)))
==================
Functions with parameters
==================
fun main(args: Array<String>) {}
fun sum(a: Int, b: Int) = a + b
---
(source_file
(function_declaration
(simple_identifier)
(parameter
(simple_identifier)
(user_type
(type_identifier)
(type_arguments (type_projection (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
(additive_expression
(simple_identifier)
(simple_identifier)))))
==================
Functions with return types
==================
fun answerToTheUltimateQuestionOfLifeTheUniverseAndEverything(): Int = 42
---
(source_file
(function_declaration
(simple_identifier)
(user_type (type_identifier))
(function_body (integer_literal))))
==================
Functions with return calls
==================
fun foo(p0: Int): Long {
return p0.toLong()
}
---
(source_file
(function_declaration
(simple_identifier)
(parameter
(simple_identifier)
(user_type
(type_identifier)))
(user_type
(type_identifier))
(function_body
(statements
(jump_expression
(call_expression
(navigation_expression
(simple_identifier)
(navigation_suffix
(simple_identifier)))
(call_suffix
(value_arguments))))))))
=====================
Override functions
======================
override fun boo() = foo()
---
(source_file
(function_declaration
(modifiers
(member_modifier))
(simple_identifier)
(function_body
(call_expression
(simple_identifier)
(call_suffix
(value_arguments))))))
=====================
Set function call
======================
fun test() {
isAccessible = true
set(it, COROUTINE_SUSPENDED)
}
---
(source_file
(function_declaration
(simple_identifier)
(function_body
(statements
(assignment
(directly_assignable_expression
(simple_identifier))
(boolean_literal))
(call_expression
(simple_identifier)
(call_suffix
(value_arguments
(value_argument
(simple_identifier))
(value_argument
(simple_identifier)))))))))
==================
Anonymous function
==================
fun()
val anon = fun()
---
(source_file
(anonymous_function)
(property_declaration
(variable_declaration
(simple_identifier))
(anonymous_function)))
==================
Anonymous function with parameters
==================
fun(x: Int)
val anon = fun(x: Int)
---
(source_file
(anonymous_function
(parameter
(simple_identifier)
(user_type
(type_identifier))))
(property_declaration
(variable_declaration
(simple_identifier))
(anonymous_function
(parameter
(simple_identifier)
(user_type
(type_identifier))))))
==================
Anonymous function with return type
==================
fun(): Int
val anon = fun(): Int
---
(source_file
(anonymous_function
(user_type
(type_identifier)))
(property_declaration
(variable_declaration
(simple_identifier))
(anonymous_function
(user_type
(type_identifier)))))
==================
Anonymous function with body
==================
fun() = true
fun() { assert(true) }
val anon = fun() = true
val anon = fun() { assert(true) }
---
(source_file
(anonymous_function
(function_body
(boolean_literal)))
(anonymous_function
(function_body
(statements
(call_expression
(simple_identifier)
(call_suffix
(value_arguments
(value_argument
(boolean_literal))))))))
(property_declaration
(variable_declaration
(simple_identifier))
(anonymous_function
(function_body
(boolean_literal))))
(property_declaration
(variable_declaration
(simple_identifier))
(anonymous_function
(function_body
(statements
(call_expression
(simple_identifier)
(call_suffix
(value_arguments
(value_argument
(boolean_literal))))))))))

@ -0,0 +1,124 @@
==================
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.
"""
---
(source_file
(line_string_literal)
(multi_line_string_literal))
==================
String interpolation
==================
"Sample $string.interpolation literal"
"Sample ${"string.interpolation"} literal"
"""
Multiline
${"""string interpolation"""} $literal
"""
---
(source_file
(line_string_literal (interpolated_identifier))
(line_string_literal (interpolated_expression (line_string_literal)))
(multi_line_string_literal
(interpolated_expression (multi_line_string_literal))
(interpolated_identifier)))
==================
Integer literals
==================
0
8
23
9847
---
(source_file
(integer_literal)
(integer_literal)
(integer_literal)
(integer_literal))
==================
Real literals
==================
0.0
-23.434
1e-10
4.3f
+53.9e-3F
---
(source_file
(real_literal)
(prefix_expression (real_literal))
(real_literal)
(real_literal)
(prefix_expression (real_literal)))
===================
Unicode literals
===================
assertEquals("\u214E\uA7B5\u2CEF", "\u2132\uA7B4\u2CEF".lowercase())
---
(source_file
(call_expression
(simple_identifier)
(call_suffix
(value_arguments
(value_argument
(line_string_literal
(character_escape_seq)
(character_escape_seq)
(character_escape_seq)))
(value_argument
(call_expression
(navigation_expression
(line_string_literal
(character_escape_seq)
(character_escape_seq)
(character_escape_seq))
(navigation_suffix
(simple_identifier)))
(call_suffix
(value_arguments))))))))

@ -0,0 +1,195 @@
==================
Dot after newline
==================
bar.foo()
.show()
---
(source_file
(call_expression
(navigation_expression
(call_expression
(navigation_expression (simple_identifier)
(navigation_suffix (simple_identifier)))
(call_suffix (value_arguments)))
(navigation_suffix (simple_identifier)))
(call_suffix (value_arguments))))
==================
Eq after newline
==================
fun foo()
= 1
---
(source_file
(function_declaration (simple_identifier)
(function_body (integer_literal))))
==================
Binary operator after newline
==================
fun foo() {
val bar = x
&& y
}
---
(source_file
(function_declaration (simple_identifier)
(function_body
(statements
(property_declaration
(variable_declaration (simple_identifier))
(conjunction_expression (simple_identifier) (simple_identifier)))))))
==================
Open brace after newline
==================
fun foo():String
{ return "bar"}
---
(source_file
(function_declaration (simple_identifier)
(user_type (type_identifier))
(function_body (statements (jump_expression (line_string_literal))))))
==================
Colon after newline
==================
class Foo
: Bar {
}
---
(source_file
(class_declaration (type_identifier)
(delegation_specifier (user_type (type_identifier)))
(class_body)))
==================
Question mark after newline
==================
fun foo() {
val foo = a?.bar(true)
?: x.foo()
?: break
}
---
(source_file
(function_declaration (simple_identifier)
(function_body
(statements
(property_declaration
(variable_declaration (simple_identifier))
(elvis_expression
(elvis_expression
(call_expression
(navigation_expression (simple_identifier)
(navigation_suffix (simple_identifier)))
(call_suffix
(value_arguments (value_argument (boolean_literal)))))
(call_expression
(navigation_expression (simple_identifier)
(navigation_suffix (simple_identifier)))
(call_suffix (value_arguments))))
(jump_expression)))))))
==================
get after newline
==================
class Foo {
val maxMemory: Long
get() = bar() / 1024
}
---
(source_file
(class_declaration (type_identifier)
(class_body
(property_declaration
(variable_declaration (simple_identifier)
(user_type (type_identifier))))
(getter
(function_body
(multiplicative_expression
(call_expression (simple_identifier)
(call_suffix (value_arguments)))
(integer_literal)))))))
==================
Newline in function call
==================
// The Kotlin grammar does not allow newlines/semicolons in function calls,
// but tree-sitter uses context-aware lexing to overcome this.
foo(1,
2)
---
(source_file
(comment)
(comment)
(call_expression (simple_identifier)
(call_suffix
(value_arguments
(value_argument (integer_literal))
(value_argument (integer_literal))))))
==================
Else after newline
==================
if (!foo) 3
else boo()
---
(source_file
(if_expression
(prefix_expression
(simple_identifier))
(control_structure_body
(integer_literal))
(control_structure_body
(call_expression
(simple_identifier)
(call_suffix
(value_arguments))))))
==================
Else after newline
==================
if (!foo) 3 else boo()
---
(source_file
(if_expression
(prefix_expression
(simple_identifier))
(control_structure_body
(integer_literal))
(control_structure_body
(call_expression
(simple_identifier)
(call_suffix
(value_arguments))))))

@ -0,0 +1,23 @@
==================
Actual as an identifier
==================
fun foo() {
val actual = IntArray(n)
actual[0]++
}
---
(source_file
(function_declaration (simple_identifier)
(function_body
(statements
(property_declaration
(variable_declaration (simple_identifier))
(call_expression (simple_identifier)
(call_suffix
(value_arguments (value_argument (simple_identifier))))))
(postfix_expression
(indexing_expression (simple_identifier)
(indexing_suffix (integer_literal))))))))

@ -0,0 +1,111 @@
==================
File annotations
==================
@file:JvmName("HelloWorld")
val x = 4
---
(source_file
(file_annotation
(constructor_invocation
(user_type (type_identifier))
(value_arguments (value_argument (line_string_literal)))))
(property_declaration
(variable_declaration
(simple_identifier))
(integer_literal)))
===================
Multiple file annotations
===================
@file:JvmMultifileClass
@file:JvmName("BuildersKt")
@file:OptIn(ExperimentalContracts::class)
---
(source_file
(file_annotation
(user_type
(type_identifier)))
(file_annotation
(constructor_invocation
(user_type
(type_identifier))
(value_arguments
(value_argument
(line_string_literal)))))
(file_annotation
(constructor_invocation
(user_type
(type_identifier))
(value_arguments
(value_argument
(callable_reference
(type_identifier)))))))
==================
Imports
==================
import java.util.Scanner
import java.util.StringBuilder
import java.io.Path
import java.io.Files
fun main() {
}
---
(source_file
(import_list
(import_header
(identifier
(simple_identifier)
(simple_identifier)
(simple_identifier)))
(import_header
(identifier
(simple_identifier)
(simple_identifier)
(simple_identifier))))
(import_list
(import_header
(identifier
(simple_identifier)
(simple_identifier)
(simple_identifier)))
(import_header
(identifier
(simple_identifier)
(simple_identifier)
(simple_identifier))))
(function_declaration
(simple_identifier)
(function_body)))
===================
Multiple Imports On A Single Line
===================
import java.io.Path import java.io.Files
---
(source_file
(import_list
(import_header
(identifier
(simple_identifier)
(simple_identifier)
(simple_identifier)))
(import_header
(identifier
(simple_identifier)
(simple_identifier)
(simple_identifier)))))

@ -0,0 +1,38 @@
==================
For statements
==================
for (value in values) {}
---
(source_file
(for_statement
(variable_declaration (simple_identifier))
(simple_identifier)
(control_structure_body)))
==================
Statements separated by semicolon
==================
override fun isDisposed(): Boolean { expectUnreached(); return false }
---
(source_file
(function_declaration
(modifiers
(member_modifier))
(simple_identifier)
(user_type
(type_identifier))
(function_body
(statements
(call_expression
(simple_identifier)
(call_suffix
(value_arguments)))
(jump_expression
(boolean_literal))))))

@ -0,0 +1,176 @@
==================
Type references
==================
something as Int
something as A
---
(source_file
(as_expression
(simple_identifier)
(user_type (type_identifier)))
(as_expression
(simple_identifier)
(user_type (type_identifier))))
==================
Nested types
==================
// TODO the introduction of scanner.c changed the AST for nested types
something as Some.NestedType
---
(source_file
(comment)
(navigation_expression
(as_expression (simple_identifier)
(user_type (type_identifier)))
(navigation_suffix (simple_identifier))))
==================
Deeply nested types
==================
// TODO the introduction of scanner.c changed the AST for nested types
somethingElse as A.Deeply.Nested.Type
---
(source_file
(comment)
(navigation_expression
(navigation_expression
(navigation_expression
(as_expression (simple_identifier) (user_type (type_identifier)))
(navigation_suffix (simple_identifier)))
(navigation_suffix (simple_identifier)))
(navigation_suffix (simple_identifier))))
==================
Generic wildcard types
==================
something as Generic<*>
---
(source_file
(as_expression
(simple_identifier)
(user_type (type_identifier)
(type_arguments (type_projection)))))
==================
Generic parameterized types
==================
something as Generic<T>
something as Generic<A, Type>
---
(source_file
(as_expression
(simple_identifier)
(user_type (type_identifier)
(type_arguments
(type_projection
(user_type (type_identifier))))))
(as_expression
(simple_identifier)
(user_type (type_identifier)
(type_arguments
(type_projection
(user_type (type_identifier)))
(type_projection
(user_type (type_identifier)))))))
==================
Function types
==================
unitFunction as () -> Unit
consumer as (Int) -> Unit
---
(source_file
(as_expression
(simple_identifier)
(function_type
(function_type_parameters)
(user_type (type_identifier))))
(as_expression
(simple_identifier)
(function_type
(function_type_parameters (user_type (type_identifier)))
(user_type (type_identifier)))))
==================
Function types with multiple parameters
==================
a as (Int, Generic<*>, Boolean) -> Unit
b as (Nested.Type, (Int)) -> Unit
---
(source_file
(as_expression
(simple_identifier)
(function_type
(function_type_parameters
(user_type (type_identifier))
(user_type (type_identifier)
(type_arguments
(type_projection)))
(user_type (type_identifier)))
(user_type (type_identifier))))
(as_expression
(simple_identifier)
(function_type
(function_type_parameters
(user_type (type_identifier) (type_identifier))
(parenthesized_type (user_type (type_identifier))))
(user_type (type_identifier)))))
==================
Function types with named parameters
==================
a as (first: A, second: B) -> Unit
---
(source_file
(as_expression
(simple_identifier)
(function_type
(function_type_parameters
(parameter
(simple_identifier)
(user_type (type_identifier)))
(parameter
(simple_identifier)
(user_type (type_identifier))))
(user_type (type_identifier)))))
==================
Function types with receiver
==================
a as T.() -> Unit
---
(source_file
(as_expression
(simple_identifier)
(function_type
(type_identifier)
(function_type_parameters)
(user_type (type_identifier)))))