[LL FIR] introduce test with reversed resolve order

^KT-56543

Merge-request: KT-MR-9299
Merged-by: Dmitrii Gridin <dmitry.gridin@jetbrains.com>
This commit is contained in:
Dmitrii Gridin
2023-03-22 17:34:07 +00:00
committed by Space Team
parent 8528519d96
commit 9a4a3d1f49
413 changed files with 55387 additions and 45 deletions
@@ -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.
*/
@@ -9,8 +9,8 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirResolveSessionService
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based.facades.LLFirAnalyzerFacadeFactory
import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.FirLowLevelCompilerBasedTestConfigurator
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer
import org.jetbrains.kotlin.analysis.test.framework.AbstractCompilerBasedTest
import org.jetbrains.kotlin.analysis.test.framework.base.registerAnalysisApiBaseTestServices
import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtSourceModuleByCompilerConfiguration
@@ -31,7 +31,9 @@ import org.jetbrains.kotlin.test.frontend.fir.FirOutputPartForDependsOnModule
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.ServiceRegistrationData
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.isKtFile
abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
final override fun TestConfigurationBuilder.configuration() {
@@ -63,7 +65,8 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
open fun TestConfigurationBuilder.configureTest() {}
inner class LowLevelFirFrontendFacade(
testServices: TestServices
testServices: TestServices,
private val facadeFactory: LLFirAnalyzerFacadeFactory,
) : FirFrontendFacade(testServices) {
override val additionalServices: List<ServiceRegistrationData>
get() = emptyList()
@@ -99,7 +102,7 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
DiagnosticCheckerFilter.EXTENDED_AND_COMMON_CHECKERS
} else DiagnosticCheckerFilter.ONLY_COMMON_CHECKERS
val analyzerFacade = LowLevelFirAnalyzerFacade(firResolveSession, allFirFiles.toMap(), diagnosticCheckerFilter)
val analyzerFacade = facadeFactory.createFirFacade(firResolveSession, allFirFiles.toMap(), diagnosticCheckerFilter)
return FirOutputPartForDependsOnModule(
module,
firResolveSession.useSiteFirSession,
@@ -115,12 +118,7 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() {
if (ignoreTest(filePath, configuration)) {
return
}
val oldEnableDeepEnsure = LLFirLazyTransformer.needCheckingIfClassMembersAreResolved
try {
LLFirLazyTransformer.needCheckingIfClassMembersAreResolved = true
super.runTest(filePath)
} finally {
LLFirLazyTransformer.needCheckingIfClassMembersAreResolved = oldEnableDeepEnsure
}
super.runTest(filePath)
}
}
}
@@ -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.
*/
@@ -10,14 +10,17 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDiagnosticsForFile
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
import org.jetbrains.kotlin.fir.AbstractFirAnalyzerFacade
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.Fir2IrCommonMemberStorage
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
import org.jetbrains.kotlin.fir.backend.Fir2IrResult
import org.jetbrains.kotlin.fir.backend.IrBuiltInsOverFir
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.model.TestFile
class LowLevelFirAnalyzerFacade(
open class LowLevelFirAnalyzerFacade(
val firResolveSession: LLFirResolveSession,
val allFirFiles: Map<TestFile, FirFile>,
private val diagnosticCheckerFilter: DiagnosticCheckerFilter,
@@ -25,7 +28,14 @@ class LowLevelFirAnalyzerFacade(
override val scopeSession: ScopeSession
get() = ScopeSession()
private var resolved: Boolean = false
override fun runCheckers(): Map<FirFile, List<KtDiagnostic>> {
if (!resolved) {
runResolution()
resolved = true
}
return allFirFiles.values.associateWith { firFile ->
val ktFile = firFile.psi as KtFile
val diagnostics = ktFile.collectDiagnosticsForFile(firResolveSession, diagnosticCheckerFilter)
@@ -34,7 +44,8 @@ class LowLevelFirAnalyzerFacade(
}
}
override fun runResolution(): List<FirFile> = shouldNotBeCalled()
override fun runResolution(): List<FirFile> = allFirFiles.values.toList()
override fun convertToIr(
fir2IrExtensions: Fir2IrExtensions,
commonMemberStorage: Fir2IrCommonMemberStorage,
@@ -1,16 +1,18 @@
/*
* 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.
*/
package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.AbstractCompilerBasedTestForFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based.facades.LLFirAnalyzerFacadeFactoryWithoutPreresolve
import org.jetbrains.kotlin.test.bind
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration
abstract class AbstractDiagnosisCompilerTestDataTest : AbstractCompilerBasedTestForFir() {
abstract class AbstractDiagnosticCompilerTestDataTest : AbstractCompilerBasedTestForFir() {
override fun TestConfigurationBuilder.configureTest() {
baseFirDiagnosticTestConfiguration(frontendFacade = ::LowLevelFirFrontendFacade)
baseFirDiagnosticTestConfiguration(frontendFacade = ::LowLevelFirFrontendFacade.bind(LLFirAnalyzerFacadeFactoryWithoutPreresolve))
}
}
@@ -1,18 +1,24 @@
/*
* 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.
*/
package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.AbstractCompilerBasedTestForFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based.facades.LLFirAnalyzerFacadeFactoryWithoutPreresolve
import org.jetbrains.kotlin.test.bind
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration
import org.jetbrains.kotlin.test.runners.baseFirSpecDiagnosticTestConfiguration
abstract class AbstractLLFirDiagnosisCompilerTestDataSpecTest : AbstractCompilerBasedTestForFir() {
abstract class AbstractLLFirDiagnosticCompilerTestDataSpecTest : AbstractCompilerBasedTestForFir() {
override fun TestConfigurationBuilder.configureTest() {
baseFirDiagnosticTestConfiguration(frontendFacade = ::LowLevelFirFrontendFacade)
baseFirSpecDiagnosticTestConfiguration()
baseFirDiagnosticTestConfiguration(frontendFacade = ::LowLevelFirFrontendFacade.bind(LLFirAnalyzerFacadeFactoryWithoutPreresolve))
baseFirSpecDiagnosticTestConfigurationForIde()
}
}
fun TestConfigurationBuilder.baseFirSpecDiagnosticTestConfigurationForIde() {
baseFirSpecDiagnosticTestConfiguration()
}
@@ -0,0 +1,22 @@
/*
* 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.diagnostic.compiler.based
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.AbstractCompilerBasedTestForFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based.facades.LLFirAnalyzerFacadeFactoryWithPreresolveInReversedOrder
import org.jetbrains.kotlin.test.bind
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration
abstract class AbstractLLFirPreresolvedReversedDiagnosticCompilerTestDataSpecTest : AbstractCompilerBasedTestForFir() {
override fun TestConfigurationBuilder.configureTest() {
baseFirDiagnosticTestConfiguration(
frontendFacade = ::LowLevelFirFrontendFacade.bind(LLFirAnalyzerFacadeFactoryWithPreresolveInReversedOrder)
)
baseFirSpecDiagnosticTestConfigurationForIde()
useAfterAnalysisCheckers(::FirReversedSuppressor)
}
}
@@ -0,0 +1,54 @@
/*
* 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.diagnostic.compiler.based
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.AbstractCompilerBasedTestForFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based.facades.LLFirAnalyzerFacadeFactoryWithPreresolveInReversedOrder
import org.jetbrains.kotlin.test.bind
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.WrappedException
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
import org.jetbrains.kotlin.test.model.AfterAnalysisChecker
import org.jetbrains.kotlin.test.services.moduleStructure
abstract class AbstractLLFirPreresolvedReversedDiagnosticCompilerTestDataTest : AbstractCompilerBasedTestForFir() {
override fun TestConfigurationBuilder.configureTest() {
baseFirDiagnosticTestConfiguration(
frontendFacade = ::LowLevelFirFrontendFacade.bind(LLFirAnalyzerFacadeFactoryWithPreresolveInReversedOrder)
)
useAfterAnalysisCheckers(::FirReversedSuppressor)
}
}
internal class FirReversedSuppressor(testServices: TestServices) : AfterAnalysisChecker(testServices) {
override val directiveContainers: List<DirectivesContainer> get() = listOf(Companion)
override fun suppressIfNeeded(failedAssertions: List<WrappedException>): List<WrappedException> {
if (!isDisabled()) {
return failedAssertions
}
return if (failedAssertions.isEmpty()) {
listOf(
AssertionError(
"Test contains $IGNORE_REVERSED_RESOLVE directive but no errors was reported. Please remove directive",
).wrap()
)
} else {
emptyList()
}
}
private fun isDisabled(): Boolean = IGNORE_REVERSED_RESOLVE in testServices.moduleStructure.allDirectives
companion object : SimpleDirectivesContainer() {
val IGNORE_REVERSED_RESOLVE by directive("Temporary disables reversed resolve checks until the issue is fixed")
}
}
@@ -17,7 +17,7 @@ import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiagnosisCompilerTestDataTest {
public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDiagnosticCompilerTestDataTest {
@Nested
@TestMetadata("compiler/testData/diagnostics/tests")
@TestDataPath("$PROJECT_ROOT")
@@ -16,7 +16,7 @@ import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
public class DiagnosisCompilerTestFirTestdataTestGenerated extends AbstractDiagnosisCompilerTestDataTest {
public class DiagnosticCompilerTestFirTestdataTestGenerated extends AbstractDiagnosticCompilerTestDataTest {
@Nested
@TestMetadata("compiler/fir/analysis-tests/testData/resolve")
@TestDataPath("$PROJECT_ROOT")
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
@SuppressWarnings("all")
@TestMetadata("compiler/tests-spec/testData/diagnostics")
@TestDataPath("$PROJECT_ROOT")
public class FirIdeSpecTestGenerated extends AbstractLLFirDiagnosisCompilerTestDataSpecTest {
public class FirIdeSpecTestGenerated extends AbstractLLFirDiagnosticCompilerTestDataSpecTest {
@Test
public void testAllFilesPresentInDiagnostics() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/tests-spec/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "helpers", "linked/annotations", "linked/built-in-types-and-their-semantics", "linked/control--and-data-flow-analysis.control-flow-graph.expressions-1.conditional-expressions", "linked/control--and-data-flow-analysis/performing-analysis-on-the-control-flow-graph", "linked/declarations/classifier-declaration/class-declaration/nested-and-inner-classifiers", "linked/declarations/classifier-declaration/classifier-initialization", "linked/declarations/classifier-declaration/data-class-declaration", "linked/declarations/function-declaration", "linked/declarations/property-declaration/property-initialization", "linked/declarations/type-alias", "linked/expressions/call-and-property-access-expressions", "linked/expressions/function-literals", "linked/inheritance", "linked/overload-resolution/c-level-partition", "linked/overload-resolution/determining-function-applicability-for-a-specific-call/rationale", "linked/overloadable-operators", "linked/statements/assignments/simple-assignments", "linked/type-inference/local-type-inference", "linked/type-inference/smart-casts/smart-cast-types", "linked/type-system/subtyping/subtyping-for-nullable-types", "linked/type-system/type-kinds/type-parameters");
@@ -0,0 +1,20 @@
/*
* 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.diagnostic.compiler.based.facades
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.LowLevelFirAnalyzerFacade
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.test.model.TestFile
abstract class LLFirAnalyzerFacadeFactory {
abstract fun createFirFacade(
firResolveSession: LLFirResolveSession,
allFirFiles: Map<TestFile, FirFile>,
diagnosticCheckerFilter: DiagnosticCheckerFilter
): LowLevelFirAnalyzerFacade
}
@@ -0,0 +1,34 @@
/*
* 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.diagnostic.compiler.based.facades
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.LowLevelFirAnalyzerFacade
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkPhase
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.getDeclarationsToResolve
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
object LLFirAnalyzerFacadeFactoryWithPreresolveInReversedOrder : LLFirAnalyzerFacadeFactory() {
override fun createFirFacade(
firResolveSession: LLFirResolveSession,
allFirFiles: Map<TestFile, FirFile>,
diagnosticCheckerFilter: DiagnosticCheckerFilter
): LowLevelFirAnalyzerFacade = object : LowLevelFirAnalyzerFacade(firResolveSession, allFirFiles, diagnosticCheckerFilter) {
override fun runResolution(): List<FirFile> {
val allDeclarations = allFirFiles.values.getDeclarationsToResolve().reversed()
for (declaration in allDeclarations) {
declaration.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
declaration.checkPhase(FirResolvePhase.BODY_RESOLVE)
}
return allFirFiles.values.toList()
}
}
}
@@ -0,0 +1,22 @@
/*
* 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.diagnostic.compiler.based.facades
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.LowLevelFirAnalyzerFacade
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.test.model.TestFile
object LLFirAnalyzerFacadeFactoryWithoutPreresolve : LLFirAnalyzerFacadeFactory() {
override fun createFirFacade(
firResolveSession: LLFirResolveSession,
allFirFiles: Map<TestFile, FirFile>,
diagnosticCheckerFilter: DiagnosticCheckerFilter
): LowLevelFirAnalyzerFacade {
return LowLevelFirAnalyzerFacade(firResolveSession, allFirFiles, diagnosticCheckerFilter)
}
}
@@ -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.
*/
@@ -12,13 +12,11 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceResolveS
import org.jetbrains.kotlin.analysis.project.structure.getKtModule
import org.jetbrains.kotlin.analysis.test.framework.services.environmentManager
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousInitializerSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFileSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.services.PreAnalysisHandler
@@ -64,4 +62,24 @@ internal fun TestConfigurationBuilder.useFirSessionConfigurator(configurator: (T
}
usePreAnalysisHandlers(::ConfiguratorPreAnalysisHandler)
}
}
inline fun <reified E : FirElement> FirElement.collectAllElementsOfType(): List<E> {
val result = mutableListOf<E>()
this.accept(object : FirVisitorVoid() {
override fun visitElement(element: FirElement) {
if (element is E) result += element
element.acceptChildren(this)
}
})
return result
}
fun Collection<FirFile>.getDeclarationsToResolve() = flatMap { it.collectAllElementsOfType<FirDeclaration>() }.filterNot { declaration ->
declaration is FirFile ||
declaration is FirBackingField ||
declaration is FirAnonymousFunction ||
declaration is FirValueParameter && declaration.containingFunctionSymbol is FirAnonymousFunctionSymbol
}