diff --git a/plugins/kotlin/completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt b/plugins/kotlin/completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt index 5a1d7d67b0bf..f73c75257cb8 100644 --- a/plugins/kotlin/completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt +++ b/plugins/kotlin/completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.idea.completion.handlers.KotlinClassifierInsertHandl import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject import org.jetbrains.kotlin.idea.core.completion.PackageLookupObject +import org.jetbrains.kotlin.idea.core.unwrapIfFakeOverride import org.jetbrains.kotlin.idea.highlighter.dsl.DslHighlighterExtension import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor @@ -51,10 +52,7 @@ class BasicLookupElementFactory( includeClassTypeArguments: Boolean = true, parametersAndTypeGrayed: Boolean = false ): LookupElement { - val _descriptor = if (descriptor is CallableMemberDescriptor) - DescriptorUtils.unwrapFakeOverride(descriptor) - else - descriptor + val _descriptor = descriptor.unwrapIfFakeOverride() return createLookupElementUnwrappedDescriptor(_descriptor, qualifyNestedClasses, includeClassTypeArguments, parametersAndTypeGrayed) } @@ -343,4 +341,4 @@ class BasicLookupElementFactory( presentation.icon = DefaultLookupItemRenderer.getRawIcon(this@withIconFromLookupObject, presentation.isReal) } } -} \ No newline at end of file +} diff --git a/plugins/kotlin/completion/tests/test/org/jetbrains/kotlin/idea/completion/test/handlers/CompletionMultifileHandlerTest.kt b/plugins/kotlin/completion/tests/test/org/jetbrains/kotlin/idea/completion/test/handlers/CompletionMultifileHandlerTest.kt index db2d62d0ba02..4592e2898fd6 100644 --- a/plugins/kotlin/completion/tests/test/org/jetbrains/kotlin/idea/completion/test/handlers/CompletionMultifileHandlerTest.kt +++ b/plugins/kotlin/completion/tests/test/org/jetbrains/kotlin/idea/completion/test/handlers/CompletionMultifileHandlerTest.kt @@ -30,6 +30,10 @@ class CompletionMultiFileHandlerTest : KotlinCompletionTestCase() { doTest() } + fun testStaticMethodFromGrandParent() { + doTest('\n', "StaticMethodFromGrandParent-1.java", "StaticMethodFromGrandParent-2.java") + } + fun testTopLevelFunctionImport() { doTest() } @@ -113,8 +117,13 @@ class CompletionMultiFileHandlerTest : KotlinCompletionTestCase() { fun doTest(completionChar: Char = '\n', vararg extraFileNames: String, tailText: String? = null) { val fileName = getTestName(false) + val defaultFiles = listOf("$fileName-1.kt", "$fileName-2.kt") + val filteredFiles = defaultFiles.filter { File(testDataPath, it).exists() } + + require(filteredFiles.isNotEmpty()) { "At least one of $defaultFiles should exist!" } + configureByFiles(null, *extraFileNames) - configureByFiles(null, "$fileName-1.kt", "$fileName-2.kt") + configureByFiles(null, *filteredFiles.toTypedArray()) complete(2) if (myItems != null) { val item = if (tailText == null) diff --git a/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent-1.java b/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent-1.java new file mode 100644 index 000000000000..5e99ae99df1e --- /dev/null +++ b/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent-1.java @@ -0,0 +1,2 @@ +public class Base extends GrandBase { +} \ No newline at end of file diff --git a/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent-1.kt b/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent-1.kt new file mode 100644 index 000000000000..983f43016c5d --- /dev/null +++ b/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent-1.kt @@ -0,0 +1,5 @@ +class Inheritor : Base() { + init { + fooBa + } +} \ No newline at end of file diff --git a/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent-2.java b/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent-2.java new file mode 100644 index 000000000000..6aaa195d98a5 --- /dev/null +++ b/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent-2.java @@ -0,0 +1,3 @@ +public class GrandBase { + public static void fooBar() {} +} \ No newline at end of file diff --git a/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent.kt.after b/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent.kt.after new file mode 100644 index 000000000000..5349a1ae558c --- /dev/null +++ b/plugins/kotlin/completion/tests/testData/handlers/multifile/StaticMethodFromGrandParent.kt.after @@ -0,0 +1,5 @@ +class Inheritor : Base() { + init { + fooBar() + } +} \ No newline at end of file diff --git a/plugins/kotlin/core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt b/plugins/kotlin/core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt index 32879bff09d5..b6a58aa72639 100644 --- a/plugins/kotlin/core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt +++ b/plugins/kotlin/core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt @@ -552,7 +552,10 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT // targetMatch == false, but shorten still can be preformed // TODO: Add possibility to check if descriptor from completion can't be resolved after shorten and not preform shorten than val resolvedCallsMatch = if (resolvedCall != null && resolvedCallWhenShort != null) { - resolvedCall.resultingDescriptor.original == resolvedCallWhenShort.resultingDescriptor.original + val originalCallDescriptor = resolvedCall.resultingDescriptor.original.unwrapIfFakeOverride() + val shortenedCallDescriptor = resolvedCallWhenShort.resultingDescriptor.original.unwrapIfFakeOverride() + + originalCallDescriptor == shortenedCallDescriptor } else { val resolvedCalls = selector.getCall(bindingContext)?.resolveCandidates(bindingContext, resolutionFacade) ?: emptyList() val callWhenShort = selectorAfterShortening.getCall(newContext) diff --git a/plugins/kotlin/core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt b/plugins/kotlin/core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt index 1d1019556b87..695deabe6a04 100644 --- a/plugins/kotlin/core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt +++ b/plugins/kotlin/core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt @@ -141,3 +141,7 @@ fun D.getDeepestSuperDeclarations(withThis: Boole return overriddenDeclarations.filterNot(DescriptorUtils::isOverride) } + +fun T.unwrapIfFakeOverride(): T { + return if (this is CallableMemberDescriptor) DescriptorUtils.unwrapFakeOverride(this) else this +} \ No newline at end of file diff --git a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt index 9954dff28ffa..68f8427ddf72 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt +++ b/plugins/kotlin/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.idea.analysis.analyzeInContext import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference import org.jetbrains.kotlin.idea.codeInliner.CodeToInline import org.jetbrains.kotlin.idea.codeInliner.CodeToInlineBuilder +import org.jetbrains.kotlin.idea.core.unwrapIfFakeOverride import org.jetbrains.kotlin.idea.project.findAnalyzerServices import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.references.mainReference @@ -43,10 +44,7 @@ object ReplaceWithAnnotationAnalyzer { resolutionFacade: ResolutionFacade, reformat: Boolean ): CodeToInline? { - val originalDescriptor = when (symbolDescriptor) { - is CallableMemberDescriptor -> DescriptorUtils.unwrapFakeOverride(symbolDescriptor) - else -> symbolDescriptor - }.original + val originalDescriptor = symbolDescriptor.unwrapIfFakeOverride().original return analyzeOriginal(annotation, originalDescriptor, resolutionFacade, reformat) } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java index 07748712ea8d..0060bbeafcbd 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java @@ -284,6 +284,16 @@ public class ShortenRefsTestGenerated extends AbstractShortenRefsTest { runTest("testData/shortenRefs/java/innerClassOnDemandImport.kt"); } + @TestMetadata("redundantGrandParentClassQualifier.kt") + public void testRedundantGrandParentClassQualifier() throws Exception { + runTest("testData/shortenRefs/java/redundantGrandParentClassQualifier.kt"); + } + + @TestMetadata("redundantGrandParentClassQualifierAmbiguous.kt") + public void testRedundantGrandParentClassQualifierAmbiguous() throws Exception { + runTest("testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt"); + } + @TestMetadata("staticClassNoImports.kt") public void testStaticClassNoImports() throws Exception { runTest("testData/shortenRefs/java/staticClassNoImports.kt"); diff --git a/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifier.dependency.java b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifier.dependency.java new file mode 100644 index 000000000000..d49437c89534 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifier.dependency.java @@ -0,0 +1,7 @@ +public class Container { + public static class GrandBase { + public static void foo() {} + } + + public static class Base extends GrandBase {} +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt new file mode 100644 index 000000000000..371a9fa58e0d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt @@ -0,0 +1,5 @@ +class C : Container.Base() { + init { + Container.GrandBase.foo() + } +} diff --git a/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt.after b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt.after new file mode 100644 index 000000000000..fc48439e4bc1 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt.after @@ -0,0 +1,5 @@ +class C : Container.Base() { + init { + foo() + } +} diff --git a/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.dependency.java b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.dependency.java new file mode 100644 index 000000000000..c8f642a7db0a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.dependency.java @@ -0,0 +1,9 @@ +public class Container { + public static class GrandBase { + public static void foo() {} + } + + public static class Base extends GrandBase { + public static void foo() {} + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt new file mode 100644 index 000000000000..371a9fa58e0d --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt @@ -0,0 +1,5 @@ +class C : Container.Base() { + init { + Container.GrandBase.foo() + } +} diff --git a/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt.after b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt.after new file mode 100644 index 000000000000..70fe2d4b77b3 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt.after @@ -0,0 +1,5 @@ +class C : Container.Base() { + init { + Container.GrandBase.foo() + } +}