KTIJ-28167 [AA] Support SAM constructors in KtFirReferenceShortener

Utilize `FirSamResolver` to obtain the potential SAM constructor
from the classifier

Also, accept K2_SYNTHETIC_RESOLVED in the `resolveUnqualifiedAccess`,
since this is the kind of resolve success which corresponds to the
SAM constructor call resolution

^KTIJ-28167 Fixed
This commit is contained in:
Roman Golyshev
2024-01-04 01:13:38 +01:00
committed by Space Team
parent e561de8a22
commit df8c6c694a
9 changed files with 117 additions and 5 deletions
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.FirSamResolver
import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnmatchedTypeArgumentsError
@@ -283,15 +284,26 @@ private class FirShorteningContext(val analysisSession: KtFirAnalysisSession) {
return AvailableSymbol(classifierSymbol, ImportKind.fromScope(scope))
}
private fun FirClassLikeSymbol<*>.getSamConstructor(): FirNamedFunctionSymbol? {
val samResolver = FirSamResolver(firSession, analysisSession.getScopeSessionFor(firSession))
return samResolver.getSamConstructor(fir)?.symbol
}
/**
* Finds available constructors with a given [targetClassName] within the [scope].
* Finds constructors with a given [targetClassName] available within the [scope], including SAM constructors
* (which are not explicitly declared in the class).
*
* Do not confuse with constructors **declared** in the scope (see [FirScope.processDeclaredConstructors]).
*/
private fun findAvailableConstructors(scope: FirScope, targetClassName: Name): List<FirConstructorSymbol> {
val classifierSymbol = scope.findFirstClassifierByName(targetClassName) ?: return emptyList()
private fun findAvailableConstructors(scope: FirScope, targetClassName: Name): List<FirFunctionSymbol<*>> {
val classLikeSymbol = scope.findFirstClassifierByName(targetClassName) as? FirClassLikeSymbol
?: return emptyList()
return (classifierSymbol as? FirClassSymbol)?.declarationSymbols?.filterIsInstance<FirConstructorSymbol>().orEmpty()
val constructors = (classLikeSymbol as? FirClassSymbol)?.declarationSymbols?.filterIsInstance<FirConstructorSymbol>().orEmpty()
val samConstructor = classLikeSymbol.getSamConstructor()
return constructors + listOfNotNull(samConstructor)
}
fun findFunctionsInScopes(scopes: List<FirScope>, name: Name): List<AvailableSymbol<FirFunctionSymbol<*>>> {
@@ -983,7 +995,11 @@ private class ElementsToShortenCollector(
firResolveSession, fakeFirQualifiedAccess, name, expressionInScope
)
return candidates.filter { overloadCandidate ->
overloadCandidate.candidate.currentApplicability == CandidateApplicability.RESOLVED
when (overloadCandidate.candidate.currentApplicability) {
CandidateApplicability.RESOLVED -> true
CandidateApplicability.K2_SYNTHETIC_RESOLVED -> true // SAM constructor call
else -> false
}
}
}
@@ -466,6 +466,18 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/referenceInNestedClass.kt");
}
@Test
@TestMetadata("samInterface_constructorCall.kt")
public void testSamInterface_constructorCall() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall.kt");
}
@Test
@TestMetadata("samInterface_constructorCall_java.kt")
public void testSamInterface_constructorCall_java() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall_java.kt");
}
@Test
@TestMetadata("sameNameDifferentParams.kt")
public void testSameNameDifferentParams() throws Exception {
@@ -727,6 +739,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated ext
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedClassFromSupertypes6_java.kt");
}
@Test
@TestMetadata("nestedSamInterface_constructorCall.kt")
public void testNestedSamInterface_constructorCall() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedSamInterface_constructorCall.kt");
}
@Test
@TestMetadata("TypeWithGenericsAsExtensionReceiverType_innerType.kt")
public void testTypeWithGenericsAsExtensionReceiverType_innerType() throws Exception {
@@ -466,6 +466,18 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/referenceInNestedClass.kt");
}
@Test
@TestMetadata("samInterface_constructorCall.kt")
public void testSamInterface_constructorCall() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall.kt");
}
@Test
@TestMetadata("samInterface_constructorCall_java.kt")
public void testSamInterface_constructorCall_java() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall_java.kt");
}
@Test
@TestMetadata("sameNameDifferentParams.kt")
public void testSameNameDifferentParams() throws Exception {
@@ -727,6 +739,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenera
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedClassFromSupertypes6_java.kt");
}
@Test
@TestMetadata("nestedSamInterface_constructorCall.kt")
public void testNestedSamInterface_constructorCall() throws Exception {
runTest("analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedSamInterface_constructorCall.kt");
}
@Test
@TestMetadata("TypeWithGenericsAsExtensionReceiverType_innerType.kt")
public void testTypeWithGenericsAsExtensionReceiverType_innerType() throws Exception {
@@ -0,0 +1,13 @@
// FILE: main.kt
package test
val handler = <expr>dependency.Outer.NestedSAM {}</expr>
// FILE: dependency.kt
package dependency
class Outer {
fun interface NestedSAM {
fun method()
}
}
@@ -0,0 +1,9 @@
Before shortening: dependency.Outer.NestedSAM {}
with default settings:
[qualifier] dependency.Outer
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
with SHORTEN_AND_IMPORT:
[qualifier] dependency.Outer.NestedSAM {}
with SHORTEN_AND_STAR_IMPORT:
[qualifier] dependency.Outer.NestedSAM {}
@@ -0,0 +1,7 @@
package test
fun interface KotlinSAM {
fun method()
}
val handler = <expr>test.KotlinSAM {}</expr>
@@ -0,0 +1,10 @@
Before shortening: test.KotlinSAM {}
with default settings:
[qualifier] test.KotlinSAM {}
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] test.KotlinSAM {}
with SHORTEN_AND_IMPORT:
[qualifier] test.KotlinSAM {}
with SHORTEN_AND_STAR_IMPORT:
[qualifier] test.KotlinSAM {}
@@ -0,0 +1,11 @@
// FILE: main.kt
package test
val handler = <expr>test.JavaSAM {}</expr>
// FILE: test/JavaSAM.java
package test;
public interface JavaSAM {
void method();
}
@@ -0,0 +1,10 @@
Before shortening: test.JavaSAM {}
with default settings:
[qualifier] test.JavaSAM {}
with DO_NOT_SHORTEN:
with SHORTEN_IF_ALREADY_IMPORTED:
[qualifier] test.JavaSAM {}
with SHORTEN_AND_IMPORT:
[qualifier] test.JavaSAM {}
with SHORTEN_AND_STAR_IMPORT:
[qualifier] test.JavaSAM {}