diff --git a/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt index 2a4003f376b..3a690f94aaa 100644 --- a/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt +++ b/libraries/tools/kotlin-main-kts-test/test/org/jetbrains/kotlin/mainKts/test/mainKtsTest.kt @@ -121,6 +121,12 @@ class MainKtsTest { Assert.assertEquals(OUT_FROM_IMPORT_TEST, out) } + @Test + fun testDuplicateImportError() { + val res = evalFile(File("$TEST_DATA_ROOT/import-duplicate-test.main.kts")) + assertFailed("Duplicate imports:", res) + } + @Test fun testCompilerOptions() { diff --git a/libraries/tools/kotlin-main-kts-test/testData/import-duplicate-test.main.kts b/libraries/tools/kotlin-main-kts-test/testData/import-duplicate-test.main.kts new file mode 100644 index 00000000000..72e00910c56 --- /dev/null +++ b/libraries/tools/kotlin-main-kts-test/testData/import-duplicate-test.main.kts @@ -0,0 +1,5 @@ + +@file:Import("import-common.main.kts") +@file:Import("../testData/import-common.main.kts") + +sharedVar = sharedVar + 1 diff --git a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/scriptDef.kt b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/scriptDef.kt index f08b39925fc..708eaab10bd 100644 --- a/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/scriptDef.kt +++ b/libraries/tools/kotlin-main-kts/src/org/jetbrains/kotlin/mainKts/scriptDef.kt @@ -125,11 +125,26 @@ class MainKtsConfigurator : RefineScriptCompilationConfigurationHandler { ?: return context.compilationConfiguration.asSuccess() val scriptBaseDir = (context.script as? FileBasedScriptSource)?.file?.parentFile - val importedSources = annotations.filterByAnnotationType().flatMap { - it.annotation.paths.map { sourceName -> - FileScriptSource(scriptBaseDir?.resolve(sourceName) ?: File(sourceName)) + val importedSources = linkedMapOf>() + var hasImportErrors = false + annotations.filterByAnnotationType().forEach { scriptAnnotation -> + scriptAnnotation.annotation.paths.forEach { sourceName -> + val file = (scriptBaseDir?.resolve(sourceName) ?: File(sourceName)).normalize() + val keyPath = file.absolutePath + val prevImport = importedSources.put(keyPath, file to sourceName) + if (prevImport != null) { + diagnostics.add( + ScriptDiagnostic( + ScriptDiagnostic.unspecifiedError, "Duplicate imports: \"${prevImport.second}\" and \"$sourceName\"", + sourcePath = context.script.locationId, location = scriptAnnotation.location?.locationInText + ) + ) + hasImportErrors = true + } } } + if (hasImportErrors) return ResultWithDiagnostics.Failure(diagnostics) + val compileOptions = annotations.filterByAnnotationType().flatMap { it.annotation.options.toList() } @@ -140,13 +155,14 @@ class MainKtsConfigurator : RefineScriptCompilationConfigurationHandler { resolver.resolveFromScriptSourceAnnotations(annotations.filter { it.annotation is DependsOn || it.annotation is Repository }) } } catch (e: Throwable) { - ResultWithDiagnostics.Failure(*diagnostics.toTypedArray(), e.asDiagnostics(path = context.script.locationId)) + diagnostics.add(e.asDiagnostics(path = context.script.locationId)) + ResultWithDiagnostics.Failure(diagnostics) } return resolveResult.onSuccess { resolvedClassPath -> ScriptCompilationConfiguration(context.compilationConfiguration) { updateClasspath(resolvedClassPath) - if (importedSources.isNotEmpty()) importScripts.append(importedSources) + if (importedSources.isNotEmpty()) importScripts.append(importedSources.values.map { FileScriptSource(it.first) }) if (compileOptions.isNotEmpty()) compilerOptions.append(compileOptions) }.asSuccess() }