From fc9aa87a056f0d0eaa34c55e4f15d2834f2e7fe8 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Thu, 24 Sep 2015 14:07:43 +0300 Subject: [PATCH] Report diagnostic on import with explicit import class if class was imported earlier. --- .../jetbrains/kotlin/diagnostics/Errors.java | 2 +- .../diagnostics/PositioningStrategies.kt | 14 +++ .../org/jetbrains/kotlin/psi/JetPsiUtil.java | 3 + .../resolve/QualifiedExpressionResolver.kt | 13 +- .../resolve/lazy/FileScopeProviderImpl.kt | 2 +- .../kotlin/resolve/lazy/LazyImportScope.kt | 119 +++++------------- .../tests/imports/ClassImportsConflicting.kt | 6 +- .../tests/imports/ExplicitImportsAmbiguity.kt | 4 +- .../tests/imports/ImportClassClash.kt | 48 +++++++ .../tests/imports/ImportClassClash.txt | 66 ++++++++++ .../tests/imports/NestedClassClash.kt | 4 +- .../checkers/JetDiagnosticsTestGenerated.java | 6 + .../idea/caches/resolve/resolutionApi.kt | 2 +- .../removeDuplicateImport.kt | 5 + .../removeDuplicateImport.kt.after | 4 + .../removeDuplicateImportWithAlias.kt | 5 + .../removeDuplicateImportWithAlias.kt.after | 4 + .../idea/quickfix/QuickFixTestGenerated.java | 12 ++ 18 files changed, 215 insertions(+), 104 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/imports/ImportClassClash.kt create mode 100644 compiler/testData/diagnostics/tests/imports/ImportClassClash.txt create mode 100644 idea/testData/quickfix/conflictingImports/removeDuplicateImport.kt create mode 100644 idea/testData/quickfix/conflictingImports/removeDuplicateImport.kt.after create mode 100644 idea/testData/quickfix/conflictingImports/removeDuplicateImportWithAlias.kt create mode 100644 idea/testData/quickfix/conflictingImports/removeDuplicateImportWithAlias.kt.after diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 491a8c1e1d8..0920196f4a4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -105,7 +105,7 @@ public interface Errors { DiagnosticFactory1 CANNOT_BE_IMPORTED = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 PACKAGE_CANNOT_BE_IMPORTED = DiagnosticFactory0.create(ERROR); - DiagnosticFactory1 CONFLICTING_IMPORT = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 CONFLICTING_IMPORT = DiagnosticFactory1.create(ERROR, PositioningStrategies.IMPORT_ALIAS); // Modifiers diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index feaed65970c..d7488485519 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -452,4 +452,18 @@ public object PositioningStrategies { return listOf(TextRange(element.getOperationReference().startOffset, element.endOffset)) } } + + public val IMPORT_ALIAS: PositioningStrategy = object: PositioningStrategy() { + override fun mark(element: JetImportDirective): List { + element.aliasNameNode?.let { return markNode(it) } + element.importedReference?.let { + if (it is JetQualifiedExpression) { + it.selectorExpression?.let { return markElement(it) } + } + return markElement(it) + } + return markElement(element) + } + } + } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java index 04e14b995ea..497df718d3b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetPsiUtil.java @@ -300,6 +300,9 @@ public class JetPsiUtil { @Nullable public static Name getAliasName(@NotNull JetImportDirective importDirective) { + if (importDirective.isAllUnder()) { + return null; + } String aliasName = importDirective.getAliasName(); JetExpression importedReference = importDirective.getImportedReference(); if (importedReference == null) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt index 655d22510ef..db566c8c2df 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/QualifiedExpressionResolver.kt @@ -118,14 +118,14 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa moduleDescriptor: ModuleDescriptor, trace: BindingTrace, packageFragmentForVisibilityCheck: PackageFragmentDescriptor? - ): JetScope { - val importedReference = importDirective.importedReference ?: return JetScope.Empty + ): JetScope? { // null if some error happened + val importedReference = importDirective.importedReference ?: return null val path = importedReference.asQualifierPartList(trace) - val lastPart = path.lastOrNull() ?: return JetScope.Empty + val lastPart = path.lastOrNull() ?: return null if (importDirective.isAllUnder) { val packageOrClassDescriptor = resolveToPackageOrClass(path, moduleDescriptor, trace, packageFragmentForVisibilityCheck, - scopeForFirstPart = null, inImport = true) ?: return JetScope.Empty + scopeForFirstPart = null, inImport = true) ?: return null if (packageOrClassDescriptor is ClassDescriptor && packageOrClassDescriptor.kind.isSingleton) { trace.report(Errors.CANNOT_IMPORT_MEMBERS_FROM_SINGLETON.on(lastPart.expression, packageOrClassDescriptor)) // todo report on star } @@ -135,12 +135,12 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa val aliasName = JetPsiUtil.getAliasName(importDirective) if (aliasName == null) { // import kotlin. resolveToPackageOrClass(path, moduleDescriptor, trace, packageFragmentForVisibilityCheck, scopeForFirstPart = null, inImport = true) - return JetScope.Empty + return null } val packageOrClassDescriptor = resolveToPackageOrClass(path.subList(0, path.size() - 1), moduleDescriptor, trace, packageFragmentForVisibilityCheck, scopeForFirstPart = null, inImport = true) - ?: return JetScope.Empty + ?: return null val descriptors = SmartList() val lastName = lastPart.name @@ -169,6 +169,7 @@ public class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageVa } else { tryResolveDescriptorsWhichCannotBeImported(trace, moduleDescriptor, packageOrClassDescriptor, lastPart) + return null } val importedDescriptors = descriptors.filter { isVisible(it, packageFragmentForVisibilityCheck, inImport = true) }. diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeProviderImpl.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeProviderImpl.kt index 05c32c415dd..b984d8f991e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeProviderImpl.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/FileScopeProviderImpl.kt @@ -61,7 +61,7 @@ public class FileScopeProviderImpl( .sure { "Could not find fragment ${file.getPackageFqName()} for file ${file.getName()}" } fun createImportResolver(indexedImports: IndexedImports, trace: BindingTrace) - = LazyImportResolver(storageManager, qualifiedExpressionResolver, this, moduleDescriptor, indexedImports, trace, packageFragment) + = LazyImportResolver(storageManager, qualifiedExpressionResolver, moduleDescriptor, indexedImports, trace, packageFragment) val aliasImportResolver = createImportResolver(AliasImportsIndexed(imports), bindingTrace) val allUnderImportResolver = createImportResolver(AllUnderImportsIndexed(imports), bindingTrace) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt index 4aecf68791e..5954d1c5cde 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/LazyImportScope.kt @@ -16,25 +16,27 @@ package org.jetbrains.kotlin.resolve.lazy +import com.google.common.collect.HashMultimap import com.google.common.collect.ImmutableListMultimap import com.google.common.collect.ListMultimap import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.diagnostics.Errors +import org.jetbrains.kotlin.incremental.KotlinLookupLocation +import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.JetImportDirective import org.jetbrains.kotlin.psi.JetPsiUtil import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.PlatformTypesMappedToKotlinChecker +import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.JetScope -import org.jetbrains.kotlin.incremental.components.LookupLocation -import org.jetbrains.kotlin.resolve.QualifiedExpressionResolver import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.util.collectionUtils.concat import org.jetbrains.kotlin.utils.Printer -import java.util.LinkedHashSet +import java.util.* interface IndexedImports { val imports: List @@ -67,111 +69,57 @@ class AliasImportsIndexed(allImports: Collection) : IndexedI class LazyImportResolver( val storageManager: StorageManager, val qualifiedExpressionResolver: QualifiedExpressionResolver, - val fileScopeProvider: FileScopeProvider, val moduleDescriptor: ModuleDescriptor, val indexedImports: IndexedImports, private val traceForImportResolve: BindingTrace, private val packageFragment: PackageFragmentDescriptor ) { - private val importedScopesProvider = storageManager.createMemoizedFunction { - directive: JetImportDirective -> ImportDirectiveResolveCache(directive) - } + private val importedScopesProvider = storageManager.createMemoizedFunctionWithNullableValues { + directive: JetImportDirective -> + val directiveImportScope = qualifiedExpressionResolver.processImportReference( + directive, moduleDescriptor, traceForImportResolve, packageFragment) ?: return@createMemoizedFunctionWithNullableValues null - private var directiveUnderResolve: JetImportDirective? = null - - private class ImportResolveStatus(val scope: JetScope, val descriptors: Collection) - - private inner class ImportDirectiveResolveCache(private val directive: JetImportDirective) { - - @Volatile var importResolveStatus: ImportResolveStatus? = null - - fun scopeForMode(): JetScope { - val status = importResolveStatus - if (status != null) { - return status.scope + if (!directive.isAllUnder) { + PlatformTypesMappedToKotlinChecker.checkPlatformTypesMappedToKotlin( + moduleDescriptor, traceForImportResolve, directive, directiveImportScope.getAllDescriptors()) } - return storageManager.compute { - val cachedStatus = importResolveStatus - if (cachedStatus != null) { - cachedStatus.scope - } - else { - directiveUnderResolve = directive - - try { - val directiveImportScope = qualifiedExpressionResolver.processImportReference( - directive, moduleDescriptor, traceForImportResolve, packageFragment) - val descriptors = if (directive.isAllUnder()) emptyList() else directiveImportScope.getAllDescriptors() - - PlatformTypesMappedToKotlinChecker.checkPlatformTypesMappedToKotlin(moduleDescriptor, traceForImportResolve, directive, descriptors) - - importResolveStatus = ImportResolveStatus(directiveImportScope, descriptors) - directiveImportScope - } - finally { - directiveUnderResolve = null - } - } - } - } + directiveImportScope } public fun forceResolveAllContents() { + val explicitClassImports = HashMultimap.create() for (importDirective in indexedImports.imports) { forceResolveImportDirective(importDirective) + val scope = importedScopesProvider(importDirective) + + val alias = JetPsiUtil.getAliasName(importDirective)?.identifier + if (scope != null && alias != null) { + if (scope.getClassifier(Name.identifier(alias), KotlinLookupLocation(importDirective)) != null) { + explicitClassImports.put(alias, importDirective) + } + } + } + for (alias in explicitClassImports.keySet()) { + val imports = explicitClassImports.get(alias) + if (imports.size() > 1) { + imports.forEach { + traceForImportResolve.report(Errors.CONFLICTING_IMPORT.on(it, alias)) + } + } } } public fun forceResolveImportDirective(importDirective: JetImportDirective) { getImportScope(importDirective) - - val status = importedScopesProvider(importDirective).importResolveStatus - if (status != null && !status.descriptors.isEmpty()) { - val fileScope = fileScopeProvider.getFileScope(importDirective.getContainingJetFile()) - reportConflictingImport(importDirective, fileScope, status.descriptors, traceForImportResolve) - } } - private fun reportConflictingImport( - importDirective: JetImportDirective, - fileScope: JetScope, - resolvedTo: Collection?, - trace: BindingTrace - ) { - - val importedReference = importDirective.getImportedReference() - if (importedReference == null || resolvedTo == null) return - - val aliasName = JetPsiUtil.getAliasName(importDirective) ?: return - - if (resolvedTo.size() != 1) return - - when (resolvedTo.single()) { - is ClassDescriptor -> { - if (fileScope.getClassifier(aliasName) == null) { - trace.report(Errors.CONFLICTING_IMPORT.on(importedReference, aliasName.asString())) - } - } - is PackageViewDescriptor -> { - if (fileScope.getPackage(aliasName) == null) { - trace.report(Errors.CONFLICTING_IMPORT.on(importedReference, aliasName.asString())) - } - } - } - } - - public fun selectSingleFromImports( name: Name, descriptorSelector: (JetScope, Name) -> D? ): D? { fun compute(): D? { val imports = indexedImports.importsForName(name) - if (imports.contains(directiveUnderResolve)) { - // This is the recursion in imports analysis - return null - } var target: D? = null for (directive in imports) { @@ -191,11 +139,6 @@ class LazyImportResolver( return storageManager.compute { var descriptors: Collection? = null for (directive in indexedImports.importsForName(name)) { - if (directive == directiveUnderResolve) { - // This is the recursion in imports analysis - throw IllegalStateException("Recursion while resolving many imports: " + directive.getText()) - } - val descriptorsForImport = descriptorsSelector(getImportScope(directive), name) descriptors = descriptors.concat(descriptorsForImport) } @@ -205,7 +148,7 @@ class LazyImportResolver( } public fun getImportScope(directive: JetImportDirective): JetScope { - return importedScopesProvider(directive).scopeForMode() + return importedScopesProvider(directive) ?: JetScope.Empty } } diff --git a/compiler/testData/diagnostics/tests/imports/ClassImportsConflicting.kt b/compiler/testData/diagnostics/tests/imports/ClassImportsConflicting.kt index 5a4ef3a43fa..5a10828bd29 100644 --- a/compiler/testData/diagnostics/tests/imports/ClassImportsConflicting.kt +++ b/compiler/testData/diagnostics/tests/imports/ClassImportsConflicting.kt @@ -1,8 +1,8 @@ //FILE:a.kt package a -import b.O -import c.O +import b.O +import c.O //FILE:b.kt package b @@ -12,4 +12,4 @@ object O {} //FILE:c.kt package c -object O {} +object O {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ExplicitImportsAmbiguity.kt b/compiler/testData/diagnostics/tests/imports/ExplicitImportsAmbiguity.kt index 3387bc1847f..4258ea9fc51 100644 --- a/compiler/testData/diagnostics/tests/imports/ExplicitImportsAmbiguity.kt +++ b/compiler/testData/diagnostics/tests/imports/ExplicitImportsAmbiguity.kt @@ -11,7 +11,7 @@ class X // FILE: c.kt package c -import a.X -import b.X +import a.X +import b.X class Y : X \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ImportClassClash.kt b/compiler/testData/diagnostics/tests/imports/ImportClassClash.kt new file mode 100644 index 00000000000..c7e7b0800b9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportClassClash.kt @@ -0,0 +1,48 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// FILE: 1.kt +package a + +class someFun() {} +fun someFun(i: Int) {} + +class someVal() {} +val Int.someVal: Int get() = 3 + +class A + +class B + +// FILE: 2.kt +package b + +class someFun +class someVal +class someAll + +fun A() {} + +class B + + +// FILE: 3.kt +import a.someFun +import b.someFun + +import a.someVal +import b.someVal + +import a.A +import b.A + +// FILE: 4.kt +import b.* +import a.B + +// FILE: 5.kt +package b + +import a.B + +// FILE: 6.kt +import a.B +import b.B \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/imports/ImportClassClash.txt b/compiler/testData/diagnostics/tests/imports/ImportClassClash.txt new file mode 100644 index 00000000000..4815eaeee67 --- /dev/null +++ b/compiler/testData/diagnostics/tests/imports/ImportClassClash.txt @@ -0,0 +1,66 @@ +package + +package a { + public val kotlin.Int.someVal: kotlin.Int + public fun someFun(/*0*/ i: kotlin.Int): kotlin.Unit + + public final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class someFun { + public constructor someFun() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class someVal { + public constructor someVal() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} + +package b { + public fun A(): kotlin.Unit + + public final class B { + public constructor B() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class someAll { + public constructor someAll() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class someFun { + public constructor someFun() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public final class someVal { + public constructor someVal() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } +} diff --git a/compiler/testData/diagnostics/tests/imports/NestedClassClash.kt b/compiler/testData/diagnostics/tests/imports/NestedClassClash.kt index 639bdbcba9b..d24cb8cf09a 100644 --- a/compiler/testData/diagnostics/tests/imports/NestedClassClash.kt +++ b/compiler/testData/diagnostics/tests/imports/NestedClassClash.kt @@ -14,8 +14,8 @@ class D { } // FILE: c.kt -import a.A.B -import a.D.B +import a.A.B +import a.D.B fun test(b: B) { B() diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 940d534bcb8..997356462f3 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -6603,6 +6603,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("ImportClassClash.kt") + public void testImportClassClash() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportClassClash.kt"); + doTest(fileName); + } + @TestMetadata("ImportFromCurrentWithDifferentName.kt") public void testImportFromCurrentWithDifferentName() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportFromCurrentWithDifferentName.kt"); diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt index 1fe239d3c64..83b101d6894 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/resolutionApi.kt @@ -82,7 +82,7 @@ public fun ResolutionFacade.resolveImportReference( val importDirective = JetPsiFactory(project).createImportDirective(ImportPath(fqName, false)) val qualifiedExpressionResolver = this.getFrontendService(moduleDescriptor, QualifiedExpressionResolver::class.java) return qualifiedExpressionResolver.processImportReference( - importDirective, moduleDescriptor, BindingTraceContext(), packageFragmentForVisibilityCheck = null).getAllDescriptors() + importDirective, moduleDescriptor, BindingTraceContext(), packageFragmentForVisibilityCheck = null)?.getAllDescriptors() ?: emptyList() } //NOTE: idea default API returns module search scope for file under module but not in source or production source (for example, test data ) diff --git a/idea/testData/quickfix/conflictingImports/removeDuplicateImport.kt b/idea/testData/quickfix/conflictingImports/removeDuplicateImport.kt new file mode 100644 index 00000000000..4fa84d05c87 --- /dev/null +++ b/idea/testData/quickfix/conflictingImports/removeDuplicateImport.kt @@ -0,0 +1,5 @@ +// "Remove conflicting import for 'java.util.ArrayList'" "true" +package test + +import java.util.ArrayList +import java.util.ArrayList \ No newline at end of file diff --git a/idea/testData/quickfix/conflictingImports/removeDuplicateImport.kt.after b/idea/testData/quickfix/conflictingImports/removeDuplicateImport.kt.after new file mode 100644 index 00000000000..483144d0754 --- /dev/null +++ b/idea/testData/quickfix/conflictingImports/removeDuplicateImport.kt.after @@ -0,0 +1,4 @@ +// "Remove conflicting import for 'java.util.ArrayList'" "true" +package test + +import java.util.ArrayList diff --git a/idea/testData/quickfix/conflictingImports/removeDuplicateImportWithAlias.kt b/idea/testData/quickfix/conflictingImports/removeDuplicateImportWithAlias.kt new file mode 100644 index 00000000000..42718a687ee --- /dev/null +++ b/idea/testData/quickfix/conflictingImports/removeDuplicateImportWithAlias.kt @@ -0,0 +1,5 @@ +// "Remove conflicting import for 'java.util.ArrayList'" "true" +package test + +import java.util.ArrayList as foo +import java.util.ArrayList as foo \ No newline at end of file diff --git a/idea/testData/quickfix/conflictingImports/removeDuplicateImportWithAlias.kt.after b/idea/testData/quickfix/conflictingImports/removeDuplicateImportWithAlias.kt.after new file mode 100644 index 00000000000..1d130a4e2e7 --- /dev/null +++ b/idea/testData/quickfix/conflictingImports/removeDuplicateImportWithAlias.kt.after @@ -0,0 +1,4 @@ +// "Remove conflicting import for 'java.util.ArrayList'" "true" +package test + +import java.util.ArrayList as foo diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 3c2f85ba98d..8eef5687397 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -723,6 +723,18 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/conflictingImports/removeConflictingImport.kt"); doTest(fileName); } + + @TestMetadata("removeDuplicateImport.kt") + public void testRemoveDuplicateImport() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/conflictingImports/removeDuplicateImport.kt"); + doTest(fileName); + } + + @TestMetadata("removeDuplicateImportWithAlias.kt") + public void testRemoveDuplicateImportWithAlias() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/conflictingImports/removeDuplicateImportWithAlias.kt"); + doTest(fileName); + } } @TestMetadata("idea/testData/quickfix/createFromUsage")