diff --git a/.gitmodules b/.gitmodules index b64280c6..20e0bbb4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -49,9 +49,6 @@ [submodule "assets/themes/zenburn"] path = assets/themes/zenburn url = https://github.com/colinta/zenburn.git -[submodule "assets/syntaxes/Kotlin"] - path = assets/syntaxes/02_Extra/Kotlin - url = https://github.com/vkostyukov/kotlin-sublime-package [submodule "assets/syntaxes/Elm"] path = assets/syntaxes/02_Extra/Elm url = https://github.com/elm-community/SublimeElmLanguageSupport @@ -281,3 +278,6 @@ [submodule "assets/syntaxes/02_Extra/COBOL"] path = assets/syntaxes/02_Extra/COBOL url = https://github.com/adukhan99/sublime_cobol.git +[submodule "assets/syntaxes/02_Extra/Kotlin"] + path = assets/syntaxes/02_Extra/Kotlin + url = https://github.com/guille/sublime-kotlin diff --git a/CHANGELOG.md b/CHANGELOG.md index 066b1161..341dbf42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ - Fixed manpage syntax so that ANSI escape codes don't get incorrectly highlighted and thus broken, see #3586 (@BlueElectivire) - Map several Google Cloud CLI config files to their appropriate syntax #3635 (@victor-gp) - Map all ignore dotfiles to Git Ignore syntax #3636 (@victor-gp) +- Improved Kotlin syntax, see #3698 (@guille) ## Themes diff --git a/assets/syntaxes/02_Extra/Kotlin b/assets/syntaxes/02_Extra/Kotlin index aeeed278..c3536941 160000 --- a/assets/syntaxes/02_Extra/Kotlin +++ b/assets/syntaxes/02_Extra/Kotlin @@ -1 +1 @@ -Subproject commit aeeed2780b04aea3d293c547c24cae27cafef0c5 +Subproject commit c353694169c047bd746c93c214289fc52d152cae diff --git a/assets/syntaxes/02_Extra/Kotlin.sublime-syntax b/assets/syntaxes/02_Extra/Kotlin.sublime-syntax deleted file mode 100644 index eab59192..00000000 --- a/assets/syntaxes/02_Extra/Kotlin.sublime-syntax +++ /dev/null @@ -1,398 +0,0 @@ -%YAML 1.2 ---- -# http://www.sublimetext.com/docs/3/syntax.html -name: Kotlin -file_extensions: - - kt - - kts -scope: source.Kotlin -contexts: - main: - - include: comments - - match: '^\s*(package)\b(?:\s*([^ ;$]+)\s*)?' - captures: - 1: keyword.other.kotlin - 2: entity.name.package.kotlin - - include: imports - - include: statements - classes: - - match: (?" - pop: true - - include: generics - - match: \( - push: - - match: \) - pop: true - - include: parameters - - match: (:) - captures: - 1: keyword.operator.declaration.kotlin - push: - - match: "(?={|$)" - pop: true - - match: \w+ - scope: entity.other.inherited-class.kotlin - - match: \( - push: - - match: \) - pop: true - - include: expressions - - match: '\{' - push: - - match: '\}' - pop: true - - include: statements - comments: - - match: /\* - captures: - 0: punctuation.definition.comment.kotlin - push: - - meta_scope: comment.block.kotlin - - match: \*/ - captures: - 0: punctuation.definition.comment.kotlin - pop: true - - match: \s*((//).*$\n?) - captures: - 1: comment.line.double-slash.kotlin - 2: punctuation.definition.comment.kotlin - constants: - - match: \b(true|false|null|this|super)\b - scope: constant.language.kotlin - - match: '\b((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)([LlFf])?\b' - scope: constant.numeric.kotlin - - match: '\b([A-Z][A-Z0-9_]+)\b' - scope: constant.other.kotlin - expressions: - - match: \( - push: - - match: \) - pop: true - - include: expressions - - include: types - - include: strings - - include: constants - - include: comments - - include: keywords - functions: - - match: (?=\s*\b(?:fun)\b) - push: - - match: '(?=$|\})' - pop: true - - match: \b(fun)\b - captures: - 1: keyword.other.kotlin - push: - - match: (?=\() - pop: true - - match: < - push: - - match: ">" - pop: true - - include: generics - - match: '([\.<\?>\w]+\.)?(\w+)' - captures: - 2: entity.name.function.kotlin - - match: \( - push: - - match: \) - pop: true - - include: parameters - - match: (:) - captures: - 1: keyword.operator.declaration.kotlin - push: - - match: "(?={|=|$)" - pop: true - - include: types - - match: '\{' - push: - - match: '(?=\})' - pop: true - - include: statements - - match: (=) - captures: - 1: keyword.operator.assignment.kotlin - push: - - match: (?=$) - pop: true - - include: expressions - generics: - - match: (:) - captures: - 1: keyword.operator.declaration.kotlin - push: - - match: (?=,|>) - pop: true - - include: types - - include: keywords - - match: \w+ - scope: storage.type.generic.kotlin - getters-and-setters: - - match: \b(get)\b\s*\(\s*\) - captures: - 1: entity.name.function.kotlin - push: - - match: '\}|(?=\bset\b)|$' - pop: true - - match: (=) - captures: - 1: keyword.operator.assignment.kotlin - push: - - match: (?=$|\bset\b) - pop: true - - include: expressions - - match: '\{' - push: - - match: '\}' - pop: true - - include: expressions - - match: \b(set)\b\s*(?=\() - captures: - 1: entity.name.function.kotlin - push: - - match: '\}|(?=\bget\b)|$' - pop: true - - match: \( - push: - - match: \) - pop: true - - include: parameters - - match: (=) - captures: - 1: keyword.operator.assignment.kotlin - push: - - match: (?=$|\bset\b) - pop: true - - include: expressions - - match: '\{' - push: - - match: '\}' - pop: true - - include: expressions - imports: - - match: '^\s*(import)\s+[^ $]+\s+(as)?' - captures: - 1: keyword.other.kotlin - 2: keyword.other.kotlin - keywords: - - match: \b(var|val|public|private|protected|abstract|final|sealed|enum|open|attribute|annotation|override|inline|vararg|in|out|internal|data|tailrec|operator|infix|const|yield|typealias|typeof|reified|suspend)\b - scope: storage.modifier.kotlin - - match: \b(try|catch|finally|throw)\b - scope: keyword.control.catch-exception.kotlin - - match: \b(if|else|while|for|do|return|when|where|break|continue)\b - scope: keyword.control.kotlin - - match: \b(in|is|!in|!is|as|as\?|assert)\b - scope: keyword.operator.kotlin - - match: (==|!=|===|!==|<=|>=|<|>) - scope: keyword.operator.comparison.kotlin - - match: (=) - scope: keyword.operator.assignment.kotlin - - match: (::) - scope: keyword.operator.kotlin - - match: (:) - scope: keyword.operator.declaration.kotlin - - match: \b(by)\b - scope: keyword.other.by.kotlin - - match: (\?\.) - scope: keyword.operator.safenav.kotlin - - match: (\.) - scope: keyword.operator.dot.kotlin - - match: (\?:) - scope: keyword.operator.elvis.kotlin - - match: (\-\-|\+\+) - scope: keyword.operator.increment-decrement.kotlin - - match: (\+=|\-=|\*=|\/=) - scope: keyword.operator.arithmetic.assign.kotlin - - match: (\.\.) - scope: keyword.operator.range.kotlin - - match: (\-|\+|\*|\/|%) - scope: keyword.operator.arithmetic.kotlin - - match: (!|&&|\|\|) - scope: keyword.operator.logical.kotlin - - match: (;) - scope: punctuation.terminator.kotlin - namespaces: - - match: \b(namespace)\b - scope: keyword.other.kotlin - - match: '\{' - push: - - match: '\}' - pop: true - - include: statements - parameters: - - match: (:) - captures: - 1: keyword.operator.declaration.kotlin - push: - - match: (?=,|\)|=) - pop: true - - include: types - - match: (=) - captures: - 1: keyword.operator.declaration.kotlin - push: - - match: (?=,|\)) - pop: true - - include: expressions - - include: keywords - - match: \w+ - scope: variable.parameter.function.kotlin - statements: - - include: namespaces - - include: typedefs - - include: classes - - include: functions - - include: variables - - include: getters-and-setters - - include: expressions - strings: - - match: '"""' - captures: - 0: punctuation.definition.string.begin.kotlin - push: - - meta_scope: string.quoted.third.kotlin - - match: '"""' - captures: - 0: punctuation.definition.string.end.kotlin - pop: true - - match: '(\$\w+|\$\{[^\}]+\})' - scope: variable.parameter.template.kotlin - - match: \\. - scope: constant.character.escape.kotlin - - match: '"' - captures: - 0: punctuation.definition.string.begin.kotlin - push: - - meta_scope: string.quoted.double.kotlin - - match: '"' - captures: - 0: punctuation.definition.string.end.kotlin - pop: true - - match: '(\$\w+|\$\{[^\}]+\})' - scope: variable.parameter.template.kotlin - - match: \\. - scope: constant.character.escape.kotlin - - match: "'" - captures: - 0: punctuation.definition.string.begin.kotlin - push: - - meta_scope: string.quoted.single.kotlin - - match: "'" - captures: - 0: punctuation.definition.string.end.kotlin - pop: true - - match: \\. - scope: constant.character.escape.kotlin - - match: "`" - captures: - 0: punctuation.definition.string.begin.kotlin - push: - - meta_scope: string.quoted.single.kotlin - - match: "`" - captures: - 0: punctuation.definition.string.end.kotlin - pop: true - typedefs: - - match: (?=\s*(?:type)) - push: - - match: (?=$) - pop: true - - match: \b(type)\b - scope: keyword.other.kotlin - - match: < - push: - - match: ">" - pop: true - - include: generics - - include: expressions - types: - - match: \b(Nothing|Any|Unit|String|CharSequence|Int|Boolean|Char|Long|Double|Float|Short|Byte|dynamic)\b - scope: storage.type.buildin.kotlin - - match: \b(IntArray|BooleanArray|CharArray|LongArray|DoubleArray|FloatArray|ShortArray|ByteArray)\b - scope: storage.type.buildin.array.kotlin - - match: \b(Array|Collection|List|Map|Set|MutableList|MutableMap|MutableSet|Sequence)<\b - captures: - 1: storage.type.buildin.collection.kotlin - push: - - match: ">" - pop: true - - include: types - - include: keywords - - match: \w+< - push: - - match: ">" - pop: true - - include: types - - include: keywords - - match: '\{' - push: - - match: '\}' - pop: true - - include: statements - - match: \( - push: - - match: \) - pop: true - - include: types - - match: (->) - scope: keyword.operator.declaration.kotlin - variables: - - match: (?=\s*\b(?:var|val)\b) - push: - - match: (?=:|=|(\b(by)\b)|$) - pop: true - - match: \b(var|val)\b - captures: - 1: keyword.other.kotlin - push: - - match: (?=:|=|(\b(by)\b)|$) - pop: true - - match: < - push: - - match: ">" - pop: true - - include: generics - - match: '([\.<\?>\w]+\.)?(\w+)' - captures: - 2: entity.name.variable.kotlin - - match: (:) - captures: - 1: keyword.operator.declaration.kotlin - push: - - match: (?==|$) - pop: true - - include: types - - include: getters-and-setters - - match: \b(by)\b - captures: - 1: keyword.other.kotlin - push: - - match: (?=$) - pop: true - - include: expressions - - match: (=) - captures: - 1: keyword.operator.assignment.kotlin - push: - - match: (?=$) - pop: true - - include: expressions - - include: getters-and-setters diff --git a/tests/syntax-tests/highlighted/Kotlin/test.kt b/tests/syntax-tests/highlighted/Kotlin/test.kt index dcb1560e..bb17aba2 100644 --- a/tests/syntax-tests/highlighted/Kotlin/test.kt +++ b/tests/syntax-tests/highlighted/Kotlin/test.kt @@ -1,85 +1,85 @@ -import kotlin.math.* +import kotlin.math.* -data class Example( - val name: String, - val numbers: List<Int?> +data class Example( + val name: String, + val numbers: List<Int?> ) -fun interface JokeInterface { - fun isFunny(): Boolean +fun interface JokeInterface { + fun isFunny(): Boolean } -abstract class AbstractJoke : JokeInterface { - override fun isFunny() = false - abstract fun content(): String +abstract class AbstractJoke : JokeInterface { + override fun isFunny() = false + abstract fun content(): String } -class Joke : AbstractJoke() { - override fun isFunny(): Boolean { +class Joke : AbstractJoke() { + override fun isFunny(): Boolean {  return true - } - override fun content(): String = "content of joke here, haha" + } + override fun content(): String = "content of joke here, haha" } -class DelegatedJoke(val joke: Joke) : JokeInterface by joke { - val number: Long = 123L +class DelegatedJoke(val joke: Joke) : JokeInterface by joke { + val number: Long = 123L - companion object { - const val someConstant = "some constant text" - } + companion object { + const val someConstant = "some constant text" + } } -object SomeSingleton +object SomeSingleton -sealed class Shape { - abstract fun area(): Double +sealed class Shape { + abstract fun area(): Double } -data class Square(val sideLength: Double) : Shape() { - override fun area(): Double = sideLength.pow(2) +data class Square(val sideLength: Double) : Shape() { + override fun area(): Double = sideLength.pow(2) } -object Point : Shape() { - override fun area() = .0 +object Point : Shape() { + override fun area() = .0 } -class Circle(val radius: Double) : Shape() { - override fun area(): Double { - return PI * radius * radius - } +class Circle(val radius: Double) : Shape() { + override fun area(): Double { + return PI * radius * radius + } } -fun String.extensionMethod() = "test" +fun String.extensionMethod() = "test" -fun main() { - val name = """ +fun main() { + val name = """  multiline  string    some numbers: 123123 42 - """.trimIndent() - val example = Example(name = name, numbers = listOf(512, 42, null, -1)) + """.trimIndent() + val example = Example(name = name, numbers = listOf(512, 42, null, -1)) - example.numbers - .filterNotNull() - .forEach { println(it) } + example.numbers + .filterNotNull() + .forEach { println(it) } - setOf(Joke(), DelegatedJoke(Joke()).joke) - .filter(JokeInterface::isFunny) - .map(AbstractJoke::content) - .forEachIndexed { index: Int, joke -> - println("I heard a funny joke(#${index + 1}): $joke") - } + setOf(Joke(), DelegatedJoke(Joke()).joke) + .filter(JokeInterface::isFunny) + .map(AbstractJoke::content) + .forEachIndexed { index: Int, joke -> + println("I heard a funny joke(#${index + 1}): $joke") + } - listOf(Square(12.3), Point, Circle(5.2)) - .associateWith(Shape::area) - .toList() - .sortedBy { it.second } - .forEach { - println("${it.first}: ${it.second}") - } + listOf(Square(12.3), Point, Circle(5.2)) + .associateWith(Shape::area) + .toList() + .sortedBy { it.second } + .forEach { + println("${it.first}: ${it.second}") + } - println("some string".extensionMethod()) + println("some string".extensionMethod()) - require(SomeSingleton::class.simpleName == "SomeSingletonName") { "something does not seem right..." } + require(SomeSingleton::class.simpleName == "SomeSingletonName") { "something does not seem right..." } }