Skip to content

Commit aa72546

Browse files
authored
Merge pull request #55 from sourcegraph/nsc/analyzer-exception-catch
catch exceptions instead of letting them hard fail builds
2 parents f1035f5 + 19dd6cd commit aa72546

File tree

2 files changed

+76
-11
lines changed
  • semanticdb-kotlinc/src

2 files changed

+76
-11
lines changed

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

+55-11
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
package com.sourcegraph.semanticdb_kotlinc
22

3+
import java.io.PrintWriter
4+
import java.io.Writer
35
import java.nio.file.Files
46
import java.nio.file.Path
57
import java.nio.file.Paths
68
import kotlin.contracts.ExperimentalContracts
79
import org.jetbrains.kotlin.analyzer.AnalysisResult
10+
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
11+
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
12+
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
13+
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
14+
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
815
import org.jetbrains.kotlin.com.intellij.openapi.project.Project
16+
import org.jetbrains.kotlin.config.CompilerConfiguration
917
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
1018
import org.jetbrains.kotlin.psi.*
1119
import org.jetbrains.kotlin.resolve.BindingTrace
1220
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
21+
import org.jetbrains.kotlin.utils.rethrow
22+
import java.io.StringWriter
1323

1424
@ExperimentalContracts
1525
class Analyzer(
@@ -19,24 +29,37 @@ class Analyzer(
1929
) : AnalysisHandlerExtension {
2030
private val globals = GlobalSymbolsCache()
2131

32+
private val messageCollector =
33+
CompilerConfiguration()
34+
.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, false))
35+
2236
override fun analysisCompleted(
2337
project: Project,
2438
module: ModuleDescriptor,
2539
bindingTrace: BindingTrace,
2640
files: Collection<KtFile>
27-
): AnalysisResult? {
28-
val resolver = DescriptorResolver(bindingTrace).also { globals.resolver = it }
29-
for (file in files) {
30-
val lineMap = LineMap(project, file)
31-
val document = SemanticdbVisitor(sourceroot, resolver, file, lineMap, globals).build()
32-
semanticdbOutPathForFile(file)?.apply {
33-
Files.write(this, TextDocuments { addDocuments(document) }.toByteArray())
41+
): AnalysisResult? =
42+
try {
43+
val resolver = DescriptorResolver(bindingTrace).also { globals.resolver = it }
44+
for (file in files) {
45+
try {
46+
val lineMap = LineMap(project, file)
47+
val document =
48+
SemanticdbVisitor(sourceroot, resolver, file, lineMap, globals).build()
49+
semanticdbOutPathForFile(file)?.apply {
50+
Files.write(this, TextDocuments { addDocuments(document) }.toByteArray())
51+
}
52+
callback(document)
53+
} catch (e: Exception) {
54+
handleException(e)
55+
}
3456
}
35-
callback(document)
36-
}
3757

38-
return super.analysisCompleted(project, module, bindingTrace, files)
39-
}
58+
super.analysisCompleted(project, module, bindingTrace, files)
59+
} catch (e: Exception) {
60+
handleException(e)
61+
super.analysisCompleted(project, module, bindingTrace, files)
62+
}
4063

4164
private fun semanticdbOutPathForFile(file: KtFile): Path? {
4265
val normalizedPath = Paths.get(file.virtualFilePath).normalize()
@@ -57,4 +80,25 @@ class Analyzer(
5780
"given file is not under the sourceroot.\n\tSourceroot: $sourceroot\n\tFile path: ${file.virtualFilePath}\n\tNormalized file path: $normalizedPath")
5881
return null
5982
}
83+
84+
private fun handleException(e: Exception) {
85+
val writer =
86+
PrintWriter(
87+
object : Writer() {
88+
val buf = StringBuffer()
89+
override fun close() =
90+
messageCollector.report(
91+
CompilerMessageSeverity.EXCEPTION, buf.toString())
92+
override fun flush() = Unit
93+
override fun write(data: CharArray, offset: Int, len: Int) {
94+
buf.append(data, offset, len)
95+
}
96+
},
97+
false)
98+
writer.println("Exception in semanticdb-kotlin compiler plugin:")
99+
e.printStackTrace(writer)
100+
writer.println(
101+
"Please report a bug to https://github.com/sourcegraph/lsif-kotlin with the stack trace above.")
102+
writer.close()
103+
}
60104
}

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

+21
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,27 @@ class AnalyzerTest {
121121
assertSoftly(document.symbolsList) { withClue(this) { symbols.forEach(::shouldContain) } }
122122
}
123123

124+
@Test
125+
fun `exception test`(@TempDir path: Path) {
126+
val buildPath = File(path.resolve("build").toString()).apply { mkdir() }
127+
val result =
128+
KotlinCompilation()
129+
.apply {
130+
sources = listOf(SourceFile.testKt(""))
131+
compilerPlugins = listOf(AnalyzerRegistrar { throw Exception("sample text") })
132+
verbose = false
133+
pluginOptions =
134+
listOf(
135+
PluginOption("semanticdb-kotlinc", "sourceroot", path.toString()),
136+
PluginOption("semanticdb-kotlinc", "targetroot", buildPath.toString()))
137+
commandLineProcessors = listOf(AnalyzerCommandLineProcessor())
138+
workingDir = path.toFile()
139+
}
140+
.compile()
141+
142+
result.exitCode shouldBe KotlinCompilation.ExitCode.OK
143+
}
144+
124145
@Test
125146
// shamelessly stolen code snippet from https://learnxinyminutes.com/docs/kotlin/
126147
fun `learn x in y test`(@TempDir path: Path) {

0 commit comments

Comments
 (0)