diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt index 5a1d7d67b0b..6d3159c08ca 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicLookupElementFactory.kt +++ b/idea/idea-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) } diff --git a/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent-1.java b/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent-1.java new file mode 100644 index 00000000000..5e99ae99df1 --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent-1.java @@ -0,0 +1,2 @@ +public class Base extends GrandBase { +} \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent-1.kt b/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent-1.kt new file mode 100644 index 00000000000..983f43016c5 --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent-1.kt @@ -0,0 +1,5 @@ +class Inheritor : Base() { + init { + fooBa + } +} \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent-2.java b/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent-2.java new file mode 100644 index 00000000000..6aaa195d98a --- /dev/null +++ b/idea/idea-completion/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/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent.kt.after b/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent.kt.after new file mode 100644 index 00000000000..5349a1ae558 --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/StaticMethodFromGrandParent.kt.after @@ -0,0 +1,5 @@ +class Inheritor : Base() { + init { + fooBar() + } +} \ No newline at end of file diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/CompletionMultifileHandlerTest.kt b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/CompletionMultifileHandlerTest.kt index db2d62d0ba0..4592e2898fd 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/CompletionMultifileHandlerTest.kt +++ b/idea/idea-completion/tests/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/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt index 32879bff09d..b6a58aa7263 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/ShortenReferences.kt +++ b/idea/idea-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/idea/idea-core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt index 1d1019556b8..695deabe6a0 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/descriptorUtils.kt +++ b/idea/idea-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/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt index 9954dff28ff..68f8427ddf7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/replaceWith/ReplaceWithAnnotationAnalyzer.kt +++ b/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/idea/testData/shortenRefs/java/redundantGrandParentClassQualifier.dependency.java b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifier.dependency.java new file mode 100644 index 00000000000..d49437c8953 --- /dev/null +++ b/idea/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/idea/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt new file mode 100644 index 00000000000..371a9fa58e0 --- /dev/null +++ b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt @@ -0,0 +1,5 @@ +class C : Container.Base() { + init { + Container.GrandBase.foo() + } +} diff --git a/idea/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt.after b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt.after new file mode 100644 index 00000000000..fc48439e4bc --- /dev/null +++ b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt.after @@ -0,0 +1,5 @@ +class C : Container.Base() { + init { + foo() + } +} diff --git a/idea/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.dependency.java b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.dependency.java new file mode 100644 index 00000000000..c8f642a7db0 --- /dev/null +++ b/idea/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/idea/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt new file mode 100644 index 00000000000..371a9fa58e0 --- /dev/null +++ b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt @@ -0,0 +1,5 @@ +class C : Container.Base() { + init { + Container.GrandBase.foo() + } +} diff --git a/idea/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt.after b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt.after new file mode 100644 index 00000000000..70fe2d4b77b --- /dev/null +++ b/idea/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt.after @@ -0,0 +1,5 @@ +class C : Container.Base() { + init { + Container.GrandBase.foo() + } +} diff --git a/idea/tests/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java b/idea/tests/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java index 7ce628bca25..d4d66526fab 100644 --- a/idea/tests/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java @@ -301,6 +301,16 @@ public class ShortenRefsTestGenerated extends AbstractShortenRefsTest { runTest("idea/testData/shortenRefs/java/innerClassOnDemandImport.kt"); } + @TestMetadata("redundantGrandParentClassQualifier.kt") + public void testRedundantGrandParentClassQualifier() throws Exception { + runTest("idea/testData/shortenRefs/java/redundantGrandParentClassQualifier.kt"); + } + + @TestMetadata("redundantGrandParentClassQualifierAmbiguous.kt") + public void testRedundantGrandParentClassQualifierAmbiguous() throws Exception { + runTest("idea/testData/shortenRefs/java/redundantGrandParentClassQualifierAmbiguous.kt"); + } + @TestMetadata("staticClassNoImports.kt") public void testStaticClassNoImports() throws Exception { runTest("idea/testData/shortenRefs/java/staticClassNoImports.kt");