on master help sign in
Add kotlin language (#1689)
f83843cMichael Daffin
.gitmodules+6−1
@@ -209,7 +209,7 @@
209[submodule "helix-syntax/languages/tree-sitter-graphql"]
209[submodule "helix-syntax/languages/tree-sitter-graphql"]
210 path = helix-syntax/languages/tree-sitter-graphql
210 path = helix-syntax/languages/tree-sitter-graphql
211 url = https://github.com/bkegley/tree-sitter-graphql
211 url = https://github.com/bkegley/tree-sitter-graphql
212− shallow = true
212+ shallow = true
213[submodule "helix-syntax/languages/tree-sitter-elm"]
213[submodule "helix-syntax/languages/tree-sitter-elm"]
214 path = helix-syntax/languages/tree-sitter-elm
214 path = helix-syntax/languages/tree-sitter-elm
215 url = https://github.com/elm-tooling/tree-sitter-elm
215 url = https://github.com/elm-tooling/tree-sitter-elm
@@ -229,3 +229,8 @@
229[submodule "helix-syntax/languages/tree-sitter-erlang"]
229[submodule "helix-syntax/languages/tree-sitter-erlang"]
230 path = helix-syntax/languages/tree-sitter-erlang
230 path = helix-syntax/languages/tree-sitter-erlang
231 url = https://github.com/the-mikedavis/tree-sitter-erlang
231 url = https://github.com/the-mikedavis/tree-sitter-erlang
232+ shallow = true
233+[submodule "helix-syntax/languages/tree-sitter-kotlin"]
234+ path = helix-syntax/languages/tree-sitter-kotlin
235+ url = https://github.com/fwcd/tree-sitter-kotlin.git
236+ shallow = true
book/src/generated/lang-support.md+1
@@ -27,6 +27,7 @@
27| javascript | ✓ | | ✓ | `typescript-language-server` |
27| javascript | ✓ | | ✓ | `typescript-language-server` |
28| json | ✓ | | ✓ | |
28| json | ✓ | | ✓ | |
29| julia | ✓ | | | `julia` |
29| julia | ✓ | | | `julia` |
30+| kotlin | ✓ | | | `kotlin-language-server` |
30| latex | ✓ | | | |
31| latex | ✓ | | | |
31| lean | ✓ | | | `lean` |
32| lean | ✓ | | | `lean` |
32| ledger | ✓ | | | |
33| ledger | ✓ | | | |
helix-syntax/languages/tree-sitter-kotlinnew file+1

Submodule changed.

languages.toml+9
@@ -741,3 +741,12 @@ file-types = ["erl", "hrl", "app", "rebar.config"]
741roots = ["rebar.config"]
741roots = ["rebar.config"]
742comment-token = "%%"
742comment-token = "%%"
743indent = { tab-width = 4, unit = " " }
743indent = { tab-width = 4, unit = " " }
744+
745+[[language]]
746+name = "kotlin"
747+scope = "source.kotlin"
748+file-types = ["kt", "kts"]
749+roots = ["settings.gradle", "settings.gradle.kts"]
750+comment-token = "//"
751+indent = { tab-width = 4, unit = " " }
752+language-server = { command = "kotlin-language-server" }
runtime/queries/kotlin/folds.scmnew file+17
@@ -0,0 +1,17 @@
1+[
2+ (import_list)
3+
4+ (when_expression)
5+ (control_structure_body)
6+
7+ (lambda_literal)
8+ (function_body)
9+ (primary_constructor)
10+ (secondary_constructor)
11+ (anonymous_initializer)
12+
13+ (class_body)
14+ (enum_class_body)
15+
16+ (interpolated_expression)
17+] @fold
runtime/queries/kotlin/highlights.scmnew file+295
@@ -0,0 +1,295 @@
1+;;; Operators & Punctuation
2+
3+(multi_line_string_literal
4+ "$" @punctuation
5+ (interpolated_identifier) @none)
6+(multi_line_string_literal
7+ "${" @punctuation
8+ (interpolated_expression) @none
9+ "}" @punctuation.)
10+
11+; NOTE: `interpolated_identifier`s can be highlighted in any way
12+(line_string_literal
13+ "$" @punctuation
14+ (interpolated_identifier) @none)
15+(line_string_literal
16+ "${" @punctuation
17+ (interpolated_expression) @none
18+ "}" @punctuation)
19+
20+[
21+ "."
22+ ","
23+ ";"
24+ ":"
25+ "::"
26+] @punctuation.delimiter
27+
28+[
29+ "(" ")"
30+ "[" "]"
31+ "{" "}"
32+] @punctuation.bracket
33+
34+[
35+ "!"
36+ "!="
37+ "!=="
38+ "="
39+ "=="
40+ "==="
41+ ">"
42+ ">="
43+ "<"
44+ "<="
45+ "||"
46+ "&&"
47+ "+"
48+ "++"
49+ "+="
50+ "-"
51+ "--"
52+ "-="
53+ "*"
54+ "*="
55+ "/"
56+ "/="
57+ "%"
58+ "%="
59+ "?."
60+ "?:"
61+ "!!"
62+ "is"
63+ "!is"
64+ "in"
65+ "!in"
66+ "as"
67+ "as?"
68+ ".."
69+ "->"
70+] @operator
71+
72+;;; Keywords
73+
74+(type_alias "typealias" @keyword)
75+[
76+ (class_modifier)
77+ (member_modifier)
78+ (function_modifier)
79+ (property_modifier)
80+ (platform_modifier)
81+ (variance_modifier)
82+ (parameter_modifier)
83+ (visibility_modifier)
84+ (reification_modifier)
85+ (inheritance_modifier)
86+]@keyword
87+
88+[
89+ "val"
90+ "var"
91+ "enum"
92+ "class"
93+ "object"
94+ "interface"
95+; "typeof" ; NOTE: It is reserved for future use
96+] @keyword
97+
98+("fun") @keyword.function
99+
100+(jump_expression) @keyword.control.return
101+
102+[
103+ "if"
104+ "else"
105+ "when"
106+] @keyword.control.conditional
107+
108+[
109+ "for"
110+ "do"
111+ "while"
112+] @keyword.control.repeat
113+
114+[
115+ "try"
116+ "catch"
117+ "throw"
118+ "finally"
119+] @keyword.control.exception
120+
121+(annotation
122+ "@" @attribute (use_site_target)? @attribute)
123+(annotation
124+ (user_type
125+ (type_identifier) @attribute))
126+(annotation
127+ (constructor_invocation
128+ (user_type
129+ (type_identifier) @attribute)))
130+
131+(file_annotation
132+ "@" @attribute "file" @attribute ":" @attribute)
133+(file_annotation
134+ (user_type
135+ (type_identifier) @attribute))
136+(file_annotation
137+ (constructor_invocation
138+ (user_type
139+ (type_identifier) @attribute)))
140+
141+;;; Literals
142+; NOTE: Escapes not allowed in multi-line strings
143+(line_string_literal (character_escape_seq) @constant.character.escape)
144+
145+[
146+ (line_string_literal)
147+ (multi_line_string_literal)
148+] @string
149+
150+(character_literal) @constant.character
151+
152+[
153+ "null" ; should be highlighted the same as booleans
154+ (boolean_literal)
155+] @constant.builtin.boolean
156+
157+(real_literal) @constant.numeric.float
158+[
159+ (integer_literal)
160+ (long_literal)
161+ (hex_literal)
162+ (bin_literal)
163+ (unsigned_literal)
164+] @constant.numeric.integer
165+
166+[
167+ (comment)
168+ (shebang_line)
169+] @comment
170+
171+;;; Function calls
172+
173+(call_expression
174+ . (simple_identifier) @function.builtin
175+ (#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)$"))
176+
177+; object.function() or object.property.function()
178+(call_expression
179+ (navigation_expression
180+ (navigation_suffix
181+ (simple_identifier) @function) . ))
182+
183+; function()
184+(call_expression
185+ . (simple_identifier) @function)
186+
187+;;; Function definitions
188+
189+; lambda parameters
190+(lambda_literal
191+ (lambda_parameters
192+ (variable_declaration
193+ (simple_identifier) @variable.parameter)))
194+
195+(parameter_with_optional_type
196+ (simple_identifier) @variable.parameter)
197+
198+(parameter
199+ (simple_identifier) @variable.parameter)
200+
201+(anonymous_initializer
202+ ("init") @constructor)
203+
204+(constructor_invocation
205+ (user_type
206+ (type_identifier) @constructor))
207+
208+(secondary_constructor
209+ ("constructor") @constructor)
210+(primary_constructor) @constructor
211+
212+(getter
213+ ("get") @function.builtin)
214+(setter
215+ ("set") @function.builtin)
216+
217+(function_declaration
218+ . (simple_identifier) @function)
219+
220+; TODO: Seperate labeled returns/breaks/continue/super/this
221+; Must be implemented in the parser first
222+(label) @label
223+
224+(import_header
225+ (identifier
226+ (simple_identifier) @function @_import .)
227+ (import_alias
228+ (type_identifier) @function)?
229+ (#match? @_import "^[a-z]"))
230+
231+; The last `simple_identifier` in a `import_header` will always either be a function
232+; or a type. Classes can appear anywhere in the import path, unlike functions
233+(import_header
234+ (identifier
235+ (simple_identifier) @type @_import)
236+ (import_alias
237+ (type_identifier) @type)?
238+ (#match? @_import "^[A-Z]"))
239+
240+(import_header
241+ "import" @keyword.control.import)
242+
243+(package_header
244+ . (identifier)) @namespace
245+
246+((type_identifier) @type.builtin
247+ (#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)$"))
248+
249+(type_identifier) @type
250+
251+(enum_entry
252+ (simple_identifier) @constant)
253+
254+(_
255+ (navigation_suffix
256+ (simple_identifier) @constant
257+ (#match? @constant "^[A-Z][A-Z0-9_]*$")))
258+
259+; SCREAMING CASE identifiers are assumed to be constants
260+((simple_identifier) @constant
261+(#match? @constant "^[A-Z][A-Z0-9_]*$"))
262+
263+; id_1.id_2.id_3: `id_2` and `id_3` are assumed as object properties
264+(_
265+ (navigation_suffix
266+ (simple_identifier) @variable.other.member))
267+
268+(class_body
269+ (property_declaration
270+ (variable_declaration
271+ (simple_identifier) @variable.other.member)))
272+
273+(class_parameter
274+ (simple_identifier) @variable.other.member)
275+
276+; `super` keyword inside classes
277+(super_expression) @variable.builtin
278+
279+; `this` this keyword inside classes
280+(this_expression) @variable.builtin
281+
282+;;; Identifiers
283+; `field` keyword inside property getter/setter
284+; FIXME: This will highlight the keyword outside of getters and setters
285+; since tree-sitter does not allow us to check for arbitrary nestation
286+((simple_identifier) @variable.builtin
287+(#eq? @variable.builtin "field"))
288+
289+; `it` keyword inside lambdas
290+; FIXME: This will highlight the keyword outside of lambdas since tree-sitter
291+; does not allow us to check for arbitrary nestation
292+((simple_identifier) @variable.builtin
293+(#eq? @variable.builtin "it"))
294+
295+(simple_identifier) @variable
runtime/queries/kotlin/injections.scmnew file+36
@@ -0,0 +1,36 @@
1+((comment) @injection.content
2+ (#set! injection.language "comment"))
3+
4+; There are 3 ways to define a regex
5+; - "[abc]?".toRegex()
6+((call_expression
7+ (navigation_expression
8+ ([(line_string_literal) (multi_line_string_literal)] @injection.content)
9+ (navigation_suffix
10+ ((simple_identifier) @_function
11+ (#eq? @_function "toRegex")))))
12+ (#set! injection.language "regex"))
13+
14+; - Regex("[abc]?")
15+((call_expression
16+ ((simple_identifier) @_function
17+ (#eq? @_function "Regex"))
18+ (call_suffix
19+ (value_arguments
20+ (value_argument
21+ [ (line_string_literal) (multi_line_string_literal) ] @injection.content))))
22+ (#set! injection.language "regex"))
23+
24+; - Regex.fromLiteral("[abc]?")
25+((call_expression
26+ (navigation_expression
27+ ((simple_identifier) @_class
28+ (#eq? @_class "Regex"))
29+ (navigation_suffix
30+ ((simple_identifier) @_function
31+ (#eq? @_function "fromLiteral"))))
32+ (call_suffix
33+ (value_arguments
34+ (value_argument
35+ [ (line_string_literal) (multi_line_string_literal) ] @injection.content))))
36+ (#set! injection.language "regex"))