diff --git a/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt b/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt index 4cb235e2420..d0afada0fd7 100644 --- a/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt +++ b/compiler/test-infrastructure/tests/org/jetbrains/kotlin/test/services/SourceFileProvider.kt @@ -6,14 +6,10 @@ package org.jetbrains.kotlin.test.services import com.intellij.openapi.project.Project -import com.intellij.openapi.util.text.StringUtilRt import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.PsiManager -import com.intellij.testFramework.LightVirtualFile import org.jetbrains.kotlin.KtInMemoryTextSourceFile import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir -import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.sourceFiles.LightTreeFile import org.jetbrains.kotlin.test.model.TestFile @@ -115,13 +111,15 @@ fun SourceFileProvider.getKtFilesForSourceFiles(testFiles: Collection, } fun SourceFileProvider.getLightTreeKtFileForSourceFile(testFile: TestFile): LightTreeFile { - val shortName = testFile.name.substringAfterLast('/').substringAfterLast('\\') + val shortName = testFile.toLightTreeShortName() val sourceFile = KtInMemoryTextSourceFile(shortName, "/$shortName", getContentOfSourceFile(testFile)) val linesMapping = sourceFile.text.toSourceLinesMapping() val lightTree = LightTree2Fir.buildLightTree(sourceFile.text) return LightTreeFile(lightTree, sourceFile, linesMapping) } +fun TestFile.toLightTreeShortName() = name.substringAfterLast('/').substringAfterLast('\\') + fun SourceFileProvider.getLightTreeFilesForSourceFiles(testFiles: Collection): Map { return testFiles.mapNotNull { if (!it.isKtFile) return@mapNotNull null diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt index 6c29fd38515..5b067992b7b 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt @@ -51,6 +51,7 @@ import org.jetbrains.kotlin.test.getAnalyzerServices import org.jetbrains.kotlin.test.model.FrontendFacade import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.runners.lightTreeSyntaxDiagnosticsReporterHolder import org.jetbrains.kotlin.test.services.* import java.nio.file.Paths @@ -319,6 +320,7 @@ open class FirFrontendFacade( IrGenerationExtension.getInstances(project), parser, enablePluginPhases, + testServices.lightTreeSyntaxDiagnosticsReporterHolder?.reporter, ) val firFiles = firAnalyzerFacade.runResolution() val filesMap = firFiles.mapNotNull { firFile -> diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt index 3bee981e913..2ec0f7c0c82 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.test.frontend.fir.handlers -import com.intellij.lang.impl.PsiBuilderImpl import com.intellij.psi.PsiElement import org.jetbrains.kotlin.* import org.jetbrains.kotlin.checkers.diagnostics.factories.DebugInfoDiagnosticFactory0 @@ -46,6 +45,7 @@ import org.jetbrains.kotlin.test.directives.model.singleValue import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact import org.jetbrains.kotlin.test.model.TestFile import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.runners.lightTreeSyntaxDiagnosticsReporterHolder import org.jetbrains.kotlin.test.services.* import org.jetbrains.kotlin.test.utils.AbstractTwoAttributesMetaInfoProcessor import org.jetbrains.kotlin.util.OperatorNameConventions @@ -118,20 +118,20 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes ) } } else { - collectLightTreeSyntaxErrors(firFile).flatMap { sourceElement -> - FirSyntaxErrors.SYNTAX.on( - sourceElement, - PsiBuilderImpl.getErrorMessage(sourceElement.lighterASTNode) ?: "Syntax error", - positioningStrategy = null - ).toMetaInfos( - module, - testFile, - globalMetadataInfoHandler1 = globalMetadataInfoHandler, - lightTreeEnabled, - lightTreeComparingModeEnabled, - forceRenderArguments, - ) - } + testServices.lightTreeSyntaxDiagnosticsReporterHolder + ?.reporter + ?.diagnosticsByFilePath + ?.get("/${testFile.toLightTreeShortName()}") + ?.flatMap { + it.toMetaInfos( + module, + testFile, + globalMetadataInfoHandler1 = globalMetadataInfoHandler, + lightTreeEnabled, + lightTreeComparingModeEnabled, + forceRenderArguments, + ) + }.orEmpty() } globalMetadataInfoHandler.addMetadataInfosForFile(testFile, metaInfos) diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/lightTreeDiagnostics.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/lightTreeDiagnostics.kt deleted file mode 100644 index ce5dcac735f..00000000000 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/lightTreeDiagnostics.kt +++ /dev/null @@ -1,76 +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.test.frontend.fir.handlers - -import com.intellij.lang.LighterASTNode -import com.intellij.psi.TokenType -import com.intellij.util.diff.FlyweightCapableTreeStructure -import org.jetbrains.kotlin.KtLightSourceElement -import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.visitors.FirVisitor -import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.toKtLightSourceElement -import org.jetbrains.kotlin.util.getChildren - -private typealias Tree = FlyweightCapableTreeStructure - -private class LightTreeErrorsCollector(private val tree: Tree) { - private inline fun LighterASTNode.forEachChildren(f: (LighterASTNode) -> Unit) { - val kidsArray = this.getChildren(tree) - for (kid in kidsArray) { - val tokenType = kid.tokenType - if (KtTokens.COMMENTS.contains(tokenType) || tokenType == KtTokens.WHITE_SPACE || tokenType == KtTokens.SEMICOLON) continue - f(kid) - } - } - - fun collectErrorNodes(node: LighterASTNode, acc: MutableList = mutableListOf()): List { - if (node.tokenType == TokenType.ERROR_ELEMENT) { - acc.add(node) - } else { - node.forEachChildren { child -> - collectErrorNodes(child, acc) - } - } - return acc - } - -} - -private data class TreeWithOffset(val tree: Tree, val offset: Int) - -private data class VisitorState( - val lastTree: Tree? = null, - val visitedTrees: MutableSet = mutableSetOf(), - val result: MutableList = mutableListOf() -) - -private object FirTreesExtractVisitor : FirVisitor() { - override fun visitElement(element: FirElement, data: VisitorState) { - val source = element.source ?: return - val currentTree = source.treeStructure - val (lastTree, visitedTrees, result) = data - val newData = if (lastTree !== currentTree && visitedTrees.add(currentTree)) { - val newTreeWithOffset = TreeWithOffset(currentTree, element.source?.startOffset ?: 0) - result.add(newTreeWithOffset) - data.copy(lastTree = lastTree) - } else { - data - } - element.acceptChildren(this, newData) - } -} - -internal fun collectLightTreeSyntaxErrors(file: FirFile): List { - val state = VisitorState() - file.accept(FirTreesExtractVisitor,state) - return state.result.flatMap { (tree, offset) -> - LightTreeErrorsCollector(tree).collectErrorNodes(tree.root).map { - it.toKtLightSourceElement(tree, startOffset = it.startOffset + offset, endOffset = it.endOffset + offset) - } - } -} diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt index 48a5307f228..4e70e51561c 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.test.runners import org.jetbrains.kotlin.config.ExplicitApiMode +import org.jetbrains.kotlin.diagnostics.impl.SimpleDiagnosticsCollector import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver import org.jetbrains.kotlin.platform.jvm.JvmPlatforms @@ -39,6 +40,8 @@ import org.jetbrains.kotlin.test.services.sourceProviders.CoroutineHelpersSource import org.jetbrains.kotlin.test.FirParser import org.jetbrains.kotlin.test.directives.CodegenTestDirectives import org.jetbrains.kotlin.test.services.JsLibraryProvider +import org.jetbrains.kotlin.test.services.TestService +import org.jetbrains.kotlin.test.services.TestServices abstract class AbstractFirDiagnosticTestBase(val parser: FirParser) : AbstractKotlinCompilerTest() { override fun TestConfigurationBuilder.configuration() { @@ -49,12 +52,23 @@ abstract class AbstractFirDiagnosticTestBase(val parser: FirParser) : AbstractKo } abstract class AbstractFirPsiDiagnosticTest : AbstractFirDiagnosticTestBase(FirParser.Psi) -abstract class AbstractFirLightTreeDiagnosticsTest : AbstractFirDiagnosticTestBase(FirParser.LightTree) +abstract class AbstractFirLightTreeDiagnosticsTest : AbstractFirDiagnosticTestBase(FirParser.LightTree) { + override fun configure(builder: TestConfigurationBuilder) { + super.configure(builder) + builder.useAdditionalService { LightTreeSyntaxDiagnosticsReporterHolder() } + } +} + +class LightTreeSyntaxDiagnosticsReporterHolder : TestService { + val reporter = SimpleDiagnosticsCollector() +} + +val TestServices.lightTreeSyntaxDiagnosticsReporterHolder: LightTreeSyntaxDiagnosticsReporterHolder? by TestServices.nullableTestServiceAccessor() abstract class AbstractFirWithActualizerDiagnosticsTest(val parser: FirParser) : AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JVM_IR) { override fun configure(builder: TestConfigurationBuilder) { super.configure(builder) - with (builder) { + with(builder) { defaultDirectives { +CodegenTestDirectives.IGNORE_FIR2IR_EXCEPTIONS_IF_FIR_CONTAINS_ERRORS } diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt index 1c0038fb072..8b57dcaba69 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.builtins.DefaultBuiltIns -import org.jetbrains.kotlin.config.LanguageVersionSettings +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.KtDiagnostic import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector @@ -48,6 +48,7 @@ class FirAnalyzerFacade( val irGeneratorExtensions: Collection, val parser: FirParser, val enablePluginPhases: Boolean = false, + val diagnosticReporterForLightTree: DiagnosticReporter? = null ) : AbstractFirAnalyzerFacade() { private var firFiles: List? = null private var _scopeSession: ScopeSession? = null @@ -61,7 +62,7 @@ class FirAnalyzerFacade( val firProvider = (session.firProvider as FirProviderImpl) firFiles = when (parser) { FirParser.LightTree -> { - val builder = LightTree2Fir(session, firProvider.kotlinScopeProvider) + val builder = LightTree2Fir(session, firProvider.kotlinScopeProvider, diagnosticReporterForLightTree) lightTreeFiles.map { builder.buildFirFile(it.lightTree, it.sourceFile, it.linesMapping).also { firFile -> firProvider.recordFile(firFile)