From 9a2da67919d9413d1797d238746eda629c3fee93 Mon Sep 17 00:00:00 2001 From: Alexander Podkhalyuzin Date: Fri, 20 Sep 2019 14:07:10 -0700 Subject: [PATCH] ShortenReferences: cleanup code & add tests for property-function conflicts --- .../multifile/PropertyFunctionConflict-1.kt | 7 ++ .../multifile/PropertyFunctionConflict-2.kt | 5 ++ .../PropertyFunctionConflict.kt.after | 9 +++ .../CompletionMultifileHandlerTest.kt | 4 + .../kotlin/idea/core/ShortenReferences.kt | 76 +++++++++---------- .../PropertyFunctionConflict.dependency.kt | 6 ++ .../shortenRefs/PropertyFunctionConflict.kt | 7 ++ .../PropertyFunctionConflict.kt.after | 9 +++ .../shortenRefs/ShortenRefsTestGenerated.java | 5 ++ 9 files changed, 87 insertions(+), 41 deletions(-) create mode 100644 idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict-1.kt create mode 100644 idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict-2.kt create mode 100644 idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict.kt.after create mode 100644 idea/testData/shortenRefs/PropertyFunctionConflict.dependency.kt create mode 100644 idea/testData/shortenRefs/PropertyFunctionConflict.kt create mode 100644 idea/testData/shortenRefs/PropertyFunctionConflict.kt.after diff --git a/idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict-1.kt b/idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict-1.kt new file mode 100644 index 00000000000..261ca171968 --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict-1.kt @@ -0,0 +1,7 @@ +package a + +class Goo { + fun x() { + foo + } +} \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict-2.kt b/idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict-2.kt new file mode 100644 index 00000000000..6a81e7b96a7 --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict-2.kt @@ -0,0 +1,5 @@ +package a.b + +fun foo(i: Int) {} +internal val Foo.foo: Int get() = 123 +class Foo {} \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict.kt.after b/idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict.kt.after new file mode 100644 index 00000000000..430297a0d7e --- /dev/null +++ b/idea/idea-completion/testData/handlers/multifile/PropertyFunctionConflict.kt.after @@ -0,0 +1,9 @@ +package a + +import a.b.foo + +class Goo { + fun x() { + foo() + } +} \ 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 474dd6d8e98..cbcf9373bcd 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 @@ -69,6 +69,10 @@ class CompletionMultiFileHandlerTest : KotlinCompletionTestCase() { doTest() } + fun testPropertyFunctionConflict() { + doTest() + } + fun testExclCharInsertImport() { doTest('!') } 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 5aad8c6b786..184a684c24d 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2000-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -37,7 +37,6 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.utils.findFirstClassifierWithDeprecationStatus import org.jetbrains.kotlin.resolve.scopes.utils.findPackage import org.jetbrains.kotlin.resolve.source.getPsi -import java.util.* class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT }) { data class Options( @@ -393,40 +392,41 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT } } - override fun analyzeQualifiedElement(element: KtUserType, bindingContext: BindingContext): AnalyzeQualifiedElementResult = - mainAnalyzeQualifiedElement(element, bindingContext).let { - if (it is AnalyzeQualifiedElementResult.Skip && element.qualifier?.text == ROOT_PREFIX_FOR_IDE_RESOLUTION_MODE) - AnalyzeQualifiedElementResult.ShortenNow - else - it + override fun analyzeQualifiedElement(element: KtUserType, bindingContext: BindingContext): AnalyzeQualifiedElementResult { + fun eval(element: KtUserType, bindingContext: BindingContext): AnalyzeQualifiedElementResult { + if (element.qualifier == null) return AnalyzeQualifiedElementResult.Skip + val referenceExpression = element.referenceExpression ?: return AnalyzeQualifiedElementResult.Skip + + val target = referenceExpression.targets(bindingContext).singleOrNull() + ?: return AnalyzeQualifiedElementResult.Skip + + val scope = element.getResolutionScope(bindingContext, resolutionFacade) + val name = target.name + + val targetByName: DeclarationDescriptor? + val isDeprecated: Boolean + + if (target is ClassifierDescriptor) { + val classifierWithDeprecation = scope.findFirstClassifierWithDeprecationStatus(name, NoLookupLocation.FROM_IDE) + targetByName = classifierWithDeprecation?.descriptor + isDeprecated = classifierWithDeprecation?.isDeprecated ?: false + } else { + targetByName = scope.findPackage(name) + isDeprecated = false + } + + val canShortenNow = targetByName?.asString() == target.asString() && !isDeprecated + return if (canShortenNow) AnalyzeQualifiedElementResult.ShortenNow else AnalyzeQualifiedElementResult.ImportDescriptors( + listOfNotNull(target) + ) } - private fun mainAnalyzeQualifiedElement(element: KtUserType, bindingContext: BindingContext): AnalyzeQualifiedElementResult { - if (element.qualifier == null) return AnalyzeQualifiedElementResult.Skip - val referenceExpression = element.referenceExpression ?: return AnalyzeQualifiedElementResult.Skip + val result = eval(element, bindingContext) + if (result is AnalyzeQualifiedElementResult.Skip && + element.qualifier?.text == ROOT_PREFIX_FOR_IDE_RESOLUTION_MODE + ) return AnalyzeQualifiedElementResult.ShortenNow - val target = referenceExpression.targets(bindingContext).singleOrNull() - ?: return AnalyzeQualifiedElementResult.Skip - - val scope = element.getResolutionScope(bindingContext, resolutionFacade) - val name = target.name - - val targetByName: DeclarationDescriptor? - val isDeprecated: Boolean - - if (target is ClassifierDescriptor) { - val classifierWithDeprecation = scope.findFirstClassifierWithDeprecationStatus(name, NoLookupLocation.FROM_IDE) - targetByName = classifierWithDeprecation?.descriptor - isDeprecated = classifierWithDeprecation?.isDeprecated ?: false - } else { - targetByName = scope.findPackage(name) - isDeprecated = false - } - - val canShortenNow = targetByName?.asString() == target.asString() && !isDeprecated - return if (canShortenNow) AnalyzeQualifiedElementResult.ShortenNow else AnalyzeQualifiedElementResult.ImportDescriptors( - listOfNotNull(target) - ) + return result } override fun shortenElement(element: KtUserType, options: Options): KtElement { @@ -486,15 +486,9 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT override fun analyzeQualifiedElement( element: KtDotQualifiedExpression, bindingContext: BindingContext - ): AnalyzeQualifiedElementResult = if (element.receiverExpression.text == ROOT_PREFIX_FOR_IDE_RESOLUTION_MODE) - AnalyzeQualifiedElementResult.ShortenNow - else - mainAnalyzeQualifiedElement(element, bindingContext) - - private fun mainAnalyzeQualifiedElement( - element: KtDotQualifiedExpression, - bindingContext: BindingContext ): AnalyzeQualifiedElementResult { + if (element.receiverExpression.text == ROOT_PREFIX_FOR_IDE_RESOLUTION_MODE) return AnalyzeQualifiedElementResult.ShortenNow + if (PsiTreeUtil.getParentOfType( element, KtImportDirective::class.java, KtPackageDirective::class.java diff --git a/idea/testData/shortenRefs/PropertyFunctionConflict.dependency.kt b/idea/testData/shortenRefs/PropertyFunctionConflict.dependency.kt new file mode 100644 index 00000000000..98c79ab5818 --- /dev/null +++ b/idea/testData/shortenRefs/PropertyFunctionConflict.dependency.kt @@ -0,0 +1,6 @@ +package a.b + +fun foo(s: String) {} +fun foo(i: Int) {} +internal val Foo.foo: Int get() = 123 +class Foo {} \ No newline at end of file diff --git a/idea/testData/shortenRefs/PropertyFunctionConflict.kt b/idea/testData/shortenRefs/PropertyFunctionConflict.kt new file mode 100644 index 00000000000..ca6b8ec341e --- /dev/null +++ b/idea/testData/shortenRefs/PropertyFunctionConflict.kt @@ -0,0 +1,7 @@ +package a + +class Goo { + fun x() { + _Qfadj4tPV.a.b.foo() + } +} \ No newline at end of file diff --git a/idea/testData/shortenRefs/PropertyFunctionConflict.kt.after b/idea/testData/shortenRefs/PropertyFunctionConflict.kt.after new file mode 100644 index 00000000000..430297a0d7e --- /dev/null +++ b/idea/testData/shortenRefs/PropertyFunctionConflict.kt.after @@ -0,0 +1,9 @@ +package a + +import a.b.foo + +class Goo { + fun x() { + foo() + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java b/idea/tests/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java index 85a9b536841..87f70a61821 100644 --- a/idea/tests/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/shortenRefs/ShortenRefsTestGenerated.java @@ -124,6 +124,11 @@ public class ShortenRefsTestGenerated extends AbstractShortenRefsTest { runTest("idea/testData/shortenRefs/PackagesToUseStarImports.kt"); } + @TestMetadata("PropertyFunctionConflict.kt") + public void testPropertyFunctionConflict() throws Exception { + runTest("idea/testData/shortenRefs/PropertyFunctionConflict.kt"); + } + @TestMetadata("removeCompanionRefInCalleeExpression.kt") public void testRemoveCompanionRefInCalleeExpression() throws Exception { runTest("idea/testData/shortenRefs/removeCompanionRefInCalleeExpression.kt");