KTIJ-26103 [Analysis API] Ignore implicit dispatch receivers in Reference Shortener
Calls to extension functions imported from objects have implicit dispatch receivers, but those receivers are not present in the code and should not be analyzed by the shortener ^KTIJ-26103 Fixed
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.fir
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationInfo
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplicationWithArgumentsInfo
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtNamedAnnotationValue
|
||||
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.expressions.arguments
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
@@ -94,3 +96,21 @@ internal fun FirAnnotation.toKtAnnotationInfo(
|
||||
isCallWithArguments = this is FirAnnotationCall && arguments.isNotEmpty(),
|
||||
index = index,
|
||||
)
|
||||
|
||||
/**
|
||||
* Implicit dispatch receiver is present when an extension function declared in object
|
||||
* is imported somewhere else and used without directly referencing the object instance
|
||||
* itself:
|
||||
*
|
||||
* ```kt
|
||||
* import Foo.bar
|
||||
*
|
||||
* object Foo { fun String.bar() {} }
|
||||
*
|
||||
* fun usage() {
|
||||
* "hello".bar() // this call has implicit 'Foo' dispatch receiver
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
internal val FirResolvedQualifier.isImplicitDispatchReceiver: Boolean
|
||||
get() = source?.kind == KtFakeSourceElementKind.ImplicitReceiver
|
||||
|
||||
+2
-2
@@ -5,11 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.fir.components
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.KtRealSourceElementKind
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtImportOptimizer
|
||||
import org.jetbrains.kotlin.analysis.api.components.KtImportOptimizerResult
|
||||
import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
|
||||
import org.jetbrains.kotlin.analysis.api.fir.isImplicitDispatchReceiver
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.FirBodyReanalyzingVisitorVoid
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.computeImportableName
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
||||
@@ -274,7 +274,7 @@ internal class KtFirImportOptimizer(
|
||||
val dispatchReceiver = dispatchReceiver
|
||||
if (
|
||||
dispatchReceiver !is FirResolvedQualifier ||
|
||||
dispatchReceiver.source?.kind != KtFakeSourceElementKind.ImplicitReceiver
|
||||
!dispatchReceiver.isImplicitDispatchReceiver
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
+3
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.analysis.api.components.ShortenCommand
|
||||
import org.jetbrains.kotlin.analysis.api.components.ShortenOption
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.analysis.api.fir.components.ElementsToShortenCollector.PartialOrderOfScope.Companion.toPartialOrder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.isImplicitDispatchReceiver
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.FirBodyReanalyzingVisitorVoid
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.computeImportableName
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
||||
@@ -427,6 +428,8 @@ private class ElementsToShortenCollector(
|
||||
}
|
||||
|
||||
private fun processTypeQualifier(resolvedQualifier: FirResolvedQualifier) {
|
||||
if (resolvedQualifier.isImplicitDispatchReceiver) return
|
||||
|
||||
val wholeClassQualifier = resolvedQualifier.classId ?: return
|
||||
val qualifierPsi = resolvedQualifier.psi ?: return
|
||||
if (!qualifierPsi.textRange.intersects(selection)) return
|
||||
|
||||
+6
@@ -232,6 +232,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/enumEntryInitUsesCompanion2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("extensionFromObject.kt")
|
||||
public void testExtensionFromObject() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/extensionFromObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleImport.kt")
|
||||
public void testMultipleImport() throws Exception {
|
||||
|
||||
+6
@@ -232,6 +232,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/enumEntryInitUsesCompanion2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("extensionFromObject.kt")
|
||||
public void testExtensionFromObject() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/extensionFromObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleImport.kt")
|
||||
public void testMultipleImport() throws Exception {
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// FILE: main.kt
|
||||
package test
|
||||
|
||||
import dependency.Bar.extFun
|
||||
|
||||
fun usage(str: String) {
|
||||
<expr>str.extFun()</expr>
|
||||
}
|
||||
|
||||
// FILE: dependency.kt
|
||||
package dependency
|
||||
|
||||
object Bar {
|
||||
fun String.extFun() {}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
Before shortening: str.extFun()
|
||||
with DO_NOT_SHORTEN:
|
||||
with SHORTEN_IF_ALREADY_IMPORTED:
|
||||
with SHORTEN_AND_IMPORT:
|
||||
with SHORTEN_AND_STAR_IMPORT:
|
||||
Reference in New Issue
Block a user