diff --git a/scip-kotlin-analysis/src/main/kotlin/org/scip_code/scip_java/kotlin_analysis/KotlinAnalysisIndexer.kt b/scip-kotlin-analysis/src/main/kotlin/org/scip_code/scip_java/kotlin_analysis/KotlinAnalysisIndexer.kt index c33ab80dc..bea734f4e 100644 --- a/scip-kotlin-analysis/src/main/kotlin/org/scip_code/scip_java/kotlin_analysis/KotlinAnalysisIndexer.kt +++ b/scip-kotlin-analysis/src/main/kotlin/org/scip_code/scip_java/kotlin_analysis/KotlinAnalysisIndexer.kt @@ -126,7 +126,16 @@ class KotlinAnalysisIndexer( val documents = mutableListOf() val ktFiles = session.modulesWithFiles.values.flatten().filterIsInstance() for (ktFile in ktFiles) { - val document = indexFile(ktFile) + val document = + try { + indexFile(ktFile) + } catch (e: Exception) { + val reason = e.message?.lineSequence()?.firstOrNull() + System.err.println( + "scip-kotlin-analysis: skipped ${ktFile.virtualFilePath}: ${e.javaClass.name}: $reason" + ) + continue + } writeShard(ktFile, document) callback(document) documents.add(document) @@ -583,6 +592,7 @@ class KotlinAnalysisIndexer( override fun visitDestructuringDeclaration( destructuringDeclaration: KtDestructuringDeclaration ) { + if (destructuringDeclaration.parent is KtFile) return val isParameter = destructuringDeclaration.parent is KtParameter val type = destructuringDeclaration.initializer?.let { renderedExpressionType(it) } diff --git a/scip-kotlin-analysis/src/main/kotlin/org/scip_code/scip_java/kotlin_analysis/Main.kt b/scip-kotlin-analysis/src/main/kotlin/org/scip_code/scip_java/kotlin_analysis/Main.kt index 5e6f41170..e9e140792 100644 --- a/scip-kotlin-analysis/src/main/kotlin/org/scip_code/scip_java/kotlin_analysis/Main.kt +++ b/scip-kotlin-analysis/src/main/kotlin/org/scip_code/scip_java/kotlin_analysis/Main.kt @@ -37,15 +37,20 @@ fun main(args: Array) { require(sourceroot != null) { "missing required flag: --sourceroot" } require(targetroot != null) { "missing required flag: --targetroot" } require(sourceRoots.isNotEmpty()) { "missing source files or directories" } - KotlinAnalysisIndexer( - sourceroot = sourceroot, - targetroot = targetroot, - sourceRoots = sourceRoots, - classpath = classpath, - jdkHome = jdkHome, - ) - .run() // The Analysis API environment leaves non-daemon threads behind; exit // explicitly so callers are not left waiting on them. + try { + KotlinAnalysisIndexer( + sourceroot = sourceroot, + targetroot = targetroot, + sourceRoots = sourceRoots, + classpath = classpath, + jdkHome = jdkHome, + ) + .run() + } catch (e: Throwable) { + e.printStackTrace() + exitProcess(1) + } exitProcess(0) } diff --git a/scip-kotlin-analysis/src/test/kotlin/org/scip_code/scip_java/kotlin_analysis/KotlinAnalysisIndexerTest.kt b/scip-kotlin-analysis/src/test/kotlin/org/scip_code/scip_java/kotlin_analysis/KotlinAnalysisIndexerTest.kt index 6391232ae..73b4b5786 100644 --- a/scip-kotlin-analysis/src/test/kotlin/org/scip_code/scip_java/kotlin_analysis/KotlinAnalysisIndexerTest.kt +++ b/scip-kotlin-analysis/src/test/kotlin/org/scip_code/scip_java/kotlin_analysis/KotlinAnalysisIndexerTest.kt @@ -93,6 +93,50 @@ class KotlinAnalysisIndexerTest { ) } + @Test + fun `a top-level destructuring in a kt file is skipped, not the file or the run`() { + val sourceroot = Files.createTempDirectory("scip-kotlin-analysis").toRealPath() + val src = Files.createDirectories(sourceroot.resolve("src")) + Files.writeString( + src.resolve("Broken.kt"), + """ + |package snapshots + | + |fun before(): Int = 1 + | + |val (first, second) = Pair(1, 2) + | + |fun after(): Int = before() + """ + .trimMargin(), + ) + Files.writeString( + src.resolve("Other.kt"), + """ + |package snapshots + | + |fun other(): Int = after() + """ + .trimMargin(), + ) + val documents = + KotlinAnalysisIndexer( + sourceroot = sourceroot, + targetroot = sourceroot.resolve("scip-targetroot"), + sourceRoots = listOf(src), + classpath = listOf(kotlinStdlibJar()), + ) + .run() + .sortedBy { it.relativePath } + + assertEquals(listOf("src/Broken.kt", "src/Other.kt"), documents.map { it.relativePath }) + val broken = definitions(documents[0]) + assertContains(broken, "snapshots/before().") + assertContains(broken, "snapshots/after().") + assertContains(references(documents[0]), "snapshots/before().") + assertContains(references(documents[1]), "snapshots/after().") + } + private fun definitions(document: Document): List = document.occurrencesList .filter { it.symbolRoles and SymbolRole.Definition.number != 0 }