diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/highlighter/KotlinHighLevelDiagnosticHighlightingPass.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/highlighter/KotlinHighLevelDiagnosticHighlightingPass.kt index 1d78992647c..5767188e69a 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/highlighter/KotlinHighLevelDiagnosticHighlightingPass.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/fir/highlighter/KotlinHighLevelDiagnosticHighlightingPass.kt @@ -12,6 +12,7 @@ import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar import com.intellij.codeInsight.daemon.impl.HighlightInfo import com.intellij.codeInsight.daemon.impl.HighlightInfoType import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.Editor import com.intellij.openapi.progress.ProgressIndicator @@ -19,7 +20,10 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.frontend.api.analyze +import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic +import org.jetbrains.kotlin.idea.frontend.api.diagnostics.getMessageWithFactoryName import org.jetbrains.kotlin.idea.highlighter.Diagnostic2Annotation import org.jetbrains.kotlin.idea.highlighter.IdeErrorMessages import org.jetbrains.kotlin.psi.KtElement @@ -37,7 +41,7 @@ class KotlinHighLevelDiagnosticHighlightingPass( if (!diagnostic.isValid) return@forEach diagnostic.textRanges.forEach { range -> HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR/*TODO*/) - .descriptionAndTooltip(Diagnostic2Annotation.getMessage(diagnostic, IdeErrorMessages::render)) + .descriptionAndTooltip(diagnostic.getMessageToRender()) .range(range) .create() ?.let(diagnosticInfos::add) @@ -45,6 +49,11 @@ class KotlinHighLevelDiagnosticHighlightingPass( } } + private fun KtDiagnostic.getMessageToRender(): String = + if (ApplicationManager.getApplication().isInternal || ApplicationManager.getApplication().isUnitTestMode) + getMessageWithFactoryName() + else message + override fun doApplyInformationToEditor() { UpdateHighlightersUtil.setHighlightersToEditor( diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt index f06355cd03a..7e0dc55132c 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt @@ -6,9 +6,9 @@ package org.jetbrains.kotlin.idea.frontend.api import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.frontend.api.calls.KtCall import org.jetbrains.kotlin.idea.frontend.api.components.* +import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic import org.jetbrains.kotlin.idea.frontend.api.scopes.* import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithDeclarations @@ -82,9 +82,9 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali fun KtClassOrObjectSymbol.buildSelfClassType(): KtType = typeProvider.buildSelfClassType(this) - fun KtElement.getDiagnostics(): Collection = diagnosticProvider.getDiagnosticsForElement(this) + fun KtElement.getDiagnostics(): Collection = diagnosticProvider.getDiagnosticsForElement(this) - fun KtFile.collectDiagnosticsForFile(): Collection = diagnosticProvider.collectDiagnosticsForFile(this) + fun KtFile.collectDiagnosticsForFile(): Collection = diagnosticProvider.collectDiagnosticsForFile(this) fun KtSymbolWithKind.getContainingSymbol(): KtSymbolWithKind? = containingDeclarationProvider.getContainingDeclaration(this) diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtDiagnosticProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtDiagnosticProvider.kt index f4384eaa680..692c20eae66 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtDiagnosticProvider.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtDiagnosticProvider.kt @@ -5,11 +5,11 @@ package org.jetbrains.kotlin.idea.frontend.api.components -import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile abstract class KtDiagnosticProvider : KtAnalysisSessionComponent() { - abstract fun getDiagnosticsForElement(element: KtElement): Collection - abstract fun collectDiagnosticsForFile(ktFile: KtFile): Collection + abstract fun getDiagnosticsForElement(element: KtElement): Collection + abstract fun collectDiagnosticsForFile(ktFile: KtFile): Collection } diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/diagnostics/KtDiagnostic.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/diagnostics/KtDiagnostic.kt index 71c3d1501bd..a666b282908 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/diagnostics/KtDiagnostic.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/diagnostics/KtDiagnostic.kt @@ -5,8 +5,21 @@ package org.jetbrains.kotlin.idea.frontend.api.diagnostics -sealed class KtDiagnostic { - abstract val message: String +import com.intellij.openapi.util.TextRange + +interface KtDiagnostic { + val factoryName: String? + val message: String + val textRanges: Collection + val isValid: Boolean get() = true } -data class KtSimpleDiagnostic(override val message: String): KtDiagnostic() \ No newline at end of file +fun KtDiagnostic.getMessageWithFactoryName(): String = + if (factoryName == null) message + else "[$factoryName] $message" + +data class KtSimpleDiagnostic( + override val factoryName: String?, + override val message: String, + override val textRanges: Collection, +) : KtDiagnostic \ 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/FirModuleResolveStateForCompletion.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/FirModuleResolveStateForCompletion.kt index 02e2b60edf7..b72b9f4ebf6 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 @@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirResolvePhase @@ -83,11 +84,11 @@ internal class FirModuleResolveStateForCompletion( } - override fun getDiagnostics(element: KtElement): List { + override fun getDiagnostics(element: KtElement): List> { error("Diagnostics should not be retrieved in completion") } - override fun collectDiagnosticsForFile(ktFile: KtFile): Collection { + override fun collectDiagnosticsForFile(ktFile: KtFile): Collection> { error("Diagnostics should not be retrieved in completion") } 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 aff59fec385..874301b35d0 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 @@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirResolvePhase @@ -68,10 +69,10 @@ internal class FirModuleResolveStateImpl( override fun getFirFile(ktFile: KtFile): FirFile = firFileBuilder.buildRawFirFileWithCaching(ktFile, rootModuleSession.cache, lazyBodiesMode = false) - override fun getDiagnostics(element: KtElement): List = + override fun getDiagnostics(element: KtElement): List> = diagnosticsCollector.getDiagnosticsFor(element) - override fun collectDiagnosticsForFile(ktFile: KtFile): Collection = + override fun collectDiagnosticsForFile(ktFile: KtFile): Collection> = diagnosticsCollector.collectDiagnosticsForFile(ktFile) override fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile? { 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 c084c9c823e..07112416bba 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 @@ -9,6 +9,7 @@ import org.jetbrains.annotations.TestOnly import com.intellij.openapi.project.Project import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.fir.* +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.FirTowerDataContext import org.jetbrains.kotlin.fir.resolve.providers.FirProvider @@ -36,9 +37,9 @@ abstract class FirModuleResolveState { internal abstract fun isFirFileBuilt(ktFile: KtFile): Boolean - internal abstract fun getDiagnostics(element: KtElement): List + internal abstract fun getDiagnostics(element: KtElement): List> - internal abstract fun collectDiagnosticsForFile(ktFile: KtFile): Collection + internal abstract fun collectDiagnosticsForFile(ktFile: KtFile): Collection> @TestOnly internal abstract fun getBuiltFirFileOrNull(ktFile: KtFile): FirFile? diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/LowLevelFirApiFacade.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/LowLevelFirApiFacade.kt index 13d6ac803a8..5823adde819 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/LowLevelFirApiFacade.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/api/LowLevelFirApiFacade.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.api import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.render @@ -120,13 +121,13 @@ fun D.withFirDeclaration( /** * Returns a list of Diagnostics compiler finds for given [KtElement] */ -fun KtElement.getDiagnostics(resolveState: FirModuleResolveState): Collection = +fun KtElement.getDiagnostics(resolveState: FirModuleResolveState): Collection> = resolveState.getDiagnostics(this) /** * Returns a list of Diagnostics compiler finds for given [KtFile] */ -fun KtFile.collectDiagnosticsForFile(resolveState: FirModuleResolveState): Collection = +fun KtFile.collectDiagnosticsForFile(resolveState: FirModuleResolveState): Collection> = resolveState.collectDiagnosticsForFile(this) /** diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt index 4a4f927c2aa..0bb4e9d8f8a 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/AbstractFirIdeDiagnosticsCollector.kt @@ -36,7 +36,7 @@ internal abstract class AbstractFirIdeDiagnosticsCollector( registerAllComponents() } - protected abstract fun onDiagnostic(diagnostic: Diagnostic) + protected abstract fun onDiagnostic(diagnostic: FirPsiDiagnostic<*>) private inner class Reporter : DiagnosticReporter() { diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/DiagnosticsCollector.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/DiagnosticsCollector.kt index 00a69635a81..227a091fb15 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/DiagnosticsCollector.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/DiagnosticsCollector.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.FileStructureCache import org.jetbrains.kotlin.psi.KtElement @@ -15,13 +16,13 @@ internal class DiagnosticsCollector( private val fileStructureCache: FileStructureCache, private val cache: ModuleFileCache, ) { - fun getDiagnosticsFor(element: KtElement): List = + fun getDiagnosticsFor(element: KtElement): List> = fileStructureCache .getFileStructure(element.containingKtFile, cache) .getStructureElementFor(element) .diagnostics.diagnosticsFor(element) - fun collectDiagnosticsForFile(ktFile: KtFile): Collection = + fun collectDiagnosticsForFile(ktFile: KtFile): Collection> = fileStructureCache .getFileStructure(ktFile, cache) .getAllDiagnosticsForFile() diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeFileDiagnosticsCollector.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeFileDiagnosticsCollector.kt index 55b13fd865a..b75ec1041fd 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeFileDiagnosticsCollector.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeFileDiagnosticsCollector.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.fir.declarations.FirFile internal class FirIdeFileDiagnosticsCollector private constructor( @@ -14,14 +15,14 @@ internal class FirIdeFileDiagnosticsCollector private constructor( ) : AbstractFirIdeDiagnosticsCollector( session, ) { - private val result = mutableListOf() + private val result = mutableListOf>() - override fun onDiagnostic(diagnostic: Diagnostic) { + override fun onDiagnostic(diagnostic: FirPsiDiagnostic<*>) { result += diagnostic } companion object { - fun collectForFile(firFile: FirFile): List = + fun collectForFile(firFile: FirFile): List> = FirIdeFileDiagnosticsCollector(firFile.session).let { collector -> collector.collectDiagnostics(firFile) collector.result diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeStructureElementDiagnosticsCollector.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeStructureElementDiagnosticsCollector.kt index 57e5c9dd0bb..cac6b26af64 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeStructureElementDiagnosticsCollector.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/diagnostics/FirIdeStructureElementDiagnosticsCollector.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.collectors.DiagnosticCollectorDeclarationAction +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.psi @@ -23,9 +24,9 @@ internal class FirIdeStructureElementDiagnosticsCollector private constructor( ) : AbstractFirIdeDiagnosticsCollector( session, ) { - private val result = mutableMapOf>() + private val result = mutableMapOf>>() - override fun onDiagnostic(diagnostic: Diagnostic) { + override fun onDiagnostic(diagnostic: FirPsiDiagnostic<*>) { (diagnostic.psiElement as? KtElement)?.let { ktElement -> result.addValueFor(ktElement, diagnostic) } diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructure.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructure.kt index f90e7e4746a..7ba5a4978de 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructure.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructure.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.file.structure import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirTowerDataContextCollector @@ -56,7 +57,7 @@ internal class FileStructure( } @OptIn(ExperimentalStdlibApi::class) - fun getAllDiagnosticsForFile(): Collection { + fun getAllDiagnosticsForFile(): Collection> { val containersForStructureElement = buildList { add(ktFile) addAll(ktFile.declarations) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt index d5e36707d4e..c1c28f4a054 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/file/structure/FileStructureElement.kt @@ -8,6 +8,8 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.file.structure import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.analysis.collectors.DiagnosticCollectorDeclarationAction +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic +import org.jetbrains.kotlin.fir.containingClass import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol @@ -23,11 +25,11 @@ import org.jetbrains.kotlin.idea.fir.low.level.api.util.ktDeclaration import org.jetbrains.kotlin.psi.* internal class FileStructureElementDiagnostics( - private val map: Map> + private val map: Map>> ) { - fun diagnosticsFor(element: KtElement): List = map[element] ?: emptyList() + fun diagnosticsFor(element: KtElement): List> = map[element] ?: emptyList() - inline fun forEach(action: (List) -> Unit) = map.values.forEach(action) + inline fun forEach(action: (List>) -> Unit) = map.values.forEach(action) } internal sealed class FileStructureElement { diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt index f94b9c3b73c..1a67d4f3829 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt @@ -40,7 +40,7 @@ private constructor( override val smartCastProvider: KtSmartCastProvider = KtFirSmartcastProvider(this, token) override val expressionTypeProvider: KtExpressionTypeProvider = KtFirExpressionTypeProvider(this, token) - override val diagnosticProvider: KtDiagnosticProvider = KtFirDiagnosticProvider(this, token) + public override val diagnosticProvider: KtDiagnosticProvider = KtFirDiagnosticProvider(this, token) override val containingDeclarationProvider = KtFirSymbolContainingDeclarationProvider(this, token) override val callResolver: KtCallResolver = KtFirCallResolver(this, token) override val scopeProvider by threadLocal { KtFirScopeProvider(this, firSymbolBuilder, project, firResolveState, token) } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirAnalysisSessionComponent.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirAnalysisSessionComponent.kt index 4690e370358..93dcfd1dffd 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirAnalysisSessionComponent.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirAnalysisSessionComponent.kt @@ -5,8 +5,12 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext +import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession internal interface KtFirAnalysisSessionComponent { @@ -16,6 +20,12 @@ internal interface KtFirAnalysisSessionComponent { val firResolveState get() = analysisSession.firResolveState fun ConeKotlinType.asKtType() = analysisSession.firSymbolBuilder.buildKtType(this) + fun FirPsiDiagnostic<*>.asKtDiagnostic(): KtDiagnostic = + (analysisSession.diagnosticProvider as KtFirDiagnosticProvider).firDiagnosticAsKtDiagnostic(this) + + fun ConeDiagnostic.asKtDiagnostic(source: FirSourceElement): KtDiagnostic? = + (analysisSession.diagnosticProvider as KtFirDiagnosticProvider).coneDiagnosticAsKtDiagnostic(this, source) + fun createTypeCheckerContext() = ConeTypeCheckerContext( isErrorTypeEqualsToAnything = true, isStubTypeEqualsToAnything = true, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt index a1deb37a83a..a3fdbef7295 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirCallResolver.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostic import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression @@ -112,13 +113,13 @@ internal class KtFirCallResolver( private fun FirErrorNamedReference.createErrorCallTarget(): KtErrorCallTarget = KtErrorCallTarget( getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol }, - KtSimpleDiagnostic(diagnostic.reason) + source?.let { diagnostic.asKtDiagnostic(it) } ?: KtSimpleDiagnostic(factoryName = null, diagnostic.reason, emptyList()) ) private fun FirErrorReferenceWithCandidate.createErrorCallTarget(): KtErrorCallTarget = KtErrorCallTarget( getCandidateSymbols().mapNotNull { it.fir.buildSymbol(firSymbolBuilder) as? KtFunctionLikeSymbol }, - KtSimpleDiagnostic(diagnostic.reason) + source?.let { diagnostic.asKtDiagnostic(it) } ?: KtSimpleDiagnostic(factoryName = null, diagnostic.reason, emptyList()) ) private fun FirResolvedNamedReference.getKtFunctionOrConstructorSymbol(): KtFunctionLikeSymbol? = diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirDiagnosticProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirDiagnosticProvider.kt index 281849f1682..530909f39c5 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirDiagnosticProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirDiagnosticProvider.kt @@ -5,13 +5,19 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components -import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.fir.FirSourceElement +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic +import org.jetbrains.kotlin.fir.analysis.diagnostics.toFirDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.idea.fir.low.level.api.api.collectDiagnosticsForFile import org.jetbrains.kotlin.idea.fir.low.level.api.api.getDiagnostics import org.jetbrains.kotlin.idea.frontend.api.ValidityToken import org.jetbrains.kotlin.idea.frontend.api.components.KtDiagnosticProvider +import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtDiagnostic +import org.jetbrains.kotlin.idea.frontend.api.diagnostics.KtSimpleDiagnostic import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion +import org.jetbrains.kotlin.idea.highlighter.IdeErrorMessages import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile @@ -19,10 +25,21 @@ internal class KtFirDiagnosticProvider( override val analysisSession: KtFirAnalysisSession, override val token: ValidityToken, ) : KtDiagnosticProvider(), KtFirAnalysisSessionComponent { - override fun getDiagnosticsForElement(element: KtElement): Collection = withValidityAssertion { - element.getDiagnostics(firResolveState) + override fun getDiagnosticsForElement(element: KtElement): Collection = withValidityAssertion { + element.getDiagnostics(firResolveState).map { it.asKtDiagnostic() } } - override fun collectDiagnosticsForFile(ktFile: KtFile): Collection = - ktFile.collectDiagnosticsForFile(firResolveState) + override fun collectDiagnosticsForFile(ktFile: KtFile): Collection = + ktFile.collectDiagnosticsForFile(firResolveState).map { it.asKtDiagnostic() } + + fun firDiagnosticAsKtDiagnostic(diagnostic: FirPsiDiagnostic<*>): KtDiagnostic { + val message = IdeErrorMessages.render(diagnostic) + return KtSimpleDiagnostic(diagnostic.factory.name, message, diagnostic.textRanges) + } + + fun coneDiagnosticAsKtDiagnostic(coneDiagnostic: ConeDiagnostic, source: FirSourceElement): KtDiagnostic? { + val firDiagnostic = coneDiagnostic.toFirDiagnostic(source) ?: return null + check(firDiagnostic is FirPsiDiagnostic<*>) + return firDiagnosticAsKtDiagnostic(firDiagnostic) + } } \ No newline at end of file