diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce4fd62..5dea0ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+## [0.9.0]
+
+### Added
+- Atom One theme. Thanks Nek-12!
+- languages snippet tests
+
+### Fixed
+- keyword highlighted in oneline comment
+- keyword highlighted inside other word
+
+### Changed
+- Kotlin version to 1.9.23
+
## [0.8.1]
### Added
diff --git a/README.md b/README.md
index 4fd42d5..c6e8505 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@

[](https://mvnrepository.com/artifact/dev.snipme)
-[](http://kotlinlang.org)
+[](http://kotlinlang.org)
[](http://www.apache.org/licenses/LICENSE-2.0)
# Highlights
@@ -15,7 +15,7 @@ repositories {
```
```shell
-implementation("dev.snipme:highlights:0.8.1")
+implementation("dev.snipme:highlights:0.9.0")
```
## Features ✨
@@ -97,6 +97,7 @@ The library comes with predefined syntax coloring themes available in `SyntaxThe
Notepad |
Matrix |
Pastel |
+ Atom One |
|
@@ -157,6 +158,19 @@ The library comes with predefined syntax coloring themes available in `SyntaxThe
-  Multiline Comment
-  Punctuation
-  Mark
+ |
+
+
+-  Code
+-  Keyword
+-  String
+-  Literal
+-  Comment
+-  Metadata
+-  Multiline Comment
+-  Punctuation
+-  Mark
+
|
@@ -169,6 +183,7 @@ The library comes with predefined syntax coloring themes available in `SyntaxThe
Notepad |
Matrix |
Pastel |
+ Atom One |
|
@@ -229,6 +244,19 @@ The library comes with predefined syntax coloring themes available in `SyntaxThe
-  Multiline Comment
-  Punctuation
-  Mark
+ |
+
+
+-  Code
+-  Keyword
+-  String
+-  Literal
+-  Comment
+-  Metadata
+-  Multiline Comment
+-  Punctuation
+-  Mark
+
|
@@ -265,14 +293,16 @@ If your project uses this code, please write me or add your info
| Application |
-
- SnippLog
- |
+ SnippLog |
+
+
+ | Application |
+ FlowMVI Sample |
## TODO 🚧
-- [ ] Migrate some lists to sets
+- [X] Migrate some lists to sets
- [ ] Optimize code analysis
- [ ] Add more themes and languages
- [ ] Support italic and underline text style
@@ -289,7 +319,7 @@ Then make sure:
License 🖋️
=======
- Copyright 2023 Tomasz Kądziołka.
+ Copyright 2023-2024 Tomasz Kądziołka.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/build.gradle.kts b/build.gradle.kts
index 5b5ac38..2a521a7 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,14 +1,14 @@
apply(from = "publish-root.gradle")
plugins {
- kotlin("multiplatform") version "1.9.22"
+ kotlin("multiplatform") version "1.9.23"
id("maven-publish")
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
id("signing")
}
group = "dev.snipme"
-version = "0.8.1"
+version = "0.9.0"
kotlin {
// Android
@@ -36,6 +36,7 @@ kotlin {
browser()
nodejs()
}
+ wasmJs()
// Dependencies
sourceSets {
val commonTest by getting {
diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts
index a616c35..8ca610e 100644
--- a/sample/build.gradle.kts
+++ b/sample/build.gradle.kts
@@ -1,7 +1,7 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
- kotlin("jvm") version "1.9.22"
+ kotlin("jvm") version "1.9.23"
application
}
@@ -31,5 +31,5 @@ application {
}
dependencies {
- implementation("dev.snipme:highlights:0.7.0")
+ implementation(":highlights")
}
\ No newline at end of file
diff --git a/sample/src/main/kotlin/Main.kt b/sample/src/main/kotlin/Main.kt
index 94d89e9..dde0f36 100644
--- a/sample/src/main/kotlin/Main.kt
+++ b/sample/src/main/kotlin/Main.kt
@@ -30,7 +30,6 @@ val sampleClass = """
}
}
""".trimIndent()
-
fun main() {
println("### HIGHLIGHTS ###")
println()
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/CodeAnalyzer.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/CodeAnalyzer.kt
index fd7c538..42e4ef3 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/CodeAnalyzer.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/CodeAnalyzer.kt
@@ -112,13 +112,15 @@ internal object CodeAnalyzer {
PHP -> analyzeCodeWithKeywords(code, PHP_KEYWORDS)
}
- private fun analyzeCodeWithKeywords(code: String, keywords: List): CodeStructure {
+ private fun analyzeCodeWithKeywords(code: String, keywords: Set): CodeStructure {
val comments = CommentLocator.locate(code)
val multiLineComments = MultilineCommentLocator.locate(code)
- val strings = StringLocator.locate(code)
+ val commentRanges = (comments + multiLineComments).toRangeSet()
- val plainTextRanges = comments + multiLineComments + strings
+ val strings = StringLocator.locate(code, commentRanges)
+ val plainTextRanges = (comments + multiLineComments + strings).toRangeSet()
+ // TODO Apply ignored ranges to other locators
return CodeStructure(
marks = MarkLocator.locate(code),
punctuations = PunctuationLocator.locate(code),
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/Extensions.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/Extensions.kt
index 7529e57..b374a00 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/Extensions.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/Extensions.kt
@@ -1,5 +1,15 @@
package dev.snipme.highlights.internal
+import dev.snipme.highlights.model.PhraseLocation
+
+inline operator fun Set.get(i: Int): E? {
+ this.forEachIndexed { index, t ->
+ if (i == index) return t
+ }
+
+ return null
+}
+
fun String.indicesOf(
phrase: String,
): Set {
@@ -42,18 +52,29 @@ fun String.lengthToEOF(start: Int = 0): Int {
return endIndex - start
}
-// TODO Create unit tests for this
// Sometimes keyword can be found in the middle of word.
// This returns information if index points only to the keyword
fun String.isIndependentPhrase(
code: String,
index: Int,
): Boolean {
- if (index == 0) return true
if (index == code.lastIndex) return true
+ if (code.length == this.length) return true
val charBefore = code[maxOf(index - 1, 0)]
val charAfter = code[minOf(index + this.length, code.lastIndex)]
- return charBefore.isLetter().not() && charAfter.isDigit().not()
+ if (index == 0) {
+ return charAfter.isDigit().not() && charAfter.isLetter().not()
+ }
+
+ return charBefore.isLetter().not() &&
+ charAfter.isDigit().not() && (charAfter == code.last() || charAfter.isLetter().not())
+}
+
+fun Set.toRangeSet(): Set =
+ this.map { IntRange(it.start, it.end) }.toSet()
+
+operator fun IntRange.contains(range: IntRange): Boolean {
+ return range.first >= this.first && range.last <= this.last
}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/SyntaxTokens.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/SyntaxTokens.kt
index ebea5b2..7a1a351 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/SyntaxTokens.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/SyntaxTokens.kt
@@ -145,6 +145,6 @@ internal object SyntaxTokens {
val PUNCTUATION_CHARACTERS = listOf(",", ".", ":", ";")
val MARK_CHARACTERS = listOf("(", ")", "=", "{", "}", "<", ">", "-", "+", "[", "]", "|", "&")
- private fun String.toTokenList() = trimIndent().split(",")
+ private fun String.toTokenList() = trimIndent().split(",").toSet()
}
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/AnnotationLocator.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/AnnotationLocator.kt
index 2b90047..f36a8f1 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/AnnotationLocator.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/AnnotationLocator.kt
@@ -6,7 +6,7 @@ import dev.snipme.highlights.internal.indicesOf
internal object AnnotationLocator {
- fun locate(code: String): List {
+ fun locate(code: String): Set {
val foundAnnotations = emptyList()
val locations = mutableSetOf()
code.split(*TOKEN_DELIMITERS.toTypedArray())
@@ -28,6 +28,6 @@ internal object AnnotationLocator {
}
}
- return locations.toList()
+ return locations.toSet()
}
}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/CommentLocator.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/CommentLocator.kt
index 47fdb5c..97bf233 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/CommentLocator.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/CommentLocator.kt
@@ -1,13 +1,13 @@
package dev.snipme.highlights.internal.locator
-import dev.snipme.highlights.model.PhraseLocation
import dev.snipme.highlights.internal.SyntaxTokens.COMMENT_DELIMITERS
import dev.snipme.highlights.internal.indicesOf
import dev.snipme.highlights.internal.lengthToEOF
+import dev.snipme.highlights.model.PhraseLocation
internal object CommentLocator {
- fun locate(code: String): List {
+ fun locate(code: String): Set {
val locations = mutableListOf()
val indices = mutableListOf()
COMMENT_DELIMITERS.forEach { delimiter ->
@@ -18,6 +18,7 @@ internal object CommentLocator {
val end = start + code.lengthToEOF(start)
locations.add(PhraseLocation(start, end))
}
- return locations
+
+ return locations.toSet()
}
}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/KeywordLocator.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/KeywordLocator.kt
index bd65bc8..4a5b3a1 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/KeywordLocator.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/KeywordLocator.kt
@@ -9,21 +9,16 @@ internal object KeywordLocator {
fun locate(
code: String,
- keywords: List,
- ignoreRanges: List = emptyList(),
- ): List {
- val locations = mutableListOf()
+ keywords: Set,
+ ignoreRanges: Set = emptySet(),
+ ): Set {
+ val locations = mutableSetOf()
val foundKeywords = findKeywords(code, keywords)
- val interpretedKeywords = foundKeywords.filterNot { keyword ->
- val index = code.indexOf(keyword)
- val length = keyword.length
- ignoreRanges.any { it.start <= index && it.end >= index + length }
- }
-
- interpretedKeywords.forEach { keyword ->
+ foundKeywords.forEach { keyword ->
val indices = code
.indicesOf(keyword)
+ .filterNot { index -> ignoreRanges.any { index in it } }
.filter { keyword.isIndependentPhrase(code, it) }
indices.forEach { index ->
@@ -31,10 +26,10 @@ internal object KeywordLocator {
}
}
- return locations.toList()
+ return locations
}
- private fun findKeywords(code: String, keywords: List): Set =
+ private fun findKeywords(code: String, keywords: Set): Set =
TOKEN_DELIMITERS.toTypedArray().let { delimiters ->
code.split(*delimiters, ignoreCase = true) // Split into words
.asSequence() // Reduce amount of operations
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/MarkLocator.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/MarkLocator.kt
index 0dbebc3..4cb4a68 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/MarkLocator.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/MarkLocator.kt
@@ -5,7 +5,7 @@ import dev.snipme.highlights.internal.indicesOf
import dev.snipme.highlights.model.PhraseLocation
internal object MarkLocator {
- fun locate(code: String): List {
+ fun locate(code: String): Set {
val locations = mutableListOf()
code.asSequence()
.toSet()
@@ -16,6 +16,6 @@ internal object MarkLocator {
}
}
- return locations
+ return locations.toSet()
}
}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/MultilineCommentLocator.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/MultilineCommentLocator.kt
index 2806128..100001c 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/MultilineCommentLocator.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/MultilineCommentLocator.kt
@@ -1,14 +1,14 @@
package dev.snipme.highlights.internal.locator
-import dev.snipme.highlights.model.PhraseLocation
import dev.snipme.highlights.internal.SyntaxTokens.MULTILINE_COMMENT_DELIMITERS
import dev.snipme.highlights.internal.indicesOf
+import dev.snipme.highlights.model.PhraseLocation
private const val START_INDEX = 0
internal object MultilineCommentLocator {
- fun locate(code: String): List {
+ fun locate(code: String): Set {
val locations = mutableListOf()
val comments = mutableListOf>()
val startIndices = mutableListOf()
@@ -30,6 +30,6 @@ internal object MultilineCommentLocator {
locations.add(PhraseLocation(start, end))
}
- return locations
+ return locations.toSet()
}
}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/NumericLiteralLocator.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/NumericLiteralLocator.kt
index 340a111..572bc56 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/NumericLiteralLocator.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/NumericLiteralLocator.kt
@@ -11,11 +11,11 @@ private val NUMBER_SPECIAL_CHARACTERS = listOf('_')
internal object NumericLiteralLocator {
- fun locate(code: String): List {
+ fun locate(code: String): Set {
return findDigitIndices(code)
}
- private fun findDigitIndices(code: String): List {
+ private fun findDigitIndices(code: String): Set {
val foundPhrases = mutableSetOf()
val locations = mutableSetOf()
@@ -45,7 +45,7 @@ internal object NumericLiteralLocator {
foundPhrases.add(number)
}
- return locations.toList()
+ return locations.toSet()
}
// Returns if given index is the beginning of word (there is no letter before)
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/PunctuationLocator.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/PunctuationLocator.kt
index 9d96368..f61c65f 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/PunctuationLocator.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/PunctuationLocator.kt
@@ -6,7 +6,7 @@ import dev.snipme.highlights.internal.indicesOf
import dev.snipme.highlights.model.PhraseLocation
internal object PunctuationLocator {
- fun locate(code: String): List {
+ fun locate(code: String): Set {
val locations = mutableSetOf()
code.asSequence()
.map { it.toString().trim() }
@@ -21,6 +21,6 @@ internal object PunctuationLocator {
}
}
- return locations.toList()
+ return locations.toSet()
}
}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/StringLocator.kt b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/StringLocator.kt
index 03a251f..1956521 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/StringLocator.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/StringLocator.kt
@@ -1,8 +1,9 @@
package dev.snipme.highlights.internal.locator
-import dev.snipme.highlights.model.PhraseLocation
import dev.snipme.highlights.internal.SyntaxTokens.STRING_DELIMITERS
+import dev.snipme.highlights.internal.contains
import dev.snipme.highlights.internal.indicesOf
+import dev.snipme.highlights.model.PhraseLocation
private const val START_INDEX = 0
private const val TWO_ELEMENTS = 2
@@ -10,10 +11,16 @@ private const val QUOTE_ENDING_POSITION = 1
internal object StringLocator {
- fun locate(code: String): List = findStrings(code)
+ fun locate(
+ code: String,
+ ignoreRanges: Set = emptySet(),
+ ): Set = findStrings(code, ignoreRanges)
- private fun findStrings(code: String): List {
- val locations = mutableListOf()
+ private fun findStrings(
+ code: String,
+ ignoreRanges: Set,
+ ): Set {
+ val locations = mutableSetOf()
// Find index of each string delimiter like " or ' or """
STRING_DELIMITERS.forEach {
@@ -22,14 +29,19 @@ internal object StringLocator {
// For given indices find words between
for (i in START_INDEX..textIndices.lastIndex step TWO_ELEMENTS) {
- if (textIndices.getOrNull(i + 1) != null) {
- locations.add(
- PhraseLocation(
- textIndices[i],
- textIndices[i + 1] + QUOTE_ENDING_POSITION
- )
+ if (textIndices.getOrNull(i + 1) == null) continue
+
+ // Skip unwanted phrases
+ val textRange = IntRange(textIndices[i], textIndices[i + 1])
+ if (ignoreRanges.any { ignored -> textRange in ignored })
+ continue
+
+ locations.add(
+ PhraseLocation(
+ textIndices[i],
+ textIndices[i + 1] + QUOTE_ENDING_POSITION
)
- }
+ )
}
}
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/model/CodeStructure.kt b/src/commonMain/kotlin/dev/snipme/highlights/model/CodeStructure.kt
index 05ce814..604dc88 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/model/CodeStructure.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/model/CodeStructure.kt
@@ -2,58 +2,61 @@ package dev.snipme.highlights.model
data class PhraseLocation(val start: Int, val end: Int)
-// TODO Migrate to set
data class CodeStructure(
- val marks: List,
- val punctuations: List,
- val keywords: List,
- val strings: List,
- val literals: List,
- val comments: List,
- val multilineComments: List,
- val annotations: List,
+ val marks: Set,
+ val punctuations: Set,
+ val keywords: Set,
+ val strings: Set,
+ val literals: Set,
+ val comments: Set,
+ val multilineComments: Set,
+ val annotations: Set,
val incremental: Boolean,
) {
fun move(position: Int) =
CodeStructure(
- marks = marks.map { it.copy(start = it.start + position, end = it.end + position) },
+ marks = marks.map {
+ it.copy(start = it.start + position, end = it.end + position)
+ }.toSet(),
punctuations = punctuations.map {
it.copy(
start = it.start + position,
end = it.end + position
)
- },
+ }.toSet(),
keywords = keywords.map {
it.copy(
start = it.start + position,
end = it.end + position
)
- },
- strings = strings.map { it.copy(start = it.start + position, end = it.end + position) },
+ }.toSet(),
+ strings = strings.map {
+ it.copy(start = it.start + position, end = it.end + position)
+ }.toSet(),
literals = literals.map {
it.copy(
start = it.start + position,
end = it.end + position
)
- },
+ }.toSet(),
comments = comments.map {
it.copy(
start = it.start + position,
end = it.end + position
)
- },
+ }.toSet(),
multilineComments = multilineComments.map {
it.copy(
start = it.start + position,
end = it.end + position
)
- },
+ }.toSet(),
annotations = annotations.map {
it.copy(
start = it.start + position,
end = it.end + position
)
- },
+ }.toSet(),
incremental = true,
)
@@ -83,7 +86,7 @@ data class CodeStructure(
incremental = true,
)
- fun printPhrases(code: String) {
+ fun printStructure(code: String) {
print("marks = ${marks.join(code)}")
print("punctuations = ${punctuations.join(code)}")
print("keywords = ${keywords.join(code)}")
@@ -94,6 +97,6 @@ data class CodeStructure(
print("annotations = ${annotations.join(code)}")
}
- private fun List.join(code: String) =
- this.map { code.substring(it.start, it.end) }.joinToString(separator = " ") + "\n"
+ private fun Set.join(code: String) =
+ this.joinToString(separator = " ") { code.substring(it.start, it.end) } + "\n"
}
diff --git a/src/commonMain/kotlin/dev/snipme/highlights/model/SyntaxThemes.kt b/src/commonMain/kotlin/dev/snipme/highlights/model/SyntaxThemes.kt
index 453dd89..733e75b 100644
--- a/src/commonMain/kotlin/dev/snipme/highlights/model/SyntaxThemes.kt
+++ b/src/commonMain/kotlin/dev/snipme/highlights/model/SyntaxThemes.kt
@@ -5,6 +5,7 @@ private const val MONOKAI_KEY = "monokai"
private const val NOTEPAD_KEY = "notepad"
private const val MATRIX_KEY = "matrix"
private const val PASTEL_KEY = "pastel"
+private const val ATOM_ONE_KEY = "atomone"
object SyntaxThemes {
@@ -68,6 +69,18 @@ object SyntaxThemes {
multilineComment = 0x888A85,
punctuation = 0xCB956D,
mark = 0xCB956D
+ ),
+ ATOM_ONE_KEY to SyntaxTheme(
+ key = ATOM_ONE_KEY,
+ code = 0xBBBBBB,
+ keyword = 0xD55FDE,
+ string = 0x89CA78,
+ literal = 0xD19A66,
+ comment = 0x5C6370,
+ metadata = 0xE5C07B,
+ multilineComment = 0x5C6370,
+ punctuation = 0xEF596F,
+ mark = 0x2BBAC5
)
)
@@ -131,7 +144,20 @@ object SyntaxThemes {
multilineComment = 0x888A85,
punctuation = 0xCB956D,
mark = 0xCB956D
+ ),
+ ATOM_ONE_KEY to SyntaxTheme(
+ key = ATOM_ONE_KEY,
+ code = 0x383A42,
+ keyword = 0xA626A4,
+ string = 0x50A14F,
+ literal = 0x986801,
+ comment = 0xA1A1A1,
+ metadata = 0xC18401,
+ multilineComment = 0xA1A1A1,
+ punctuation = 0xE45649,
+ mark = 0x526FFF,
)
+
)
fun themes(darkMode: Boolean = false) = if (darkMode) dark else light
@@ -143,6 +169,7 @@ object SyntaxThemes {
fun notepad(darkMode: Boolean = false) = themes(darkMode)[NOTEPAD_KEY]!!
fun matrix(darkMode: Boolean = false) = themes(darkMode)[MATRIX_KEY]!!
fun pastel(darkMode: Boolean = false) = themes(darkMode)[PASTEL_KEY]!!
+ fun atom(darkMode: Boolean = false) = themes(darkMode)[ATOM_ONE_KEY]!!
fun getNames(): List = SyntaxThemes.light.map {
it.key
@@ -151,4 +178,4 @@ object SyntaxThemes {
}
fun SyntaxTheme.useDark(darkMode: Boolean) = if (darkMode) dark[key] else light[key]
-}
\ No newline at end of file
+}
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/CodeAnalyzerTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/CodeAnalyzerTest.kt
index df4c45f..742a030 100644
--- a/src/commonTest/kotlin/dev/snipme/highlights/internal/CodeAnalyzerTest.kt
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/CodeAnalyzerTest.kt
@@ -22,7 +22,7 @@ internal class CodeAnalyzerTest {
val result = CodeAnalyzer.analyze(testCode)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(30, 31),
PhraseLocation(31, 32)
),
@@ -30,7 +30,7 @@ internal class CodeAnalyzerTest {
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(36, 37),
PhraseLocation(41, 42),
PhraseLocation(42, 43),
@@ -41,7 +41,7 @@ internal class CodeAnalyzerTest {
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(14, 19),
PhraseLocation(22, 29)
),
@@ -49,35 +49,35 @@ internal class CodeAnalyzerTest {
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(33, 36),
),
result.strings
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(45, 52),
),
result.literals
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(9, 13),
),
result.comments
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(0, 8),
),
result.multilineComments
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(38, 40),
),
result.annotations
@@ -119,7 +119,7 @@ internal class CodeAnalyzerTest {
assertEquals(true, result.incremental)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(30, 31),
PhraseLocation(31, 32),
),
@@ -127,7 +127,7 @@ internal class CodeAnalyzerTest {
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(36, 37),
PhraseLocation(41, 42),
PhraseLocation(42, 43),
@@ -138,7 +138,7 @@ internal class CodeAnalyzerTest {
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(14, 19),
PhraseLocation(22, 29),
),
@@ -146,35 +146,35 @@ internal class CodeAnalyzerTest {
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(33, 36),
),
result.strings
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(45, 52),
),
result.literals
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(9, 13),
),
result.comments
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(0, 8),
),
result.multilineComments
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(38, 40),
),
result.annotations
@@ -208,48 +208,48 @@ internal class CodeAnalyzerTest {
assertEquals(true, result.incremental)
assertEquals(
- emptyList(),
+ emptySet(),
result.marks
)
assertEquals(
- emptyList(),
+ emptySet(),
result.punctuations
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(14, 19),
),
result.keywords
)
assertEquals(
- emptyList(),
+ emptySet(),
result.strings
)
assertEquals(
- emptyList(),
+ emptySet(),
result.literals
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(9, 13),
),
result.comments
)
assertEquals(
- listOf(
+ setOf(
PhraseLocation(0, 8),
),
result.multilineComments
)
assertEquals(
- emptyList(),
+ emptySet(),
result.annotations
)
}
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/ExtensionsKtTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/ExtensionsKtTest.kt
index 757be60..49f054e 100644
--- a/src/commonTest/kotlin/dev/snipme/highlights/internal/ExtensionsKtTest.kt
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/ExtensionsKtTest.kt
@@ -5,63 +5,241 @@ import kotlin.test.assertEquals
internal class ExtensionsKtTest {
- @Test
- fun `Returns empty result of phrase that is not present`() {
- val text = "b c d"
- val phrase = "//a"
+ class IndicesOfTest {
- val result = text.indicesOf(phrase)
+ @Test
+ fun `Returns empty result of phrase that is not present`() {
+ val text = "b c d"
+ val phrase = "//a"
- assertEquals(setOf(), result)
- }
+ val result = text.indicesOf(phrase)
- @Test
- fun `Returns index of phrase at start`() {
- val text = "//a b c d"
- val phrase = "//a"
+ assertEquals(setOf(), result)
+ }
- val result = text.indicesOf(phrase)
+ @Test
+ fun `Returns index of phrase at start`() {
+ val text = "//a b c d"
+ val phrase = "//a"
- assertEquals(setOf(0), result)
- }
+ val result = text.indicesOf(phrase)
- @Test
- fun `Returns index of phrase at end`() {
- val text = "/a b c d //a"
- val phrase = "//a"
+ assertEquals(setOf(0), result)
+ }
- val result = text.indicesOf(phrase)
+ @Test
+ fun `Returns index of phrase at end`() {
+ val text = "/a b c d //a"
+ val phrase = "//a"
- assertEquals(setOf(9), result)
- }
+ val result = text.indicesOf(phrase)
- @Test
- fun `Returns index of phrase at start and end`() {
- val text = "//a b c d //a"
- val phrase = "//a"
+ assertEquals(setOf(9), result)
+ }
- val result = text.indicesOf(phrase)
+ @Test
+ fun `Returns index of phrase at start and end`() {
+ val text = "//a b c d //a"
+ val phrase = "//a"
- assertEquals(setOf(0, 10), result)
- }
+ val result = text.indicesOf(phrase)
+
+ assertEquals(setOf(0, 10), result)
+ }
+
+ @Test
+ fun `Returns all indices of phrase at end`() {
+ val text = "//a /a b //ac d //a"
+ val phrase = "//a"
+
+ val result = text.indicesOf(phrase)
+
+ assertEquals(setOf(0, 9, 16), result)
+ }
- @Test
- fun `Returns all indices of phrase at end`() {
- val text = "//a /a b //ac d //a"
- val phrase = "//a"
+ @Test
+ fun `Returns all indices of special phrase`() {
+ val text = "//a /a b /** d //a"
+ val phrase = "/**"
- val result = text.indicesOf(phrase)
+ val result = text.indicesOf(phrase)
- assertEquals(setOf(0, 9, 16), result)
+ assertEquals(setOf(9), result)
+ }
}
- @Test
- fun `Returns all indices of special phrase`() {
- val text = "//a /a b /** d //a"
- val phrase = "/**"
+ class IsIndependentPhraseTest {
+
+ @Test
+ fun `Returns true for phrase at start`() {
+ val code = "class "
+ val index = 0
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(true, result)
+ }
+
+ @Test
+ fun `Returns false for wrong phrase at start`() {
+ val code = "classa "
+ val index = 1
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(false, result)
+ }
+
+ @Test
+ fun `Returns true for phrase at end`() {
+ val code = "asas class"
+ val index = 5
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(true, result)
+ }
+
+ @Test
+ fun `Returns false for wrong phrase at end`() {
+ val code = "asas classa"
+ val index = 6
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(false, result)
+ }
+
+ @Test
+ fun `Returns false for phrase with wrong prefix at end`() {
+ val code = "asas aclass"
+ val index = 6
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(false, result)
+ }
+
+ @Test
+ fun `Returns false for phrase at start other phrase`() {
+ val code = "valuable"
+ val index = 0
+
+ val result = "val".isIndependentPhrase(code, index)
+
+ assertEquals(false, result)
+ }
+
+ @Test
+ fun `Returns false for phrase at end other phrase`() {
+ val code = "inval"
+ val index = 2
+
+ val result = "val".isIndependentPhrase(code, index)
+
+ assertEquals(false, result)
+ }
+
+ @Test
+ fun `Returns false for phrase inside other phrase`() {
+ val code = "invaluable"
+ val index = 2
+
+ val result = "val".isIndependentPhrase(code, index)
+
+ assertEquals(false, result)
+ }
+
+ @Test
+ fun `Returns true for phrase is whole code`() {
+ val code = "class"
+ val index = 0
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(true, result)
+ }
+
+ @Test
+ fun `Returns true for phrase is with new line`() {
+ val code = "class\n"
+ val index = 0
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(true, result)
+ }
+
+ @Test
+ fun `Returns true for phrase is with new line and space`() {
+ val code = """
+ class
+ """
+ val index = 3
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(true, result)
+ }
+
+ @Test
+ fun `Returns true for phrase that starts with number`() {
+ val code = "9class"
+ val index = 1
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(true, result)
+ }
+
+ @Test
+ fun `Returns false for phrase that ends with number`() {
+ val code = "class9"
+ val index = 0
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(false, result)
+ }
+
+ @Test
+ fun `Returns false for phrase that is between numbers`() {
+ val code = "9class9"
+ val index = 1
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(false, result)
+ }
+
+ @Test
+ fun `Returns true for phrase that starts special character`() {
+ val code = ".class"
+ val index = 1
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(true, result)
+ }
+
+ @Test
+ fun `Returns true for phrase that ends with special character`() {
+ val code = "class."
+ val index = 0
+
+ val result = "class".isIndependentPhrase(code, index)
+
+ assertEquals(true, result)
+ }
+
+ @Test
+ fun `Returns true for phrase that is between special characters`() {
+ val code = ".class."
+ val index = 1
- val result = text.indicesOf(phrase)
+ val result = "class".isIndependentPhrase(code, index)
- assertEquals(setOf(9), result)
+ assertEquals(true, result)
+ }
}
}
\ No newline at end of file
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/language/JavaTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/language/JavaTest.kt
new file mode 100644
index 0000000..f5bfb72
--- /dev/null
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/language/JavaTest.kt
@@ -0,0 +1,21 @@
+import dev.snipme.highlights.Highlights
+import dev.snipme.highlights.model.SyntaxLanguage
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class JavaTest {
+
+ @Test
+ fun test() {
+ val code = """
+ this.class.abcd ) new
+ """.trimIndent()
+
+ val result = Highlights.Builder(
+ language = SyntaxLanguage.JAVA,
+ code = code
+ ).build().getCodeStructure()
+
+ assertEquals(3, result.keywords.size)
+ }
+}
\ No newline at end of file
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/language/KotlinTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/language/KotlinTest.kt
new file mode 100644
index 0000000..a7c89b7
--- /dev/null
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/language/KotlinTest.kt
@@ -0,0 +1,43 @@
+package dev.snipme.highlights.internal.language
+
+import dev.snipme.highlights.Highlights
+import dev.snipme.highlights.model.SyntaxLanguage
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class KotlinTest {
+
+ @Test
+ fun test() {
+ val code = """
+ val intent = 0
+ copy(input = input(intent.value)) // highlights "value"
+
+ // calling configure() is equivalent to:
+
+ val new = 1
+
+ val initialPages = 0
+
+ // Visibility modifiers
+ internal val internalVar: Int = 10
+ private fun privateFunction() {
+ println("This is a private function")
+ }
+
+ // Data types
+ val number: Int = 42
+ val pi: Double = 3.14
+ val isValid: Boolean = true
+ """.trimIndent()
+
+ val result = Highlights.Builder(
+ language = SyntaxLanguage.KOTLIN,
+ code = code
+ ).build().getCodeStructure()
+
+ result.printStructure(code)
+
+ assertEquals(11, result.keywords.size)
+ }
+}
\ No newline at end of file
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/AnnotationLocatorTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/AnnotationLocatorTest.kt
index 7cf902d..fbc10b4 100644
--- a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/AnnotationLocatorTest.kt
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/AnnotationLocatorTest.kt
@@ -1,5 +1,6 @@
package dev.snipme.highlights.internal.locator
+import dev.snipme.highlights.internal.get
import dev.snipme.highlights.model.PhraseLocation
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -94,4 +95,4 @@ internal class AnnotationLocatorTest {
assertEquals(PhraseLocation(79, 88), result[1])
assertEquals(PhraseLocation(56, 71), result[2])
}
-}
\ No newline at end of file
+}
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/KeywordLocatorTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/KeywordLocatorTest.kt
index c2d1fa1..f2413fb 100644
--- a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/KeywordLocatorTest.kt
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/KeywordLocatorTest.kt
@@ -1,5 +1,6 @@
package dev.snipme.highlights.internal.locator
+import dev.snipme.highlights.internal.get
import dev.snipme.highlights.model.PhraseLocation
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -9,8 +10,8 @@ internal class KeywordLocatorTest {
@Test
fun `Returns empty list for no keywords`() {
val testCode = "class NewClass"
- val keywords = listOf()
- val expectedResult = emptyList()
+ val keywords = setOf()
+ val expectedResult = emptySet()
val result = KeywordLocator.locate(testCode, keywords)
@@ -20,7 +21,7 @@ internal class KeywordLocatorTest {
@Test
fun `Returns location of first found keyword`() {
val testCode = "class NewClass"
- val keywords = listOf("static", "new", "class")
+ val keywords = setOf("static", "new", "class")
val result = KeywordLocator.locate(testCode, keywords)
@@ -31,7 +32,7 @@ internal class KeywordLocatorTest {
@Test
fun `Returns location of all found keyword in line`() {
val testCode = "class NewClass extends { }"
- val keywords = listOf("static", "new", "class", "extends")
+ val keywords = setOf("static", "new", "class", "extends")
val result = KeywordLocator.locate(testCode, keywords)
@@ -43,7 +44,7 @@ internal class KeywordLocatorTest {
@Test
fun `Returns location of all keyword next to each other`() {
val testCode = "this.class.abcd ) new"
- val keywords = listOf("this", "new", "class")
+ val keywords = setOf("this", "new", "class")
val result = KeywordLocator.locate(testCode, keywords)
@@ -56,7 +57,7 @@ internal class KeywordLocatorTest {
@Test
fun `Returns location of word that is proper keyword only`() {
val testCode = "class 1class 1 class1 class& %class aclass"
- val keywords = listOf("this", "new", "class")
+ val keywords = setOf("this", "new", "class")
val result = KeywordLocator.locate(testCode, keywords)
@@ -74,7 +75,7 @@ internal class KeywordLocatorTest {
static class Example2 {}
}
""".trimIndent()
- val keywords = listOf("static", "class", "extends")
+ val keywords = setOf("static", "class", "extends")
val result = KeywordLocator.locate(testCode, keywords)
@@ -90,7 +91,19 @@ internal class KeywordLocatorTest {
val testCode = """
aclassa
""".trimIndent()
- val keywords = listOf("static", "class", "extends")
+ val keywords = setOf("static", "class", "extends")
+
+ val result = KeywordLocator.locate(testCode, keywords)
+
+ assertEquals(0, result.size)
+ }
+
+ @Test
+ fun `Not returns location of keyword inside phrase from start`() {
+ val testCode = """
+ val intent = 0
+ """.trimIndent()
+ val keywords = setOf("int")
val result = KeywordLocator.locate(testCode, keywords)
@@ -102,9 +115,9 @@ internal class KeywordLocatorTest {
val testCode = """
// This class is static and should extend another class
""".trimIndent()
- val keywords = listOf("static", "class", "extends")
+ val keywords = setOf("static", "class", "extends")
- val result = KeywordLocator.locate(testCode, keywords, listOf(PhraseLocation(0, 55)))
+ val result = KeywordLocator.locate(testCode, keywords, setOf(IntRange(0, 55)))
assertEquals(0, result.size)
}
@@ -116,9 +129,9 @@ internal class KeywordLocatorTest {
This class is static and should extend another class
*/
""".trimIndent()
- val keywords = listOf("static", "class", "extends")
+ val keywords = setOf("static", "class", "extends")
- val result = KeywordLocator.locate(testCode, keywords, listOf(PhraseLocation(0, 56)))
+ val result = KeywordLocator.locate(testCode, keywords, setOf(IntRange(0, 56)))
assertEquals(0, result.size)
}
@@ -126,11 +139,11 @@ internal class KeywordLocatorTest {
@Test
fun `Not returns keywords from string`() {
val testCode = """
- val text = "This class is static and should extend another class"
+ "This class is static and should extend another class"
""".trimIndent()
- val keywords = listOf("static", "class", "extends")
+ val keywords = setOf("static", "class", "extends")
- val result = KeywordLocator.locate(testCode, keywords, listOf(PhraseLocation(0, 54)))
+ val result = KeywordLocator.locate(testCode, keywords, setOf(IntRange(0, 54)))
assertEquals(0, result.size)
}
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/MarkLocatorTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/MarkLocatorTest.kt
index 219d4f1..e1d4844 100644
--- a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/MarkLocatorTest.kt
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/MarkLocatorTest.kt
@@ -1,5 +1,6 @@
package dev.snipme.highlights.internal.locator
+import dev.snipme.highlights.internal.get
import dev.snipme.highlights.model.PhraseLocation
import kotlin.test.assertEquals
import kotlin.test.Test
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/MultilineCommentLocatorTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/MultilineCommentLocatorTest.kt
index 16a7b94..cf03a09 100644
--- a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/MultilineCommentLocatorTest.kt
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/MultilineCommentLocatorTest.kt
@@ -1,5 +1,6 @@
package dev.snipme.highlights.internal.locator
+import dev.snipme.highlights.internal.get
import dev.snipme.highlights.model.PhraseLocation
import kotlin.test.Test
import kotlin.test.assertEquals
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/NumericLiteralLocatorTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/NumericLiteralLocatorTest.kt
index 7aecbcd..bbdfb10 100644
--- a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/NumericLiteralLocatorTest.kt
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/NumericLiteralLocatorTest.kt
@@ -1,5 +1,6 @@
package dev.snipme.highlights.internal.locator
+import dev.snipme.highlights.internal.get
import dev.snipme.highlights.model.PhraseLocation
import kotlin.test.assertEquals
import kotlin.test.Test
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/PunctuationLocatorTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/PunctuationLocatorTest.kt
index bbf8071..ed6f566 100644
--- a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/PunctuationLocatorTest.kt
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/PunctuationLocatorTest.kt
@@ -1,5 +1,6 @@
package dev.snipme.highlights.internal.locator
+import dev.snipme.highlights.internal.get
import dev.snipme.highlights.model.PhraseLocation
import kotlin.test.Test
import kotlin.test.assertEquals
diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/StringLocatorTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/StringLocatorTest.kt
index e854675..2cc542e 100644
--- a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/StringLocatorTest.kt
+++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/StringLocatorTest.kt
@@ -1,5 +1,6 @@
package dev.snipme.highlights.internal.locator
+import dev.snipme.highlights.internal.get
import dev.snipme.highlights.model.PhraseLocation
import kotlin.test.Test
import kotlin.test.assertEquals