Add kotlin language (#1689)

* Add kotlin language

Queries taken from https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/kotlin seem to work well enough for my needs though I don't use kotlin heavily.

* Update lang-support doc

* Updates the kotlin highlight query to use helixs scopes

* Updates the queries from PR feedback

* Adds 'shallow = true' to gitmodules

* Removes kotlin locals.scm

* Remove blank line

Co-authored-by: Ivan Tham <pickfire@riseup.net>

Co-authored-by: Ivan Tham <pickfire@riseup.net>
This commit is contained in:
Michael Daffin 2022-02-23 14:25:44 +00:00 committed by GitHub
parent 40eb1268c7
commit f83843ceba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 365 additions and 1 deletions

7
.gitmodules vendored
View file

@ -209,7 +209,7 @@
[submodule "helix-syntax/languages/tree-sitter-graphql"]
path = helix-syntax/languages/tree-sitter-graphql
url = https://github.com/bkegley/tree-sitter-graphql
shallow = true
shallow = true
[submodule "helix-syntax/languages/tree-sitter-elm"]
path = helix-syntax/languages/tree-sitter-elm
url = https://github.com/elm-tooling/tree-sitter-elm
@ -229,3 +229,8 @@
[submodule "helix-syntax/languages/tree-sitter-erlang"]
path = helix-syntax/languages/tree-sitter-erlang
url = https://github.com/the-mikedavis/tree-sitter-erlang
shallow = true
[submodule "helix-syntax/languages/tree-sitter-kotlin"]
path = helix-syntax/languages/tree-sitter-kotlin
url = https://github.com/fwcd/tree-sitter-kotlin.git
shallow = true

View file

@ -27,6 +27,7 @@
| javascript | ✓ | | ✓ | `typescript-language-server` |
| json | ✓ | | ✓ | |
| julia | ✓ | | | `julia` |
| kotlin | ✓ | | | `kotlin-language-server` |
| latex | ✓ | | | |
| lean | ✓ | | | `lean` |
| ledger | ✓ | | | |

@ -0,0 +1 @@
Subproject commit a4f71eb9b8c9b19ded3e0e9470be4b1b77c2b569

View file

@ -741,3 +741,12 @@ file-types = ["erl", "hrl", "app", "rebar.config"]
roots = ["rebar.config"]
comment-token = "%%"
indent = { tab-width = 4, unit = " " }
[[language]]
name = "kotlin"
scope = "source.kotlin"
file-types = ["kt", "kts"]
roots = ["settings.gradle", "settings.gradle.kts"]
comment-token = "//"
indent = { tab-width = 4, unit = " " }
language-server = { command = "kotlin-language-server" }

View file

@ -0,0 +1,17 @@
[
(import_list)
(when_expression)
(control_structure_body)
(lambda_literal)
(function_body)
(primary_constructor)
(secondary_constructor)
(anonymous_initializer)
(class_body)
(enum_class_body)
(interpolated_expression)
] @fold

View file

@ -0,0 +1,295 @@
;;; Operators & Punctuation
(multi_line_string_literal
"$" @punctuation
(interpolated_identifier) @none)
(multi_line_string_literal
"${" @punctuation
(interpolated_expression) @none
"}" @punctuation.)
; NOTE: `interpolated_identifier`s can be highlighted in any way
(line_string_literal
"$" @punctuation
(interpolated_identifier) @none)
(line_string_literal
"${" @punctuation
(interpolated_expression) @none
"}" @punctuation)
[
"."
","
";"
":"
"::"
] @punctuation.delimiter
[
"(" ")"
"[" "]"
"{" "}"
] @punctuation.bracket
[
"!"
"!="
"!=="
"="
"=="
"==="
">"
">="
"<"
"<="
"||"
"&&"
"+"
"++"
"+="
"-"
"--"
"-="
"*"
"*="
"/"
"/="
"%"
"%="
"?."
"?:"
"!!"
"is"
"!is"
"in"
"!in"
"as"
"as?"
".."
"->"
] @operator
;;; Keywords
(type_alias "typealias" @keyword)
[
(class_modifier)
(member_modifier)
(function_modifier)
(property_modifier)
(platform_modifier)
(variance_modifier)
(parameter_modifier)
(visibility_modifier)
(reification_modifier)
(inheritance_modifier)
]@keyword
[
"val"
"var"
"enum"
"class"
"object"
"interface"
; "typeof" ; NOTE: It is reserved for future use
] @keyword
("fun") @keyword.function
(jump_expression) @keyword.control.return
[
"if"
"else"
"when"
] @keyword.control.conditional
[
"for"
"do"
"while"
] @keyword.control.repeat
[
"try"
"catch"
"throw"
"finally"
] @keyword.control.exception
(annotation
"@" @attribute (use_site_target)? @attribute)
(annotation
(user_type
(type_identifier) @attribute))
(annotation
(constructor_invocation
(user_type
(type_identifier) @attribute)))
(file_annotation
"@" @attribute "file" @attribute ":" @attribute)
(file_annotation
(user_type
(type_identifier) @attribute))
(file_annotation
(constructor_invocation
(user_type
(type_identifier) @attribute)))
;;; Literals
; NOTE: Escapes not allowed in multi-line strings
(line_string_literal (character_escape_seq) @constant.character.escape)
[
(line_string_literal)
(multi_line_string_literal)
] @string
(character_literal) @constant.character
[
"null" ; should be highlighted the same as booleans
(boolean_literal)
] @constant.builtin.boolean
(real_literal) @constant.numeric.float
[
(integer_literal)
(long_literal)
(hex_literal)
(bin_literal)
(unsigned_literal)
] @constant.numeric.integer
[
(comment)
(shebang_line)
] @comment
;;; Function calls
(call_expression
. (simple_identifier) @function.builtin
(#match? @function.builtin "^(arrayOf|arrayOfNulls|byteArrayOf|shortArrayOf|intArrayOf|longArrayOf|ubyteArrayOf|ushortArrayOf|uintArrayOf|ulongArrayOf|floatArrayOf|doubleArrayOf|booleanArrayOf|charArrayOf|emptyArray|mapOf|setOf|listOf|emptyMap|emptySet|emptyList|mutableMapOf|mutableSetOf|mutableListOf|print|println|error|TODO|run|runCatching|repeat|lazy|lazyOf|enumValues|enumValueOf|assert|check|checkNotNull|require|requireNotNull|with|suspend|synchronized)$"))
; object.function() or object.property.function()
(call_expression
(navigation_expression
(navigation_suffix
(simple_identifier) @function) . ))
; function()
(call_expression
. (simple_identifier) @function)
;;; Function definitions
; lambda parameters
(lambda_literal
(lambda_parameters
(variable_declaration
(simple_identifier) @variable.parameter)))
(parameter_with_optional_type
(simple_identifier) @variable.parameter)
(parameter
(simple_identifier) @variable.parameter)
(anonymous_initializer
("init") @constructor)
(constructor_invocation
(user_type
(type_identifier) @constructor))
(secondary_constructor
("constructor") @constructor)
(primary_constructor) @constructor
(getter
("get") @function.builtin)
(setter
("set") @function.builtin)
(function_declaration
. (simple_identifier) @function)
; TODO: Seperate labeled returns/breaks/continue/super/this
; Must be implemented in the parser first
(label) @label
(import_header
(identifier
(simple_identifier) @function @_import .)
(import_alias
(type_identifier) @function)?
(#match? @_import "^[a-z]"))
; The last `simple_identifier` in a `import_header` will always either be a function
; or a type. Classes can appear anywhere in the import path, unlike functions
(import_header
(identifier
(simple_identifier) @type @_import)
(import_alias
(type_identifier) @type)?
(#match? @_import "^[A-Z]"))
(import_header
"import" @keyword.control.import)
(package_header
. (identifier)) @namespace
((type_identifier) @type.builtin
(#match? @function.builtin "^(Byte|Short|Int|Long|UByte|UShort|UInt|ULong|Float|Double|Boolean|Char|String|Array|ByteArray|ShortArray|IntArray|LongArray|UByteArray|UShortArray|UIntArray|ULongArray|FloatArray|DoubleArray|BooleanArray|CharArray|Map|Set|List|EmptyMap|EmptySet|EmptyList|MutableMap|MutableSet|MutableList)$"))
(type_identifier) @type
(enum_entry
(simple_identifier) @constant)
(_
(navigation_suffix
(simple_identifier) @constant
(#match? @constant "^[A-Z][A-Z0-9_]*$")))
; SCREAMING CASE identifiers are assumed to be constants
((simple_identifier) @constant
(#match? @constant "^[A-Z][A-Z0-9_]*$"))
; id_1.id_2.id_3: `id_2` and `id_3` are assumed as object properties
(_
(navigation_suffix
(simple_identifier) @variable.other.member))
(class_body
(property_declaration
(variable_declaration
(simple_identifier) @variable.other.member)))
(class_parameter
(simple_identifier) @variable.other.member)
; `super` keyword inside classes
(super_expression) @variable.builtin
; `this` this keyword inside classes
(this_expression) @variable.builtin
;;; Identifiers
; `field` keyword inside property getter/setter
; FIXME: This will highlight the keyword outside of getters and setters
; since tree-sitter does not allow us to check for arbitrary nestation
((simple_identifier) @variable.builtin
(#eq? @variable.builtin "field"))
; `it` keyword inside lambdas
; FIXME: This will highlight the keyword outside of lambdas since tree-sitter
; does not allow us to check for arbitrary nestation
((simple_identifier) @variable.builtin
(#eq? @variable.builtin "it"))
(simple_identifier) @variable

View file

@ -0,0 +1,36 @@
((comment) @injection.content
(#set! injection.language "comment"))
; There are 3 ways to define a regex
; - "[abc]?".toRegex()
((call_expression
(navigation_expression
([(line_string_literal) (multi_line_string_literal)] @injection.content)
(navigation_suffix
((simple_identifier) @_function
(#eq? @_function "toRegex")))))
(#set! injection.language "regex"))
; - Regex("[abc]?")
((call_expression
((simple_identifier) @_function
(#eq? @_function "Regex"))
(call_suffix
(value_arguments
(value_argument
[ (line_string_literal) (multi_line_string_literal) ] @injection.content))))
(#set! injection.language "regex"))
; - Regex.fromLiteral("[abc]?")
((call_expression
(navigation_expression
((simple_identifier) @_class
(#eq? @_class "Regex"))
(navigation_suffix
((simple_identifier) @_function
(#eq? @_function "fromLiteral"))))
(call_suffix
(value_arguments
(value_argument
[ (line_string_literal) (multi_line_string_literal) ] @injection.content))))
(#set! injection.language "regex"))