[LL FIR] rework transformers, so transformers resolve only a specific set of declarations
The change is needed for the parallel resolution (^KT-55750), so we can resolve the declaration under a lock that is specific to this declaration. Previously, if LL FIR was resolving some FirClass, LL FIR resolved all its children too, and it had no control over what parts of the FIR tree were modified. The same applied to the designation path, sometimes the classes on the designation path might be unexpectedly (and without lock) modified. This commit introduces LLFirResolveTarget, which specifies which exact declarations should be resolved during the lazy resolution of the declaration. All elements outside the declarations specified for resolve in LLFirResolveTarget, should not be modified. The logic of lazy transformers is the following: - Go to target declaration collecting all scopes from the file and containing classes - Resolve only declarations that are specified by the LLFirResolveTarget, performing the resolve under a separate lock for each declaration ^KT-56543 ^KT-57619 Fixed
This commit is contained in:
committed by
Space Team
parent
18a8cfb090
commit
72def186a3
+42
@@ -70,6 +70,12 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFile2.kt")
|
||||
public void testAnnotationOnFile2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFileWithImport.kt")
|
||||
public void testAnnotationOnFileWithImport() throws Exception {
|
||||
@@ -388,6 +394,30 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/NotEqualsOperator.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFile.kt")
|
||||
public void testPackageFromAnnotationOnFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFileWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFileWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFileWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunction.kt")
|
||||
public void testPackageFromAnnotationOnFunction() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunctionWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFunctionWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunctionWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageReference.kt")
|
||||
public void testPackageReference() throws Exception {
|
||||
@@ -769,12 +799,24 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedFile.kt")
|
||||
public void testDanglingAnnotationsResolvedFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
|
||||
public void testDanglingAnnotationsResolvedLocal() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedPackageFile.kt")
|
||||
public void testDanglingAnnotationsResolvedPackageFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedPackageFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
|
||||
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
|
||||
|
||||
+42
@@ -70,6 +70,12 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFile2.kt")
|
||||
public void testAnnotationOnFile2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFileWithImport.kt")
|
||||
public void testAnnotationOnFileWithImport() throws Exception {
|
||||
@@ -388,6 +394,30 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/NotEqualsOperator.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFile.kt")
|
||||
public void testPackageFromAnnotationOnFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFileWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFileWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFileWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunction.kt")
|
||||
public void testPackageFromAnnotationOnFunction() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunctionWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFunctionWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunctionWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageReference.kt")
|
||||
public void testPackageReference() throws Exception {
|
||||
@@ -769,12 +799,24 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedFile.kt")
|
||||
public void testDanglingAnnotationsResolvedFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
|
||||
public void testDanglingAnnotationsResolvedLocal() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedPackageFile.kt")
|
||||
public void testDanglingAnnotationsResolvedPackageFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedPackageFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
|
||||
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
|
||||
|
||||
+42
@@ -70,6 +70,12 @@ public class FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerate
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFile2.kt")
|
||||
public void testAnnotationOnFile2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFileWithImport.kt")
|
||||
public void testAnnotationOnFileWithImport() throws Exception {
|
||||
@@ -388,6 +394,30 @@ public class FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerate
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/NotEqualsOperator.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFile.kt")
|
||||
public void testPackageFromAnnotationOnFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFileWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFileWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFileWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunction.kt")
|
||||
public void testPackageFromAnnotationOnFunction() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunctionWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFunctionWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunctionWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageReference.kt")
|
||||
public void testPackageReference() throws Exception {
|
||||
@@ -741,12 +771,24 @@ public class FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerate
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedFile.kt")
|
||||
public void testDanglingAnnotationsResolvedFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
|
||||
public void testDanglingAnnotationsResolvedLocal() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedPackageFile.kt")
|
||||
public void testDanglingAnnotationsResolvedPackageFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedPackageFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
|
||||
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
|
||||
|
||||
+42
@@ -70,6 +70,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFile2.kt")
|
||||
public void testAnnotationOnFile2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFileWithImport.kt")
|
||||
public void testAnnotationOnFileWithImport() throws Exception {
|
||||
@@ -388,6 +394,30 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/NotEqualsOperator.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFile.kt")
|
||||
public void testPackageFromAnnotationOnFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFileWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFileWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFileWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunction.kt")
|
||||
public void testPackageFromAnnotationOnFunction() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunctionWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFunctionWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunctionWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageReference.kt")
|
||||
public void testPackageReference() throws Exception {
|
||||
@@ -769,12 +799,24 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedFile.kt")
|
||||
public void testDanglingAnnotationsResolvedFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
|
||||
public void testDanglingAnnotationsResolvedLocal() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedPackageFile.kt")
|
||||
public void testDanglingAnnotationsResolvedPackageFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedPackageFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
|
||||
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
|
||||
|
||||
+42
@@ -70,6 +70,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFile2.kt")
|
||||
public void testAnnotationOnFile2() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/AnnotationOnFile2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationOnFileWithImport.kt")
|
||||
public void testAnnotationOnFileWithImport() throws Exception {
|
||||
@@ -388,6 +394,30 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/NotEqualsOperator.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFile.kt")
|
||||
public void testPackageFromAnnotationOnFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFileWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFileWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFileWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunction.kt")
|
||||
public void testPackageFromAnnotationOnFunction() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunction.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageFromAnnotationOnFunctionWithUnresolvedReference.kt")
|
||||
public void testPackageFromAnnotationOnFunctionWithUnresolvedReference() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/PackageFromAnnotationOnFunctionWithUnresolvedReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("PackageReference.kt")
|
||||
public void testPackageReference() throws Exception {
|
||||
@@ -769,12 +799,24 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedFile.kt")
|
||||
public void testDanglingAnnotationsResolvedFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
|
||||
public void testDanglingAnnotationsResolvedLocal() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedPackageFile.kt")
|
||||
public void testDanglingAnnotationsResolvedPackageFile() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedPackageFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
|
||||
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
@file:kotlin.<caret>Suppress("message")
|
||||
|
||||
package foo
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in kotlin.Suppress) constructor(vararg names: kotlin.String)
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
@file:kotlin.jv<caret>m.JvmName("Name")
|
||||
|
||||
package foo
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: package kotlin.jvm
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
@file:kotlin.jv<caret>m.JvmName23("Name")
|
||||
|
||||
package foo
|
||||
|
||||
// COMPILATION_ERRORS
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: package kotlin.jvm
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package foo
|
||||
|
||||
@kotlin.jv<caret>m.JvmName("Name")
|
||||
fun boo() {
|
||||
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: package kotlin.jvm
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package foo
|
||||
|
||||
@kotlin.jv<caret>m.JvmName2("Name")
|
||||
fun boo() {
|
||||
|
||||
}
|
||||
|
||||
// COMPILATION_ERRORS
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: package kotlin.jvm
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
// COMPILATION_ERRORS
|
||||
@kotlin.jvm.Jvm<caret>Name("")
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: (in kotlin.jvm.JvmName) constructor(name: kotlin.String)
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
// COMPILATION_ERRORS
|
||||
@kotlin.j<caret>vm.JvmName("")
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
Resolved to:
|
||||
0: package kotlin.jvm
|
||||
+3
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirLazyResolveContractChecker
|
||||
|
||||
internal class LLFirGlobalResolveComponents(val project: Project) {
|
||||
companion object {
|
||||
@@ -15,5 +16,6 @@ internal class LLFirGlobalResolveComponents(val project: Project) {
|
||||
}
|
||||
}
|
||||
|
||||
val lockProvider: LLFirLockProvider = LLFirLockProvider()
|
||||
val checker: LLFirLazyResolveContractChecker = LLFirLazyResolveContractChecker()
|
||||
val lockProvider: LLFirLockProvider = LLFirLockProvider(checker)
|
||||
}
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
@@ -34,6 +34,11 @@ internal class LLFirLazyDeclarationResolver : FirLazyDeclarationResolver() {
|
||||
val fir = symbol.fir as? FirRegularClass ?: return
|
||||
val session = fir.moduleData.session
|
||||
if (session !is LLFirResolvableModuleSession) return
|
||||
// TODO: should be implemented in the context of KT-56543
|
||||
val moduleComponents = session.moduleComponents
|
||||
moduleComponents.firModuleLazyDeclarationResolver.lazyResolveWithCallableMembers(
|
||||
target = fir,
|
||||
scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
|
||||
toPhase = toPhase,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.api
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.nullableJavaSymbolProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirLibraryOrLibrarySourceResolvableModuleSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.FirElementFinder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingClass
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getContainingFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
|
||||
@@ -45,9 +46,6 @@ open class FirDesignation(
|
||||
val path: List<FirRegularClass>,
|
||||
val target: FirElementWithResolveState,
|
||||
) {
|
||||
val firstNonFileDeclaration: FirElementWithResolveState
|
||||
get() = path.firstOrNull() ?: target
|
||||
|
||||
fun toSequence(includeTarget: Boolean): Sequence<FirElementWithResolveState> = sequence {
|
||||
yieldAll(path)
|
||||
if (includeTarget) yield(target)
|
||||
@@ -96,6 +94,12 @@ private fun collectDesignationPath(target: FirElementWithResolveState): List<Fir
|
||||
return collectDesignationPathWithContainingClass(target, containingClassId)
|
||||
}
|
||||
|
||||
is FirAnonymousInitializer -> {
|
||||
val containingClassId = target.containingClass().symbol.classId
|
||||
if (containingClassId.isLocal) return null
|
||||
return collectDesignationPathWithContainingClass(target, containingClassId)
|
||||
}
|
||||
|
||||
is FirErrorProperty -> {
|
||||
return if (target.diagnostic == ConeDestructuringDeclarationsOnTopLevel) emptyList() else null
|
||||
}
|
||||
|
||||
+36
-39
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.api
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.DeclarationCopyBuilder.withBodyFrom
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirGlobalResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionDepended
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FileTowerProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.FirTowerContextProvider
|
||||
@@ -146,7 +145,11 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
val scopeSession = firResolveSession.getScopeSessionFor(session)
|
||||
firFile.lazyResolveToPhase(FirResolvePhase.IMPORTS)
|
||||
|
||||
val importingScopes = createImportingScopes(firFile, firFile.moduleData.session, scopeSession, useCaching = false)
|
||||
return firFile.createTowerDataContext(scopeSession)
|
||||
}
|
||||
|
||||
private fun FirFile.createTowerDataContext(scopeSession: ScopeSession): FirTowerDataContext {
|
||||
val importingScopes = createImportingScopes(this, moduleData.session, scopeSession, useCaching = false)
|
||||
val fileScopeElements = importingScopes.map { it.asTowerDataElement(isLocal = false) }
|
||||
return FirTowerDataContext().addNonLocalTowerDataElements(fileScopeElements)
|
||||
}
|
||||
@@ -195,6 +198,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
replacement: RawFirReplacement,
|
||||
firFile: FirFile,
|
||||
collector: FirTowerDataContextCollector? = null,
|
||||
firResolveSession: LLFirResolvableResolveSession,
|
||||
): FirAnnotation {
|
||||
val annotationCall = buildFileFirAnnotation(
|
||||
session = firFile.moduleData.session,
|
||||
@@ -211,14 +215,16 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
?: buildErrorWithAttachment("FirFile session expected to be a resolvable session but was ${firFile.llFirSession::class.java}") {
|
||||
withEntry("firSession", firFile.llFirSession) { it.toString() }
|
||||
}
|
||||
val declarationResolver = llFirResolvableSession.moduleComponents.firModuleLazyDeclarationResolver
|
||||
|
||||
val declarationResolver = llFirResolvableSession.moduleComponents.firModuleLazyDeclarationResolver
|
||||
declarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock(
|
||||
FirDesignationWithFile(path = emptyList(), target = fileAnnotationsContainer, firFile),
|
||||
onAirCreatedDeclaration = true,
|
||||
collector
|
||||
)
|
||||
|
||||
collector?.addFileContext(firFile, firFile.createTowerDataContext(firResolveSession.getScopeSessionFor(llFirResolvableSession)))
|
||||
|
||||
return annotationCall
|
||||
}
|
||||
|
||||
@@ -240,6 +246,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
replacement = replacement,
|
||||
firFile = originalFirFile,
|
||||
collector = collector,
|
||||
firResolveSession = firResolveSession,
|
||||
)
|
||||
} else {
|
||||
error("Cannot find enclosing declaration for ${replacement.from.getElementTextInContext()}")
|
||||
@@ -247,9 +254,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
}
|
||||
|
||||
val originalDeclaration = nonLocalDeclaration.getOrBuildFirOfType<FirDeclaration>(firResolveSession)
|
||||
|
||||
val originalDesignation = originalDeclaration.collectDesignation()
|
||||
|
||||
val newDeclarationWithReplacement = RawFirNonLocalDeclarationBuilder.buildWithReplacement(
|
||||
session = originalDeclaration.moduleData.session,
|
||||
scopeProvider = originalDeclaration.moduleData.session.kotlinScopeProvider,
|
||||
@@ -259,41 +264,33 @@ object LowLevelFirApiFacadeForResolveOnAir {
|
||||
)
|
||||
|
||||
val isInBodyReplacement = isInBodyReplacement(nonLocalDeclaration, replacement)
|
||||
|
||||
val globalResolveComponents = LLFirGlobalResolveComponents.getInstance(firResolveSession.project)
|
||||
|
||||
return globalResolveComponents.lockProvider.withLock(originalFirFile) {
|
||||
val copiedFirDeclaration = if (isInBodyReplacement) {
|
||||
when (originalDeclaration) {
|
||||
is FirSimpleFunction ->
|
||||
originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirSimpleFunction)
|
||||
is FirProperty ->
|
||||
originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirProperty)
|
||||
is FirRegularClass ->
|
||||
originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirRegularClass)
|
||||
is FirScript ->
|
||||
originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirScript)
|
||||
is FirTypeAlias -> newDeclarationWithReplacement
|
||||
else -> error("Not supported type ${originalDeclaration::class.simpleName}")
|
||||
}
|
||||
} else newDeclarationWithReplacement
|
||||
|
||||
val onAirDesignation = FirDesignationWithFile(
|
||||
path = originalDesignation.path,
|
||||
target = copiedFirDeclaration,
|
||||
firFile = originalFirFile
|
||||
)
|
||||
val resolvableSession = onAirDesignation.target.llFirResolvableSession
|
||||
?: error("Expected resolvable session")
|
||||
resolvableSession.moduleComponents.firModuleLazyDeclarationResolver
|
||||
.runLazyDesignatedOnAirResolveToBodyWithoutLock(
|
||||
designation = onAirDesignation,
|
||||
onAirCreatedDeclaration = onAirCreatedDeclaration,
|
||||
towerDataContextCollector = collector,
|
||||
)
|
||||
copiedFirDeclaration
|
||||
val copiedFirDeclaration = if (isInBodyReplacement) {
|
||||
when (originalDeclaration) {
|
||||
is FirSimpleFunction -> originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirSimpleFunction)
|
||||
is FirProperty -> originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirProperty)
|
||||
is FirRegularClass -> originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirRegularClass)
|
||||
is FirScript -> originalDeclaration.withBodyFrom(newDeclarationWithReplacement as FirScript)
|
||||
is FirTypeAlias -> newDeclarationWithReplacement
|
||||
else -> error("Not supported type ${originalDeclaration::class.simpleName}")
|
||||
}
|
||||
} else {
|
||||
newDeclarationWithReplacement
|
||||
}
|
||||
|
||||
val onAirDesignation = FirDesignationWithFile(
|
||||
path = originalDesignation.path,
|
||||
target = copiedFirDeclaration,
|
||||
firFile = originalFirFile
|
||||
)
|
||||
|
||||
val resolvableSession = onAirDesignation.target.llFirResolvableSession ?: error("Expected resolvable session")
|
||||
resolvableSession.moduleComponents.firModuleLazyDeclarationResolver.runLazyDesignatedOnAirResolveToBodyWithoutLock(
|
||||
designation = onAirDesignation,
|
||||
onAirCreatedDeclaration = onAirCreatedDeclaration,
|
||||
towerDataContextCollector = collector,
|
||||
)
|
||||
|
||||
return copiedFirDeclaration
|
||||
}
|
||||
|
||||
private fun isInBodyReplacement(ktDeclaration: KtDeclaration, replacement: RawFirReplacement): Boolean {
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
|
||||
/**
|
||||
* [LLFirResolveTarget] representing a class with all callable members (functions and properties).
|
||||
*/
|
||||
class LLFirClassWithAllCallablesResolveTarget(
|
||||
override val firFile: FirFile,
|
||||
override val path: List<FirRegularClass>,
|
||||
val target: FirRegularClass,
|
||||
) : LLFirResolveTarget() {
|
||||
override fun forEachTarget(action: (FirElementWithResolveState) -> Unit) {
|
||||
action(target)
|
||||
forEachCallable(action)
|
||||
}
|
||||
|
||||
inline fun forEachCallable(action: (FirCallableDeclaration) -> Unit) {
|
||||
for (member in target.declarations) {
|
||||
if (member is FirCallableDeclaration) {
|
||||
action(member)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun toStringForTarget(): String = target.name.asString()
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
|
||||
/**
|
||||
* [LLFirResolveTarget] representing a class with all class members to be resolved (this includes callables, init blocks, and classifiers)
|
||||
*/
|
||||
class LLFirClassWithAllMembersResolveTarget(
|
||||
override val firFile: FirFile,
|
||||
override val path: List<FirRegularClass>,
|
||||
val target: FirRegularClass,
|
||||
) : LLFirResolveTarget() {
|
||||
override fun forEachTarget(action: (FirElementWithResolveState) -> Unit) {
|
||||
action(target)
|
||||
forEachMember(action)
|
||||
}
|
||||
|
||||
inline fun forEachMember(action: (FirDeclaration) -> Unit) {
|
||||
target.declarations.forEach(action)
|
||||
}
|
||||
|
||||
override fun toStringForTarget(): String = target.name.asString()
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
|
||||
class LLFirClassWithSpecificMembersResolveTarget(
|
||||
override val firFile: FirFile,
|
||||
override val path: List<FirRegularClass>,
|
||||
val target: FirRegularClass,
|
||||
val members: List<FirDeclaration>
|
||||
) : LLFirResolveTarget() {
|
||||
override fun forEachTarget(action: (FirElementWithResolveState) -> Unit) {
|
||||
action(target)
|
||||
forEachMember(action)
|
||||
}
|
||||
|
||||
fun forEachMember(action: (FirDeclaration) -> Unit) {
|
||||
members.forEach(action)
|
||||
}
|
||||
|
||||
override fun toStringForTarget(): String =
|
||||
members.joinToString(prefix = "[", postfix = "]") { it.symbol.toString() }
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
|
||||
|
||||
/**
|
||||
* Target to be lazily resolved by LL FIR lazy resolver.
|
||||
*
|
||||
* Specifies the path to the resolve targets and resolve targets themselves.
|
||||
* Those targets are going to be resolved by [org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirModuleLazyDeclarationResolver]
|
||||
*/
|
||||
sealed class LLFirResolveTarget {
|
||||
/**
|
||||
* [FirFile] where the targets are located
|
||||
*/
|
||||
abstract val firFile: FirFile
|
||||
|
||||
/**
|
||||
* The list of [FirRegularClass] which are the required to go from file to target declarations in the top-down order.
|
||||
*
|
||||
* If resolve target is [FirRegularClass] itself, it's not included into the [path]
|
||||
*/
|
||||
abstract val path: List<FirRegularClass>
|
||||
|
||||
/**
|
||||
* Executions the [action] for each target that this [LLFirResolveTarget] represents.
|
||||
*/
|
||||
abstract fun forEachTarget(action: (FirElementWithResolveState) -> Unit)
|
||||
|
||||
override fun toString(): String = buildString {
|
||||
append(this::class.simpleName)
|
||||
append("(")
|
||||
buildList {
|
||||
add(firFile.name)
|
||||
path.mapTo(this) { it.name.asString() }
|
||||
add(toStringForTarget())
|
||||
}.joinTo(this, separator = " -> ")
|
||||
append(")")
|
||||
}
|
||||
|
||||
protected abstract fun toStringForTarget(): String
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
|
||||
/**
|
||||
* [LLFirResolveTarget] representing single target to resolve. The [target] can be any of [FirElementWithResolveState]
|
||||
*/
|
||||
class LLFirSingleResolveTarget(
|
||||
override val firFile: FirFile,
|
||||
override val path: List<FirRegularClass>,
|
||||
val target: FirElementWithResolveState,
|
||||
) : LLFirResolveTarget() {
|
||||
|
||||
override fun forEachTarget(action: (FirElementWithResolveState) -> Unit) {
|
||||
action(target)
|
||||
}
|
||||
|
||||
override fun toStringForTarget(): String = when (target) {
|
||||
is FirConstructor -> "constructor"
|
||||
is FirClassLikeDeclaration -> target.symbol.name.asString()
|
||||
is FirCallableDeclaration -> target.symbol.name.asString()
|
||||
is FirAnonymousInitializer -> ("<init-block>")
|
||||
is FirFileAnnotationsContainer -> "<file annotations>"
|
||||
else -> "???"
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
|
||||
/**
|
||||
* [LLFirResolveTarget] representing all declarations in file. All of them are going to be resolved.
|
||||
*/
|
||||
class LLFirWholeFileResolveTarget(
|
||||
override val firFile: FirFile,
|
||||
) : LLFirResolveTarget() {
|
||||
override val path: List<FirRegularClass> get() = emptyList()
|
||||
|
||||
override fun forEachTarget(action: (FirElementWithResolveState) -> Unit) {
|
||||
fun goInside(target: FirElementWithResolveState) {
|
||||
action(target)
|
||||
if (target is FirRegularClass) {
|
||||
target.declarations.forEach(::goInside)
|
||||
}
|
||||
}
|
||||
forEachTopLevelDeclaration(::goInside)
|
||||
}
|
||||
|
||||
inline fun forEachTopLevelDeclaration(action: (FirElementWithResolveState) -> Unit) {
|
||||
action(firFile.annotationsContainer)
|
||||
|
||||
for (member in firFile.declarations) {
|
||||
action(member)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toStringForTarget(): String = "*"
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
|
||||
fun LLFirResolveTarget.forEachPathElementAndTarget(action: (FirElementWithResolveState) -> Unit) {
|
||||
path.forEach(action)
|
||||
forEachTarget(action)
|
||||
}
|
||||
|
||||
fun FirDesignationWithFile.asResolveTarget(): LLFirSingleResolveTarget = LLFirSingleResolveTarget(firFile, path, target)
|
||||
+52
-51
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
@@ -12,9 +12,12 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.Persisten
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContextForProvider
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.DiagnosticCollectorComponents
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.util.withSourceCodeAnalysisExceptionUnwrapping
|
||||
|
||||
internal abstract class FileStructureElementDiagnosticRetriever {
|
||||
@@ -25,6 +28,49 @@ internal abstract class FileStructureElementDiagnosticRetriever {
|
||||
): FileStructureElementDiagnosticList
|
||||
}
|
||||
|
||||
internal class ClassDiagnosticRetriever(
|
||||
private val structureElementDeclaration: FirRegularClass
|
||||
) : FileStructureElementDiagnosticRetriever() {
|
||||
override fun retrieve(
|
||||
firFile: FirFile,
|
||||
collector: FileStructureElementDiagnosticsCollector,
|
||||
moduleComponents: LLFirModuleResolveComponents,
|
||||
): FileStructureElementDiagnosticList {
|
||||
val sessionHolder = SessionHolderImpl(moduleComponents.session, moduleComponents.scopeSessionProvider.getScopeSession())
|
||||
val context = PersistenceContextCollector.collectContext(sessionHolder, firFile, structureElementDeclaration)
|
||||
return withSourceCodeAnalysisExceptionUnwrapping {
|
||||
collector.collectForStructureElement(structureElementDeclaration) { components ->
|
||||
Visitor(structureElementDeclaration, context, components)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Visitor(
|
||||
private val structureElementDeclaration: FirRegularClass,
|
||||
context: CheckerContextForProvider,
|
||||
components: DiagnosticCollectorComponents
|
||||
) : LLFirDiagnosticVisitor(context, components) {
|
||||
|
||||
override fun shouldVisitDeclaration(declaration: FirDeclaration): Boolean {
|
||||
return when {
|
||||
declaration == structureElementDeclaration -> true
|
||||
shouldDiagnosticsAlwaysBeCheckedOn(declaration) -> true
|
||||
declaration is FirDefaultPropertyAccessor -> shouldVisitDeclaration(declaration.propertySymbol.fir)
|
||||
declaration is FirValueParameter -> shouldVisitDeclaration(declaration.containingFunctionSymbol.fir)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun shouldDiagnosticsAlwaysBeCheckedOn(firElement: FirElement) = when (firElement.source?.kind) {
|
||||
KtFakeSourceElementKind.PropertyFromParameter -> true
|
||||
KtFakeSourceElementKind.ImplicitConstructor -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class SingleNonLocalDeclarationDiagnosticRetriever(
|
||||
private val structureElementDeclaration: FirDeclaration
|
||||
) : FileStructureElementDiagnosticRetriever() {
|
||||
@@ -34,66 +80,21 @@ internal class SingleNonLocalDeclarationDiagnosticRetriever(
|
||||
moduleComponents: LLFirModuleResolveComponents,
|
||||
): FileStructureElementDiagnosticList {
|
||||
val sessionHolder = SessionHolderImpl(moduleComponents.session, moduleComponents.scopeSessionProvider.getScopeSession())
|
||||
val context = moduleComponents.globalResolveComponents.lockProvider.withLock(firFile) {
|
||||
PersistenceContextCollector.collectContext(sessionHolder, firFile, structureElementDeclaration)
|
||||
}
|
||||
val context = PersistenceContextCollector.collectContext(sessionHolder, firFile, structureElementDeclaration)
|
||||
return withSourceCodeAnalysisExceptionUnwrapping {
|
||||
collector.collectForStructureElement(structureElementDeclaration) { components ->
|
||||
Visitor(structureElementDeclaration, context, components)
|
||||
Visitor(context, components)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Visitor(
|
||||
private val structureElementDeclaration: FirDeclaration,
|
||||
context: CheckerContextForProvider,
|
||||
components: DiagnosticCollectorComponents
|
||||
) : LLFirDiagnosticVisitor(context, components) {
|
||||
private var insideAlwaysVisitableDeclarations = 0
|
||||
|
||||
override fun shouldVisitDeclaration(declaration: FirDeclaration): Boolean {
|
||||
if (declaration.shouldVisitWithNestedDeclarations()) {
|
||||
insideAlwaysVisitableDeclarations++
|
||||
}
|
||||
|
||||
if (insideAlwaysVisitableDeclarations > 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
return when {
|
||||
structureElementDeclaration !is FirRegularClass -> true
|
||||
structureElementDeclaration == declaration -> true
|
||||
declaration.hasAnnotation(StandardClassIds.Annotations.Suppress, context.session) -> {
|
||||
useRegularComponents = false
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirDeclaration.shouldVisitWithNestedDeclarations(): Boolean {
|
||||
if (shouldDiagnosticsAlwaysBeCheckedOn(this)) return true
|
||||
return when (this) {
|
||||
is FirAnonymousInitializer -> true
|
||||
is FirEnumEntry -> false
|
||||
is FirValueParameter -> true
|
||||
is FirConstructor -> isPrimary
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDeclarationExit(declaration: FirDeclaration) {
|
||||
if (declaration.shouldVisitWithNestedDeclarations()) {
|
||||
insideAlwaysVisitableDeclarations--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun shouldDiagnosticsAlwaysBeCheckedOn(firElement: FirElement) = when (firElement.source?.kind) {
|
||||
KtFakeSourceElementKind.PropertyFromParameter -> true
|
||||
KtFakeSourceElementKind.ImplicitConstructor -> true
|
||||
else -> false
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContextForProvi
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.CheckerRunningDiagnosticCollectorVisitor
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.DiagnosticCollectorComponents
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
|
||||
internal open class LLFirDiagnosticVisitor(
|
||||
context: CheckerContextForProvider,
|
||||
@@ -37,5 +38,21 @@ internal open class LLFirDiagnosticVisitor(
|
||||
}
|
||||
checkCanceled()
|
||||
element.accept(components.reportCommitter, context)
|
||||
|
||||
if (element is FirRegularClass) {
|
||||
suppressReportedDiagnosticsOnClassMembers(element)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Some FirClassChecker may report diagnostics on class member headers.
|
||||
* That diagnostics should be suppressed if we have a `@Suppress` annotation on class member.
|
||||
*/
|
||||
private fun suppressReportedDiagnosticsOnClassMembers(element: FirRegularClass) {
|
||||
for (member in element.declarations) {
|
||||
withAnnotationContainer(member) {
|
||||
member.accept(components.reportCommitter, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -8,14 +8,17 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.ContextByDesignationCollector
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.containingClass
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContextForProvider
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor
|
||||
import org.jetbrains.kotlin.fir.containingClass
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||
import org.jetbrains.kotlin.fir.renderWithType
|
||||
import org.jetbrains.kotlin.fir.resolve.SessionHolder
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
|
||||
private class ContextCollectingDiagnosticCollectorVisitor private constructor(
|
||||
sessionHolder: SessionHolder,
|
||||
@@ -60,13 +63,20 @@ internal object PersistenceContextCollector {
|
||||
is FirClassLikeDeclaration -> declaration.symbol.classId.isLocal
|
||||
is FirCallableDeclaration -> declaration.symbol.callableId.isLocal
|
||||
is FirDanglingModifierList -> declaration.containingClass()?.classId?.isLocal == true
|
||||
is FirAnonymousInitializer -> declaration.containingClass().classId.isLocal
|
||||
is FirScript -> false
|
||||
else -> error("Unsupported declaration ${declaration.renderWithType()}")
|
||||
}
|
||||
|
||||
require(!isLocal) {
|
||||
"Cannot collect context for local declaration ${declaration.renderWithType()}"
|
||||
}
|
||||
|
||||
val designation = declaration.collectDesignation(firFile)
|
||||
designation.path.forEach { firClass ->
|
||||
firClass.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
|
||||
}
|
||||
|
||||
return ContextCollectingDiagnosticCollectorVisitor.collect(sessionHolder, designation)
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
@@ -116,6 +116,16 @@ internal fun PsiElement.getNonLocalContainingOrThisDeclaration(predicate: (KtDec
|
||||
when (parent) {
|
||||
is KtScript -> propose(parent)
|
||||
is KtDestructuringDeclaration -> propose(parent)
|
||||
is KtAnonymousInitializer -> {
|
||||
val container = parent.containingDeclaration
|
||||
if (container is KtClassOrObject &&
|
||||
!container.isObjectLiteral() &&
|
||||
declarationCanBeLazilyResolved(container) &&
|
||||
predicate(parent)
|
||||
) {
|
||||
propose(parent)
|
||||
}
|
||||
}
|
||||
is KtNamedDeclaration -> {
|
||||
val isKindApplicable = when (parent) {
|
||||
is KtClassOrObject -> !parent.isObjectLiteral()
|
||||
|
||||
+152
-19
@@ -5,43 +5,176 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirLazyResolveContractChecker
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.lockWithPCECheck
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.lockWithPCECheck
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
/**
|
||||
* Keyed locks provider.
|
||||
*/
|
||||
internal class LLFirLockProvider {
|
||||
|
||||
//We temporarily disable multi-locks to fix deadlocks problem
|
||||
internal class LLFirLockProvider(private val checker: LLFirLazyResolveContractChecker) {
|
||||
private val globalLock = ReentrantLock()
|
||||
|
||||
private val locksForImports = ContainerUtil.createConcurrentSoftMap<FirFile, ReentrantLock>()
|
||||
private val superTypesLock = ReentrantLock()
|
||||
private val implicitTypesLock = ReentrantLock()
|
||||
private val statusLock = ReentrantLock()
|
||||
private val compilerAnnotationsLock = ReentrantLock()
|
||||
|
||||
inline fun <R> withLock(
|
||||
inline fun <R> withGlobalLock(
|
||||
key: FirFile,
|
||||
lockingIntervalMs: Long = DEFAULT_LOCKING_INTERVAL,
|
||||
action: () -> R
|
||||
): R {
|
||||
return globalLock.lockWithPCECheck(lockingIntervalMs) {
|
||||
val session = key.llFirSession
|
||||
if (!session.isValid) {
|
||||
throw ProcessCanceledException()
|
||||
}
|
||||
): R = globalLock.lockWithPCECheck(lockingIntervalMs) {
|
||||
val session = key.llFirSession
|
||||
if (!session.isValid) {
|
||||
throw ProcessCanceledException()
|
||||
}
|
||||
|
||||
action()
|
||||
}
|
||||
|
||||
fun withGlobalPhaseLock(
|
||||
phase: FirResolvePhase,
|
||||
action: () -> Unit
|
||||
) {
|
||||
val lock = when (phase) {
|
||||
FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE -> implicitTypesLock
|
||||
FirResolvePhase.STATUS -> statusLock
|
||||
FirResolvePhase.SUPER_TYPES -> superTypesLock
|
||||
FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS -> compilerAnnotationsLock
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (lock == null) {
|
||||
action()
|
||||
} else {
|
||||
lock.lockWithPCECheck(DEFAULT_LOCKING_INTERVAL, action)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <R> withLocksForImportResolution(
|
||||
file: FirFile,
|
||||
action: () -> R
|
||||
): R {
|
||||
return locksForImports.getOrPut(file) { ReentrantLock() }.lockWithPCECheck(DEFAULT_LOCKING_INTERVAL) { action() }
|
||||
inline fun withLock(
|
||||
target: FirElementWithResolveState,
|
||||
phase: FirResolvePhase,
|
||||
action: () -> Unit
|
||||
) {
|
||||
checker.lazyResolveToPhaseInside(phase) {
|
||||
target.withCriticalSection(phase, action)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun withJumpingLock(
|
||||
target: FirElementWithResolveState,
|
||||
phase: FirResolvePhase,
|
||||
action: () -> Unit
|
||||
) {
|
||||
target.withCriticalSection(phase, action)
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks an a [FirElementWithResolveState] to resolve from `toPhase - 1` to [toPhase] and then updates the [FirElementWithResolveState.resolveState] to a [toPhase].
|
||||
*
|
||||
* If [FirElementWithResolveState] is already at least at [toPhase], does nothing.
|
||||
*
|
||||
* Otherwise:
|
||||
* - Marks [FirElementWithResolveState] as in a process of resovle
|
||||
* - performs the resolve by calling [action]
|
||||
* - updates the resolve phase to [toPhase]
|
||||
* - notifies other threads waiting on the same lock that the declaration is already resolved by this thread, so other thread can continue its execution.
|
||||
*
|
||||
*
|
||||
* Contention handling:
|
||||
* - on lock acquisition, no real lock or barrier is created. Instead, the [FirElementWithResolveState.resolveState] is updated to indicate that the declaration is being resolved now.
|
||||
* - If some other thread tries to resolve current [FirElementWithResolveState], it changes `resolveState` and puts the barrier there. Then it awaits on it until the initial thread which hold the lock finishes its job.
|
||||
* - This way, no barrier is used in a case when no contention arise.
|
||||
*/
|
||||
private inline fun FirElementWithResolveState.withCriticalSection(
|
||||
toPhase: FirResolvePhase,
|
||||
action: () -> Unit
|
||||
) {
|
||||
while (true) {
|
||||
checkCanceled()
|
||||
|
||||
@OptIn(ResolveStateAccess::class)
|
||||
val stateSnapshot = resolveState
|
||||
if (stateSnapshot.resolvePhase >= toPhase) {
|
||||
// already resolved by some other thread
|
||||
return
|
||||
}
|
||||
when (stateSnapshot) {
|
||||
is FirInProcessOfResolvingToPhaseStateWithoutBarrier -> {
|
||||
// some thread is resolving the phase, so we wait until it finishes
|
||||
trySettingBarrier(toPhase, stateSnapshot)
|
||||
continue
|
||||
}
|
||||
is FirInProcessOfResolvingToPhaseStateWithBarrier -> {
|
||||
// some thread is waiting on a barrier as the declaration is beeing resovled, so we try too
|
||||
if (!waitOnBarrier(stateSnapshot)) continue
|
||||
checkPhase(toPhase)
|
||||
return
|
||||
}
|
||||
is FirResolvedToPhaseState -> {
|
||||
if (!tryLock(toPhase, stateSnapshot)) continue
|
||||
try {
|
||||
action()
|
||||
} finally {
|
||||
unlock(toPhase)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun waitOnBarrier(
|
||||
stateSnapshot: FirInProcessOfResolvingToPhaseStateWithBarrier
|
||||
): Boolean {
|
||||
return stateSnapshot.barrier.await(DEFAULT_LOCKING_INTERVAL, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
|
||||
private fun FirElementWithResolveState.trySettingBarrier(
|
||||
toPhase: FirResolvePhase,
|
||||
stateSnapshot: FirResolveState
|
||||
) {
|
||||
val latch = CountDownLatch(1)
|
||||
val newState = FirInProcessOfResolvingToPhaseStateWithBarrier(toPhase, latch)
|
||||
resolveStateFieldUpdater.compareAndSet(this, stateSnapshot, newState)
|
||||
}
|
||||
|
||||
private fun FirElementWithResolveState.tryLock(
|
||||
toPhase: FirResolvePhase,
|
||||
stateSnapshot: FirResolveState
|
||||
): Boolean {
|
||||
val newState = FirInProcessOfResolvingToPhaseStateWithoutBarrier(toPhase)
|
||||
return resolveStateFieldUpdater.compareAndSet(this, stateSnapshot, newState)
|
||||
}
|
||||
|
||||
private fun FirElementWithResolveState.unlock(toPhase: FirResolvePhase) {
|
||||
when (val stateSnapshotAfter = resolveStateFieldUpdater.getAndSet(this, FirResolvedToPhaseState(toPhase))) {
|
||||
is FirInProcessOfResolvingToPhaseStateWithoutBarrier -> {}
|
||||
is FirInProcessOfResolvingToPhaseStateWithBarrier -> {
|
||||
stateSnapshotAfter.barrier.countDown()
|
||||
}
|
||||
is FirResolvedToPhaseState -> {
|
||||
error("phase is unexpectedly unlocked $stateSnapshotAfter")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val resolveStateFieldUpdater = AtomicReferenceFieldUpdater.newUpdater(
|
||||
FirElementWithResolveState::class.java,
|
||||
FirResolveState::class.java,
|
||||
"resolveState"
|
||||
)
|
||||
|
||||
private const val DEFAULT_LOCKING_INTERVAL = 50L
|
||||
+58
-13
@@ -1,18 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignationWithFile
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirClassWithSpecificMembersResolveTarget
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
internal object FileElementFactory {
|
||||
/**
|
||||
@@ -40,12 +39,58 @@ internal object FileElementFactory {
|
||||
moduleComponents,
|
||||
)
|
||||
|
||||
else -> NonReanalyzableDeclarationStructureElement(
|
||||
firFile,
|
||||
firDeclaration,
|
||||
ktDeclaration,
|
||||
moduleComponents,
|
||||
ktDeclaration is KtClassOrObject && ktDeclaration !is KtEnumEntry -> {
|
||||
lazyResolveClassWithGeneratedMembers(firDeclaration as FirRegularClass, moduleComponents)
|
||||
NonReanalyzableClassDeclarationStructureElement(
|
||||
firFile,
|
||||
firDeclaration,
|
||||
ktDeclaration,
|
||||
moduleComponents,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
NonReanalyzableNonClassDeclarationStructureElement(
|
||||
firFile,
|
||||
firDeclaration,
|
||||
ktDeclaration,
|
||||
moduleComponents,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun lazyResolveClassWithGeneratedMembers(firClass: FirRegularClass, moduleComponents: LLFirModuleResolveComponents) {
|
||||
val classMembersToResolve = buildList {
|
||||
for (member in firClass.declarations) {
|
||||
when {
|
||||
member is FirPrimaryConstructor && member.source?.kind == KtFakeSourceElementKind.ImplicitConstructor -> {
|
||||
add(member)
|
||||
}
|
||||
|
||||
member is FirProperty && member.source?.kind == KtFakeSourceElementKind.PropertyFromParameter -> {
|
||||
add(member)
|
||||
}
|
||||
|
||||
member is FirField && member.source?.kind == KtFakeSourceElementKind.ClassDelegationField -> {
|
||||
add(member)
|
||||
}
|
||||
|
||||
member is FirDanglingModifierList -> {
|
||||
add(member)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val firClassDesignation = firClass.collectDesignationWithFile()
|
||||
val designationWithMembers = LLFirClassWithSpecificMembersResolveTarget(
|
||||
firClassDesignation.firFile,
|
||||
firClassDesignation.path,
|
||||
firClass,
|
||||
classMembersToResolve,
|
||||
)
|
||||
|
||||
moduleComponents.firModuleLazyDeclarationResolver.lazyResolveTarget(designationWithMembers, FirResolvePhase.BODY_RESOLVE)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+64
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecific
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceByTraversingWholeTree
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
|
||||
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
@@ -22,6 +23,8 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class FileStructure private constructor(
|
||||
@@ -44,7 +47,7 @@ internal class FileStructure private constructor(
|
||||
private val structureElements = ConcurrentHashMap<KtElement, FileStructureElement>()
|
||||
|
||||
fun getStructureElementFor(element: KtElement): FileStructureElement {
|
||||
val declaration = element.getNonLocalContainingOrThisDeclaration()
|
||||
val declaration = getStructureKtElement(element)
|
||||
val container: KtElement
|
||||
if (declaration != null) {
|
||||
container = declaration
|
||||
@@ -52,11 +55,61 @@ internal class FileStructure private constructor(
|
||||
val modifierList = PsiTreeUtil.getParentOfType(element, KtModifierList::class.java, false)
|
||||
container = if (modifierList != null && modifierList.nextSibling is PsiErrorElement) {
|
||||
modifierList
|
||||
} else element.containingKtFile
|
||||
} else {
|
||||
element.containingKtFile
|
||||
}
|
||||
}
|
||||
|
||||
return getStructureElementForDeclaration(container)
|
||||
}
|
||||
|
||||
private fun getStructureKtElement(element: KtElement): KtDeclaration? {
|
||||
val container = element.getNonLocalContainingOrThisDeclaration()
|
||||
when {
|
||||
container is KtClassOrObject && container.isInsideSuperClassCall(element) -> {
|
||||
container.primaryConstructor?.let { return it }
|
||||
}
|
||||
|
||||
container is KtPrimaryConstructor && container.isInsideAnnotationOnParameter(element) -> {
|
||||
container.containingClassOrObject?.let { return it }
|
||||
}
|
||||
}
|
||||
|
||||
return container
|
||||
}
|
||||
|
||||
private fun KtClassOrObject.isInsideSuperClassCall(element: KtElement): Boolean {
|
||||
for (entry in superTypeListEntries) {
|
||||
if (entry is KtSuperTypeCallEntry && entry.isAncestor(element, strict = false)) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun KtPrimaryConstructor.isInsideAnnotationOnParameter(element: KtElement): Boolean {
|
||||
for (parameter in valueParameters) {
|
||||
for (annotation in parameter.annotationEntries) {
|
||||
val target = annotation.useSiteTarget?.getAnnotationUseSiteTarget() ?: continue
|
||||
when (target) {
|
||||
AnnotationUseSiteTarget.FIELD,
|
||||
AnnotationUseSiteTarget.PROPERTY,
|
||||
AnnotationUseSiteTarget.PROPERTY_GETTER,
|
||||
AnnotationUseSiteTarget.PROPERTY_SETTER,
|
||||
AnnotationUseSiteTarget.SETTER_PARAMETER -> {
|
||||
if (annotation.isAncestor(element)) return true
|
||||
}
|
||||
AnnotationUseSiteTarget.FILE,
|
||||
AnnotationUseSiteTarget.RECEIVER,
|
||||
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER,
|
||||
AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun getStructureElementForDeclaration(declaration: KtElement): FileStructureElement {
|
||||
@Suppress("CANNOT_CHECK_FOR_ERASED")
|
||||
val structureElement = structureElements.compute(declaration) { _, structureElement ->
|
||||
@@ -123,6 +176,7 @@ internal class FileStructure private constructor(
|
||||
firProvider,
|
||||
firFile
|
||||
)
|
||||
|
||||
firDeclaration.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
|
||||
return FileElementFactory.createFileStructureElement(
|
||||
firDeclaration = firDeclaration,
|
||||
@@ -133,8 +187,11 @@ internal class FileStructure private constructor(
|
||||
}
|
||||
|
||||
private fun createDanglingModifierListStructure(container: KtElement): FileStructureElement {
|
||||
val firDanglingModifierList = container.findSourceByTraversingWholeTree(moduleComponents.firFileBuilder, firFile) as? FirDanglingModifierList
|
||||
?: errorWithFirSpecificEntries("No dangling modifier found", psi = container)
|
||||
val firDanglingModifierList = container.findSourceByTraversingWholeTree(
|
||||
moduleComponents.firFileBuilder,
|
||||
firFile,
|
||||
) as? FirDanglingModifierList ?: errorWithFirSpecificEntries("No dangling modifier found", psi = container)
|
||||
|
||||
firDanglingModifierList.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
|
||||
return DanglingTopLevelModifierListStructureElement(firFile, firDanglingModifierList, moduleComponents, container.containingKtFile)
|
||||
}
|
||||
@@ -142,6 +199,8 @@ internal class FileStructure private constructor(
|
||||
private fun createStructureElement(container: KtElement): FileStructureElement = when {
|
||||
container is KtFile -> {
|
||||
val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile)
|
||||
firFile.lazyResolveToPhase(FirResolvePhase.IMPORTS)
|
||||
|
||||
moduleComponents.firModuleLazyDeclarationResolver.lazyResolve(
|
||||
target = firFile.annotationsContainer,
|
||||
scopeSession = moduleComponents.scopeSessionProvider.getScopeSession(),
|
||||
|
||||
+59
-25
@@ -6,19 +6,20 @@
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LowLevelFirApiFacadeForResolveOnAir
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.ClassDiagnosticRetriever
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.FileDiagnosticRetriever
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.FileStructureElementDiagnostics
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.SingleNonLocalDeclarationDiagnosticRetriever
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.RawFirNonLocalDeclarationBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.declarationCanBeLazilyResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withInvalidationOnException
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
|
||||
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
@@ -116,7 +117,7 @@ internal class ReanalyzableFunctionStructureElement(
|
||||
rootNonLocalDeclaration = newKtDeclaration,
|
||||
) as FirSimpleFunction
|
||||
|
||||
return moduleComponents.globalResolveComponents.lockProvider.withLock(firFile) {
|
||||
return moduleComponents.globalResolveComponents.lockProvider.withGlobalLock(firFile) {
|
||||
val upgradedPhase = minOf(originalFunction.resolvePhase, FirResolvePhase.DECLARATIONS)
|
||||
|
||||
withInvalidationOnException(moduleComponents.session) {
|
||||
@@ -166,7 +167,7 @@ internal class ReanalyzablePropertyStructureElement(
|
||||
rootNonLocalDeclaration = newKtDeclaration,
|
||||
) as FirProperty
|
||||
|
||||
return moduleComponents.globalResolveComponents.lockProvider.withLock(firFile) {
|
||||
return moduleComponents.globalResolveComponents.lockProvider.withGlobalLock(firFile) {
|
||||
val getterPhase = originalProperty.getter?.resolvePhase ?: originalProperty.resolvePhase
|
||||
val setterPhase = originalProperty.setter?.resolvePhase ?: originalProperty.resolvePhase
|
||||
val upgradedPhase = minOf(originalProperty.resolvePhase, getterPhase, setterPhase, FirResolvePhase.DECLARATIONS)
|
||||
@@ -197,13 +198,63 @@ internal class ReanalyzablePropertyStructureElement(
|
||||
}
|
||||
}
|
||||
|
||||
internal class NonReanalyzableDeclarationStructureElement(
|
||||
internal sealed class NonReanalyzableDeclarationStructureElement(
|
||||
firFile: FirFile,
|
||||
moduleComponents: LLFirModuleResolveComponents,
|
||||
) : FileStructureElement(firFile, moduleComponents)
|
||||
|
||||
internal class NonReanalyzableClassDeclarationStructureElement(
|
||||
firFile: FirFile,
|
||||
val fir: FirRegularClass,
|
||||
override val psi: KtClassOrObject,
|
||||
moduleComponents: LLFirModuleResolveComponents,
|
||||
) : NonReanalyzableDeclarationStructureElement(firFile, moduleComponents) {
|
||||
|
||||
override val mappings = KtToFirMapping(fir, Recorder())
|
||||
|
||||
override val diagnostics = FileStructureElementDiagnostics(
|
||||
firFile,
|
||||
ClassDiagnosticRetriever(fir),
|
||||
moduleComponents,
|
||||
)
|
||||
|
||||
private inner class Recorder : FirElementsRecorder() {
|
||||
override fun visitProperty(property: FirProperty, data: MutableMap<KtElement, FirElement>) {
|
||||
if (property.source?.kind == KtFakeSourceElementKind.PropertyFromParameter) {
|
||||
super.visitProperty(property, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: MutableMap<KtElement, FirElement>) {
|
||||
}
|
||||
|
||||
override fun visitConstructor(constructor: FirConstructor, data: MutableMap<KtElement, FirElement>) {
|
||||
if (constructor is FirPrimaryConstructor && constructor.source?.kind == KtFakeSourceElementKind.ImplicitConstructor) {
|
||||
super.visitConstructor(constructor, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: MutableMap<KtElement, FirElement>) {
|
||||
}
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: MutableMap<KtElement, FirElement>) {
|
||||
if (regularClass != fir) return
|
||||
super.visitRegularClass(regularClass, data)
|
||||
}
|
||||
|
||||
override fun visitTypeAlias(typeAlias: FirTypeAlias, data: MutableMap<KtElement, FirElement>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class NonReanalyzableNonClassDeclarationStructureElement(
|
||||
firFile: FirFile,
|
||||
val fir: FirDeclaration,
|
||||
override val psi: KtDeclaration,
|
||||
moduleComponents: LLFirModuleResolveComponents,
|
||||
) : FileStructureElement(firFile, moduleComponents) {
|
||||
override val mappings = KtToFirMapping(fir, recorder)
|
||||
) : NonReanalyzableDeclarationStructureElement(firFile, moduleComponents) {
|
||||
|
||||
override val mappings = KtToFirMapping(fir, Recorder)
|
||||
|
||||
override val diagnostics = FileStructureElementDiagnostics(
|
||||
firFile,
|
||||
@@ -211,24 +262,7 @@ internal class NonReanalyzableDeclarationStructureElement(
|
||||
moduleComponents,
|
||||
)
|
||||
|
||||
|
||||
companion object {
|
||||
private val recorder = object : FirElementsRecorder() {
|
||||
override fun visitProperty(property: FirProperty, data: MutableMap<KtElement, FirElement>) {
|
||||
val psi = property.psi as? KtProperty ?: return super.visitProperty(property, data)
|
||||
if (!isReanalyzableContainer(psi) || !declarationCanBeLazilyResolved(psi)) {
|
||||
super.visitProperty(property, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: MutableMap<KtElement, FirElement>) {
|
||||
val psi = simpleFunction.psi as? KtNamedFunction ?: return super.visitSimpleFunction(simpleFunction, data)
|
||||
if (!isReanalyzableContainer(psi) || !declarationCanBeLazilyResolved(psi)) {
|
||||
super.visitSimpleFunction(simpleFunction, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private object Recorder : FirElementsRecorder()
|
||||
}
|
||||
|
||||
internal class DanglingTopLevelModifierListStructureElement(
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
|
||||
internal class LLFirLazyResolveContractChecker {
|
||||
private val currentTransformerPhase = ThreadLocal.withInitial<FirResolvePhase?> { null }
|
||||
|
||||
inline fun lazyResolveToPhaseInside(phase: FirResolvePhase, resolve: () -> Unit) {
|
||||
if (currentTransformerPhase.get() == FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) return
|
||||
checkIfCanLazyResolveToPhase(phase)
|
||||
val previousPhase = currentTransformerPhase.get()
|
||||
currentTransformerPhase.set(phase)
|
||||
try {
|
||||
resolve()
|
||||
} finally {
|
||||
currentTransformerPhase.set(previousPhase)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkIfCanLazyResolveToPhase(requestedPhase: FirResolvePhase) {
|
||||
val currentPhase = currentTransformerPhase.get() ?: return
|
||||
|
||||
if (requestedPhase >= currentPhase) {
|
||||
error(
|
||||
"""`lazyResolveToPhase($requestedPhase)` cannot be called from a transformer with a phase $currentPhase.
|
||||
`lazyResolveToPhase` can be called only from a transformer with a phase which is strictly greater than a requested phase;
|
||||
i.e., `lazyResolveToPhase(A)` may be only called from a lazy transformer with a phase B, where A < B. This is a contract of lazy resolve""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+149
-124
@@ -7,11 +7,13 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.tryCollectDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirClassWithAllMembersResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirSingleResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.forEachPathElementAndTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirModuleData
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformerExecutor
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyResolverRunner
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.withOnAirDesignation
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getContainingFile
|
||||
@@ -19,73 +21,24 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.rethrowExceptionWithDetails
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.resolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
|
||||
internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirModuleResolveComponents) {
|
||||
|
||||
private fun FirDeclaration.isValidForResolve(): Boolean = when (origin) {
|
||||
is FirDeclarationOrigin.Source,
|
||||
is FirDeclarationOrigin.ImportedFromObjectOrStatic,
|
||||
is FirDeclarationOrigin.Delegated,
|
||||
is FirDeclarationOrigin.Synthetic,
|
||||
is FirDeclarationOrigin.SubstitutionOverride,
|
||||
is FirDeclarationOrigin.SamConstructor,
|
||||
is FirDeclarationOrigin.IntersectionOverride -> {
|
||||
when (this) {
|
||||
is FirFile -> true
|
||||
is FirSyntheticProperty -> false
|
||||
is FirSyntheticPropertyAccessor -> false
|
||||
is FirSimpleFunction,
|
||||
is FirProperty,
|
||||
is FirPropertyAccessor,
|
||||
is FirField,
|
||||
is FirTypeAlias,
|
||||
is FirConstructor -> resolvePhase < FirResolvePhase.BODY_RESOLVE
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
check(resolvePhase == FirResolvePhase.BODY_RESOLVE) {
|
||||
"Expected body resolve phase for origin $origin but found $resolvePhase"
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirElementWithResolveState.isValidForResolve() = when (this) {
|
||||
is FirDeclaration -> isValidForResolve()
|
||||
is FirFileAnnotationsContainer -> true
|
||||
else -> throwUnexpectedFirElementError(this)
|
||||
}
|
||||
|
||||
private fun resolveContainingFileToImports(target: FirElementWithResolveState) {
|
||||
if (target.resolvePhase >= FirResolvePhase.IMPORTS) return
|
||||
val firFile = target.getContainingFile() ?: return
|
||||
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return
|
||||
moduleComponents.globalResolveComponents.lockProvider.withLocksForImportResolution(firFile) {
|
||||
resolveFileToImportsWithoutLock(firFile)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveFileToImportsWithoutLock(firFile: FirFile) {
|
||||
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return
|
||||
checkCanceled()
|
||||
firFile.transform<FirElement, Any?>(FirImportResolveTransformer(firFile.moduleData.session), null)
|
||||
@OptIn(ResolveStateAccess::class)
|
||||
firFile.resolveState = FirResolvePhase.IMPORTS.asResolveState()
|
||||
}
|
||||
|
||||
/**
|
||||
* Run designated resolve only designation with fully resolved path (synchronized).
|
||||
* Lazily resolves the [target] to a given [toPhase].
|
||||
*
|
||||
* Might resolve additional required declarations.
|
||||
*
|
||||
* Resolution is performed under the lock specific to each declaration which is going to be resolved.
|
||||
*
|
||||
* Suitable for body resolve or/and on-air resolve.
|
||||
* @see lazyResolve for ordinary resolve
|
||||
* @param target target non-local declaration
|
||||
*/
|
||||
fun lazyResolve(
|
||||
target: FirElementWithResolveState,
|
||||
@@ -93,77 +46,68 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
|
||||
toPhase: FirResolvePhase,
|
||||
) {
|
||||
val fromPhase = target.resolvePhase
|
||||
if (fromPhase >= toPhase) return
|
||||
try {
|
||||
doLazyResolve(target, scopeSession, toPhase)
|
||||
resolveContainingFileToImports(target)
|
||||
if (toPhase == FirResolvePhase.IMPORTS) return
|
||||
|
||||
lazyResolveTargets(
|
||||
targets = LLFirResolveMultiDesignationCollector.getDesignationsToResolve(target),
|
||||
scopeSession = scopeSession,
|
||||
toPhase = toPhase,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
handleExceptionFromResolve(e, target, fromPhase, toPhase)
|
||||
}
|
||||
}
|
||||
|
||||
private fun doLazyResolve(
|
||||
target: FirElementWithResolveState,
|
||||
/**
|
||||
* Lazily resolves the [target] with all callable members to a given [toPhase].
|
||||
*
|
||||
* Might resolve additional required declarations.
|
||||
*
|
||||
* Resolution is performed under the lock specific to each declaration which is going to be resolved.
|
||||
*
|
||||
* Suitable for body resolve or/and on-air resolve.
|
||||
*/
|
||||
fun lazyResolveWithCallableMembers(
|
||||
target: FirRegularClass,
|
||||
scopeSession: ScopeSession,
|
||||
toPhase: FirResolvePhase,
|
||||
) {
|
||||
if (target.resolvePhase >= toPhase) return
|
||||
resolveContainingFileToImports(target)
|
||||
if (toPhase == FirResolvePhase.IMPORTS) return
|
||||
val fromPhase = target.resolvePhase
|
||||
try {
|
||||
resolveContainingFileToImports(target)
|
||||
if (toPhase == FirResolvePhase.IMPORTS) return
|
||||
|
||||
for (designation in declarationDesignationsToResolve(target)) {
|
||||
if (!designation.target.isValidForResolve()) continue
|
||||
if (designation.target.resolvePhase >= toPhase) continue
|
||||
moduleComponents.globalResolveComponents.lockProvider.withLock(designation.firFile) {
|
||||
runLazyDesignatedResolveWithoutLock(
|
||||
designation = designation,
|
||||
scopeSession = scopeSession,
|
||||
toPhase = toPhase,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun declarationDesignationsToResolve(target: FirElementWithResolveState): List<FirDesignationWithFile> {
|
||||
return when (target) {
|
||||
is FirPropertyAccessor -> declarationDesignationsToResolve(target.propertySymbol.fir)
|
||||
is FirBackingField -> declarationDesignationsToResolve(target.propertySymbol.fir)
|
||||
is FirTypeParameter -> declarationDesignationsToResolve(target.containingDeclarationSymbol.fir)
|
||||
is FirValueParameter -> declarationDesignationsToResolve(target.containingFunctionSymbol.fir)
|
||||
is FirFile -> {
|
||||
val validForResolveDeclarations = buildList {
|
||||
add(target.annotationsContainer)
|
||||
target.declarations.filterTo(this) { it.isValidForResolve() }
|
||||
}
|
||||
|
||||
validForResolveDeclarations.map {
|
||||
FirDesignationWithFile(path = emptyList(), target = it, firFile = target)
|
||||
}
|
||||
}
|
||||
else -> listOfNotNull(target.tryCollectDesignationWithFile())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun runLazyDesignatedResolveWithoutLock(
|
||||
designation: FirDesignationWithFile,
|
||||
scopeSession: ScopeSession,
|
||||
toPhase: FirResolvePhase,
|
||||
) {
|
||||
val declarationResolvePhase = designation.target.resolvePhase
|
||||
if (declarationResolvePhase >= toPhase) return
|
||||
|
||||
var currentPhase = maxOf(declarationResolvePhase, FirResolvePhase.IMPORTS)
|
||||
|
||||
while (currentPhase < toPhase) {
|
||||
currentPhase = currentPhase.next
|
||||
checkCanceled()
|
||||
|
||||
LLFirLazyTransformerExecutor.execute(
|
||||
phase = currentPhase,
|
||||
designation = designation,
|
||||
lazyResolveTargets(
|
||||
targets = LLFirResolveMultiDesignationCollector.getDesignationsToResolveWithCallableMembers(target),
|
||||
scopeSession = scopeSession,
|
||||
lockProvider = moduleComponents.globalResolveComponents.lockProvider,
|
||||
towerDataContextCollector = null
|
||||
toPhase = toPhase,
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
handleExceptionFromResolve(e, target, fromPhase, toPhase)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lazily resolves all the declarations which are specified for resolve by [target]
|
||||
*
|
||||
* Might resolve additional required declarations.
|
||||
*
|
||||
* Resolution is performed under the lock specific to each declaration which is going to be resolved.
|
||||
*
|
||||
* Suitable for body resolve or/and on-air resolve.
|
||||
*/
|
||||
fun lazyResolveTarget(
|
||||
target: LLFirResolveTarget,
|
||||
toPhase: FirResolvePhase
|
||||
) {
|
||||
try {
|
||||
lazyResolveTargets(listOf(target), moduleComponents.scopeSessionProvider.getScopeSession(), toPhase)
|
||||
} catch (e: Exception) {
|
||||
handleExceptionFromResolve(e, target, toPhase)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +117,10 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
resolveFileToImportsWithoutLock(designation.firFile)
|
||||
val resolveTarget = when (designation.target) {
|
||||
is FirRegularClass -> LLFirClassWithAllMembersResolveTarget(designation.firFile, designation.path, designation.target)
|
||||
else -> LLFirSingleResolveTarget(designation.firFile, designation.path, designation.target)
|
||||
}
|
||||
|
||||
fun runTransformation() {
|
||||
val scopeSession = ScopeSession()
|
||||
@@ -182,9 +130,9 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
|
||||
currentPhase = currentPhase.next
|
||||
checkCanceled()
|
||||
|
||||
LLFirLazyTransformerExecutor.execute(
|
||||
LLFirLazyResolverRunner.runLazyResolverByPhase(
|
||||
phase = currentPhase,
|
||||
designation = designation,
|
||||
target = resolveTarget,
|
||||
scopeSession = scopeSession,
|
||||
lockProvider = moduleComponents.globalResolveComponents.lockProvider,
|
||||
towerDataContextCollector = towerDataContextCollector,
|
||||
@@ -198,6 +146,58 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
|
||||
runTransformation()
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveContainingFileToImports(target: FirElementWithResolveState) {
|
||||
if (target.resolvePhase >= FirResolvePhase.IMPORTS) return
|
||||
val firFile = target.getContainingFile() ?: return
|
||||
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return
|
||||
moduleComponents.globalResolveComponents.lockProvider.withLock(firFile, FirResolvePhase.IMPORTS) {
|
||||
resolveFileToImportsWithoutLock(firFile)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveFileToImportsWithoutLock(firFile: FirFile) {
|
||||
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return
|
||||
checkCanceled()
|
||||
firFile.transform<FirElement, Any?>(FirImportResolveTransformer(firFile.moduleData.session), null)
|
||||
}
|
||||
|
||||
private fun lazyResolveTargets(
|
||||
targets: List<LLFirResolveTarget>,
|
||||
scopeSession: ScopeSession,
|
||||
toPhase: FirResolvePhase,
|
||||
) {
|
||||
if (targets.isEmpty()) return
|
||||
var currentPhase = getMinResolvePhase(targets).coerceAtLeast(FirResolvePhase.IMPORTS)
|
||||
if (currentPhase >= toPhase) return
|
||||
|
||||
while (currentPhase < toPhase) {
|
||||
currentPhase = currentPhase.next
|
||||
checkCanceled()
|
||||
|
||||
for (target in targets) {
|
||||
LLFirLazyResolverRunner.runLazyResolverByPhase(
|
||||
phase = currentPhase,
|
||||
target = target,
|
||||
scopeSession = scopeSession,
|
||||
lockProvider = moduleComponents.globalResolveComponents.lockProvider,
|
||||
towerDataContextCollector = null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMinResolvePhase(designations: List<LLFirResolveTarget>): FirResolvePhase {
|
||||
var min = FirResolvePhase.BODY_RESOLVE
|
||||
for (designation in designations) {
|
||||
if (min == FirResolvePhase.RAW_FIR) break
|
||||
designation.forEachPathElementAndTarget { target ->
|
||||
min = minOf(min, target.resolvePhase)
|
||||
}
|
||||
}
|
||||
|
||||
return min
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleExceptionFromResolve(
|
||||
@@ -226,4 +226,29 @@ private fun handleExceptionFromResolve(
|
||||
withEntry("moduleData", firDeclarationToResolve.moduleData) { it.toString() }
|
||||
withFirEntry("firDeclarationToResolve", firDeclarationToResolve)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleExceptionFromResolve(
|
||||
exception: Exception,
|
||||
designation: LLFirResolveTarget,
|
||||
toPhase: FirResolvePhase?
|
||||
): Nothing {
|
||||
val llFirSession = designation.firFile.llFirSession
|
||||
llFirSession.invalidate()
|
||||
val moduleData = llFirSession.llFirModuleData
|
||||
rethrowExceptionWithDetails(
|
||||
buildString {
|
||||
appendLine("Error while resolving ${designation::class.java.name} ")
|
||||
appendLine("to $toPhase")
|
||||
appendLine("module data: ${moduleData::class}")
|
||||
appendLine("KtModule: ${moduleData.ktModule::class}")
|
||||
appendLine("platform: ${moduleData.ktModule.platform}")
|
||||
},
|
||||
exception = exception,
|
||||
) {
|
||||
withEntry("KtModule", moduleData.ktModule) { it.moduleDescription }
|
||||
withEntry("session", designation.firFile.llFirSession) { it.toString() }
|
||||
withEntry("moduleData", moduleData) { it.toString() }
|
||||
withEntry("firDesignationToResolve", designation) { it.toString() }
|
||||
}
|
||||
}
|
||||
+19
-12
@@ -17,10 +17,18 @@ internal object LLFirPhaseUpdater {
|
||||
newPhase: FirResolvePhase,
|
||||
updateForLocalDeclarations: Boolean,
|
||||
) {
|
||||
if (updateForLocalDeclarations) {
|
||||
target.acceptChildren(PhaseUpdatingTransformer, newPhase)
|
||||
} else {
|
||||
updatePhaseForNonLocals(target, newPhase, isTargetDeclaration = true)
|
||||
updatePhaseForNonLocals(target, newPhase, isTargetDeclaration = true)
|
||||
|
||||
if (updateForLocalDeclarations && target is FirCallableDeclaration) {
|
||||
when (target) {
|
||||
is FirFunction -> target.body?.accept(PhaseUpdatingTransformer, newPhase)
|
||||
is FirVariable -> {
|
||||
target.initializer?.accept(PhaseUpdatingTransformer, newPhase)
|
||||
target.getter?.body?.accept(PhaseUpdatingTransformer, newPhase)
|
||||
target.setter?.body?.accept(PhaseUpdatingTransformer, newPhase)
|
||||
target.backingField?.accept(PhaseUpdatingTransformer, newPhase)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +37,8 @@ internal object LLFirPhaseUpdater {
|
||||
if (element.resolvePhase >= newPhase) return
|
||||
if (!isTargetDeclaration) {
|
||||
// phase update for target declaration happens as a declaration publication event after resolve is finished
|
||||
element.replaceResolveState(newPhase.asResolveState())
|
||||
@OptIn(ResolveStateAccess::class)
|
||||
element.resolveState = newPhase.asResolveState()
|
||||
}
|
||||
|
||||
if (element is FirTypeParameterRefsOwner) {
|
||||
@@ -48,13 +57,9 @@ internal object LLFirPhaseUpdater {
|
||||
is FirProperty -> {
|
||||
element.getter?.let { updatePhaseForNonLocals(it, newPhase, isTargetDeclaration = false) }
|
||||
element.setter?.let { updatePhaseForNonLocals(it, newPhase, isTargetDeclaration = false) }
|
||||
element.backingField?.let { updatePhaseForNonLocals(it, newPhase, isTargetDeclaration = false) }
|
||||
}
|
||||
is FirClass -> {
|
||||
element.declarations.forEach {
|
||||
updatePhaseForNonLocals(it, newPhase, isTargetDeclaration = false)
|
||||
}
|
||||
}
|
||||
else -> Unit
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +68,9 @@ private object PhaseUpdatingTransformer : FirVisitor<Unit, FirResolvePhase>() {
|
||||
override fun visitElement(element: FirElement, data: FirResolvePhase) {
|
||||
if (element is FirElementWithResolveState) {
|
||||
if (element.resolvePhase >= data && element !is FirDefaultPropertyAccessor) return
|
||||
element.replaceResolveState(data.asResolveState())
|
||||
|
||||
@OptIn(ResolveStateAccess::class)
|
||||
element.resolveState = data.asResolveState()
|
||||
}
|
||||
|
||||
element.acceptChildren(this, data)
|
||||
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirClassWithAllCallablesResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirWholeFileResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.asResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.tryCollectDesignationWithFile
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
||||
|
||||
internal object LLFirResolveMultiDesignationCollector {
|
||||
fun getDesignationsToResolve(target: FirElementWithResolveState): List<LLFirResolveTarget> {
|
||||
return when (target) {
|
||||
is FirFile -> listOf(LLFirWholeFileResolveTarget(target))
|
||||
else -> getMainDesignationToResolve(target)?.withAnnotationContainer()
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
fun getDesignationsToResolveWithCallableMembers(target: FirRegularClass): List<LLFirResolveTarget> {
|
||||
val designation = target.tryCollectDesignationWithFile() ?: return emptyList()
|
||||
val resolveTarget = LLFirClassWithAllCallablesResolveTarget(designation.firFile, designation.path, target)
|
||||
return resolveTarget.withAnnotationContainer()
|
||||
}
|
||||
|
||||
private fun LLFirResolveTarget.withAnnotationContainer(): List<LLFirResolveTarget> {
|
||||
val annotationsContainer = firFile.annotationsContainer
|
||||
if (!annotationsContainer.shouldBeResolved()) return listOf(this)
|
||||
return buildList {
|
||||
add(annotationsContainer.collectDesignationWithFile().asResolveTarget())
|
||||
add(this@withAnnotationContainer)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMainDesignationToResolve(target: FirElementWithResolveState): LLFirResolveTarget? {
|
||||
require(target !is FirFile)
|
||||
if (!target.shouldBeResolved()) return null
|
||||
return when (target) {
|
||||
is FirPropertyAccessor -> getMainDesignationToResolve(target.propertySymbol.fir)
|
||||
is FirBackingField -> getMainDesignationToResolve(target.propertySymbol.fir)
|
||||
is FirTypeParameter -> getMainDesignationToResolve(target.containingDeclarationSymbol.fir)
|
||||
is FirValueParameter -> getMainDesignationToResolve(target.containingFunctionSymbol.fir)
|
||||
else -> target.tryCollectDesignationWithFile()?.asResolveTarget()
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirElementWithResolveState.shouldBeResolved() = when (this) {
|
||||
is FirDeclaration -> shouldBeResolved()
|
||||
is FirFileAnnotationsContainer -> annotations.isNotEmpty()
|
||||
else -> throwUnexpectedFirElementError(this)
|
||||
}
|
||||
|
||||
private fun FirDeclaration.shouldBeResolved(): Boolean = when (origin) {
|
||||
is FirDeclarationOrigin.Source,
|
||||
is FirDeclarationOrigin.ImportedFromObjectOrStatic,
|
||||
is FirDeclarationOrigin.Delegated,
|
||||
is FirDeclarationOrigin.Synthetic,
|
||||
is FirDeclarationOrigin.SubstitutionOverride,
|
||||
is FirDeclarationOrigin.SamConstructor,
|
||||
is FirDeclarationOrigin.IntersectionOverride -> {
|
||||
when (this) {
|
||||
is FirFile -> true
|
||||
is FirSyntheticProperty -> false
|
||||
is FirSyntheticPropertyAccessor -> false
|
||||
is FirSimpleFunction,
|
||||
is FirProperty,
|
||||
is FirPropertyAccessor,
|
||||
is FirField,
|
||||
is FirTypeAlias,
|
||||
is FirConstructor -> true
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
@OptIn(ResolveStateAccess::class)
|
||||
check(resolvePhase == FirResolvePhase.BODY_RESOLVE) {
|
||||
"Expected body resolve phase for origin $origin but found $resolveState"
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
@@ -49,20 +49,18 @@ internal fun FirDeclaration.getKtDeclarationForFirElement(): KtDeclaration {
|
||||
return declaration
|
||||
}
|
||||
|
||||
internal fun declarationCanBeLazilyResolved(declaration: KtDeclaration): Boolean {
|
||||
return when (declaration) {
|
||||
!is KtNamedDeclaration -> false
|
||||
is KtDestructuringDeclarationEntry, is KtFunctionLiteral, is KtTypeParameter -> false
|
||||
is KtPrimaryConstructor -> false
|
||||
is KtParameter -> declaration.hasValOrVar() && declaration.containingClassOrObject?.getClassId() != null
|
||||
is KtCallableDeclaration, is KtEnumEntry -> {
|
||||
when (val parent = declaration.parent) {
|
||||
is KtFile -> true
|
||||
is KtClassBody -> (parent.parent as? KtClassOrObject)?.getClassId() != null
|
||||
else -> false
|
||||
}
|
||||
internal fun declarationCanBeLazilyResolved(declaration: KtDeclaration): Boolean = when (declaration) {
|
||||
is KtDestructuringDeclarationEntry, is KtFunctionLiteral, is KtTypeParameter -> false
|
||||
is KtPrimaryConstructor -> (declaration.parent as? KtClassOrObject)?.getClassId() != null
|
||||
is KtParameter -> declaration.hasValOrVar() && declaration.containingClassOrObject?.getClassId() != null
|
||||
is KtCallableDeclaration, is KtEnumEntry, is KtClassInitializer -> {
|
||||
when (val parent = declaration.parent) {
|
||||
is KtFile -> true
|
||||
is KtClassBody -> (parent.parent as? KtClassOrObject)?.getClassId() != null
|
||||
else -> false
|
||||
}
|
||||
is KtClassLikeDeclaration -> declaration.getClassId() != null
|
||||
else -> error("Unexpected ${declaration::class.qualifiedName}")
|
||||
}
|
||||
!is KtNamedDeclaration -> false
|
||||
is KtClassLikeDeclaration -> declaration.getClassId() != null
|
||||
else -> error("Unexpected ${declaration::class.qualifiedName}")
|
||||
}
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.LLFirDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
|
||||
|
||||
internal abstract class LLFirAbstractBodyTargetResolver(
|
||||
resolveTarget: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
private val scopeSession: ScopeSession,
|
||||
resolvePhase: FirResolvePhase,
|
||||
protected val implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession = ImplicitBodyResolveComputationSession()
|
||||
) : LLFirTargetResolver(resolveTarget, lockProvider, resolvePhase) {
|
||||
|
||||
protected fun createReturnTypeCalculator(): ReturnTypeCalculator = createReturnTypeCalculatorForIDE(
|
||||
scopeSession,
|
||||
implicitBodyResolveComputationSession,
|
||||
::LLFirDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
|
||||
)
|
||||
|
||||
abstract val transformer: FirAbstractBodyResolveTransformerDispatcher
|
||||
|
||||
override fun checkResolveConsistency() {
|
||||
check(resolverPhase == transformer.transformerPhase) {
|
||||
"Inconsistent Resolver($resolverPhase) and Transformer(${transformer.transformerPhase}) phases"
|
||||
}
|
||||
}
|
||||
|
||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||
transformer.context.withFile(firFile, transformer.components) {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||
override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) {
|
||||
transformer.declarationsTransformer.context.withContainingClass(firClass) {
|
||||
transformer.declarationsTransformer.withRegularClass(firClass) {
|
||||
action()
|
||||
firClass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun calculateLazyBodies(declaration: FirElementWithResolveState) {
|
||||
val firDesignation = FirDesignationWithFile(nestedClassesStack, declaration, resolveTarget.firFile)
|
||||
FirLazyBodiesCalculator.calculateLazyBodiesInside(firDesignation)
|
||||
}
|
||||
}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkAnnotationArgumentsMappingIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirAnnotationArgumentsMappingTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
internal object LLFirAnnotationArgumentMappingLazyResolver : LLFirLazyResolver(FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirAnnotationArgumentsMappingTargetResolver(target, lockProvider, session, scopeSession)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
if (target !is FirAnnotationContainer) return
|
||||
for (annotation in target.annotations) {
|
||||
if (annotation is FirAnnotationCall) {
|
||||
checkAnnotationArgumentsMappingIsResolved(annotation, target)
|
||||
}
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirAnnotationArgumentsMappingTargetResolver(
|
||||
resolveTarget: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirAbstractBodyTargetResolver(
|
||||
resolveTarget,
|
||||
lockProvider,
|
||||
scopeSession,
|
||||
FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING,
|
||||
) {
|
||||
override val transformer = FirAnnotationArgumentsMappingTransformer(
|
||||
session,
|
||||
scopeSession,
|
||||
resolverPhase,
|
||||
returnTypeCalculator = createReturnTypeCalculator()
|
||||
)
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
FirLazyBodiesCalculator.calculateAnnotations(target)
|
||||
when (target) {
|
||||
is FirRegularClass -> {
|
||||
target.transformAnnotations(transformer.declarationsTransformer, ResolutionMode.ContextIndependent)
|
||||
target.transformTypeParameters(transformer.declarationsTransformer, ResolutionMode.ContextIndependent)
|
||||
target.transformSuperTypeRefs(transformer.declarationsTransformer, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
is FirCallableDeclaration, is FirAnonymousInitializer, is FirDanglingModifierList, is FirFileAnnotationsContainer, is FirTypeAlias, is FirScript -> {
|
||||
target.transformSingle(transformer, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
else -> throwUnexpectedFirElementError(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirAnnotationArgumentsResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
internal object LLFirAnnotationArgumentsLazyResolver : LLFirLazyResolver(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirAnnotationArgumentsTargetResolver(target, lockProvider, session, scopeSession)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
if (target !is FirAnnotationContainer) return
|
||||
val unresolvedAnnotation = target.annotations.firstOrNull { it.annotationTypeRef !is FirResolvedTypeRef }
|
||||
check(unresolvedAnnotation == null) {
|
||||
"Unexpected annotationTypeRef annotation, expected resolvedType but actual ${unresolvedAnnotation?.annotationTypeRef}"
|
||||
}
|
||||
|
||||
target.checkPhase(resolverPhase)
|
||||
|
||||
for (annotation in target.annotations) {
|
||||
for (argument in annotation.argumentMapping.mapping.values) {
|
||||
checkTypeRefIsResolved(argument.typeRef, "annotation argument", target) {
|
||||
withFirEntry("firAnnotation", annotation)
|
||||
withFirEntry("firArgument", argument)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirAnnotationArgumentsTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirAbstractBodyTargetResolver(
|
||||
target,
|
||||
lockProvider,
|
||||
scopeSession,
|
||||
FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS,
|
||||
) {
|
||||
override val transformer = FirAnnotationArgumentsResolveTransformer(
|
||||
session,
|
||||
scopeSession,
|
||||
resolverPhase,
|
||||
returnTypeCalculator = createReturnTypeCalculator()
|
||||
)
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
FirLazyBodiesCalculator.calculateAnnotations(target)
|
||||
when (target) {
|
||||
is FirRegularClass -> {
|
||||
target.transformAnnotations(transformer.declarationsTransformer, ResolutionMode.ContextIndependent)
|
||||
target.transformTypeParameters(transformer.declarationsTransformer, ResolutionMode.ContextIndependent)
|
||||
target.transformSuperTypeRefs(transformer.declarationsTransformer, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
is FirCallableDeclaration, is FirAnonymousInitializer, is FirDanglingModifierList, is FirFileAnnotationsContainer, is FirTypeAlias, is FirScript -> {
|
||||
target.transformSingle(transformer, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
else -> throwUnexpectedFirElementError(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkBodyIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDefaultValueIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkInitializerIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
|
||||
internal object LLFirBodyLazyResolver : LLFirLazyResolver(FirResolvePhase.BODY_RESOLVE) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirBodyTargetResolver(target, lockProvider, session, scopeSession, towerDataContextCollector)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = true)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
when (target) {
|
||||
is FirValueParameter -> checkDefaultValueIsResolved(target)
|
||||
is FirVariable -> checkInitializerIsResolved(target)
|
||||
is FirFunction -> checkBodyIsResolved(target)
|
||||
}
|
||||
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirBodyTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) : LLFirAbstractBodyTargetResolver(
|
||||
target,
|
||||
lockProvider,
|
||||
scopeSession,
|
||||
FirResolvePhase.BODY_RESOLVE,
|
||||
) {
|
||||
override val transformer = object : FirBodyResolveTransformer(
|
||||
session,
|
||||
phase = resolverPhase,
|
||||
implicitTypeOnly = false,
|
||||
scopeSession = scopeSession,
|
||||
returnTypeCalculator = createReturnTypeCalculator(),
|
||||
firTowerDataContextCollector = towerDataContextCollector,
|
||||
) {
|
||||
override val preserveCFGForClasses: Boolean get() = false
|
||||
}
|
||||
|
||||
override fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean {
|
||||
when (target) {
|
||||
is FirRegularClass -> {
|
||||
if (target.resolvePhase >= resolverPhase) return true
|
||||
|
||||
withRegularClass(target) {
|
||||
transformer.firTowerDataContextCollector?.addDeclarationContext(target, transformer.context.towerDataContext)
|
||||
}
|
||||
|
||||
// resolve class CFG graph here, to do this we need to have property & init blocks resoled
|
||||
resolveMemberProperties(target)
|
||||
performCustomResolveUnderLock(target) {
|
||||
calculateCFG(target)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun calculateCFG(target: FirRegularClass) {
|
||||
checkWithAttachmentBuilder(
|
||||
target.controlFlowGraphReference == null,
|
||||
{ "controlFlowGraphReference should be null if class phase < $resolverPhase)" },
|
||||
) {
|
||||
withFirEntry("firClass", target)
|
||||
}
|
||||
|
||||
val dataFlowAnalyzer = transformer.declarationsTransformer.dataFlowAnalyzer
|
||||
dataFlowAnalyzer.enterClass(target, buildGraph = true)
|
||||
val controlFlowGraph = dataFlowAnalyzer.exitClass()
|
||||
?: buildErrorWithAttachment("CFG should not be null as buildGraph is specified") {
|
||||
withFirEntry("firClass", target)
|
||||
}
|
||||
|
||||
target.replaceControlFlowGraphReference(FirControlFlowGraphReferenceImpl(controlFlowGraph))
|
||||
}
|
||||
|
||||
private fun resolveMemberProperties(target: FirRegularClass) {
|
||||
withRegularClass(target) {
|
||||
for (member in target.declarations) {
|
||||
if (member is FirCallableDeclaration || member is FirAnonymousInitializer) {
|
||||
/* TODO we should resolve only properties and init blocks here but due to the recent changes in the compiler, we also have to do this for all callable members
|
||||
we should avoid doing it as it leads to additional work and also can might to problems with incremental analysis
|
||||
*/
|
||||
member.lazyResolveToPhase(resolverPhase.previous)
|
||||
performResolve(member)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
val contextCollector = transformer.firTowerDataContextCollector
|
||||
if (contextCollector != null && target is FirDeclaration) {
|
||||
val bodyResolveContext = transformer.context
|
||||
if (target is FirFunction) {
|
||||
bodyResolveContext.forFunctionBody(target, transformer.components) {
|
||||
contextCollector.addDeclarationContext(target, bodyResolveContext.towerDataContext)
|
||||
}
|
||||
} else {
|
||||
contextCollector.addDeclarationContext(target, bodyResolveContext.towerDataContext)
|
||||
}
|
||||
}
|
||||
|
||||
when (target) {
|
||||
is FirRegularClass -> {
|
||||
error("should be resolved in ${::doResolveWithoutLock.name}")
|
||||
}
|
||||
is FirDanglingModifierList, is FirFileAnnotationsContainer, is FirTypeAlias -> {
|
||||
// no bodies here
|
||||
}
|
||||
is FirCallableDeclaration, is FirAnonymousInitializer, is FirScript -> {
|
||||
calculateLazyBodies(target)
|
||||
target.transformSingle(transformer, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
else -> throwUnexpectedFirElementError(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsComputationSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredAnnotationsResolveTransformer
|
||||
|
||||
internal object LLFirCompilerAnnotationsLazyResolver : LLFirLazyResolver(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirCompilerRequiredAnnotationsTargetResolver(target, lockProvider, session, scopeSession)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
// TODO add proper check that COMPILER_REQUIRED_ANNOTATIONS are resolved
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class LLFirCompilerRequiredAnnotationsTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS, isJumpingPhase = true) {
|
||||
private val transformer =
|
||||
FirCompilerRequiredAnnotationsResolveTransformer(session, scopeSession, CompilerRequiredAnnotationsComputationSession())
|
||||
|
||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||
transformer.annotationTransformer.withFileAndFileScopes(firFile) {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||
override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) {
|
||||
transformer.annotationTransformer.withRegularClass(firClass) {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
FirLazyBodiesCalculator.calculateCompilerAnnotations(target)
|
||||
when (target) {
|
||||
is FirTypeAlias -> {
|
||||
transformer.transformTypeAlias(target, null)
|
||||
}
|
||||
is FirRegularClass -> {
|
||||
transformer.annotationTransformer.resolveRegularClass(
|
||||
target,
|
||||
transformChildren = {
|
||||
target.transformSuperTypeRefs(transformer.annotationTransformer, null)
|
||||
},
|
||||
afterChildrenTransform = {
|
||||
transformer.annotationTransformer.calculateDeprecations(target)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
|
||||
internal object LLFirContractsLazyResolver : LLFirLazyResolver(FirResolvePhase.CONTRACTS) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirContractsTargetResolver(target, lockProvider, session, scopeSession)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
if (target is FirContractDescriptionOwner) {
|
||||
// TODO checkContractDescriptionIsResolved(declaration)
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirContractsTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirAbstractBodyTargetResolver(
|
||||
target,
|
||||
lockProvider,
|
||||
scopeSession,
|
||||
FirResolvePhase.CONTRACTS
|
||||
) {
|
||||
override val transformer = FirContractResolveTransformer(session, scopeSession)
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
when (target) {
|
||||
is FirRegularClass, is FirAnonymousInitializer, is FirDanglingModifierList, is FirFileAnnotationsContainer, is FirTypeAlias, is FirScript -> {
|
||||
// no contracts here
|
||||
}
|
||||
is FirCallableDeclaration -> {
|
||||
// TODO calculate bodies only when in-body contract is present
|
||||
calculateLazyBodies(target)
|
||||
target.transformSingle(transformer, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
else -> throwUnexpectedFirElementError(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignation
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
|
||||
internal class LLFirDeclarationTransformer(private val designation: FirDesignation) {
|
||||
private val designationWithoutTargetIterator = designation.toSequence(includeTarget = false).iterator()
|
||||
private var isInsideTargetDeclaration: Boolean = false
|
||||
private var designationPassed: Boolean = false
|
||||
|
||||
inline fun <D> visitDeclarationContent(
|
||||
visitor: FirVisitor<Unit, D>,
|
||||
declaration: FirDeclaration,
|
||||
data: D,
|
||||
default: () -> FirDeclaration
|
||||
): FirDeclaration = processDeclarationContent(declaration, default) {
|
||||
it.accept(visitor, data)
|
||||
}
|
||||
|
||||
inline fun <D> transformDeclarationContent(
|
||||
transformer: FirDefaultTransformer<D>,
|
||||
declaration: FirDeclaration,
|
||||
data: D,
|
||||
default: () -> FirDeclaration
|
||||
): FirDeclaration = processDeclarationContent(declaration, default) { toTransform ->
|
||||
toTransform.transform<FirElement, D>(transformer, data).also { transformed ->
|
||||
check(transformed === toTransform) {
|
||||
"become $transformed `${transformed.render()}`, was ${toTransform}: `${toTransform.render()}`"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun processDeclarationContent(
|
||||
declaration: FirDeclaration,
|
||||
default: () -> FirDeclaration,
|
||||
applyToDesignated: (FirElementWithResolveState) -> Unit,
|
||||
): FirDeclaration {
|
||||
//It means that we are inside the target declaration
|
||||
if (isInsideTargetDeclaration) {
|
||||
return default()
|
||||
}
|
||||
|
||||
//It means that we already transform target declaration and now can skip all others
|
||||
if (designationPassed) {
|
||||
return declaration
|
||||
}
|
||||
|
||||
if (designationWithoutTargetIterator.hasNext()) {
|
||||
applyToDesignated(designationWithoutTargetIterator.next())
|
||||
} else {
|
||||
try {
|
||||
isInsideTargetDeclaration = true
|
||||
designationPassed = true
|
||||
applyToDesignated(designation.target)
|
||||
} finally {
|
||||
isInsideTargetDeclaration = false
|
||||
}
|
||||
}
|
||||
|
||||
return declaration
|
||||
}
|
||||
|
||||
fun ensureDesignationPassed() {
|
||||
check(designationPassed) { "Designation not passed for declaration ${designation.target::class.simpleName}" }
|
||||
}
|
||||
}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkAnnotationArgumentsMappingIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirAnnotationArgumentsMappingTransformer
|
||||
|
||||
/**
|
||||
* Transform designation into ANNOTATIONS_ARGUMENTS_MAPPING declaration. Affects only for target declaration, it's children and dependents
|
||||
*/
|
||||
internal class LLFirDesignatedAnnotationArgumentsMappingTransformer(
|
||||
private val designation: FirDesignationWithFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirLazyTransformer, FirAnnotationArgumentsMappingTransformer(session, scopeSession, FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING) {
|
||||
private val ideDeclarationTransformer = LLFirDeclarationTransformer(designation)
|
||||
|
||||
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration =
|
||||
ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) {
|
||||
super.transformDeclarationContent(declaration, data)
|
||||
}
|
||||
|
||||
override fun transformDeclaration() {
|
||||
FirLazyBodiesCalculator.calculateAnnotations(designation.firFile)
|
||||
designation.firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(
|
||||
target,
|
||||
FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING,
|
||||
updateForLocalDeclarations = false,
|
||||
)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING)
|
||||
if (target !is FirAnnotationContainer) return
|
||||
for (annotation in target.annotations) {
|
||||
if (annotation is FirAnnotationCall) {
|
||||
checkAnnotationArgumentsMappingIsResolved(annotation, target)
|
||||
}
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
|
||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirAnnotationArgumentsResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
|
||||
internal class LLFirDesignatedAnnotationArgumentsResolveTransformer(
|
||||
private val designation: FirDesignationWithFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirLazyTransformer, FirAnnotationArgumentsResolveTransformer(session, scopeSession, FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS) {
|
||||
|
||||
private fun moveNextDeclaration(designationIterator: Iterator<FirElementWithResolveState>) {
|
||||
if (!designationIterator.hasNext()) {
|
||||
FirLazyBodiesCalculator.calculateAnnotations(designation.target)
|
||||
designation.target.transform<FirDeclaration, ResolutionMode>(declarationsTransformer, ResolutionMode.ContextIndependent)
|
||||
return
|
||||
}
|
||||
when (val nextElement = designationIterator.next()) {
|
||||
is FirFile -> {
|
||||
context.withFile(nextElement, components) {
|
||||
moveNextDeclaration(designationIterator)
|
||||
}
|
||||
}
|
||||
is FirRegularClass -> {
|
||||
context.withRegularClass(nextElement, components) {
|
||||
moveNextDeclaration(designationIterator)
|
||||
}
|
||||
}
|
||||
is FirEnumEntry -> {
|
||||
context.forEnumEntry {
|
||||
moveNextDeclaration(designationIterator)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
error("Unexpected declaration in designation: ${nextElement::class.qualifiedName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformDeclaration() {
|
||||
val designationIterator = designation.toSequenceWithFile(includeTarget = false).iterator()
|
||||
moveNextDeclaration(designationIterator)
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(
|
||||
target,
|
||||
FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS,
|
||||
updateForLocalDeclarations = false,
|
||||
)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
if (target !is FirAnnotationContainer) return
|
||||
val unresolvedAnnotation = target.annotations.firstOrNull { it.annotationTypeRef !is FirResolvedTypeRef }
|
||||
check(unresolvedAnnotation == null) {
|
||||
"Unexpected annotationTypeRef annotation, expected resolvedType but actual ${unresolvedAnnotation?.annotationTypeRef}"
|
||||
}
|
||||
target.checkPhase(FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS)
|
||||
|
||||
for (annotation in target.annotations) {
|
||||
for (argument in annotation.argumentMapping.mapping.values) {
|
||||
checkTypeRefIsResolved(argument.typeRef, "annotation argument", target) {
|
||||
withFirEntry("firAnnotation", annotation)
|
||||
withFirEntry("firArgument", argument)
|
||||
}
|
||||
}
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.CompilerRequiredAnnotationsComputationSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompilerRequiredAnnotationsResolveTransformer
|
||||
|
||||
internal class LLFirDesignatedAnnotationsResolveTransformed(
|
||||
private val designation: FirDesignationWithFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirLazyTransformer,
|
||||
FirCompilerRequiredAnnotationsResolveTransformer(session, scopeSession, CompilerRequiredAnnotationsComputationSession()) {
|
||||
|
||||
private fun moveNextDeclaration(designationIterator: Iterator<FirElementWithResolveState>) {
|
||||
if (!designationIterator.hasNext()) {
|
||||
val declaration = designation.target
|
||||
FirLazyBodiesCalculator.calculateCompilerAnnotations(declaration)
|
||||
if (declaration is FirRegularClass || declaration is FirTypeAlias) {
|
||||
declaration.transform<FirDeclaration, Nothing?>(this, null)
|
||||
}
|
||||
return
|
||||
}
|
||||
when (val nextElement = designationIterator.next()) {
|
||||
is FirFile -> {
|
||||
withFileAndScopes(nextElement) {
|
||||
moveNextDeclaration(designationIterator)
|
||||
}
|
||||
}
|
||||
is FirRegularClass -> {
|
||||
moveNextDeclaration(designationIterator)
|
||||
}
|
||||
else -> {
|
||||
error("Unexpected declaration in designation: ${nextElement::class.qualifiedName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformDeclaration() {
|
||||
val designationIterator = designation.toSequenceWithFile(includeTarget = false).iterator()
|
||||
moveNextDeclaration(designationIterator)
|
||||
}
|
||||
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(
|
||||
target,
|
||||
FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS,
|
||||
updateForLocalDeclarations = false,
|
||||
)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS)
|
||||
// todo add proper check that COMPILER_REQUIRED_ANNOTATIONS are resolved
|
||||
// checkNestedDeclarationsAreResolved(declaration)
|
||||
}
|
||||
}
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.LLFirEnsureBasedTransformerForReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
|
||||
|
||||
/**
|
||||
* Transform designation into BODY_RESOLVE declaration. Affects only for target declaration and it's children
|
||||
*/
|
||||
internal class LLFirDesignatedBodyResolveTransformer(
|
||||
private val designation: FirDesignationWithFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?
|
||||
) : LLFirLazyTransformer, FirBodyResolveTransformer(
|
||||
session,
|
||||
phase = FirResolvePhase.BODY_RESOLVE,
|
||||
implicitTypeOnly = false,
|
||||
scopeSession = scopeSession,
|
||||
returnTypeCalculator = createReturnTypeCalculatorForIDE(
|
||||
scopeSession,
|
||||
ImplicitBodyResolveComputationSession(),
|
||||
::LLFirEnsureBasedTransformerForReturnTypeCalculator
|
||||
),
|
||||
firTowerDataContextCollector = towerDataContextCollector
|
||||
) {
|
||||
private val ideDeclarationTransformer = LLFirDeclarationTransformer(designation)
|
||||
|
||||
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration =
|
||||
ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) {
|
||||
super.transformDeclarationContent(declaration, data)
|
||||
}
|
||||
|
||||
override fun transformDeclaration() {
|
||||
designation.firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextIndependent)
|
||||
ideDeclarationTransformer.ensureDesignationPassed()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, FirResolvePhase.BODY_RESOLVE, updateForLocalDeclarations = true)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(FirResolvePhase.BODY_RESOLVE)
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirAbstractContractResolveTransformerDispatcher
|
||||
|
||||
/**
|
||||
* Transform designation into CONTRACTS declaration. Affects only for target declaration and it's children
|
||||
*/
|
||||
internal class LLFirDesignatedContractsResolveTransformer(
|
||||
private val designation: FirDesignationWithFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirLazyTransformer, FirAbstractContractResolveTransformerDispatcher(session, scopeSession) {
|
||||
|
||||
private val ideDeclarationTransformer = LLFirDeclarationTransformer(designation)
|
||||
|
||||
override val contractDeclarationsTransformer: FirDeclarationsContractResolveTransformer
|
||||
get() = object : FirDeclarationsContractResolveTransformer() {
|
||||
override fun transformDeclarationContent(firClass: FirClass, data: ResolutionMode) {
|
||||
ideDeclarationTransformer.transformDeclarationContent(this, firClass, data) {
|
||||
super.transformDeclarationContent(firClass, data)
|
||||
firClass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration =
|
||||
ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) {
|
||||
super.transformDeclarationContent(declaration, data)
|
||||
}
|
||||
|
||||
override fun transformDeclaration() {
|
||||
FirLazyBodiesCalculator.calculateLazyBodiesInside(designation)
|
||||
designation.firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextIndependent)
|
||||
ideDeclarationTransformer.ensureDesignationPassed()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, FirResolvePhase.CONTRACTS, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(FirResolvePhase.CONTRACTS)
|
||||
if (target is FirContractDescriptionOwner) {
|
||||
// TODO checkContractDescriptionIsResolved(declaration)
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.mpp.FirExpectActualMatcherTransformer
|
||||
|
||||
internal class LLFirDesignatedExpectActualMatcherTransformer(
|
||||
private val designation: FirDesignationWithFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirLazyTransformer, FirExpectActualMatcherTransformer(session, scopeSession) {
|
||||
|
||||
private val declarationTransformer = LLFirDeclarationTransformer(designation)
|
||||
|
||||
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): FirStatement {
|
||||
return declarationTransformer.transformDeclarationContent(this, regularClass, data) {
|
||||
super.transformRegularClass(regularClass, data) as FirDeclaration
|
||||
} as FirStatement
|
||||
}
|
||||
|
||||
override fun transformFile(file: FirFile, data: Nothing?): FirFile {
|
||||
return declarationTransformer.transformDeclarationContent(this, file, data) {
|
||||
super.transformFile(file, data)
|
||||
} as FirFile
|
||||
}
|
||||
|
||||
override fun transformDeclaration() {
|
||||
FirLazyBodiesCalculator.calculateLazyBodiesInside(designation)
|
||||
designation.firFile.transform<FirFile, Nothing?>(this, null)
|
||||
declarationTransformer.ensureDesignationPassed()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(
|
||||
target,
|
||||
FirResolvePhase.EXPECT_ACTUAL_MATCHING,
|
||||
updateForLocalDeclarations = false,
|
||||
)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(FirResolvePhase.EXPECT_ACTUAL_MATCHING)
|
||||
// TODO check if expect-actual matching is present
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompanionGenerationTransformer
|
||||
import org.jetbrains.kotlin.fir.declarations.resolvePhase
|
||||
|
||||
internal class LLFirDesignatedGeneratedCompanionObjectResolveTransformer(
|
||||
val designation: FirDesignationWithFile,
|
||||
session: FirSession
|
||||
) : LLFirLazyTransformer {
|
||||
private val transformer: FirCompanionGenerationTransformer = FirCompanionGenerationTransformer(session)
|
||||
|
||||
override fun transformDeclaration() {
|
||||
designation.target.transform<FirDeclaration, Nothing?>(transformer, null)
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, FirResolvePhase.COMPANION_GENERATION, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
check(target.resolvePhase >= FirResolvePhase.COMPANION_GENERATION)
|
||||
}
|
||||
}
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.LLFirDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkReturnTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitAwareBodyResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
|
||||
|
||||
/**
|
||||
* Transform designation into IMPLICIT_TYPES_BODY_RESOLVE declaration. Affects only for target declaration, it's children and dependents
|
||||
*/
|
||||
internal class LLFirDesignatedImplicitTypesTransformer(
|
||||
private val designation: FirDesignationWithFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
implicitBodyResolveComputationSession: ImplicitBodyResolveComputationSession = ImplicitBodyResolveComputationSession(),
|
||||
) : LLFirLazyTransformer, FirImplicitAwareBodyResolveTransformer(
|
||||
session,
|
||||
implicitBodyResolveComputationSession = implicitBodyResolveComputationSession,
|
||||
phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE,
|
||||
implicitTypeOnly = true,
|
||||
scopeSession = scopeSession,
|
||||
firTowerDataContextCollector = towerDataContextCollector,
|
||||
returnTypeCalculator = createReturnTypeCalculatorForIDE(
|
||||
scopeSession,
|
||||
implicitBodyResolveComputationSession,
|
||||
::LLFirDesignatedImpliciteTypesBodyResolveTransformerForReturnTypeCalculator
|
||||
)
|
||||
) {
|
||||
private val ideDeclarationTransformer = LLFirDeclarationTransformer(designation)
|
||||
|
||||
override fun transformDeclarationContent(declaration: FirDeclaration, data: ResolutionMode): FirDeclaration =
|
||||
ideDeclarationTransformer.transformDeclarationContent(this, declaration, data) {
|
||||
super.transformDeclarationContent(declaration, data)
|
||||
}
|
||||
|
||||
override fun transformDeclaration() {
|
||||
designation.firFile.transform<FirFile, ResolutionMode>(this, ResolutionMode.ContextIndependent)
|
||||
ideDeclarationTransformer.ensureDesignationPassed()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(
|
||||
target,
|
||||
FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE,
|
||||
updateForLocalDeclarations = false, /* here should be true if we resolved the body*/
|
||||
)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
|
||||
if (target is FirCallableDeclaration) {
|
||||
checkReturnTypeRefIsResolved(target)
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDeclarationStatusIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.StatusComputationSession
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
/**
|
||||
* Transform designation into STATUS phase. Affects only for designation, members of designation classes, target declaration, it's children and dependents
|
||||
*/
|
||||
internal class LLFirDesignatedStatusResolveTransformer(
|
||||
private val designation: FirDesignationWithFile,
|
||||
private val session: FirSession,
|
||||
private val scopeSession: ScopeSession,
|
||||
) : LLFirLazyTransformer {
|
||||
private inner class FirDesignatedStatusResolveTransformerForIDE(
|
||||
private val designationIterator: Iterator<FirRegularClass>,
|
||||
) : FirStatusResolveTransformer(session, scopeSession, StatusComputationSession()) {
|
||||
|
||||
private var isInsideTargetDeclaration = false
|
||||
|
||||
override fun transformClass(klass: FirClass, data: FirResolvedDeclarationStatus?): FirStatement {
|
||||
return storeClass(klass) {
|
||||
resolveClassTypeParameters(klass)
|
||||
if (isInsideTargetDeclaration) {
|
||||
transformDeclarationContent(klass, data)
|
||||
} else {
|
||||
resolveCallableMembers(klass, data)
|
||||
moveNextDeclaration()
|
||||
}
|
||||
klass
|
||||
} as FirStatement
|
||||
}
|
||||
|
||||
private fun resolveClassTypeParameters(klass: FirClass) {
|
||||
klass.typeParameters.forEach { it.transformSingle(this, data = null) }
|
||||
}
|
||||
|
||||
private fun resolveCallableMembers(
|
||||
klass: FirClass,
|
||||
data: FirResolvedDeclarationStatus?
|
||||
) {
|
||||
for (member in klass.declarations) {
|
||||
if (member is FirClassLikeDeclaration) continue
|
||||
// we need the types to be resolved here to compute visibility
|
||||
// implicit types will not be handled (see bug in the compiler KT-55446)
|
||||
member.lazyResolveToPhase(FirResolvePhase.TYPES)
|
||||
member.transformSingle(this, data)
|
||||
}
|
||||
}
|
||||
|
||||
fun moveNextDeclaration() {
|
||||
if (!designationIterator.hasNext()) {
|
||||
isInsideTargetDeclaration = true
|
||||
designation.target.transform<FirDeclaration, _>(this, data = null)
|
||||
return
|
||||
}
|
||||
val nextClass = designationIterator.next()
|
||||
transformClassContent(nextClass, data = null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun transformDeclaration() {
|
||||
val designationIterator = designation.path.iterator()
|
||||
val transformer = FirDesignatedStatusResolveTransformerForIDE(designationIterator)
|
||||
transformer.moveNextDeclaration()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, FirResolvePhase.STATUS, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
if (target !is FirAnonymousInitializer) {
|
||||
target.checkPhase(FirResolvePhase.STATUS)
|
||||
}
|
||||
if (target is FirMemberDeclaration) {
|
||||
checkDeclarationStatusIsResolved(target)
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkReceiverTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkReturnTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTypeResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
/**
|
||||
* Transform designation into TYPES phase. Affects only for designation, target declaration and it's children
|
||||
*/
|
||||
internal class LLFirDesignatedTypeResolverTransformer(
|
||||
private val designation: FirDesignationWithFile,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirLazyTransformer, FirTypeResolveTransformer(session, scopeSession) {
|
||||
|
||||
private val declarationTransformer = LLFirDeclarationTransformer(designation)
|
||||
|
||||
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
|
||||
return if (element is FirDeclaration && (element is FirRegularClass || element is FirFile)) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
declarationTransformer.transformDeclarationContent(this, element, data) {
|
||||
super.transformElement(element, data)
|
||||
} as E
|
||||
} else {
|
||||
super.transformElement(element, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformDeclaration() {
|
||||
designation.firFile.transform<FirFile, Any?>(this, null)
|
||||
declarationTransformer.ensureDesignationPassed()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, FirResolvePhase.TYPES, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun transformTypeRef(typeRef: FirTypeRef, data: Any?): FirResolvedTypeRef {
|
||||
FirLazyBodiesCalculator.calculateAnnotations(typeRef, session)
|
||||
return super.transformTypeRef(typeRef, data)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(FirResolvePhase.TYPES)
|
||||
when (target) {
|
||||
is FirCallableDeclaration -> {
|
||||
checkReturnTypeRefIsResolved(target, acceptImplicitTypeRef = true)
|
||||
checkReceiverTypeRefIsResolved(target)
|
||||
}
|
||||
|
||||
is FirTypeParameter -> {
|
||||
for (bound in target.bounds) {
|
||||
checkTypeRefIsResolved(bound, "type parameter bound", target)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
(target as? FirDeclaration)?.let {
|
||||
checkTypeParametersAreResolved(it)
|
||||
checkClassMembersAreResolved(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.mpp.FirExpectActualMatcherTransformer
|
||||
|
||||
internal object LLFirExpectActualMatcherLazyResolver : LLFirLazyResolver(FirResolvePhase.EXPECT_ACTUAL_MATCHING) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirExpectActualMatchingTargetResolver(target, lockProvider, session, scopeSession)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
// TODO check if expect-actual matching is present
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirExpectActualMatchingTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.EXPECT_ACTUAL_MATCHING) {
|
||||
private val transformer = FirExpectActualMatcherTransformer(session, scopeSession)
|
||||
|
||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||
action()
|
||||
}
|
||||
|
||||
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||
override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) {
|
||||
action()
|
||||
}
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
if (target !is FirMemberDeclaration) return
|
||||
if (!target.canHaveExpectCounterPart()) return
|
||||
transformer.transformMemberDeclaration(target)
|
||||
}
|
||||
|
||||
private fun FirMemberDeclaration.canHaveExpectCounterPart(): Boolean = when (this) {
|
||||
is FirEnumEntry -> true
|
||||
is FirProperty -> true
|
||||
is FirConstructor -> true
|
||||
is FirSimpleFunction -> true
|
||||
is FirRegularClass -> true
|
||||
is FirTypeAlias -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirCompanionGenerationTransformer
|
||||
|
||||
internal object LLFirGeneratedCompanionObjectLazyResolver : LLFirLazyResolver(FirResolvePhase.COMPANION_GENERATION) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirCompanionGenerationTargetResolver(target, lockProvider, session)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirCompanionGenerationTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.COMPANION_GENERATION) {
|
||||
private val transformer: FirCompanionGenerationTransformer = FirCompanionGenerationTransformer(session)
|
||||
|
||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||
action()
|
||||
}
|
||||
|
||||
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||
override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) {
|
||||
action()
|
||||
}
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
if (target !is FirRegularClass) return
|
||||
transformer.generateAndUpdateCompanion(target)
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkReturnTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitAwareBodyResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
internal object LLFirImplicitTypesLazyResolver : LLFirLazyResolver(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirImplicitBodyTargetResolver(target, lockProvider, session, scopeSession, towerDataContextCollector)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(
|
||||
target,
|
||||
resolverPhase,
|
||||
updateForLocalDeclarations = false/* here should be true if we resolved the body*/
|
||||
)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
if (target is FirCallableDeclaration) {
|
||||
checkReturnTypeRefIsResolved(target)
|
||||
}
|
||||
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirImplicitBodyTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) : LLFirAbstractBodyTargetResolver(
|
||||
target,
|
||||
lockProvider,
|
||||
scopeSession,
|
||||
FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE,
|
||||
) {
|
||||
override val transformer = object : FirImplicitAwareBodyResolveTransformer(
|
||||
session,
|
||||
implicitBodyResolveComputationSession = implicitBodyResolveComputationSession,
|
||||
phase = resolverPhase,
|
||||
implicitTypeOnly = true,
|
||||
scopeSession = scopeSession,
|
||||
firTowerDataContextCollector = towerDataContextCollector,
|
||||
returnTypeCalculator = createReturnTypeCalculator(),
|
||||
) {
|
||||
override val preserveCFGForClasses: Boolean get() = false
|
||||
}
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
when (target) {
|
||||
is FirRegularClass, is FirDanglingModifierList, is FirAnonymousInitializer, is FirFileAnnotationsContainer, is FirTypeAlias, is FirScript -> {
|
||||
// no implicit bodies here
|
||||
}
|
||||
is FirCallableDeclaration -> {
|
||||
calculateLazyBodies(target)
|
||||
target.transformSingle(transformer, ResolutionMode.ContextIndependent)
|
||||
}
|
||||
else -> throwUnexpectedFirElementError(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import java.util.*
|
||||
|
||||
internal object LLFirLazyPhaseResolverByPhase {
|
||||
private val byPhase = EnumMap<FirResolvePhase, LLFirLazyResolver>(FirResolvePhase::class.java).apply {
|
||||
this[FirResolvePhase.COMPANION_GENERATION] = LLFirGeneratedCompanionObjectLazyResolver
|
||||
this[FirResolvePhase.SUPER_TYPES] = LLFirSupertypeLazyResolver
|
||||
this[FirResolvePhase.TYPES] = LLFirTypeLazyResolver
|
||||
this[FirResolvePhase.STATUS] = LLFirStatusLazyResolver
|
||||
this[FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS] = LLFirCompilerAnnotationsLazyResolver
|
||||
this[FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS] = LLFirAnnotationArgumentsLazyResolver
|
||||
this[FirResolvePhase.CONTRACTS] = LLFirContractsLazyResolver
|
||||
this[FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE] = LLFirImplicitTypesLazyResolver
|
||||
this[FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING] = LLFirAnnotationArgumentMappingLazyResolver
|
||||
this[FirResolvePhase.BODY_RESOLVE] = LLFirBodyLazyResolver
|
||||
this[FirResolvePhase.EXPECT_ACTUAL_MATCHING] = LLFirExpectActualMatcherLazyResolver
|
||||
this[FirResolvePhase.SEALED_CLASS_INHERITORS] = LLFirSealedClassInheritorsLazyResolver
|
||||
}
|
||||
|
||||
fun getByPhase(phase: FirResolvePhase): LLFirLazyResolver = byPhase.getValue(phase)
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
|
||||
internal abstract class LLFirLazyResolver(
|
||||
val resolverPhase: FirResolvePhase,
|
||||
) {
|
||||
abstract fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
)
|
||||
|
||||
abstract fun checkIsResolved(target: FirElementWithResolveState)
|
||||
|
||||
abstract fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState)
|
||||
|
||||
fun checkIsResolved(designation: LLFirResolveTarget) {
|
||||
designation.forEachTarget(::checkIsResolved)
|
||||
}
|
||||
|
||||
protected fun checkNestedDeclarationsAreResolved(target: FirElementWithResolveState) {
|
||||
if (target !is FirDeclaration) return
|
||||
checkFunctionParametersAreResolved(target)
|
||||
checkPropertyAccessorsAreResolved(target)
|
||||
checkPropertyBackingFieldIsResolved(target)
|
||||
checkTypeParametersAreResolved(target)
|
||||
}
|
||||
|
||||
private fun checkPropertyAccessorsAreResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirProperty) {
|
||||
declaration.getter?.let { checkIsResolved(it) }
|
||||
declaration.setter?.let { checkIsResolved(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun checkPropertyBackingFieldIsResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirProperty) {
|
||||
declaration.backingField?.let { checkIsResolved(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun checkFunctionParametersAreResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirFunction) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
checkIsResolved(parameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkTypeParametersAreResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirTypeParameterRefsOwner) {
|
||||
for (parameter in declaration.typeParameters) {
|
||||
if (parameter is FirTypeParameter) {
|
||||
checkIsResolved(parameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
|
||||
internal object LLFirLazyResolverRunner {
|
||||
fun runLazyResolverByPhase(
|
||||
phase: FirResolvePhase,
|
||||
target: LLFirResolveTarget,
|
||||
scopeSession: ScopeSession,
|
||||
lockProvider: LLFirLockProvider,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val lazyResolver = LLFirLazyPhaseResolverByPhase.getByPhase(phase)
|
||||
val firFile = target.firFile
|
||||
val session = firFile.moduleData.session
|
||||
|
||||
// TODO: global lock should be dropped in the context of KT-56550
|
||||
lockProvider.withGlobalLock(firFile) {
|
||||
lockProvider.withGlobalPhaseLock(phase) {
|
||||
lazyResolver.resolve(target, lockProvider, session, scopeSession, towerDataContextCollector)
|
||||
}
|
||||
}
|
||||
|
||||
lazyResolver.checkIsResolved(target)
|
||||
}
|
||||
}
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
|
||||
internal interface LLFirLazyTransformer {
|
||||
fun transformDeclaration()
|
||||
|
||||
fun checkIsResolved(target: FirElementWithResolveState)
|
||||
|
||||
fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState)
|
||||
|
||||
fun checkNestedDeclarationsAreResolved(target: FirElementWithResolveState) {
|
||||
if (target !is FirDeclaration) return
|
||||
checkFunctionParametersAreResolved(target)
|
||||
checkPropertyAccessorsAreResolved(target)
|
||||
checkClassMembersAreResolved(target)
|
||||
}
|
||||
|
||||
fun checkClassMembersAreResolved(declaration: FirDeclaration) {
|
||||
if (!needCheckingIfClassMembersAreResolved) return
|
||||
if (declaration is FirClass) {
|
||||
for (member in declaration.declarations) {
|
||||
checkClassMembersAreResolved(member)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkPropertyAccessorsAreResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirProperty) {
|
||||
declaration.getter?.let { checkIsResolved(it) }
|
||||
declaration.setter?.let { checkIsResolved(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun checkFunctionParametersAreResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirFunction) {
|
||||
for (parameter in declaration.valueParameters) {
|
||||
checkIsResolved(parameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkTypeParametersAreResolved(declaration: FirDeclaration) {
|
||||
if (declaration is FirTypeParameterRefsOwner) {
|
||||
for (parameter in declaration.typeParameters) {
|
||||
if (parameter is FirTypeParameter) {
|
||||
checkIsResolved(parameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal var needCheckingIfClassMembersAreResolved: Boolean = false
|
||||
@TestOnly set
|
||||
|
||||
val DUMMY = object : LLFirLazyTransformer {
|
||||
override fun transformDeclaration() {}
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {}
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.asResolveState
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
|
||||
internal object LLFirLazyTransformerExecutor {
|
||||
fun execute(
|
||||
phase: FirResolvePhase,
|
||||
designation: FirDesignationWithFile,
|
||||
scopeSession: ScopeSession,
|
||||
lockProvider: LLFirLockProvider,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?
|
||||
) {
|
||||
val lazyTransformer = LazyTransformerFactory.createLazyTransformer(
|
||||
phase,
|
||||
designation,
|
||||
scopeSession,
|
||||
lockProvider,
|
||||
towerDataContextCollector,
|
||||
)
|
||||
|
||||
lockProvider.withLock(designation.firFile) {
|
||||
lazyTransformer.transformDeclaration()
|
||||
lazyTransformer.updatePhaseForDeclarationInternals(designation.target)
|
||||
designation.target.replaceResolveState(phase.asResolveState())
|
||||
lazyTransformer.checkIsResolved(designation.target)
|
||||
}
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
|
||||
internal object LLFirSealedClassInheritorsLazyResolver : LLFirLazyResolver(FirResolvePhase.SEALED_CLASS_INHERITORS) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirSealedClassInheritorsDesignatedResolver(target, lockProvider)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class LLFirSealedClassInheritorsDesignatedResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.SEALED_CLASS_INHERITORS) {
|
||||
|
||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||
action()
|
||||
}
|
||||
|
||||
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||
override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) {
|
||||
action()
|
||||
}
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
// just update the phase
|
||||
}
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.asResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkDeclarationStatusIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirStatusResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.StatusComputationSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhaseWithCallableMembers
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
internal object LLFirStatusLazyResolver : LLFirLazyResolver(FirResolvePhase.STATUS) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirStatusTargetResolver(target, lockProvider, session, scopeSession)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
if (target !is FirAnonymousInitializer) {
|
||||
target.checkPhase(resolverPhase)
|
||||
}
|
||||
if (target is FirMemberDeclaration) {
|
||||
checkDeclarationStatusIsResolved(target)
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirStatusTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
private val statusComputationSession: StatusComputationSession = StatusComputationSession()
|
||||
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.STATUS, isJumpingPhase = true) {
|
||||
private val transformer = Transformer(session, scopeSession)
|
||||
|
||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||
action()
|
||||
}
|
||||
|
||||
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||
override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) {
|
||||
firClass.lazyResolveToPhase(resolverPhase.previous)
|
||||
resolveClass(firClass, action)
|
||||
}
|
||||
|
||||
private fun resolveClassTypeParameters(klass: FirClass) {
|
||||
klass.typeParameters.forEach { it.transformSingle(transformer, data = null) }
|
||||
}
|
||||
|
||||
private fun resolveCallableMembers(klass: FirClass) {
|
||||
// we need the types to be resolved here to compute visibility
|
||||
// implicit types will not be handled (see bug in the compiler KT-55446)
|
||||
klass.lazyResolveToPhaseWithCallableMembers(resolverPhase.previous)
|
||||
for (member in klass.declarations) {
|
||||
if (member !is FirCallableDeclaration) continue
|
||||
performResolve(member)
|
||||
}
|
||||
}
|
||||
|
||||
override fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean {
|
||||
return when (target) {
|
||||
is FirRegularClass -> {
|
||||
resolveClass(target, action = {})
|
||||
true
|
||||
}
|
||||
else -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
when (target) {
|
||||
is FirRegularClass -> {
|
||||
error("should be resolved in doResolveWithoutLock")
|
||||
}
|
||||
else -> {
|
||||
target.transformSingle(transformer, data = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveClass(firClass: FirRegularClass, action: () -> Unit) {
|
||||
transformer.statusComputationSession.startComputing(firClass)
|
||||
transformer.forceResolveStatusesOfSupertypes(firClass)
|
||||
|
||||
performCustomResolveUnderLock(firClass) {
|
||||
transformer.transformClassStatus(firClass)
|
||||
transformer.transformValueClassRepresentation(firClass)
|
||||
transformer.storeClass(firClass) {
|
||||
resolveClassTypeParameters(firClass)
|
||||
firClass
|
||||
}
|
||||
}
|
||||
|
||||
transformer.storeClass(firClass) {
|
||||
resolveCallableMembers(firClass)
|
||||
firClass
|
||||
}
|
||||
|
||||
transformer.storeClass(firClass) {
|
||||
action()
|
||||
firClass
|
||||
}
|
||||
|
||||
transformer.statusComputationSession.endComputing(firClass)
|
||||
}
|
||||
|
||||
|
||||
private inner class Transformer(
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : FirStatusResolveTransformer(session, scopeSession, statusComputationSession) {
|
||||
|
||||
override fun FirDeclaration.needResolveMembers(): Boolean = false
|
||||
override fun FirDeclaration.needResolveNestedClassifiers(): Boolean = false
|
||||
|
||||
override fun transformClass(klass: FirClass, data: FirResolvedDeclarationStatus?): FirStatement {
|
||||
return klass
|
||||
}
|
||||
|
||||
override fun resolveClassForSuperType(regularClass: FirRegularClass): Boolean {
|
||||
if (regularClass.resolvePhase >= resolverPhase) return true
|
||||
regularClass.lazyResolveToPhase(resolverPhase.previous)
|
||||
|
||||
val designation = regularClass.collectDesignationWithFile().asResolveTarget()
|
||||
val resolver = LLFirStatusTargetResolver(designation, lockProvider, session, scopeSession, statusComputationSession)
|
||||
resolver.resolveDesignation()
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
+152
-54
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignation
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDesignation
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirResolvableSession
|
||||
@@ -20,33 +21,102 @@ import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirApplySupertypesTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirSupertypeResolverVisitor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.SupertypeComputationStatus
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.toSymbol
|
||||
import org.jetbrains.kotlin.fir.types.type
|
||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
|
||||
/**
|
||||
* Transform designation into SUPER_TYPES phase. Affects only the designation, target declaration, its children, and dependents.
|
||||
*/
|
||||
internal class LLFirDesignatedSupertypeResolverTransformer(
|
||||
private val designation: FirDesignationWithFile,
|
||||
internal object LLFirSupertypeLazyResolver : LLFirLazyResolver(FirResolvePhase.SUPER_TYPES) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirSuperTypeTargetResolver(target, lockProvider, session, scopeSession)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
when (target) {
|
||||
is FirClass -> {
|
||||
for (superTypeRef in target.superTypeRefs) {
|
||||
checkTypeRefIsResolved(superTypeRef, "class super type", target)
|
||||
}
|
||||
}
|
||||
|
||||
is FirTypeAlias -> {
|
||||
checkTypeRefIsResolved(target.expandedTypeRef, typeRefName = "type alias expanded type", target)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class LLFirSuperTypeTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
private val session: FirSession,
|
||||
private val scopeSession: ScopeSession,
|
||||
private val lockProvider: LLFirLockProvider
|
||||
) : LLFirLazyTransformer {
|
||||
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.SUPER_TYPES) {
|
||||
|
||||
private val supertypeComputationSession = SupertypeComputationSession()
|
||||
|
||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||
action()
|
||||
}
|
||||
|
||||
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||
override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) {
|
||||
doResolveWithoutLock(firClass)
|
||||
action()
|
||||
}
|
||||
|
||||
override fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean {
|
||||
when (target) {
|
||||
is FirRegularClass, is FirTypeAlias -> {
|
||||
val designationToResolve = FirDesignationWithFile(nestedClassesStack, target, resolveTarget.firFile)
|
||||
val collected = collect(designationToResolve)
|
||||
supertypeComputationSession.breakLoops(session)
|
||||
apply(collected)
|
||||
}
|
||||
else -> {
|
||||
performCustomResolveUnderLock(target) {
|
||||
// just update the phase
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
error("Should be resolved without lock in ${::doResolveWithoutLock.name}")
|
||||
}
|
||||
|
||||
private inner class DesignatedFirSupertypeResolverVisitor(classDesignation: FirDesignation) :
|
||||
FirSupertypeResolverVisitor(
|
||||
session = session,
|
||||
supertypeComputationSession = supertypeComputationSession,
|
||||
scopeSession = scopeSession,
|
||||
scopeForLocalClass = null,
|
||||
localClassesNavigationInfo = null
|
||||
localClassesNavigationInfo = null,
|
||||
) {
|
||||
val declarationTransformer = LLFirDeclarationTransformer(classDesignation)
|
||||
|
||||
@@ -87,6 +157,7 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
|
||||
supertypeComputationStatus.supertypeRefs.forEach { crawlSupertype(it.type) }
|
||||
}
|
||||
}
|
||||
|
||||
return visited.values
|
||||
}
|
||||
|
||||
@@ -94,9 +165,7 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
|
||||
checkCanceled()
|
||||
val resolver = DesignatedFirSupertypeResolverVisitor(designation)
|
||||
designation.firFile.lazyResolveToPhase(FirResolvePhase.IMPORTS)
|
||||
lockProvider.withLock(designation.firFile) {
|
||||
designation.firFile.accept(resolver, null)
|
||||
}
|
||||
designation.firFile.accept(resolver, null)
|
||||
resolver.declarationTransformer.ensureDesignationPassed()
|
||||
visited[designation.target] = designation
|
||||
}
|
||||
@@ -135,55 +204,84 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
|
||||
for (designation in designations) {
|
||||
checkCanceled()
|
||||
val applier = DesignatedFirApplySupertypesTransformer(designation)
|
||||
designation.firFile.transform<FirElement, Void?>(applier, null)
|
||||
applier.declarationTransformer.ensureDesignationPassed()
|
||||
(designation.target as FirDeclaration).lazyResolveToPhase(resolverPhase.previous)
|
||||
performCustomResolveUnderLock(designation.target) {
|
||||
designation.firFile.transform<FirElement, Void?>(applier, null)
|
||||
applier.declarationTransformer.ensureDesignationPassed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val filesToDesignations = designations.groupBy { it.firFile }
|
||||
for (designationsPerFile in filesToDesignations) {
|
||||
checkCanceled()
|
||||
lockProvider.withLock(designationsPerFile.key) {
|
||||
val session = designationsPerFile.key.llFirResolvableSession
|
||||
?: error("When FirFile exists for the declaration, the session should be resolvevablable")
|
||||
withInvalidationOnException(session) {
|
||||
applyToFileSymbols(designationsPerFile.value)
|
||||
}
|
||||
val session = designationsPerFile.key.llFirResolvableSession
|
||||
?: error("When FirFile exists for the declaration, the session should be resolvable")
|
||||
withInvalidationOnException(session) {
|
||||
applyToFileSymbols(designationsPerFile.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformDeclaration() {
|
||||
val targetDesignation = if (designation.target !is FirClassLikeDeclaration) {
|
||||
val resolvableTarget = designation.path.lastOrNull() ?: return
|
||||
val targetPath = designation.path.dropLast(1)
|
||||
FirDesignationWithFile(targetPath, resolvableTarget, designation.firFile)
|
||||
} else designation
|
||||
|
||||
val collected = collect(targetDesignation)
|
||||
supertypeComputationSession.breakLoops(session)
|
||||
apply(collected)
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, FirResolvePhase.SUPER_TYPES, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(FirResolvePhase.SUPER_TYPES)
|
||||
when (target) {
|
||||
is FirClass -> {
|
||||
for (superTypeRef in target.superTypeRefs) {
|
||||
checkTypeRefIsResolved(superTypeRef, "class super type", target)
|
||||
}
|
||||
}
|
||||
|
||||
is FirTypeAlias -> {
|
||||
checkTypeRefIsResolved(target.expandedTypeRef, typeRefName = "type alias expanded type", target)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirDeclarationTransformer(private val designation: FirDesignation) {
|
||||
private val designationWithoutTargetIterator = designation.toSequence(includeTarget = false).iterator()
|
||||
private var isInsideTargetDeclaration: Boolean = false
|
||||
private var designationPassed: Boolean = false
|
||||
|
||||
inline fun <D> visitDeclarationContent(
|
||||
visitor: FirVisitor<Unit, D>,
|
||||
declaration: FirDeclaration,
|
||||
data: D,
|
||||
default: () -> FirDeclaration
|
||||
): FirDeclaration = processDeclarationContent(declaration, default) {
|
||||
it.accept(visitor, data)
|
||||
}
|
||||
|
||||
inline fun <D> transformDeclarationContent(
|
||||
transformer: FirDefaultTransformer<D>,
|
||||
declaration: FirDeclaration,
|
||||
data: D,
|
||||
default: () -> FirDeclaration
|
||||
): FirDeclaration = processDeclarationContent(declaration, default) { toTransform ->
|
||||
toTransform.transform<FirElement, D>(transformer, data).also { transformed ->
|
||||
check(transformed === toTransform) {
|
||||
"become $transformed `${transformed.render()}`, was ${toTransform}: `${toTransform.render()}`"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun processDeclarationContent(
|
||||
declaration: FirDeclaration,
|
||||
default: () -> FirDeclaration,
|
||||
applyToDesignated: (FirElementWithResolveState) -> Unit,
|
||||
): FirDeclaration {
|
||||
//It means that we are inside the target declaration
|
||||
if (isInsideTargetDeclaration) {
|
||||
return default()
|
||||
}
|
||||
|
||||
//It means that we already transform target declaration and now can skip all others
|
||||
if (designationPassed) {
|
||||
return declaration
|
||||
}
|
||||
|
||||
if (designationWithoutTargetIterator.hasNext()) {
|
||||
applyToDesignated(designationWithoutTargetIterator.next())
|
||||
} else {
|
||||
try {
|
||||
isInsideTargetDeclaration = true
|
||||
designationPassed = true
|
||||
applyToDesignated(designation.target)
|
||||
} finally {
|
||||
isInsideTargetDeclaration = false
|
||||
}
|
||||
}
|
||||
|
||||
return declaration
|
||||
}
|
||||
|
||||
fun ensureDesignationPassed() {
|
||||
check(designationPassed) { "Designation not passed for declaration ${designation.target::class.simpleName}" }
|
||||
}
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.*
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
|
||||
internal abstract class LLFirTargetResolver(
|
||||
protected val resolveTarget: LLFirResolveTarget,
|
||||
protected val lockProvider: LLFirLockProvider,
|
||||
protected val resolverPhase: FirResolvePhase,
|
||||
private val isJumpingPhase: Boolean = false,
|
||||
) {
|
||||
private val _nestedClassesStack = mutableListOf<FirRegularClass>()
|
||||
|
||||
val nestedClassesStack: List<FirRegularClass> get() = _nestedClassesStack.toList()
|
||||
|
||||
protected abstract fun withFile(firFile: FirFile, action: () -> Unit)
|
||||
|
||||
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||
protected abstract fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit)
|
||||
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
protected fun withRegularClass(firClass: FirRegularClass, action: () -> Unit) {
|
||||
_nestedClassesStack += firClass
|
||||
withRegularClassImpl(firClass, action)
|
||||
check(_nestedClassesStack.removeLast() === firClass)
|
||||
}
|
||||
|
||||
protected open fun checkResolveConsistency() {}
|
||||
|
||||
protected open fun doResolveWithoutLock(target: FirElementWithResolveState): Boolean = false
|
||||
protected abstract fun doLazyResolveUnderLock(target: FirElementWithResolveState)
|
||||
|
||||
fun resolveDesignation() {
|
||||
checkResolveConsistency()
|
||||
withFile(resolveTarget.firFile) {
|
||||
goToTargets(resolveTarget.path.iterator())
|
||||
}
|
||||
}
|
||||
|
||||
private fun goToTargets(iterator: Iterator<FirRegularClass>) {
|
||||
if (iterator.hasNext()) {
|
||||
val firClass = iterator.next()
|
||||
withRegularClass(firClass) {
|
||||
goToTargets(iterator)
|
||||
}
|
||||
} else {
|
||||
when (resolveTarget) {
|
||||
is LLFirClassWithSpecificMembersResolveTarget -> {
|
||||
performResolve(resolveTarget.target)
|
||||
withRegularClass(resolveTarget.target) {
|
||||
resolveTarget.forEachMember(::performResolve)
|
||||
}
|
||||
}
|
||||
is LLFirClassWithAllMembersResolveTarget -> {
|
||||
performResolve(resolveTarget.target)
|
||||
withRegularClass(resolveTarget.target) {
|
||||
resolveTarget.forEachMember(::performResolve)
|
||||
}
|
||||
}
|
||||
is LLFirClassWithAllCallablesResolveTarget -> {
|
||||
performResolve(resolveTarget.target)
|
||||
withRegularClass(resolveTarget.target) {
|
||||
resolveTarget.forEachCallable(::performResolve)
|
||||
}
|
||||
}
|
||||
is LLFirSingleResolveTarget -> {
|
||||
performResolve(resolveTarget.target)
|
||||
}
|
||||
is LLFirWholeFileResolveTarget -> {
|
||||
resolveTarget.forEachTopLevelDeclaration(::resolveTargetWithNestedDeclarations)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveTargetWithNestedDeclarations(target: FirElementWithResolveState) {
|
||||
performResolve(target)
|
||||
if (target is FirRegularClass) {
|
||||
withRegularClass(target) {
|
||||
for (member in target.declarations) {
|
||||
resolveTargetWithNestedDeclarations(member)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun performResolve(target: FirElementWithResolveState) {
|
||||
if (doResolveWithoutLock(target)) return
|
||||
performCustomResolveUnderLock(target) {
|
||||
doLazyResolveUnderLock(target)
|
||||
}
|
||||
}
|
||||
|
||||
protected inline fun performCustomResolveUnderLock(target: FirElementWithResolveState, crossinline action: () -> Unit) {
|
||||
checkThatResolvedAtLeastToPreviousPhase(target)
|
||||
withPossiblyJumpingLock(target) {
|
||||
action()
|
||||
LLFirLazyPhaseResolverByPhase.getByPhase(resolverPhase).updatePhaseForDeclarationInternals(target)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun withPossiblyJumpingLock(target: FirElementWithResolveState, action: () -> Unit) {
|
||||
if (isJumpingPhase) {
|
||||
lockProvider.withJumpingLock(target, resolverPhase, action)
|
||||
} else {
|
||||
lockProvider.withLock(target, resolverPhase, action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkThatResolvedAtLeastToPreviousPhase(target: FirElementWithResolveState) {
|
||||
when (val previousPhase = resolverPhase.previous) {
|
||||
FirResolvePhase.IMPORTS -> {}
|
||||
else -> {
|
||||
target.checkPhase(previousPhase)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.LLFirPhaseUpdater
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkReceiverTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkReturnTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkTypeRefIsResolved
|
||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTypeResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
internal object LLFirTypeLazyResolver : LLFirLazyResolver(FirResolvePhase.TYPES) {
|
||||
override fun resolve(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?,
|
||||
) {
|
||||
val resolver = LLFirTypeTargetResolver(target, lockProvider, session, scopeSession)
|
||||
resolver.resolveDesignation()
|
||||
}
|
||||
|
||||
override fun updatePhaseForDeclarationInternals(target: FirElementWithResolveState) {
|
||||
LLFirPhaseUpdater.updateDeclarationInternalsPhase(target, resolverPhase, updateForLocalDeclarations = false)
|
||||
}
|
||||
|
||||
override fun checkIsResolved(target: FirElementWithResolveState) {
|
||||
target.checkPhase(resolverPhase)
|
||||
if (target is FirConstructor) {
|
||||
target.delegatedConstructor?.let { delegated ->
|
||||
checkTypeRefIsResolved(delegated.constructedTypeRef, "constructor type reference", target, acceptImplicitTypeRef = true)
|
||||
}
|
||||
}
|
||||
when (target) {
|
||||
is FirCallableDeclaration -> {
|
||||
checkReturnTypeRefIsResolved(target, acceptImplicitTypeRef = true)
|
||||
checkReceiverTypeRefIsResolved(target)
|
||||
}
|
||||
|
||||
is FirTypeParameter -> {
|
||||
for (bound in target.bounds) {
|
||||
checkTypeRefIsResolved(bound, "type parameter bound", target)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
|
||||
checkNestedDeclarationsAreResolved(target)
|
||||
}
|
||||
}
|
||||
|
||||
private class LLFirTypeTargetResolver(
|
||||
target: LLFirResolveTarget,
|
||||
lockProvider: LLFirLockProvider,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
) : LLFirTargetResolver(target, lockProvider, FirResolvePhase.TYPES) {
|
||||
private val transformer = object : FirTypeResolveTransformer(session, scopeSession) {
|
||||
override fun transformTypeRef(typeRef: FirTypeRef, data: Any?): FirResolvedTypeRef {
|
||||
FirLazyBodiesCalculator.calculateAnnotations(typeRef, session)
|
||||
return super.transformTypeRef(typeRef, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun withFile(firFile: FirFile, action: () -> Unit) {
|
||||
transformer.withFileScope(firFile) {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("Should never be called directly, only for override purposes, please use withRegularClass", level = DeprecationLevel.ERROR)
|
||||
override fun withRegularClassImpl(firClass: FirRegularClass, action: () -> Unit) {
|
||||
firClass.lazyResolveToPhase(resolverPhase.previous)
|
||||
transformer.withClassDeclarationCleanup(firClass) {
|
||||
performCustomResolveUnderLock(firClass) {
|
||||
resolveClassTypes(firClass)
|
||||
}
|
||||
|
||||
transformer.withClassScopes(
|
||||
firClass,
|
||||
actionInsideStaticScope = {
|
||||
resolveConstructors(firClass)
|
||||
},
|
||||
action = action,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveConstructors(firClass: FirRegularClass): Unit = transformer.withScopeCleanup {
|
||||
transformer.addTypeParametersScope(firClass)
|
||||
|
||||
for (member in firClass.declarations) {
|
||||
if (member !is FirConstructor) continue
|
||||
|
||||
member.lazyResolveToPhase(resolverPhase.previous)
|
||||
|
||||
performCustomResolveUnderLock(member) {
|
||||
// ConstructedTypeRef should be resolved only with type parameters, but not with nested classes and classes from supertypes
|
||||
transformer.transformDelegatedConstructorCall(member)
|
||||
|
||||
transformer.withClassScopes(firClass) {
|
||||
member.accept(transformer, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||
when (target) {
|
||||
is FirDanglingModifierList, is FirFileAnnotationsContainer, is FirCallableDeclaration, is FirTypeAlias, is FirScript -> {
|
||||
target.accept(transformer, null)
|
||||
}
|
||||
|
||||
is FirRegularClass -> {
|
||||
resolveClassTypes(target)
|
||||
}
|
||||
is FirAnonymousInitializer -> {}
|
||||
else -> error("Unknown declaration ${target::class.java}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveClassTypes(firClass: FirRegularClass) {
|
||||
transformer.transformClassTypeParameters(firClass, null)
|
||||
transformer.withScopeCleanup {
|
||||
firClass.transformAnnotations(transformer, null)
|
||||
}
|
||||
|
||||
transformer.withClassScopes(firClass) {
|
||||
for (contextReceiver in firClass.contextReceivers) {
|
||||
contextReceiver.transformSingle(transformer, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignationWithFile
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirLockProvider
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
|
||||
internal object LazyTransformerFactory {
|
||||
fun createLazyTransformer(
|
||||
phase: FirResolvePhase,
|
||||
designation: FirDesignationWithFile,
|
||||
scopeSession: ScopeSession,
|
||||
lockProvider: LLFirLockProvider,
|
||||
towerDataContextCollector: FirTowerDataContextCollector?
|
||||
): LLFirLazyTransformer = when (phase) {
|
||||
FirResolvePhase.COMPANION_GENERATION -> LLFirDesignatedGeneratedCompanionObjectResolveTransformer(
|
||||
designation = designation,
|
||||
session = designation.firFile.moduleData.session,
|
||||
)
|
||||
FirResolvePhase.SEALED_CLASS_INHERITORS -> LLFirLazyTransformer.DUMMY
|
||||
FirResolvePhase.SUPER_TYPES -> LLFirDesignatedSupertypeResolverTransformer(
|
||||
designation = designation,
|
||||
session = designation.firFile.moduleData.session,
|
||||
scopeSession = scopeSession,
|
||||
lockProvider = lockProvider
|
||||
)
|
||||
FirResolvePhase.TYPES -> LLFirDesignatedTypeResolverTransformer(
|
||||
designation,
|
||||
designation.firFile.moduleData.session,
|
||||
scopeSession,
|
||||
)
|
||||
FirResolvePhase.STATUS -> LLFirDesignatedStatusResolveTransformer(
|
||||
designation,
|
||||
designation.firFile.moduleData.session,
|
||||
scopeSession,
|
||||
)
|
||||
FirResolvePhase.EXPECT_ACTUAL_MATCHING -> LLFirDesignatedExpectActualMatcherTransformer(
|
||||
designation,
|
||||
designation.firFile.moduleData.session,
|
||||
scopeSession
|
||||
)
|
||||
FirResolvePhase.COMPILER_REQUIRED_ANNOTATIONS -> LLFirDesignatedAnnotationsResolveTransformed(
|
||||
designation,
|
||||
designation.firFile.moduleData.session,
|
||||
scopeSession,
|
||||
)
|
||||
FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS -> LLFirDesignatedAnnotationArgumentsResolveTransformer(
|
||||
designation,
|
||||
designation.firFile.moduleData.session,
|
||||
scopeSession,
|
||||
)
|
||||
FirResolvePhase.CONTRACTS -> LLFirDesignatedContractsResolveTransformer(
|
||||
designation,
|
||||
designation.firFile.moduleData.session,
|
||||
scopeSession,
|
||||
)
|
||||
FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE -> LLFirDesignatedImplicitTypesTransformer(
|
||||
designation,
|
||||
designation.firFile.moduleData.session,
|
||||
scopeSession,
|
||||
towerDataContextCollector
|
||||
)
|
||||
FirResolvePhase.ANNOTATIONS_ARGUMENTS_MAPPING -> LLFirDesignatedAnnotationArgumentsMappingTransformer(
|
||||
designation,
|
||||
designation.firFile.moduleData.session,
|
||||
scopeSession,
|
||||
)
|
||||
FirResolvePhase.BODY_RESOLVE -> LLFirDesignatedBodyResolveTransformer(
|
||||
designation,
|
||||
designation.firFile.moduleData.session,
|
||||
scopeSession,
|
||||
towerDataContextCollector
|
||||
)
|
||||
FirResolvePhase.RAW_FIR -> error("Non-lazy phase $phase")
|
||||
FirResolvePhase.IMPORTS -> error("Non-lazy phase $phase")
|
||||
}
|
||||
}
|
||||
+1
@@ -24,6 +24,7 @@ fun FirElementWithResolveState.getContainingFile(): FirFile? {
|
||||
is FirValueParameter -> containingFunctionSymbol.fir.getContainingFile()
|
||||
is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol)
|
||||
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFileIfAny(symbol)
|
||||
is FirAnonymousInitializer -> containingClass().getContainingFile()
|
||||
is FirDanglingModifierList -> {
|
||||
val ktFile = psi?.containingFile as? KtFile
|
||||
?: error("File for dangling modifier list cannot be null")
|
||||
|
||||
+14
-1
@@ -9,10 +9,13 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirEle
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.builder.LLFirFileBuilder
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirProvider
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.realPsi
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
|
||||
@@ -95,7 +98,7 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider(
|
||||
*/
|
||||
declarations?.firstOrNull { it.psi == this || it.psi == original }
|
||||
}
|
||||
this is KtConstructor<*> -> {
|
||||
this is KtConstructor<*> || this is KtClassInitializer -> {
|
||||
val containingClass = containingClassOrObject
|
||||
?: errorWithFirSpecificEntries("Container class should be not null for KtConstructor", psi = this)
|
||||
val containerClassFir = containingClass.findFir(provider) as? FirRegularClass ?: return null
|
||||
@@ -112,6 +115,16 @@ private fun KtDeclaration.findSourceNonLocalFirDeclarationByProvider(
|
||||
return candidate?.takeIf { it.realPsi == this }
|
||||
}
|
||||
|
||||
fun FirAnonymousInitializer.containingClass(): FirRegularClass {
|
||||
val dispatchReceiverType = this.dispatchReceiverType as? ConeLookupTagBasedType
|
||||
?: error("dispatchReceiverType for FirAnonymousInitializer modifier cannot be null")
|
||||
|
||||
val dispatchReceiverSymbol = dispatchReceiverType.lookupTag.toSymbol(llFirSession)
|
||||
?: error("symbol for FirAnonymousInitializer cannot be null")
|
||||
|
||||
return dispatchReceiverSymbol.fir as FirRegularClass
|
||||
}
|
||||
|
||||
val ORIGINAL_DECLARATION_KEY = com.intellij.openapi.util.Key<KtDeclaration>("ORIGINAL_DECLARATION_KEY")
|
||||
var KtDeclaration.originalDeclaration by UserDataProperty(ORIGINAL_DECLARATION_KEY)
|
||||
|
||||
|
||||
+23
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
||||
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedArgumentList
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
@@ -43,6 +45,27 @@ internal inline fun checkTypeRefIsResolved(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun checkBodyIsResolved(function: FirFunction) {
|
||||
val block = function.body ?: return
|
||||
checkTypeRefIsResolved(block.typeRef, "block type", function) {
|
||||
withFirEntry("block", block)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun checkInitializerIsResolved(variable: FirVariable) {
|
||||
val initializer = variable.initializer ?: return
|
||||
checkTypeRefIsResolved(initializer.typeRef, "initializer type", variable) {
|
||||
withFirEntry("initializer", initializer)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun checkDefaultValueIsResolved(parameter: FirValueParameter) {
|
||||
val defaultValue = parameter.defaultValue ?: return
|
||||
checkTypeRefIsResolved(defaultValue.typeRef, "default value type", parameter) {
|
||||
withFirEntry("defaultValue", defaultValue)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun checkReturnTypeRefIsResolved(declaration: FirCallableDeclaration, acceptImplicitTypeRef: Boolean = false) {
|
||||
checkTypeRefIsResolved(declaration.returnTypeRef, typeRefName = "return type", declaration, acceptImplicitTypeRef)
|
||||
}
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
open class B(x: () -> Unit)
|
||||
|
||||
class A() : B(1, {
|
||||
foo()
|
||||
})
|
||||
|
||||
fun foo() {}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
open class B(x: () -> Unit)
|
||||
|
||||
class A : B(1, {
|
||||
foo()
|
||||
})
|
||||
|
||||
fun foo() {}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
open class A(x: () -> Unit)
|
||||
|
||||
class B : A {
|
||||
constructor(i: Int) : super(
|
||||
{
|
||||
foo(i)
|
||||
}
|
||||
)
|
||||
|
||||
constructor(l: Long) : super(
|
||||
{
|
||||
foo(l)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun foo(any: Any) {}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
open class A(x: () -> Unit)
|
||||
|
||||
class B : A {
|
||||
constructor(i: Int) : super(
|
||||
{
|
||||
foo(i)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun foo(any: Any) {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
class A(var x: Int)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class A(
|
||||
@setparam:Ann
|
||||
@get:Ann
|
||||
@set:Ann
|
||||
@field:Ann
|
||||
@property:Ann
|
||||
var x: Int
|
||||
)
|
||||
|
||||
annotation class Ann
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class Anno
|
||||
|
||||
open class A
|
||||
|
||||
class B : @Anno A()
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class Anno
|
||||
|
||||
interface A
|
||||
|
||||
class B : @Anno A
|
||||
@@ -0,0 +1,7 @@
|
||||
interface A<T>
|
||||
|
||||
typealias AS = A<String>
|
||||
|
||||
class C : AS {
|
||||
constructor()
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
class A {/* NonReanalyzableDeclarationStructureElement */
|
||||
class A {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
fun x() {/* ReanalyzableFunctionStructureElement */
|
||||
|
||||
}
|
||||
fun y(): Int = 10/* ReanalyzableFunctionStructureElement */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
class X {/* NonReanalyzableDeclarationStructureElement */
|
||||
class X {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
var x: Int/* ReanalyzablePropertyStructureElement */
|
||||
get() = field
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
|
||||
val y = 42/* NonReanalyzableDeclarationStructureElement */
|
||||
val y = 42/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
|
||||
var z: Int = 15/* ReanalyzablePropertyStructureElement */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class A
|
||||
|
||||
(val a: Int)/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
|
||||
{/* NonReanalyzableClassDeclarationStructureElement */
|
||||
constructor() : this(1) {/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
class Foo {/* NonReanalyzableDeclarationStructureElement */
|
||||
class Foo {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
@Suppress("") @MustBeDocumented
|
||||
}
|
||||
class Bar {/* NonReanalyzableDeclarationStructureElement */
|
||||
class Bar {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
@Suppress("") @MustBeDocumented
|
||||
}
|
||||
class Outer {/* NonReanalyzableDeclarationStructureElement */
|
||||
class Inner {/* NonReanalyzableDeclarationStructureElement */
|
||||
class Outer {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
class Inner {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
@Suppress("") @MustBeDocumented
|
||||
}
|
||||
fun foo() {/* ReanalyzableFunctionStructureElement */
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
class A {/* NonReanalyzableDeclarationStructureElement */
|
||||
class A {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
val a = run {
|
||||
class X()
|
||||
|
||||
val y = 10
|
||||
}/* NonReanalyzableDeclarationStructureElement */
|
||||
}/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
}
|
||||
|
||||
inline fun <R> run(block: () -> R): R {/* ReanalyzableFunctionStructureElement */
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
enum class A {/* NonReanalyzableDeclarationStructureElement */
|
||||
X,/* NonReanalyzableDeclarationStructureElement */
|
||||
Y,/* NonReanalyzableDeclarationStructureElement */
|
||||
enum class A {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
X,/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
Y,/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
Z
|
||||
|
||||
;/* NonReanalyzableDeclarationStructureElement */
|
||||
;/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
|
||||
fun foo(){/* ReanalyzableFunctionStructureElement */}
|
||||
|
||||
val x = 10/* NonReanalyzableDeclarationStructureElement */
|
||||
val x = 10/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
|
||||
fun bar() = 10/* NonReanalyzableDeclarationStructureElement */
|
||||
fun bar() = 10/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
enum class A {/* NonReanalyzableDeclarationStructureElement */
|
||||
X {/* NonReanalyzableDeclarationStructureElement */
|
||||
enum class A {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
X {/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
fun localInX() = 1
|
||||
},
|
||||
Y {/* NonReanalyzableDeclarationStructureElement */
|
||||
Y {/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
override fun foo() {}
|
||||
},
|
||||
Z,
|
||||
|
||||
;/* NonReanalyzableDeclarationStructureElement */
|
||||
;/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
|
||||
open fun foo() {/* ReanalyzableFunctionStructureElement */}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class A {/* NonReanalyzableDeclarationStructureElement */
|
||||
init {
|
||||
class A {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
init {/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
val x = 10
|
||||
class B
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ fun a() {/* ReanalyzableFunctionStructureElement */
|
||||
class X
|
||||
}
|
||||
|
||||
class Y {/* NonReanalyzableDeclarationStructureElement */
|
||||
class Y {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
fun b() {/* ReanalyzableFunctionStructureElement */
|
||||
class Z
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ fun x() {/* ReanalyzableFunctionStructureElement */
|
||||
}
|
||||
}
|
||||
|
||||
class A {/* NonReanalyzableDeclarationStructureElement */
|
||||
class A {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
fun z() {/* ReanalyzableFunctionStructureElement */
|
||||
fun q() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
fun foo() {/* ReanalyzableFunctionStructureElement */
|
||||
var x: Int
|
||||
}
|
||||
class A {/* NonReanalyzableDeclarationStructureElement */
|
||||
class A {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
fun q() {/* ReanalyzableFunctionStructureElement */
|
||||
val y = 42
|
||||
}
|
||||
}
|
||||
class B {/* NonReanalyzableDeclarationStructureElement */
|
||||
class C {/* NonReanalyzableDeclarationStructureElement */
|
||||
class B {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
class C {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
fun u() {/* ReanalyzableFunctionStructureElement */
|
||||
var z: Int = 15
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
class A {/* NonReanalyzableDeclarationStructureElement */
|
||||
typealias X = Int/* NonReanalyzableDeclarationStructureElement */
|
||||
}
|
||||
class A {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
typealias X = Int/* NonReanalyzableNonClassDeclarationStructureElement */
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
class A {/* NonReanalyzableDeclarationStructureElement */
|
||||
class B {/* NonReanalyzableDeclarationStructureElement */
|
||||
class A {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
class B {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
fun x() {/* ReanalyzableFunctionStructureElement */
|
||||
}
|
||||
|
||||
class C {/* NonReanalyzableDeclarationStructureElement */
|
||||
class C {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class E {/* NonReanalyzableDeclarationStructureElement */
|
||||
class E {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
|
||||
}
|
||||
|
||||
fun y(): Int = 10/* ReanalyzableFunctionStructureElement */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ var x: Int = 10/* ReanalyzablePropertyStructureElement */
|
||||
field = value
|
||||
}
|
||||
|
||||
class X {/* NonReanalyzableDeclarationStructureElement */
|
||||
class X {/* NonReanalyzableClassDeclarationStructureElement */
|
||||
var y: Int = 10/* ReanalyzablePropertyStructureElement */
|
||||
get() = field
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user