diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt index 29dcdfcf67f..8c2886ca9b2 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirReferenceShortener.kt @@ -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 { - val classifierSymbol = scope.findFirstClassifierByName(targetClassName) ?: return emptyList() + private fun findAvailableConstructors(scope: FirScope, targetClassName: Name): List> { + val classLikeSymbol = scope.findFirstClassifierByName(targetClassName) as? FirClassLikeSymbol + ?: return emptyList() - return (classifierSymbol as? FirClassSymbol)?.declarationSymbols?.filterIsInstance().orEmpty() + val constructors = (classLikeSymbol as? FirClassSymbol)?.declarationSymbols?.filterIsInstance().orEmpty() + val samConstructor = classLikeSymbol.getSamConstructor() + + return constructors + listOfNotNull(samConstructor) } fun findFunctionsInScopes(scopes: List, name: Name): List>> { @@ -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 + } } } diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java index bcdd2cfcc5e..88f997a0b46 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/references/FirIdeNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java @@ -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 { diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java index 1407087169e..c3a54679167 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/references/FirStandaloneNormalAnalysisSourceModuleReferenceShortenerTestGenerated.java @@ -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 { diff --git a/analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedSamInterface_constructorCall.kt b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedSamInterface_constructorCall.kt new file mode 100644 index 00000000000..25b1a3e30ba --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedSamInterface_constructorCall.kt @@ -0,0 +1,13 @@ +// FILE: main.kt +package test + +val handler = dependency.Outer.NestedSAM {} + +// FILE: dependency.kt +package dependency + +class Outer { + fun interface NestedSAM { + fun method() + } +} diff --git a/analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedSamInterface_constructorCall.txt b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedSamInterface_constructorCall.txt new file mode 100644 index 00000000000..74040a343f6 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/nestedClasses/nestedSamInterface_constructorCall.txt @@ -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 {} diff --git a/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall.kt b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall.kt new file mode 100644 index 00000000000..5304316225c --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall.kt @@ -0,0 +1,7 @@ +package test + +fun interface KotlinSAM { + fun method() +} + +val handler = test.KotlinSAM {} diff --git a/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall.txt b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall.txt new file mode 100644 index 00000000000..bb53a4969c6 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall.txt @@ -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 {} diff --git a/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall_java.kt b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall_java.kt new file mode 100644 index 00000000000..7765ddcd399 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall_java.kt @@ -0,0 +1,11 @@ +// FILE: main.kt +package test + +val handler = test.JavaSAM {} + +// FILE: test/JavaSAM.java +package test; + +public interface JavaSAM { + void method(); +} diff --git a/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall_java.txt b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall_java.txt new file mode 100644 index 00000000000..1d638b29b27 --- /dev/null +++ b/analysis/analysis-api/testData/components/referenceShortener/shortenRange/samInterface_constructorCall_java.txt @@ -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 {}