report presence of multiple different versions of kotlin-runtime on the classpath as compilation error if other compilation errors have occurred
This commit is contained in:
+15
-3
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
|||||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class AnalyzerWithCompilerReport(collector: MessageCollector) {
|
class AnalyzerWithCompilerReport(collector: MessageCollector) {
|
||||||
private val messageCollector: MessageSeverityCollector = MessageSeverityCollector(collector)
|
private val messageCollector: MessageSeverityCollector = MessageSeverityCollector(collector)
|
||||||
|
|
||||||
@@ -51,7 +52,8 @@ class AnalyzerWithCompilerReport(collector: MessageCollector) {
|
|||||||
val bindingContext = analysisResult.bindingContext
|
val bindingContext = analysisResult.bindingContext
|
||||||
val classes = bindingContext.getKeys(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY)
|
val classes = bindingContext.getKeys(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY)
|
||||||
if (!classes.isEmpty()) {
|
if (!classes.isEmpty()) {
|
||||||
val message = StringBuilder("Supertypes of the following classes cannot be resolved. " + "Please make sure you have the required dependencies in the classpath:\n")
|
val message = StringBuilder("Supertypes of the following classes cannot be resolved. " +
|
||||||
|
"Please make sure you have the required dependencies in the classpath:\n")
|
||||||
for (descriptor in classes) {
|
for (descriptor in classes) {
|
||||||
val fqName = DescriptorUtils.getFqName(descriptor).asString()
|
val fqName = DescriptorUtils.getFqName(descriptor).asString()
|
||||||
val unresolved = bindingContext.get(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY, descriptor)
|
val unresolved = bindingContext.get(TraceBasedErrorReporter.INCOMPLETE_HIERARCHY, descriptor)
|
||||||
@@ -116,9 +118,19 @@ class AnalyzerWithCompilerReport(collector: MessageCollector) {
|
|||||||
return messageCollector.anyReported(CompilerMessageSeverity.ERROR)
|
return messageCollector.anyReported(CompilerMessageSeverity.ERROR)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun analyzeAndReport(files: Collection<KtFile>, analyzer: () -> AnalysisResult) {
|
interface Analyzer {
|
||||||
analysisResult = analyzer.invoke()
|
fun analyze(): AnalysisResult
|
||||||
|
|
||||||
|
fun reportEnvironmentErrors() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun analyzeAndReport(files: Collection<KtFile>, analyzer: Analyzer) {
|
||||||
|
analysisResult = analyzer.analyze()
|
||||||
reportSyntaxErrors(files)
|
reportSyntaxErrors(files)
|
||||||
|
if (analysisResult.bindingContext.diagnostics.any { it.isValid && it.severity == Severity.ERROR }) {
|
||||||
|
analyzer.reportEnvironmentErrors()
|
||||||
|
}
|
||||||
val abiVersionErrors = abiVersionErrors
|
val abiVersionErrors = abiVersionErrors
|
||||||
reportDiagnostics(analysisResult.bindingContext.diagnostics, messageCollector, !abiVersionErrors.isEmpty())
|
reportDiagnostics(analysisResult.bindingContext.diagnostics, messageCollector, !abiVersionErrors.isEmpty())
|
||||||
if (hasErrors()) {
|
if (hasErrors()) {
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import com.intellij.util.Function;
|
|||||||
import com.intellij.util.SmartList;
|
import com.intellij.util.SmartList;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlin.jvm.functions.Function0;
|
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -232,11 +231,16 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments> {
|
|||||||
private static AnalyzerWithCompilerReport analyzeAndReportErrors(@NotNull MessageCollector messageCollector,
|
private static AnalyzerWithCompilerReport analyzeAndReportErrors(@NotNull MessageCollector messageCollector,
|
||||||
@NotNull final List<KtFile> sources, @NotNull final Config config) {
|
@NotNull final List<KtFile> sources, @NotNull final Config config) {
|
||||||
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(messageCollector);
|
AnalyzerWithCompilerReport analyzerWithCompilerReport = new AnalyzerWithCompilerReport(messageCollector);
|
||||||
analyzerWithCompilerReport.analyzeAndReport(sources, new Function0<AnalysisResult>() {
|
analyzerWithCompilerReport.analyzeAndReport(sources, new AnalyzerWithCompilerReport.Analyzer() {
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public AnalysisResult invoke() {
|
public AnalysisResult analyze() {
|
||||||
return TopDownAnalyzerFacadeForJS.analyzeFiles(sources, config);
|
return TopDownAnalyzerFacadeForJS.analyzeFiles(sources, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reportEnvironmentErrors() {
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return analyzerWithCompilerReport;
|
return analyzerWithCompilerReport;
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-16
@@ -16,15 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cli.jvm.compiler
|
package org.jetbrains.kotlin.cli.jvm.compiler
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.io.JarUtil
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
|
import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
import org.jetbrains.kotlin.cli.common.CompilerPluginContext
|
import org.jetbrains.kotlin.cli.common.CompilerPluginContext
|
||||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
import org.jetbrains.kotlin.cli.common.messages.*
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageUtil
|
|
||||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll
|
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll
|
||||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.*
|
import org.jetbrains.kotlin.cli.jvm.config.*
|
||||||
@@ -46,11 +44,13 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.util.PerformanceCounter
|
import org.jetbrains.kotlin.util.PerformanceCounter
|
||||||
import org.jetbrains.kotlin.utils.KotlinPaths
|
import org.jetbrains.kotlin.utils.KotlinPaths
|
||||||
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.reflect.Constructor
|
import java.lang.reflect.Constructor
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
import java.util.jar.Attributes
|
||||||
|
|
||||||
object KotlinToJVMBytecodeCompiler {
|
object KotlinToJVMBytecodeCompiler {
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
moduleVisibilityManager.addFriendPath(path)
|
moduleVisibilityManager.addFriendPath(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetDescription = "in targets [" + chunk.joinToString { input -> input.getModuleName() + "-" + input.getModuleType() } + "]"
|
val targetDescription = "in targets [" + chunk.joinToString { input -> input.getModuleName() + "-" + input.getModuleType() } + "]"
|
||||||
val result = analyze(environment, targetDescription) ?: return false
|
val result = analyze(environment, targetDescription) ?: return false
|
||||||
|
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||||
@@ -270,18 +270,24 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
val analysisStart = PerformanceCounter.currentTime()
|
val analysisStart = PerformanceCounter.currentTime()
|
||||||
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
|
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
|
||||||
analyzerWithCompilerReport.analyzeAndReport(
|
analyzerWithCompilerReport.analyzeAndReport(
|
||||||
environment.getSourceFiles(), {
|
environment.getSourceFiles(), object : AnalyzerWithCompilerReport.Analyzer {
|
||||||
val sharedTrace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
override fun analyze(): AnalysisResult {
|
||||||
val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project,
|
val sharedTrace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
||||||
environment.getModuleName())
|
val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project,
|
||||||
|
environment.getModuleName())
|
||||||
|
|
||||||
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
|
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
|
||||||
moduleContext,
|
moduleContext,
|
||||||
environment.getSourceFiles(),
|
environment.getSourceFiles(),
|
||||||
sharedTrace,
|
sharedTrace,
|
||||||
environment.configuration.get(JVMConfigurationKeys.MODULES),
|
environment.configuration.get(JVMConfigurationKeys.MODULES),
|
||||||
environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS),
|
environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS),
|
||||||
JvmPackagePartProvider(environment))
|
JvmPackagePartProvider(environment))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reportEnvironmentErrors() {
|
||||||
|
reportRuntimeConflicts(collector, environment.configuration.jvmClasspathRoots)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
val analysisNanos = PerformanceCounter.currentTime() - analysisStart
|
val analysisNanos = PerformanceCounter.currentTime() - analysisStart
|
||||||
val message = "ANALYZE: " + environment.getSourceFiles().size + " files (" +
|
val message = "ANALYZE: " + environment.getSourceFiles().size + " files (" +
|
||||||
@@ -397,4 +403,24 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
assert(result != null) { "Message collector not specified in compiler configuration" }
|
assert(result != null) { "Message collector not specified in compiler configuration" }
|
||||||
return result!!
|
return result!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun reportRuntimeConflicts(messageCollector: MessageCollector, jvmClasspathRoots: List<File>) {
|
||||||
|
fun String.removeIdeaVersionSuffix(): String {
|
||||||
|
val versionIndex = indexOfAny(arrayListOf("-IJ", "-Idea"))
|
||||||
|
return if (versionIndex >= 0) substring(0, versionIndex) else this
|
||||||
|
}
|
||||||
|
|
||||||
|
val runtimes = jvmClasspathRoots.filter { it.name == PathUtil.KOTLIN_JAVA_RUNTIME_JAR && it.exists() }
|
||||||
|
|
||||||
|
val runtimeVersions = runtimes.map {
|
||||||
|
JarUtil.getJarAttribute(it, Attributes.Name.IMPLEMENTATION_VERSION).orEmpty().removeIdeaVersionSuffix()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtimeVersions.toSet().size > 1) {
|
||||||
|
messageCollector.report(CompilerMessageSeverity.ERROR,
|
||||||
|
"Conflicting versions of Kotlin runtime on classpath: " + runtimes.joinToString { it.path },
|
||||||
|
CompilerMessageLocation.NO_LOCATION)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
$TESTDATA_DIR$/conflictingRuntimeVersions.kt
|
||||||
|
-classpath
|
||||||
|
$TESTDATA_DIR$/kotlin-runtime-4584-stub/kotlin-runtime.jar
|
||||||
|
-d
|
||||||
|
$TEMP_DIR$
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
error: conflicting versions of Kotlin runtime on classpath: compiler/testData/cli/jvm/kotlin-runtime-4584-stub/kotlin-runtime.jar, $PROJECT_DIR$/lib/kotlin-runtime.jar
|
||||||
|
compiler/testData/cli/jvm/conflictingRuntimeVersions.kt:1:9: error: unresolved reference: unresolvedFunction
|
||||||
|
val f = unresolvedFunction()
|
||||||
|
^
|
||||||
|
COMPILATION_ERROR
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
$TESTDATA_DIR$/simple.kt
|
||||||
|
-classpath
|
||||||
|
$TESTDATA_DIR$/kotlin-runtime-4584-stub/kotlin-runtime.jar
|
||||||
|
-d
|
||||||
|
$TEMP_DIR$
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
OK
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
val f = unresolvedFunction()
|
||||||
Binary file not shown.
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion;
|
|||||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
import org.jetbrains.kotlin.test.Tmpdir;
|
import org.jetbrains.kotlin.test.Tmpdir;
|
||||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||||
|
import org.jetbrains.kotlin.utils.PathUtil;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.rules.TestName;
|
import org.junit.rules.TestName;
|
||||||
|
|
||||||
@@ -83,6 +84,7 @@ public class CliBaseTest {
|
|||||||
) {
|
) {
|
||||||
String normalizedOutputWithoutExitCode = pureOutput
|
String normalizedOutputWithoutExitCode = pureOutput
|
||||||
.replace(new File(testDataDir).getAbsolutePath(), "$TESTDATA_DIR$")
|
.replace(new File(testDataDir).getAbsolutePath(), "$TESTDATA_DIR$")
|
||||||
|
.replace(PathUtil.getKotlinPathsForDistDirectory().getHomePath().getAbsolutePath(), "$PROJECT_DIR$")
|
||||||
.replace("expected version is " + version, "expected version is $ABI_VERSION$")
|
.replace("expected version is " + version, "expected version is $ABI_VERSION$")
|
||||||
.replace("\\", "/")
|
.replace("\\", "/")
|
||||||
.replace(KotlinVersion.VERSION, "$VERSION$");
|
.replace(KotlinVersion.VERSION, "$VERSION$");
|
||||||
|
|||||||
@@ -73,6 +73,18 @@ public class KotlincExecutableTestGenerated extends AbstractKotlincExecutableTes
|
|||||||
doJvmTest(fileName);
|
doJvmTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("conflictingRuntimeVersion.args")
|
||||||
|
public void testConflictingRuntimeVersion() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/conflictingRuntimeVersion.args");
|
||||||
|
doJvmTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("conflictingRuntimeVersionNoError.args")
|
||||||
|
public void testConflictingRuntimeVersionNoError() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/conflictingRuntimeVersionNoError.args");
|
||||||
|
doJvmTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("diagnosticsOrder.args")
|
@TestMetadata("diagnosticsOrder.args")
|
||||||
public void testDiagnosticsOrder() throws Exception {
|
public void testDiagnosticsOrder() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/diagnosticsOrder.args");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/diagnosticsOrder.args");
|
||||||
|
|||||||
@@ -161,6 +161,11 @@
|
|||||||
<exclude>kotlin/internal/OnlyInputTypes*</exclude>
|
<exclude>kotlin/internal/OnlyInputTypes*</exclude>
|
||||||
<exclude>kotlin/internal</exclude>
|
<exclude>kotlin/internal</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|||||||
@@ -228,6 +228,16 @@
|
|||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,13 @@
|
|||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
<version>2.6</version>
|
<version>2.6</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>empty-javadoc-jar</id>
|
<id>empty-javadoc-jar</id>
|
||||||
|
|||||||
Reference in New Issue
Block a user