diff --git a/.gitignore b/.gitignore index 155a83d..ec38158 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ gradle-app.setting # JDT-specific (Eclipse Java Development Tools) .classpath # MacOS files -*.DS_Store \ No newline at end of file +*.DS_Store +/.kotlin/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 8736058..d8d7d68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [0.9.3] + +### Fixed +- strings in comment locating + ## [0.9.2] ### Fixed diff --git a/README.md b/README.md index 300ff75..20e680d 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ repositories { ``` ```shell -implementation("dev.snipme:highlights:0.9.2") +implementation("dev.snipme:highlights:0.9.3") ``` ## Features ✨ diff --git a/build.gradle.kts b/build.gradle.kts index c00f902..17e6fc7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "dev.snipme" -version = "0.9.2" +version = "0.9.3" kotlin { // Android 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 1956521..aea821a 100644 --- a/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/StringLocator.kt +++ b/src/commonMain/kotlin/dev/snipme/highlights/internal/locator/StringLocator.kt @@ -24,9 +24,15 @@ internal object StringLocator { // Find index of each string delimiter like " or ' or """ STRING_DELIMITERS.forEach { - val textIndices = mutableListOf() + var textIndices = mutableListOf() textIndices += code.indicesOf(it) + // Exclude positions basing on ignoreRanges + textIndices = textIndices.filter { index -> + val textRange = IntRange(index, index + QUOTE_ENDING_POSITION) + ignoreRanges.none { ignored -> textRange in ignored } + }.toMutableList() + // For given indices find words between for (i in START_INDEX..textIndices.lastIndex step TWO_ELEMENTS) { if (textIndices.getOrNull(i + 1) == null) continue diff --git a/src/commonTest/kotlin/dev/snipme/highlights/internal/language/CommentTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/language/CommentTest.kt new file mode 100644 index 0000000..3fb07e7 --- /dev/null +++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/language/CommentTest.kt @@ -0,0 +1,77 @@ +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 CommentTest { + + @Test + fun test() { + val code = """ + /** + * Class's start + */ + class PagesComponent( + context: ComponentContext, + container: () -> PagesContainer, // inject using DI or create + ) : ComponentContext by context, + PagesStore by context.retainedStore(factory = container) { + + 'a' + + private val navigator = PagesNavigation() + + val pages = childPages( + source = navigator, + serializer = PageConfig.serializer(), + initialPages = { Pages(items = List(5) { PageConfig(it) }, selectedIndex = 0) }, + childFactory = ::PageComponent, + ) + + "b" + + init { + // subscribe to the store following the component 's lifecycle + subscribe { + actions.collect { action -> + when (action) { + is SelectPage -> navigator.select(action.index) + } + } + } + } + } + + class PageComponent( + page: PageConfig, + context: ComponentContext, + ) : ComponentContext by context, + Container { + + override val store = store(PageState(page.page), coroutineScope()) { + + `c` + + // state keeper will preserve the store's state + keepState(context.stateKeeper, PageState.serializer()) + reduce { intent -> + when (intent) { + is ClickedIncrementCounter -> updateState { + copy(counter = counter + 1) + } + } + } + } + } + """.trimIndent() + + val result = Highlights.Builder( + language = SyntaxLanguage.KOTLIN, + code = code + ).build().getCodeStructure() + + assertEquals(2, result.strings.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 index a7c89b7..ad3835e 100644 --- a/src/commonTest/kotlin/dev/snipme/highlights/internal/language/KotlinTest.kt +++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/language/KotlinTest.kt @@ -36,8 +36,6 @@ class KotlinTest { 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/CommentLocatorTest.kt b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/CommentLocatorTest.kt index 4bc970b..78db186 100644 --- a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/CommentLocatorTest.kt +++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/CommentLocatorTest.kt @@ -31,4 +31,24 @@ internal class CommentLocatorTest { assertEquals(1, result.size) assertEquals(PhraseLocation(6, 21), result.first()) } + + @Test + fun `Returns location of whole comment with single apostrophe`() { + val testCode = "// the component's lifecycle" + + val result = CommentLocator.locate(testCode) + + assertEquals(1, result.size) + assertEquals(PhraseLocation(0, 28), result.first()) + } + + @Test + fun `Returns location of whole comment with multiple quotations`() { + val testCode = """// "This" 'is a' comment`s quote""" + + val result = CommentLocator.locate(testCode) + + assertEquals(1, result.size) + assertEquals(PhraseLocation(0, 32), result.first()) + } } \ No newline at end of file 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 2cc542e..ecc6246 100644 --- a/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/StringLocatorTest.kt +++ b/src/commonTest/kotlin/dev/snipme/highlights/internal/locator/StringLocatorTest.kt @@ -94,4 +94,18 @@ internal class StringLocatorTest { assertEquals(1, result.size) assertEquals(PhraseLocation(19, 22), result[0]) } + + @Test + fun `NOT returns location of escaped string phrase`() { + val testCode = """ + val b = "a\"" + val a = 'a\'' + """.trimIndent() + + val result = StringLocator.locate(testCode) + + assertEquals(2, result.size) + assertEquals(PhraseLocation(8, 12), result[1]) + assertEquals(PhraseLocation(22, 26), result[0]) + } } \ No newline at end of file