Unnamed repository; edit this file 'description' to name the repository.
Add indents and textobjects for Kotlin (#12925)
Sebastian Dörner 2025-02-21
parent 3d7e273 · commit 0deb8bb
-rw-r--r--book/src/generated/lang-support.md2
-rw-r--r--languages.toml2
-rw-r--r--runtime/queries/kotlin/highlights.scm26
-rw-r--r--runtime/queries/kotlin/indents.scm44
-rw-r--r--runtime/queries/kotlin/injections.scm14
-rw-r--r--runtime/queries/kotlin/textobjects.scm42
6 files changed, 106 insertions, 24 deletions
diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index 0e6c6072..833196b6 100644
--- a/book/src/generated/lang-support.md
+++ b/book/src/generated/lang-support.md
@@ -121,7 +121,7 @@
| just | ✓ | ✓ | ✓ | |
| kdl | ✓ | ✓ | ✓ | |
| koka | ✓ | | ✓ | `koka` |
-| kotlin | ✓ | | | `kotlin-language-server` |
+| kotlin | ✓ | ✓ | ✓ | `kotlin-language-server` |
| koto | ✓ | ✓ | ✓ | `koto-ls` |
| latex | ✓ | ✓ | | `texlab` |
| ld | ✓ | | ✓ | |
diff --git a/languages.toml b/languages.toml
index 01c0181f..321f1864 100644
--- a/languages.toml
+++ b/languages.toml
@@ -1940,7 +1940,7 @@ language-servers = [ "kotlin-language-server" ]
[[grammar]]
name = "kotlin"
-source = { git = "https://github.com/fwcd/tree-sitter-kotlin", rev = "a4f71eb9b8c9b19ded3e0e9470be4b1b77c2b569" }
+source = { git = "https://github.com/fwcd/tree-sitter-kotlin", rev = "c4ddea359a7ff4d92360b2efcd6cfce5dc25afe6" }
[[language]]
name = "hcl"
diff --git a/runtime/queries/kotlin/highlights.scm b/runtime/queries/kotlin/highlights.scm
index 11fae331..68b08c3d 100644
--- a/runtime/queries/kotlin/highlights.scm
+++ b/runtime/queries/kotlin/highlights.scm
@@ -68,19 +68,10 @@
"->"
] @operator
-(multi_line_string_literal
+(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
+(string_literal
"${" @punctuation
(interpolated_expression) @none
"}" @punctuation)
@@ -108,6 +99,7 @@
"class"
"object"
"interface"
+ "companion"
; "typeof" ; NOTE: It is reserved for future use
] @keyword
@@ -156,17 +148,14 @@
;;; Literals
; NOTE: Escapes not allowed in multi-line strings
-(line_string_literal (character_escape_seq) @constant.character.escape)
+(character_literal (character_escape_seq) @constant.character.escape)
-[
- (line_string_literal)
- (multi_line_string_literal)
-] @string
+(string_literal) @string
(character_literal) @constant.character
[
- "null" ; should be highlighted the same as booleans
+ (null_literal) ; should be highlighted the same as booleans
(boolean_literal)
] @constant.builtin.boolean
@@ -180,7 +169,8 @@
] @constant.numeric.integer
[
- (comment)
+ (line_comment)
+ (multiline_comment)
(shebang_line)
] @comment
diff --git a/runtime/queries/kotlin/indents.scm b/runtime/queries/kotlin/indents.scm
new file mode 100644
index 00000000..6fe73aec
--- /dev/null
+++ b/runtime/queries/kotlin/indents.scm
@@ -0,0 +1,44 @@
+[
+ (class_body)
+ (enum_class_body)
+ (lambda_literal)
+
+ ; _block is hidden in the grammar, so list all public wrappers explicitly.
+ (function_body)
+ (anonymous_initializer)
+ (control_structure_body)
+ (secondary_constructor)
+ (try_expression)
+ (catch_block)
+ (finally_block)
+
+ (property_declaration)
+ (assignment)
+
+ (when_expression)
+ (call_expression)
+ (if_expression)
+
+ ; Binary expressions
+ (multiplicative_expression)
+ (additive_expression)
+ (range_expression)
+ (infix_expression)
+ (elvis_expression)
+ (check_expression)
+ (comparison_expression)
+ (equality_expression)
+ (comparison_expression)
+ (equality_expression)
+ (conjunction_expression)
+ (disjunction_expression)
+
+ (call_suffix)
+ (function_value_parameters)
+] @indent
+
+[
+ "}"
+ ")"
+ "]"
+] @outdent
diff --git a/runtime/queries/kotlin/injections.scm b/runtime/queries/kotlin/injections.scm
index abdc2050..40640d2b 100644
--- a/runtime/queries/kotlin/injections.scm
+++ b/runtime/queries/kotlin/injections.scm
@@ -1,11 +1,15 @@
-((comment) @injection.content
+([
+ (line_comment)
+ (multiline_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)
+ (string_literal
+ (string_content) @injection.content)
(navigation_suffix
((simple_identifier) @_function
(#eq? @_function "toRegex")))))
@@ -18,7 +22,8 @@
(call_suffix
(value_arguments
(value_argument
- [ (line_string_literal) (multi_line_string_literal) ] @injection.content))))
+ (string_literal
+ (string_content) @injection.content)))))
(#set! injection.language "regex"))
; - Regex.fromLiteral("[abc]?")
@@ -32,5 +37,6 @@
(call_suffix
(value_arguments
(value_argument
- [ (line_string_literal) (multi_line_string_literal) ] @injection.content))))
+ (string_literal
+ (string_content) @injection.content)))))
(#set! injection.language "regex"))
diff --git a/runtime/queries/kotlin/textobjects.scm b/runtime/queries/kotlin/textobjects.scm
new file mode 100644
index 00000000..46bb26b2
--- /dev/null
+++ b/runtime/queries/kotlin/textobjects.scm
@@ -0,0 +1,42 @@
+(function_declaration
+ (function_body)? @function.inside) @function.around
+
+; Unlike function_body above, the constructor body is does not have its own
+; symbol in the current grammar.
+(secondary_constructor) @function.around
+
+(class_declaration
+ (class_body)? @class.inside) @class.around
+
+(class_declaration
+ (enum_class_body) @class.inside) @class.around
+
+[
+ (line_comment)
+ (multiline_comment)
+] @comment.inside
+
+(line_comment)+ @comment.around
+
+(multiline_comment) @comment.around
+
+(enum_entry) @entry.around
+(lambda_literal) @entry.around
+(property_declaration) @entry.around
+(object_declaration) @entry.around
+(assignment) @entry.around
+
+; TODO: This doesn't work with annotations yet, but fixing it without breaking
+; the case of multiple parameters is non-trivial.
+(function_value_parameters
+ ((_) @parameter.inside . ","? @parameter.around) @parameter.around)
+
+; secondary constructor uses function_value_parameters above
+(primary_constructor
+ ((_)@parameter.inside . ","? @parameter.around) @parameter.around)
+
+(function_type_parameters
+ ((_)@parameter.inside . ","? @parameter.around) @parameter.around)
+
+(value_arguments
+ ((_)@parameter.inside . ","? @parameter.around) @parameter.around)