From 71b5b6df7c1ab57fde03354259bea4b27b586b68 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Fri, 9 Oct 2020 11:36:27 +0300 Subject: [PATCH] FIR IDE: add tests for lazy resolving single declaration in file --- .../kotlin/generators/tests/GenerateTests.kt | 4 ++ .../level/api/FirIdeResolveStateService.kt | 37 +++++++---- .../api/FirModuleResolveStateForCompletion.kt | 4 ++ .../level/api/FirModuleResolveStateImpl.kt | 5 ++ .../level/api/api/FirModuleResolveState.kt | 4 ++ .../level/api/file/builder/FirFileBuilder.kt | 3 + .../testdata/lazyResolve/classMembers.kt | 17 +++++ .../testdata/lazyResolve/classMembers.txt | 15 +++++ .../lazyResolve/propertyWithGetter.kt | 8 +++ .../lazyResolve/propertyWithGetter.txt | 7 ++ .../propertyWithGetterAndSetter.kt | 12 ++++ .../propertyWithGetterAndSetter.txt | 9 +++ .../lazyResolve/secondaryConstructor.kt | 11 ++++ .../lazyResolve/secondaryConstructor.txt | 9 +++ .../testdata/lazyResolve/topLevelFunctions.kt | 9 +++ .../lazyResolve/topLevelFunctions.txt | 6 ++ ...ctionsWithExpressionBodyAndExplicitType.kt | 7 ++ ...tionsWithExpressionBodyAndExplicitType.txt | 6 ++ .../topLevelFunctionsWithImplicitType.kt | 7 ++ .../topLevelFunctionsWithImplicitType.txt | 8 +++ .../AbstractFirLazyDeclarationResolveTest.kt | 47 ++++++++++++++ ...irLazyDeclarationResolveTestGenerated.java | 65 +++++++++++++++++++ .../idea/fir/low/level/api/firTestUtils.kt | 10 +++ 23 files changed, 298 insertions(+), 12 deletions(-) create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.txt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.txt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetterAndSetter.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetterAndSetter.txt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/secondaryConstructor.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/secondaryConstructor.txt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctions.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctions.txt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithExpressionBodyAndExplicitType.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithExpressionBodyAndExplicitType.txt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithImplicitType.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithImplicitType.txt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirLazyDeclarationResolveTest.kt create mode 100644 idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/FirLazyDeclarationResolveTestGenerated.java diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 41b30562a6c..4ad91838165 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -84,6 +84,7 @@ import org.jetbrains.kotlin.idea.filters.AbstractKotlinExceptionFilterTest import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirLazyResolveTest import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirMultiModuleResolveTest import org.jetbrains.kotlin.idea.fir.AbstractKtDeclarationAndFirDeclarationEqualityChecker +import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirLazyDeclarationResolveTest import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirMultiModuleLazyResolveTest import org.jetbrains.kotlin.idea.folding.AbstractKotlinFoldingTest import org.jetbrains.kotlin.idea.frontend.api.fir.AbstractResolveCallTest @@ -1035,6 +1036,9 @@ fun main(args: Array) { testClass { model("multiModuleLazyResolve", recursive = false, extension = null) } + testClass { + model("lazyResolve") + } } testGroup("idea/idea-fir/tests", "idea") { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt index 033a79b0d4d..dbebb5758b5 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirIdeResolveStateService.kt @@ -11,10 +11,12 @@ import com.intellij.openapi.util.ModificationTracker import com.intellij.psi.util.CachedValue import com.intellij.psi.util.CachedValueProvider import com.intellij.psi.util.CachedValuesManager +import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.fir.dependenciesWithoutSelf import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo import org.jetbrains.kotlin.idea.caches.trackers.KotlinCodeBlockModificationListener +import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyDeclarationResolver import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionFactory import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionProvider @@ -31,22 +33,33 @@ internal class FirIdeResolveStateService(project: Project) { ConcurrentHashMap() } - private fun createResolveStateFor(moduleInfo: IdeaModuleInfo): FirModuleResolveStateImpl { - require(moduleInfo is ModuleSourceInfo) - val sessionProvider = sessionProviderStorage.getSessionProvider(moduleInfo) - val firFileBuilder = sessionProvider.rootModuleSession.firFileBuilder - return FirModuleResolveStateImpl( - moduleInfo, - sessionProvider, - firFileBuilder, - FirLazyDeclarationResolver(firFileBuilder), - ) - } fun getResolveState(moduleInfo: IdeaModuleInfo): FirModuleResolveStateImpl = - stateCache.computeIfAbsent(moduleInfo) { createResolveStateFor(moduleInfo) } + stateCache.computeIfAbsent(moduleInfo) { createResolveStateFor(moduleInfo, sessionProviderStorage) } companion object { fun getInstance(project: Project): FirIdeResolveStateService = project.service() + + internal fun createResolveStateFor( + moduleInfo: IdeaModuleInfo, + sessionProviderStorage: FirIdeSessionProviderStorage + ): FirModuleResolveStateImpl { + require(moduleInfo is ModuleSourceInfo) + val sessionProvider = sessionProviderStorage.getSessionProvider(moduleInfo) + val firFileBuilder = sessionProvider.rootModuleSession.firFileBuilder + return FirModuleResolveStateImpl( + moduleInfo, + sessionProvider, + firFileBuilder, + FirLazyDeclarationResolver(firFileBuilder), + ) + } } } + +@TestOnly +fun createResolveStateForNoCaching( + moduleInfo: IdeaModuleInfo, +): FirModuleResolveState = FirIdeResolveStateService.createResolveStateFor(moduleInfo, FirIdeSessionProviderStorage(moduleInfo.project!!)) + + diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt index 96026b9bbd2..fb5cd9e9427 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt @@ -79,4 +79,8 @@ internal class FirModuleResolveStateForCompletion( override fun findNonLocalSourceFirDeclaration(ktDeclaration: KtDeclaration): FirDeclaration { error("Should not be used in completion") } + + override fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile? { + error("Should not be used in completion") + } } \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateImpl.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateImpl.kt index bb5432cb1a6..91fac3d20f1 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateImpl.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateImpl.kt @@ -57,6 +57,11 @@ internal class FirModuleResolveStateImpl( override fun collectDiagnosticsForFile(ktFile: KtFile): Collection = diagnosticsCollector.collectDiagnosticsForFile(ktFile) + override fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile? { + val cache = sessionProvider.getModuleCache(ktFile.getModuleInfo() as ModuleSourceInfo) + return firFileBuilder.getBuiltFirFileOrNull(ktFile, cache) + } + override fun recordPsiToFirMappingsForCompletionFrom(fir: FirDeclaration, firFile: FirFile, ktFile: KtFile) { error("Should be called only from FirModuleResolveStateForCompletion") } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/FirModuleResolveState.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/FirModuleResolveState.kt index e392f286a35..a54540bbe01 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/FirModuleResolveState.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/FirModuleResolveState.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.api +import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession @@ -43,6 +44,9 @@ abstract class FirModuleResolveState { internal abstract fun collectDiagnosticsForFile(ktFile: KtFile): Collection + @TestOnly + internal abstract fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile? + abstract fun findNonLocalSourceFirDeclaration( ktDeclaration: KtDeclaration, ): FirDeclaration diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/builder/FirFileBuilder.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/builder/FirFileBuilder.kt index b517410a00c..25405870018 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/builder/FirFileBuilder.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/builder/FirFileBuilder.kt @@ -36,6 +36,9 @@ internal class FirFileBuilder( RawFirBuilder(cache.session, scopeProvider, stubMode = false, lazyBodiesMode = lazyBodiesMode).buildFirFile(ktFile) } + fun getBuiltFirFileOrNull(ktFile: KtFile, cache: ModuleFileCache): FirFile? = + cache.getCachedFirFile(ktFile) + fun isFirFileBuilt( ktFile: KtFile, cache: ModuleFileCache diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.kt new file mode 100644 index 00000000000..236a6fe7b31 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.kt @@ -0,0 +1,17 @@ +class A { + fun resolveMe() { + receive(functionWithLazyBody()) + } + + val x: Int = 10 + get() = field + set(value) { + field = value + } + + fun receive(value: String) {} + + fun functionWithLazyBody(): String { + return "42" + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.txt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.txt new file mode 100644 index 00000000000..b72e29609b4 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.txt @@ -0,0 +1,15 @@ +FILE: classMembers.kt + public final [BODY_RESOLVE] class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + this@R|/A|.R|/A.receive|(this@R|/A|.R|/A.functionWithLazyBody|()) + } + + public final [STATUS] fun receive(value: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } + + public final [STATUS] fun functionWithLazyBody(): R|kotlin/String| { LAZY_BLOCK } + + } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.kt new file mode 100644 index 00000000000..a291965a72b --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.kt @@ -0,0 +1,8 @@ +fun resolveMe() { + receive(withGetter) +} + +fun receive(value: Int){} + +val withGetter: Int + get() = 42 \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.txt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.txt new file mode 100644 index 00000000000..52e7c0988f3 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.txt @@ -0,0 +1,7 @@ +FILE: propertyWithGetter.kt + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + R|/receive|(R|/withGetter|) + } + public final [STATUS] fun receive(value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + public final [STATUS] val withGetter: R|kotlin/Int| + public get(): R|kotlin/Int| { LAZY_BLOCK } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetterAndSetter.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetterAndSetter.kt new file mode 100644 index 00000000000..905719bd4af --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetterAndSetter.kt @@ -0,0 +1,12 @@ +fun resolveMe() { + receive(withGetterAndSetter) + withGetterAndSetter = 123 +} + +fun receive(value: Int) {} + +var withGetterAndSetter: Int = 42 + get() = field + set(value) { + field = value + } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetterAndSetter.txt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetterAndSetter.txt new file mode 100644 index 00000000000..ff072b83c8b --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetterAndSetter.txt @@ -0,0 +1,9 @@ +FILE: propertyWithGetterAndSetter.kt + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + R|/receive|(R|/withGetterAndSetter|) + R|/withGetterAndSetter| = Int(123) + } + public final [STATUS] fun receive(value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } + public final [STATUS] var withGetterAndSetter: R|kotlin/Int| = IntegerLiteral(42) + public get(): R|kotlin/Int| { LAZY_BLOCK } + public set(value: R|kotlin/Int|): R|kotlin/Unit| { LAZY_BLOCK } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/secondaryConstructor.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/secondaryConstructor.kt new file mode 100644 index 00000000000..7cbfa1ab1c1 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/secondaryConstructor.kt @@ -0,0 +1,11 @@ +fun resolveMe() { + receive(A(42)) +} + +fun receive(value: A){} + +class A { + constructor(x: Int) { + val a = x + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/secondaryConstructor.txt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/secondaryConstructor.txt new file mode 100644 index 00000000000..5684066099f --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/secondaryConstructor.txt @@ -0,0 +1,9 @@ +FILE: secondaryConstructor.kt + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + R|/receive|(R|/A.A|(Int(42))) + } + public final [STATUS] fun receive(value: R|A|): R|kotlin/Unit| { LAZY_BLOCK } + public final [STATUS] class A : R|kotlin/Any| { + public constructor(x: R|kotlin/Int|): R|A| { LAZY_BLOCK } + + } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctions.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctions.kt new file mode 100644 index 00000000000..26189b69f80 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctions.kt @@ -0,0 +1,9 @@ +fun resolveMe() { + receive(functionWithLazyBody()) +} + +fun receive(value: String){} + +fun functionWithLazyBody(): String { + return "42" +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctions.txt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctions.txt new file mode 100644 index 00000000000..2d110225751 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctions.txt @@ -0,0 +1,6 @@ +FILE: topLevelFunctions.kt + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + R|/receive|(R|/functionWithLazyBody|()) + } + public final [STATUS] fun receive(value: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } + public final [STATUS] fun functionWithLazyBody(): R|kotlin/String| { LAZY_BLOCK } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithExpressionBodyAndExplicitType.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithExpressionBodyAndExplicitType.kt new file mode 100644 index 00000000000..1018387145b --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithExpressionBodyAndExplicitType.kt @@ -0,0 +1,7 @@ +fun resolveMe() { + receive(functionWithLazyBody()) +} + +fun receive(value: String){} + +fun functionWithLazyBody(): String = "42" \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithExpressionBodyAndExplicitType.txt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithExpressionBodyAndExplicitType.txt new file mode 100644 index 00000000000..f5fd7355874 --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithExpressionBodyAndExplicitType.txt @@ -0,0 +1,6 @@ +FILE: topLevelFunctionsWithExpressionBodyAndExplicitType.kt + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + R|/receive|(R|/functionWithLazyBody|()) + } + public final [STATUS] fun receive(value: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } + public final [STATUS] fun functionWithLazyBody(): R|kotlin/String| { LAZY_BLOCK } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithImplicitType.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithImplicitType.kt new file mode 100644 index 00000000000..3503630f45a --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithImplicitType.kt @@ -0,0 +1,7 @@ +fun resolveMe() { + receive(functionWithLazyBody()) +} + +fun receive(value: String){} + +fun functionWithLazyBody() = "42" \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithImplicitType.txt b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithImplicitType.txt new file mode 100644 index 00000000000..fed74e1133d --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithImplicitType.txt @@ -0,0 +1,8 @@ +FILE: topLevelFunctionsWithImplicitType.kt + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + R|/receive|(R|/functionWithLazyBody|()) + } + public final [STATUS] fun receive(value: R|kotlin/String|): R|kotlin/Unit| { LAZY_BLOCK } + public final [IMPLICIT_TYPES_BODY_RESOLVE] fun functionWithLazyBody(): R|kotlin/String| { + ^functionWithLazyBody String(42) + } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirLazyDeclarationResolveTest.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirLazyDeclarationResolveTest.kt new file mode 100644 index 00000000000..522eed89e4e --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/AbstractFirLazyDeclarationResolveTest.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2020 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.idea.fir.low.level.api + +import com.intellij.openapi.util.io.FileUtil +import org.jetbrains.kotlin.fir.FirRenderer +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.render +import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacade +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtPsiUtil +import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.io.File + +/** + * Test that we do not resolve declarations we do not need & do not build bodies for them + */ +abstract class AbstractFirLazyDeclarationResolveTest : KotlinLightCodeInsightFixtureTestCase() { + override fun isFirPlugin(): Boolean = true + + fun doTest(path: String) { + val testDataFile = File(path) + val ktFile = myFixture.configureByText(testDataFile.name, FileUtil.loadFile(testDataFile)) as KtFile + val lazyDeclarations = ktFile.collectDescendantsOfType { ktDeclaration -> !KtPsiUtil.isLocal(ktDeclaration) } + + val declarationToResolve = lazyDeclarations.firstOrNull { it.name?.toLowerCase() == "resolveme" } + ?: error("declaration with name `resolveMe` was not found") + resolveWithClearCaches(ktFile) { firModuleResolveState -> + val rendered = LowLevelFirApiFacade.withFirDeclaration( + declarationToResolve, + firModuleResolveState, + FirResolvePhase.BODY_RESOLVE + ) @Suppress("UNUSED_ANONYMOUS_PARAMETER") { firDeclaration -> + val firFile = firModuleResolveState.getBuiltFirFileOrNull(ktFile)!! + firFile.render(FirRenderer.RenderMode.WithResolvePhases) + } + val expectedFileName = testDataFile.name.replace(".kt", ".txt") + KotlinTestUtils.assertEqualsToFile(testDataFile.parentFile.resolve(expectedFileName), rendered) + } + } +} \ No newline at end of file diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/FirLazyDeclarationResolveTestGenerated.java b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/FirLazyDeclarationResolveTestGenerated.java new file mode 100644 index 00000000000..1639a1bc68b --- /dev/null +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/FirLazyDeclarationResolveTestGenerated.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2020 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.idea.fir.low.level.api; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class FirLazyDeclarationResolveTestGenerated extends AbstractFirLazyDeclarationResolveTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInLazyResolve() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("classMembers.kt") + public void testClassMembers() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/classMembers.kt"); + } + + @TestMetadata("propertyWithGetter.kt") + public void testPropertyWithGetter() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetter.kt"); + } + + @TestMetadata("propertyWithGetterAndSetter.kt") + public void testPropertyWithGetterAndSetter() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/propertyWithGetterAndSetter.kt"); + } + + @TestMetadata("secondaryConstructor.kt") + public void testSecondaryConstructor() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/secondaryConstructor.kt"); + } + + @TestMetadata("topLevelFunctions.kt") + public void testTopLevelFunctions() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctions.kt"); + } + + @TestMetadata("topLevelFunctionsWithExpressionBodyAndExplicitType.kt") + public void testTopLevelFunctionsWithExpressionBodyAndExplicitType() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithExpressionBodyAndExplicitType.kt"); + } + + @TestMetadata("topLevelFunctionsWithImplicitType.kt") + public void testTopLevelFunctionsWithImplicitType() throws Exception { + runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/lazyResolve/topLevelFunctionsWithImplicitType.kt"); + } +} diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/firTestUtils.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/firTestUtils.kt index 2f37039d23f..21f910ebab6 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/firTestUtils.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/tests/org/jetbrains/kotlin/idea/fir/low/level/api/firTestUtils.kt @@ -7,5 +7,15 @@ package org.jetbrains.kotlin.idea.fir.low.level.api import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project +import org.jetbrains.kotlin.idea.caches.project.getModuleInfo +import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState +import org.jetbrains.kotlin.idea.fir.low.level.api.api.LowLevelFirApiFacade +import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSessionProviderStorage +import org.jetbrains.kotlin.psi.KtElement internal fun Project.allModules() = ModuleManager.getInstance(this).modules.toList() + +inline fun resolveWithClearCaches(context: KtElement, action: (FirModuleResolveState) -> Unit) { + val resolveState = createResolveStateForNoCaching(context.getModuleInfo()) + action(resolveState) +} \ No newline at end of file