Skip to content

Commit bdb6897

Browse files
Fix: logic in package name handling is sensitive to trailing semicolon
1 parent 09d1d97 commit bdb6897

File tree

3 files changed

+188
-12
lines changed

3 files changed

+188
-12
lines changed

semanticdb-kotlinc/src/main/kotlin/com/sourcegraph/semanticdb_kotlinc/AnalyzerCheckers.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
111111

112112
var ancestor = fqName
113113
var depth = 0
114+
114115
while (ancestor != FqName.ROOT) {
115116
val nameNode = nameList[nameList.lastIndex - depth]
116117
val nameSource = nameNode.toKtLightSourceElement(tree)
@@ -126,7 +127,9 @@ open class AnalyzerCheckers(session: FirSession) : FirAdditionalCheckersExtensio
126127
val fqName = packageDirective.packageFqName
127128
val source = packageDirective.source
128129
if (source != null) {
129-
val names = source.treeStructure.findLastDescendant(source.lighterASTNode) { true }
130+
val names = source.treeStructure.findChildByType(source.lighterASTNode, KtNodeTypes.DOT_QUALIFIED_EXPRESSION) ?:
131+
source.treeStructure.findChildByType(source.lighterASTNode, KtNodeTypes.REFERENCE_EXPRESSION)
132+
130133
if (names != null) {
131134
eachFqNameElement(fqName, source.treeStructure, names) { fqName, name ->
132135
visitor?.visitPackage(fqName, name, context)

semanticdb-kotlinc/src/test/kotlin/com/sourcegraph/semanticdb_kotlinc/test/AnalyzerTest.kt

Lines changed: 183 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import kotlin.test.assertEquals
2121
import org.intellij.lang.annotations.Language
2222
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
2323
import org.junit.jupiter.api.io.TempDir
24+
import java.nio.file.Paths
2425

2526
@OptIn(ExperimentalCompilerApi::class)
2627
@ExperimentalContracts
@@ -39,7 +40,8 @@ class AnalyzerTest {
3940
pluginOptions =
4041
listOf(
4142
PluginOption("semanticdb-kotlinc", "sourceroot", path.toString()),
42-
PluginOption("semanticdb-kotlinc", "targetroot", buildPath.toString()))
43+
PluginOption("semanticdb-kotlinc", "targetroot", buildPath.toString())
44+
)
4345
commandLineProcessors = listOf(AnalyzerCommandLineProcessor())
4446
workingDir = path.toFile()
4547
}
@@ -59,7 +61,8 @@ class AnalyzerTest {
5961
package sample
6062
class Banana {
6163
fun foo() { }
62-
}""")
64+
}"""
65+
)
6366

6467
val occurrences =
6568
arrayOf(
@@ -132,7 +135,8 @@ class AnalyzerTest {
132135
133136
import kotlin.Boolean
134137
import kotlin.Int as KInt
135-
""")
138+
"""
139+
)
136140

137141
val occurrences =
138142
arrayOf(
@@ -205,7 +209,8 @@ class AnalyzerTest {
205209
fun localClassMethod() {}
206210
}
207211
}
208-
""")
212+
"""
213+
)
209214

210215
val occurrences =
211216
arrayOf(
@@ -314,7 +319,8 @@ class AnalyzerTest {
314319
class Class : Interface {
315320
override fun foo() {}
316321
}
317-
""")
322+
"""
323+
)
318324

319325
val occurrences =
320326
arrayOf(
@@ -447,7 +453,8 @@ class AnalyzerTest {
447453
override fun foo() {}
448454
}
449455
}
450-
""")
456+
"""
457+
)
451458

452459
val occurrences =
453460
arrayOf(
@@ -630,7 +637,8 @@ class AnalyzerTest {
630637
package sample
631638
632639
fun foo(arg: Int): Boolean = true
633-
""")
640+
"""
641+
)
634642

635643
val occurrences =
636644
arrayOf(
@@ -693,7 +701,8 @@ class AnalyzerTest {
693701
pluginOptions =
694702
listOf(
695703
PluginOption("semanticdb-kotlinc", "sourceroot", path.toString()),
696-
PluginOption("semanticdb-kotlinc", "targetroot", buildPath.toString()))
704+
PluginOption("semanticdb-kotlinc", "targetroot", buildPath.toString())
705+
)
697706
commandLineProcessors = listOf(AnalyzerCommandLineProcessor())
698707
workingDir = path.toFile()
699708
}
@@ -1119,7 +1128,8 @@ class AnalyzerTest {
11191128
counter1() // => The value of the counter is 36
11201129
println(-counter2) // => Counter(value=-5)
11211130
}
1122-
""")
1131+
"""
1132+
)
11231133

11241134
val result =
11251135
KotlinCompilation()
@@ -1130,7 +1140,8 @@ class AnalyzerTest {
11301140
pluginOptions =
11311141
listOf(
11321142
PluginOption("semanticdb-kotlinc", "sourceroot", path.toString()),
1133-
PluginOption("semanticdb-kotlinc", "targetroot", buildPath.toString()))
1143+
PluginOption("semanticdb-kotlinc", "targetroot", buildPath.toString())
1144+
)
11341145
commandLineProcessors = listOf(AnalyzerCommandLineProcessor())
11351146
workingDir = path.toFile()
11361147
}
@@ -1139,6 +1150,166 @@ class AnalyzerTest {
11391150
result.exitCode shouldBe KotlinCompilation.ExitCode.OK
11401151
}
11411152

1153+
1154+
@Test
1155+
fun `compound package name semicolon test`(@TempDir path: Path) {
1156+
val document =
1157+
compileSemanticdb(
1158+
path, """
1159+
package hello.sample;
1160+
class Apple
1161+
""".trimIndent()
1162+
)
1163+
1164+
val occurrences =
1165+
arrayOf(
1166+
SymbolOccurrence {
1167+
role = Role.REFERENCE
1168+
symbol = "hello/"
1169+
range {
1170+
startLine = 0
1171+
startCharacter = 8
1172+
endLine = 0
1173+
endCharacter = 13
1174+
}
1175+
},
1176+
SymbolOccurrence {
1177+
role = Role.REFERENCE
1178+
symbol = "hello/sample/"
1179+
range {
1180+
startLine = 0
1181+
startCharacter = 14
1182+
endLine = 0
1183+
endCharacter = 20
1184+
}
1185+
},
1186+
SymbolOccurrence {
1187+
role = Role.DEFINITION
1188+
symbol = "hello/sample/Apple#"
1189+
range {
1190+
startLine = 1
1191+
startCharacter = 6
1192+
endLine = 1
1193+
endCharacter = 11
1194+
}
1195+
},
1196+
SymbolOccurrence {
1197+
role = Role.DEFINITION
1198+
symbol = "hello/sample/Apple#`<init>`()."
1199+
range {
1200+
startLine = 1
1201+
startCharacter = 6
1202+
endLine = 1
1203+
endCharacter = 11
1204+
}
1205+
},
1206+
)
1207+
1208+
assertSoftly(document.occurrencesList) {
1209+
withClue(document.occurrencesList) { occurrences.forEach(::shouldContain) }
1210+
}
1211+
1212+
val symbols =
1213+
arrayOf(
1214+
SymbolInformation {
1215+
symbol = "hello/sample/Apple#"
1216+
language = KOTLIN
1217+
displayName = "Apple"
1218+
documentation =
1219+
Documentation {
1220+
format = Semanticdb.Documentation.Format.MARKDOWN
1221+
message = "```kotlin\npublic final class Apple : Any\n```"
1222+
}
1223+
})
1224+
1225+
assertSoftly(document.symbolsList) { withClue(this) { symbols.forEach(::shouldContain) } }
1226+
}
1227+
1228+
1229+
@Test
1230+
fun `simple package name semicolon test`(@TempDir path: Path) {
1231+
val document =
1232+
compileSemanticdb(
1233+
path,
1234+
"""
1235+
package sample;
1236+
class Banana {
1237+
fun foo() { }
1238+
}"""
1239+
)
1240+
1241+
val occurrences =
1242+
arrayOf(
1243+
SymbolOccurrence {
1244+
role = Role.REFERENCE
1245+
symbol = "sample/"
1246+
range {
1247+
startLine = 0
1248+
startCharacter = 8
1249+
endLine = 0
1250+
endCharacter = 14
1251+
}
1252+
},
1253+
SymbolOccurrence {
1254+
role = Role.DEFINITION
1255+
symbol = "sample/Banana#"
1256+
range {
1257+
startLine = 1
1258+
startCharacter = 6
1259+
endLine = 1
1260+
endCharacter = 12
1261+
}
1262+
},
1263+
SymbolOccurrence {
1264+
role = Role.DEFINITION
1265+
symbol = "sample/Banana#foo()."
1266+
range {
1267+
startLine = 2
1268+
startCharacter = 8
1269+
endLine = 2
1270+
endCharacter = 11
1271+
}
1272+
},
1273+
SymbolOccurrence {
1274+
role = Role.DEFINITION
1275+
symbol = "sample/Banana#"
1276+
range {
1277+
startLine = 1
1278+
startCharacter = 6
1279+
endLine = 1
1280+
endCharacter = 12
1281+
}
1282+
},
1283+
)
1284+
assertSoftly(document.occurrencesList) {
1285+
withClue(this) { occurrences.forEach(::shouldContain) }
1286+
}
1287+
1288+
val symbols =
1289+
arrayOf(
1290+
SymbolInformation {
1291+
symbol = "sample/Banana#"
1292+
language = KOTLIN
1293+
displayName = "Banana"
1294+
documentation =
1295+
Documentation {
1296+
format = Semanticdb.Documentation.Format.MARKDOWN
1297+
message = "```kotlin\npublic final class Banana : Any\n```"
1298+
}
1299+
},
1300+
SymbolInformation {
1301+
symbol = "sample/Banana#foo()."
1302+
language = KOTLIN
1303+
displayName = "foo"
1304+
documentation =
1305+
Documentation {
1306+
format = Semanticdb.Documentation.Format.MARKDOWN
1307+
message = "```kotlin\npublic final fun foo(): Unit\n```"
1308+
}
1309+
})
1310+
assertSoftly(document.symbolsList) { withClue(this) { symbols.forEach(::shouldContain) } }
1311+
}
1312+
11421313
@Test
11431314
fun documentation(@TempDir path: Path) {
11441315
val document =
@@ -1157,7 +1328,8 @@ class AnalyzerTest {
11571328
*
11581329
**/
11591330
inline fun docstrings(msg: String): Int { return msg.length }
1160-
""".trimIndent())
1331+
""".trimIndent()
1332+
)
11611333
document.assertDocumentation("sample/Docstrings#", "Example class docstring")
11621334
document.assertDocumentation("sample/docstrings().", "Example method docstring")
11631335
}

semanticdb-kotlinc/src/test/kotlin/com/sourcegraph/semanticdb_kotlinc/test/SemanticdbSymbolsTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class SemanticdbSymbolsTest {
106106
)
107107
.mapCheckExpectedSymbols()
108108

109+
109110
@TestFactory
110111
fun `check package symbols`() =
111112
listOf(

0 commit comments

Comments
 (0)