[FIR] Part 2. Setup running platform checkers in tests
^KT-58881
This commit is contained in:
committed by
Nikolay Lunyak
parent
727d2f46f8
commit
c4e4776c5e
+2
-1
@@ -22,7 +22,8 @@ import org.jetbrains.kotlin.utils.exceptions.withPsiEntry
|
|||||||
internal class LLDiagnosticParameterChecker(testServices: TestServices) : FirAnalysisHandler(testServices) {
|
internal class LLDiagnosticParameterChecker(testServices: TestServices) : FirAnalysisHandler(testServices) {
|
||||||
override fun processModule(module: TestModule, info: FirOutputArtifact) {
|
override fun processModule(module: TestModule, info: FirOutputArtifact) {
|
||||||
for (part in info.partsForDependsOnModules) {
|
for (part in info.partsForDependsOnModules) {
|
||||||
val diagnostics = part.firAnalyzerFacade.runCheckers().values.flatten()
|
val facade = part.firAnalyzerFacade as LowLevelFirAnalyzerFacade
|
||||||
|
val diagnostics = facade.runCheckers().values.flatten()
|
||||||
|
|
||||||
for (diagnostic in diagnostics) {
|
for (diagnostic in diagnostics) {
|
||||||
checkDiagnosticIsSuitableForFirIde(diagnostic as KtPsiDiagnostic)
|
checkDiagnosticIsSuitableForFirIde(diagnostic as KtPsiDiagnostic)
|
||||||
|
|||||||
+3
-1
@@ -10,6 +10,7 @@ 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.analysis.low.level.api.fir.api.collectDiagnosticsForFile
|
||||||
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
|
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.AbstractFirAnalyzerFacade
|
import org.jetbrains.kotlin.fir.AbstractFirAnalyzerFacade
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.pipeline.FirResult
|
import org.jetbrains.kotlin.fir.pipeline.FirResult
|
||||||
import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput
|
import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput
|
||||||
@@ -34,7 +35,8 @@ open class LowLevelFirAnalyzerFacade(
|
|||||||
|
|
||||||
private var resolved: Boolean = false
|
private var resolved: Boolean = false
|
||||||
|
|
||||||
override fun runCheckers(): Map<FirFile, List<KtDiagnostic>> {
|
// TODO: investigate
|
||||||
|
fun runCheckers(): Map<FirFile, List<KtDiagnostic>> {
|
||||||
if (!resolved) {
|
if (!resolved) {
|
||||||
runResolution()
|
runResolution()
|
||||||
resolved = true
|
resolved = true
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ interface Multimap<K, out V, out C : Collection<V>> {
|
|||||||
operator fun contains(key: K): Boolean
|
operator fun contains(key: K): Boolean
|
||||||
val keys: Set<K>
|
val keys: Set<K>
|
||||||
val values: Collection<V>
|
val values: Collection<V>
|
||||||
|
|
||||||
|
operator fun iterator(): Iterator<Map.Entry<K, C>>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MutableMultimap<K, V, C : Collection<V>> : Multimap<K, V, C> {
|
interface MutableMultimap<K, V, C : Collection<V>> : Multimap<K, V, C> {
|
||||||
@@ -72,6 +74,11 @@ abstract class BaseMultimap<K, V, C : Collection<V>, MC : MutableCollection<V>>
|
|||||||
override fun clear() {
|
override fun clear() {
|
||||||
map.clear()
|
map.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun iterator(): Iterator<Map.Entry<K, C>> {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return map.iterator() as Iterator<Map.Entry<K, C>>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SetMultimap<K, V> : BaseMultimap<K, V, Set<V>, MutableSet<V>>() {
|
class SetMultimap<K, V> : BaseMultimap<K, V, Set<V>, MutableSet<V>>() {
|
||||||
@@ -96,3 +103,9 @@ class ListMultimap<K, V> : BaseMultimap<K, V, List<V>, MutableList<V>>() {
|
|||||||
|
|
||||||
fun <K, V> setMultimapOf(): SetMultimap<K, V> = SetMultimap()
|
fun <K, V> setMultimapOf(): SetMultimap<K, V> = SetMultimap()
|
||||||
fun <K, V> listMultimapOf(): ListMultimap<K, V> = ListMultimap()
|
fun <K, V> listMultimapOf(): ListMultimap<K, V> = ListMultimap()
|
||||||
|
|
||||||
|
operator fun <K, V> MutableMultimap<K, V, *>.plusAssign(map: Map<K, Collection<V>>) {
|
||||||
|
for ((key, values) in map) {
|
||||||
|
this.putAll(key, values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ fun FirSession.runResolution(firFiles: List<FirFile>): Pair<ScopeSession, List<F
|
|||||||
|
|
||||||
fun FirSession.runCheckers(
|
fun FirSession.runCheckers(
|
||||||
scopeSession: ScopeSession,
|
scopeSession: ScopeSession,
|
||||||
firFiles: List<FirFile>,
|
firFiles: Collection<FirFile>,
|
||||||
reporter: BaseDiagnosticsCollector,
|
reporter: BaseDiagnosticsCollector,
|
||||||
mppCheckerKind: MppCheckerKind = TODO()
|
mppCheckerKind: MppCheckerKind = TODO()
|
||||||
): Map<FirFile, List<KtDiagnostic>> {
|
): Map<FirFile, List<KtDiagnostic>> {
|
||||||
|
|||||||
+11
-2
@@ -14,19 +14,28 @@ import org.jetbrains.kotlin.test.directives.CodegenTestDirectives.IGNORE_FIR_DIA
|
|||||||
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
|
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
|
||||||
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
||||||
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirAnalysisHandler
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirAnalysisHandler
|
||||||
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticCollectorService
|
||||||
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.firDiagnosticCollectorService
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
|
import org.jetbrains.kotlin.test.services.ServiceRegistrationData
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
|
import org.jetbrains.kotlin.test.services.service
|
||||||
|
|
||||||
class NoFirCompilationErrorsHandler(testServices: TestServices) : FirAnalysisHandler(testServices, failureDisablesNextSteps = true) {
|
class NoFirCompilationErrorsHandler(testServices: TestServices) : FirAnalysisHandler(testServices, failureDisablesNextSteps = true) {
|
||||||
override val directiveContainers: List<DirectivesContainer>
|
override val directiveContainers: List<DirectivesContainer>
|
||||||
get() = listOf(CodegenTestDirectives)
|
get() = listOf(CodegenTestDirectives)
|
||||||
|
|
||||||
|
override val additionalServices: List<ServiceRegistrationData>
|
||||||
|
get() = listOf(service(::FirDiagnosticCollectorService))
|
||||||
|
|
||||||
override fun processModule(module: TestModule, info: FirOutputArtifact) {
|
override fun processModule(module: TestModule, info: FirOutputArtifact) {
|
||||||
for (part in info.partsForDependsOnModules) {
|
for (part in info.partsForDependsOnModules) {
|
||||||
var hasError = false
|
var hasError = false
|
||||||
|
|
||||||
val ignoreErrors = IGNORE_FIR_DIAGNOSTICS in part.module.directives
|
val ignoreErrors = IGNORE_FIR_DIAGNOSTICS in part.module.directives
|
||||||
for ((firFile, diagnostics) in part.firAnalyzerFacade.runCheckers()) {
|
|
||||||
|
val diagnosticsPerFile = testServices.firDiagnosticCollectorService.getFrontendDiagnosticsForModule(info)
|
||||||
|
for ((firFile, diagnostics) in diagnosticsPerFile) {
|
||||||
for (diagnostic in diagnostics) {
|
for (diagnostic in diagnostics) {
|
||||||
if (diagnostic.severity == Severity.ERROR) {
|
if (diagnostic.severity == Severity.ERROR) {
|
||||||
hasError = true
|
hasError = true
|
||||||
@@ -36,7 +45,7 @@ class NoFirCompilationErrorsHandler(testServices: TestServices) : FirAnalysisHan
|
|||||||
val locationText = firFile.source?.psi?.containingFile?.let { psiFile ->
|
val locationText = firFile.source?.psi?.containingFile?.let { psiFile ->
|
||||||
PsiDiagnosticUtils.atLocation(psiFile, range)
|
PsiDiagnosticUtils.atLocation(psiFile, range)
|
||||||
} ?: "${firFile.name}:$range"
|
} ?: "${firFile.name}:$range"
|
||||||
throw IllegalStateException("${diagnostic.factory.name}: $diagnosticText at $locationText")
|
error("${diagnostic.factory.name}: $diagnosticText at $locationText")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-4
@@ -32,13 +32,13 @@ import org.jetbrains.kotlin.library.unresolvedDependencies
|
|||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
|
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
|
||||||
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
|
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
|
||||||
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticCollectorService
|
||||||
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.firDiagnosticCollectorService
|
||||||
import org.jetbrains.kotlin.test.model.BackendKinds
|
import org.jetbrains.kotlin.test.model.BackendKinds
|
||||||
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter
|
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter
|
||||||
import org.jetbrains.kotlin.test.model.FrontendKinds
|
import org.jetbrains.kotlin.test.model.FrontendKinds
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.*
|
||||||
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
|
|
||||||
import org.jetbrains.kotlin.test.services.libraryProvider
|
|
||||||
|
|
||||||
abstract class AbstractFir2IrNonJvmResultsConverter(
|
abstract class AbstractFir2IrNonJvmResultsConverter(
|
||||||
testServices: TestServices
|
testServices: TestServices
|
||||||
@@ -52,11 +52,17 @@ abstract class AbstractFir2IrNonJvmResultsConverter(
|
|||||||
protected abstract fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary>
|
protected abstract fun resolveLibraries(module: TestModule, compilerConfiguration: CompilerConfiguration): List<KotlinResolvedLibrary>
|
||||||
protected abstract val klibFactories: KlibMetadataFactories
|
protected abstract val klibFactories: KlibMetadataFactories
|
||||||
|
|
||||||
|
final override val additionalServices: List<ServiceRegistrationData>
|
||||||
|
get() = listOf(service(::FirDiagnosticCollectorService))
|
||||||
|
|
||||||
final override fun transform(module: TestModule, inputArtifact: FirOutputArtifact): IrBackendInput? =
|
final override fun transform(module: TestModule, inputArtifact: FirOutputArtifact): IrBackendInput? =
|
||||||
try {
|
try {
|
||||||
transformInternal(module, inputArtifact)
|
transformInternal(module, inputArtifact)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
if (CodegenTestDirectives.IGNORE_FIR2IR_EXCEPTIONS_IF_FIR_CONTAINS_ERRORS in module.directives && inputArtifact.hasErrors) {
|
if (
|
||||||
|
CodegenTestDirectives.IGNORE_FIR2IR_EXCEPTIONS_IF_FIR_CONTAINS_ERRORS in module.directives &&
|
||||||
|
testServices.firDiagnosticCollectorService.containsErrors(inputArtifact)
|
||||||
|
) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
throw e
|
throw e
|
||||||
|
|||||||
+2
-1
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.library.metadata.KlibMetadataFactories
|
|||||||
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
|
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
|
||||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||||
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
|
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
|
||||||
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.firDiagnosticCollectorService
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
import org.jetbrains.kotlin.utils.metadataVersion
|
import org.jetbrains.kotlin.utils.metadataVersion
|
||||||
@@ -77,7 +78,7 @@ abstract class Fir2IrJsWasmResultsConverter(testServices: TestServices) : Abstra
|
|||||||
sourceFiles,
|
sourceFiles,
|
||||||
compilerConfiguration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList(),
|
compilerConfiguration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList(),
|
||||||
diagnosticReporter,
|
diagnosticReporter,
|
||||||
inputArtifact.hasErrors,
|
testServices.firDiagnosticCollectorService.containsErrors(inputArtifact),
|
||||||
/*descriptorMangler = */null,
|
/*descriptorMangler = */null,
|
||||||
manglers.irMangler,
|
manglers.irMangler,
|
||||||
manglers.firMangler,
|
manglers.firMangler,
|
||||||
|
|||||||
+11
-1
@@ -20,12 +20,16 @@ import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
|
|||||||
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
|
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
|
||||||
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
|
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
|
||||||
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
|
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
|
||||||
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticCollectorService
|
||||||
|
import org.jetbrains.kotlin.test.frontend.fir.handlers.firDiagnosticCollectorService
|
||||||
import org.jetbrains.kotlin.test.model.BackendKinds
|
import org.jetbrains.kotlin.test.model.BackendKinds
|
||||||
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter
|
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter
|
||||||
import org.jetbrains.kotlin.test.model.FrontendKinds
|
import org.jetbrains.kotlin.test.model.FrontendKinds
|
||||||
import org.jetbrains.kotlin.test.model.TestModule
|
import org.jetbrains.kotlin.test.model.TestModule
|
||||||
|
import org.jetbrains.kotlin.test.services.ServiceRegistrationData
|
||||||
import org.jetbrains.kotlin.test.services.TestServices
|
import org.jetbrains.kotlin.test.services.TestServices
|
||||||
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
|
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
|
||||||
|
import org.jetbrains.kotlin.test.services.service
|
||||||
|
|
||||||
class Fir2IrJvmResultsConverter(
|
class Fir2IrJvmResultsConverter(
|
||||||
testServices: TestServices
|
testServices: TestServices
|
||||||
@@ -34,6 +38,9 @@ class Fir2IrJvmResultsConverter(
|
|||||||
FrontendKinds.FIR,
|
FrontendKinds.FIR,
|
||||||
BackendKinds.IrBackend
|
BackendKinds.IrBackend
|
||||||
) {
|
) {
|
||||||
|
override val additionalServices: List<ServiceRegistrationData>
|
||||||
|
get() = listOf(service(::FirDiagnosticCollectorService))
|
||||||
|
|
||||||
override fun transform(
|
override fun transform(
|
||||||
module: TestModule,
|
module: TestModule,
|
||||||
inputArtifact: FirOutputArtifact
|
inputArtifact: FirOutputArtifact
|
||||||
@@ -41,7 +48,10 @@ class Fir2IrJvmResultsConverter(
|
|||||||
return try {
|
return try {
|
||||||
transformInternal(module, inputArtifact)
|
transformInternal(module, inputArtifact)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
if (CodegenTestDirectives.IGNORE_FIR2IR_EXCEPTIONS_IF_FIR_CONTAINS_ERRORS in module.directives && inputArtifact.hasErrors) {
|
if (
|
||||||
|
CodegenTestDirectives.IGNORE_FIR2IR_EXCEPTIONS_IF_FIR_CONTAINS_ERRORS in module.directives &&
|
||||||
|
testServices.firDiagnosticCollectorService.containsErrors(inputArtifact)
|
||||||
|
) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
throw e
|
throw e
|
||||||
|
|||||||
-7
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.test.frontend.fir
|
package org.jetbrains.kotlin.test.frontend.fir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Severity
|
|
||||||
import org.jetbrains.kotlin.fir.AbstractFirAnalyzerFacade
|
import org.jetbrains.kotlin.fir.AbstractFirAnalyzerFacade
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
@@ -29,12 +28,6 @@ abstract class FirOutputArtifact(val partsForDependsOnModules: List<FirOutputPar
|
|||||||
get() = FrontendKinds.FIR
|
get() = FrontendKinds.FIR
|
||||||
|
|
||||||
val mainFirFiles: Map<TestFile, FirFile> by lazy { allFirFiles.filterKeys { !it.isAdditional } }
|
val mainFirFiles: Map<TestFile, FirFile> by lazy { allFirFiles.filterKeys { !it.isAdditional } }
|
||||||
|
|
||||||
val hasErrors: Boolean by lazy {
|
|
||||||
partsForDependsOnModules.any { part ->
|
|
||||||
part.firAnalyzerFacade.runCheckers().values.any { diagnostics -> diagnostics.any { it.severity == Severity.ERROR } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FirOutputArtifactImpl(parts: List<FirOutputPartForDependsOnModule>) : FirOutputArtifact(parts)
|
class FirOutputArtifactImpl(parts: List<FirOutputPartForDependsOnModule>) : FirOutputArtifact(parts)
|
||||||
+53
-6
@@ -15,10 +15,12 @@ import org.jetbrains.kotlin.diagnostics.*
|
|||||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
|
import org.jetbrains.kotlin.diagnostics.rendering.Renderers
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.builder.FirSyntaxErrors
|
import org.jetbrains.kotlin.fir.builder.FirSyntaxErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.pipeline.runCheckers
|
||||||
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||||
@@ -29,6 +31,10 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyDeclarationResolver
|
import org.jetbrains.kotlin.fir.symbols.lazyDeclarationResolver
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.util.ListMultimap
|
||||||
|
import org.jetbrains.kotlin.fir.util.Multimap
|
||||||
|
import org.jetbrains.kotlin.fir.util.listMultimapOf
|
||||||
|
import org.jetbrains.kotlin.fir.util.plusAssign
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitorVoid
|
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitorVoid
|
||||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
import org.jetbrains.kotlin.platform.isCommon
|
import org.jetbrains.kotlin.platform.isCommon
|
||||||
@@ -55,6 +61,7 @@ import org.jetbrains.kotlin.test.utils.AbstractTwoAttributesMetaInfoProcessor
|
|||||||
import org.jetbrains.kotlin.test.utils.MultiModuleInfoDumper
|
import org.jetbrains.kotlin.test.utils.MultiModuleInfoDumper
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.getOrPut
|
||||||
|
|
||||||
class FullDiagnosticsRenderer(private val directive: SimpleDirective) {
|
class FullDiagnosticsRenderer(private val directive: SimpleDirective) {
|
||||||
private val dumper: MultiModuleInfoDumper = MultiModuleInfoDumper(moduleHeaderTemplate = "// -- Module: <%s> --")
|
private val dumper: MultiModuleInfoDumper = MultiModuleInfoDumper(moduleHeaderTemplate = "// -- Module: <%s> --")
|
||||||
@@ -98,7 +105,7 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
|||||||
listOf(DiagnosticsDirectives)
|
listOf(DiagnosticsDirectives)
|
||||||
|
|
||||||
override val additionalServices: List<ServiceRegistrationData> =
|
override val additionalServices: List<ServiceRegistrationData> =
|
||||||
listOf(service(::DiagnosticsService))
|
listOf(service(::DiagnosticsService), service(::FirDiagnosticCollectorService))
|
||||||
|
|
||||||
private val fullDiagnosticsRenderer = FullDiagnosticsRenderer(DiagnosticsDirectives.RENDER_DIAGNOSTICS_FULL_TEXT)
|
private val fullDiagnosticsRenderer = FullDiagnosticsRenderer(DiagnosticsDirectives.RENDER_DIAGNOSTICS_FULL_TEXT)
|
||||||
|
|
||||||
@@ -107,11 +114,9 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun processModule(module: TestModule, info: FirOutputArtifact) {
|
override fun processModule(module: TestModule, info: FirOutputArtifact) {
|
||||||
for (part in info.partsForDependsOnModules) {
|
val frontendDiagnosticsPerFile = testServices.firDiagnosticCollectorService.getFrontendDiagnosticsForModule(info)
|
||||||
val firAnalyzerFacade = part.firAnalyzerFacade
|
|
||||||
val lazyDeclarationResolver = firAnalyzerFacade.result.outputs.single().session.lazyDeclarationResolver
|
|
||||||
val diagnosticsPerFile = lazyDeclarationResolver.disableLazyResolveContractChecksInside { firAnalyzerFacade.runCheckers() }
|
|
||||||
|
|
||||||
|
for (part in info.partsForDependsOnModules) {
|
||||||
val currentModule = part.module
|
val currentModule = part.module
|
||||||
val lightTreeComparingModeEnabled = FirDiagnosticsDirectives.COMPARE_WITH_LIGHT_TREE in currentModule.directives
|
val lightTreeComparingModeEnabled = FirDiagnosticsDirectives.COMPARE_WITH_LIGHT_TREE in currentModule.directives
|
||||||
val lightTreeEnabled = currentModule.directives.singleValue(FirDiagnosticsDirectives.FIR_PARSER) == FirParser.LightTree
|
val lightTreeEnabled = currentModule.directives.singleValue(FirDiagnosticsDirectives.FIR_PARSER) == FirParser.LightTree
|
||||||
@@ -119,7 +124,7 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes
|
|||||||
|
|
||||||
for (file in currentModule.files) {
|
for (file in currentModule.files) {
|
||||||
val firFile = info.mainFirFiles[file] ?: continue
|
val firFile = info.mainFirFiles[file] ?: continue
|
||||||
var diagnostics = diagnosticsPerFile[firFile] ?: continue
|
var diagnostics = frontendDiagnosticsPerFile[firFile]
|
||||||
if (AdditionalFilesDirectives.CHECK_TYPE in currentModule.directives) {
|
if (AdditionalFilesDirectives.CHECK_TYPE in currentModule.directives) {
|
||||||
diagnostics = diagnostics.filter { it.factory.name != FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.name }
|
diagnostics = diagnostics.filter { it.factory.name != FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.name }
|
||||||
}
|
}
|
||||||
@@ -598,3 +603,45 @@ fun KtDiagnostic.toMetaInfos(
|
|||||||
metaInfo
|
metaInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typealias DiagnosticsMap = Multimap<FirFile, KtDiagnostic, List<KtDiagnostic>>
|
||||||
|
|
||||||
|
class FirDiagnosticCollectorService(val testServices: TestServices) : TestService {
|
||||||
|
private val cache: MutableMap<FirOutputArtifact, DiagnosticsMap> = mutableMapOf()
|
||||||
|
|
||||||
|
fun getFrontendDiagnosticsForModule(info: FirOutputArtifact): DiagnosticsMap {
|
||||||
|
return cache.getOrPut(info) { computeDiagnostics(info) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun containsErrors(info: FirOutputArtifact): Boolean {
|
||||||
|
return getFrontendDiagnosticsForModule(info).values.any { it.severity == Severity.ERROR }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeDiagnostics(info: FirOutputArtifact): ListMultimap<FirFile, KtDiagnostic> {
|
||||||
|
val allFiles = info.partsForDependsOnModules.flatMap { it.firFiles.values }
|
||||||
|
val platformPart = info.partsForDependsOnModules.last()
|
||||||
|
val lazyDeclarationResolver = platformPart.session.lazyDeclarationResolver
|
||||||
|
val result = listMultimapOf<FirFile, KtDiagnostic>()
|
||||||
|
|
||||||
|
lazyDeclarationResolver.disableLazyResolveContractChecksInside {
|
||||||
|
result += platformPart.session.runCheckers(
|
||||||
|
platformPart.firAnalyzerFacade.scopeSession,
|
||||||
|
allFiles,
|
||||||
|
DiagnosticReporterFactory.createPendingReporter(),
|
||||||
|
mppCheckerKind = MppCheckerKind.Platform
|
||||||
|
)
|
||||||
|
|
||||||
|
for (part in info.partsForDependsOnModules) {
|
||||||
|
result += part.session.runCheckers(
|
||||||
|
platformPart.firAnalyzerFacade.scopeSession,
|
||||||
|
part.firFiles.values,
|
||||||
|
DiagnosticReporterFactory.createPendingReporter(),
|
||||||
|
mppCheckerKind = MppCheckerKind.Common
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val TestServices.firDiagnosticCollectorService: FirDiagnosticCollectorService by TestServices.testServiceAccessor()
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ package org.jetbrains.kotlin.fir
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.KtSourceFile
|
import org.jetbrains.kotlin.KtSourceFile
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
|
|
||||||
import org.jetbrains.kotlin.diagnostics.KtDiagnostic
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.pipeline.*
|
import org.jetbrains.kotlin.fir.pipeline.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
@@ -19,8 +17,6 @@ abstract class AbstractFirAnalyzerFacade {
|
|||||||
abstract val scopeSession: ScopeSession
|
abstract val scopeSession: ScopeSession
|
||||||
abstract val result: FirResult
|
abstract val result: FirResult
|
||||||
|
|
||||||
abstract fun runCheckers(): Map<FirFile, List<KtDiagnostic>>
|
|
||||||
|
|
||||||
abstract fun runResolution(): List<FirFile>
|
abstract fun runResolution(): List<FirFile>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,8 +35,6 @@ class FirAnalyzerFacade(
|
|||||||
override val result: FirResult
|
override val result: FirResult
|
||||||
get() = FirResult(listOf(ModuleCompilerAnalyzedOutput(session, scopeSession, firFiles!!)))
|
get() = FirResult(listOf(ModuleCompilerAnalyzedOutput(session, scopeSession, firFiles!!)))
|
||||||
|
|
||||||
private var collectedDiagnostics: Map<FirFile, List<KtDiagnostic>>? = null
|
|
||||||
|
|
||||||
private fun buildRawFir() {
|
private fun buildRawFir() {
|
||||||
if (firFiles != null) return
|
if (firFiles != null) return
|
||||||
firFiles = when (parser) {
|
firFiles = when (parser) {
|
||||||
@@ -55,11 +49,4 @@ class FirAnalyzerFacade(
|
|||||||
_scopeSession = session.runResolution(firFiles!!).first
|
_scopeSession = session.runResolution(firFiles!!).first
|
||||||
return firFiles!!
|
return firFiles!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun runCheckers(): Map<FirFile, List<KtDiagnostic>> {
|
|
||||||
if (_scopeSession == null) runResolution()
|
|
||||||
if (collectedDiagnostics != null) return collectedDiagnostics!!
|
|
||||||
collectedDiagnostics = session.runCheckers(scopeSession, firFiles!!, DiagnosticReporterFactory.createPendingReporter())
|
|
||||||
return collectedDiagnostics!!
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user