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..0bdee93 100644 --- a/src/commonMain/kotlin/dev/snipme/highlights/internal/SyntaxTokens.kt +++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/SyntaxTokens.kt @@ -28,8 +28,8 @@ internal object SyntaxTokens { coroutine,crossinline,data,delegate,dynamic,do,else,enum,expect,external,false,final, finally,for,fun,get,if,import,in,!in,infix,inline,interface,internal,is,!is,lazy,lateinit, native,null,object,open,operator,out,override,package,private,protected,public,reified, - return,sealed,set,super,suspend,tailrec,this,throw,true,try,typealias,typeof,val,var,vararg, - when,while,yield + return,sealed,set,super,suspend,tailrec,this,throw,true,try,typealias,typeof,val,value,var, + vararg,when,while,yield """.toTokenList() val RUST_KEYWORDS = """ @@ -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/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..010fc5e --- /dev/null +++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/language/KotlinTest.kt @@ -0,0 +1,31 @@ +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 + + """.trimIndent() + + val result = Highlights.Builder( + language = SyntaxLanguage.KOTLIN, + code = code + ).build().getCodeStructure() + + assertEquals(4, 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 afb0042..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,7 @@ 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) @@ -102,7 +103,7 @@ internal class KeywordLocatorTest { val testCode = """ val intent = 0 """.trimIndent() - val keywords = listOf("int") + val keywords = setOf("int") val result = KeywordLocator.locate(testCode, keywords) @@ -114,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) } @@ -128,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) } @@ -138,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