[Analysis API] Unwrap anonymous function expressions in reference shortener

Anonymous functions are additionally wrapped into an expression

^KTIJ-26629 Fixed
^KTIJ-26597 Fixed
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 65def45..a55da0c 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
@@ -87,7 +87,7 @@
         val declarationToVisit = file.findSmallestElementOfTypeContainingSelection<KtDeclaration>(selection)
             ?: file
 
-        val firDeclaration = declarationToVisit.getOrBuildFir(firResolveSession) as? FirDeclaration ?: return ShortenCommandImpl(
+        val firDeclaration = declarationToVisit.getCorrespondingFirDeclaration() ?: return ShortenCommandImpl(
             file.createSmartPointer(),
             importsToAdd = emptySet(),
             starImportsToAdd = emptySet(),
@@ -142,6 +142,18 @@
         )
     }
 
+    private fun KtElement.getCorrespondingFirDeclaration(): FirDeclaration? {
+        require(this is KtFile || this is KtDeclaration)
+
+        val firElement = getOrBuildFir(firResolveSession)
+
+        return when (firElement) {
+            is FirDeclaration -> firElement
+            is FirAnonymousFunctionExpression -> firElement.anonymousFunction
+            else -> null
+        }
+    }
+
     private fun buildSymbol(firSymbol: FirBasedSymbol<*>): KtSymbol = analysisSession.firSymbolBuilder.buildSymbol(firSymbol)
 }
 
@@ -154,10 +166,13 @@
 
 private data class AdditionalImports(val simpleImports: Set<FqName>, val starImports: Set<FqName>)
 
-private inline fun <reified T : KtElement> KtFile.findSmallestElementOfTypeContainingSelection(selection: TextRange): T? =
-    findElementAt(selection.startOffset)
-        ?.parentsOfType<T>(withSelf = true)
-        ?.firstOrNull { selection in it.textRange }
+private inline fun <reified T : KtElement> KtFile.findSmallestElementOfTypeContainingSelection(selection: TextRange): T? {
+    val parents = findElementAt(selection.startOffset)
+        ?.parentsWithSelf
+        ?.toList()
+
+    return parents?.filterIsInstance<T>()?.firstOrNull { selection in it.textRange }
+}
 
 /**
  * How a symbol is imported. The order of the enum entry represents the priority of imports. If a symbol is available from multiple kinds of
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 514a623..72ed502 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
@@ -53,6 +53,24 @@
     }
 
     @Test
+    @TestMetadata("anonymousFunction_annotation.kt")
+    public void testAnonymousFunction_annotation() throws Exception {
+        runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_annotation.kt");
+    }
+
+    @Test
+    @TestMetadata("anonymousFunction_receiverType.kt")
+    public void testAnonymousFunction_receiverType() throws Exception {
+        runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_receiverType.kt");
+    }
+
+    @Test
+    @TestMetadata("anonymousFunction_returnType.kt")
+    public void testAnonymousFunction_returnType() throws Exception {
+        runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_returnType.kt");
+    }
+
+    @Test
     @TestMetadata("callInsideScriptExpression.kts")
     public void testCallInsideScriptExpression() throws Exception {
         runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/callInsideScriptExpression.kts");
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 b413405..2f31239 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
@@ -53,6 +53,24 @@
     }
 
     @Test
+    @TestMetadata("anonymousFunction_annotation.kt")
+    public void testAnonymousFunction_annotation() throws Exception {
+        runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_annotation.kt");
+    }
+
+    @Test
+    @TestMetadata("anonymousFunction_receiverType.kt")
+    public void testAnonymousFunction_receiverType() throws Exception {
+        runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_receiverType.kt");
+    }
+
+    @Test
+    @TestMetadata("anonymousFunction_returnType.kt")
+    public void testAnonymousFunction_returnType() throws Exception {
+        runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_returnType.kt");
+    }
+
+    @Test
     @TestMetadata("callInsideScriptExpression.kts")
     public void testCallInsideScriptExpression() throws Exception {
         runTest("analysis/analysis-api/testData/components/referenceShortener/referenceShortener/callInsideScriptExpression.kts");
diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_annotation.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_annotation.kt
new file mode 100644
index 0000000..9806e18
--- /dev/null
+++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_annotation.kt
@@ -0,0 +1,9 @@
+// FILE: main.kt
+package test
+
+val anonymous = <expr>@dependency.Ann</expr> fun() {}
+
+// FILE: dependency.kt
+package dependency
+
+annotation class Ann
diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_annotation.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_annotation.txt
new file mode 100644
index 0000000..d98598f
--- /dev/null
+++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_annotation.txt
@@ -0,0 +1,7 @@
+Before shortening: @dependency.Ann
+with DO_NOT_SHORTEN:
+with SHORTEN_IF_ALREADY_IMPORTED:
+with SHORTEN_AND_IMPORT:
+[type] dependency.Ann
+with SHORTEN_AND_STAR_IMPORT:
+[type] dependency.Ann
diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_receiverType.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_receiverType.kt
new file mode 100644
index 0000000..72763b4
--- /dev/null
+++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_receiverType.kt
@@ -0,0 +1,9 @@
+// FILE: main.kt
+package test
+
+val anonymous = fun <expr>dependency.Type</expr>.() {}
+
+// FILE: dependency.kt
+package dependency
+
+class Type
diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_receiverType.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_receiverType.txt
new file mode 100644
index 0000000..27ecce3
--- /dev/null
+++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_receiverType.txt
@@ -0,0 +1,7 @@
+Before shortening: dependency.Type
+with DO_NOT_SHORTEN:
+with SHORTEN_IF_ALREADY_IMPORTED:
+with SHORTEN_AND_IMPORT:
+[type] dependency.Type
+with SHORTEN_AND_STAR_IMPORT:
+[type] dependency.Type
diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_returnType.kt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_returnType.kt
new file mode 100644
index 0000000..02a1777
--- /dev/null
+++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_returnType.kt
@@ -0,0 +1,9 @@
+// FILE: main.kt
+package test
+
+val anonymous = fun(): <expr>dependency.Type</expr> = dependency.Type()
+
+// FILE: dependency.kt
+package dependency
+
+class Type
diff --git a/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_returnType.txt b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_returnType.txt
new file mode 100644
index 0000000..27ecce3
--- /dev/null
+++ b/analysis/analysis-api/testData/components/referenceShortener/referenceShortener/anonymousFunction_returnType.txt
@@ -0,0 +1,7 @@
+Before shortening: dependency.Type
+with DO_NOT_SHORTEN:
+with SHORTEN_IF_ALREADY_IMPORTED:
+with SHORTEN_AND_IMPORT:
+[type] dependency.Type
+with SHORTEN_AND_STAR_IMPORT:
+[type] dependency.Type