FIR IDE: support reporting of FirLightSourceElement based diagnostics
This commit is contained in:
committed by
TeamCityServer
parent
47e8b2f9dc
commit
e2786197ff
@@ -200,20 +200,20 @@ sealed class FirPsiSourceElement<out P : PsiElement>(val psi: P) : FirSourceElem
|
|||||||
|
|
||||||
override val treeStructure: FlyweightCapableTreeStructure<LighterASTNode> by lazy { WrappedTreeStructure(psi.containingFile) }
|
override val treeStructure: FlyweightCapableTreeStructure<LighterASTNode> by lazy { WrappedTreeStructure(psi.containingFile) }
|
||||||
|
|
||||||
private class WrappedTreeStructure(file: PsiFile) : FlyweightCapableTreeStructure<LighterASTNode> {
|
internal class WrappedTreeStructure(file: PsiFile) : FlyweightCapableTreeStructure<LighterASTNode> {
|
||||||
private val lighterAST = TreeBackedLighterAST(file.node)
|
private val lighterAST = TreeBackedLighterAST(file.node)
|
||||||
|
|
||||||
private fun LighterASTNode.unwrap() = lighterAST.unwrap(this)
|
fun unwrap(node: LighterASTNode) = lighterAST.unwrap(node)
|
||||||
|
|
||||||
override fun toString(node: LighterASTNode): CharSequence = node.unwrap().text
|
override fun toString(node: LighterASTNode): CharSequence = unwrap(node).text
|
||||||
|
|
||||||
override fun getRoot(): LighterASTNode = lighterAST.root
|
override fun getRoot(): LighterASTNode = lighterAST.root
|
||||||
|
|
||||||
override fun getParent(node: LighterASTNode): LighterASTNode? =
|
override fun getParent(node: LighterASTNode): LighterASTNode? =
|
||||||
node.unwrap().psi.parent?.node?.let { TreeBackedLighterAST.wrap(it) }
|
unwrap(node).psi.parent?.node?.let { TreeBackedLighterAST.wrap(it) }
|
||||||
|
|
||||||
override fun getChildren(node: LighterASTNode, nodesRef: Ref<Array<LighterASTNode>>): Int {
|
override fun getChildren(node: LighterASTNode, nodesRef: Ref<Array<LighterASTNode>>): Int {
|
||||||
val psi = node.unwrap().psi
|
val psi = unwrap(node).psi
|
||||||
val children = mutableListOf<PsiElement>()
|
val children = mutableListOf<PsiElement>()
|
||||||
var child = psi.firstChild
|
var child = psi.firstChild
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
@@ -232,7 +232,7 @@ sealed class FirPsiSourceElement<out P : PsiElement>(val psi: P) : FirSourceElem
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getStartOffset(node: LighterASTNode): Int {
|
override fun getStartOffset(node: LighterASTNode): Int {
|
||||||
return getStartOffset(node.unwrap().psi)
|
return getStartOffset(unwrap(node).psi)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getStartOffset(element: PsiElement): Int {
|
private fun getStartOffset(element: PsiElement): Int {
|
||||||
@@ -249,7 +249,7 @@ sealed class FirPsiSourceElement<out P : PsiElement>(val psi: P) : FirSourceElem
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getEndOffset(node: LighterASTNode): Int {
|
override fun getEndOffset(node: LighterASTNode): Int {
|
||||||
return getEndOffset(node.unwrap().psi)
|
return getEndOffset(unwrap(node).psi)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getEndOffset(element: PsiElement): Int {
|
private fun getEndOffset(element: PsiElement): Int {
|
||||||
@@ -296,6 +296,19 @@ class FirLightSourceElement(
|
|||||||
) : FirSourceElement() {
|
) : FirSourceElement() {
|
||||||
override val elementType: IElementType
|
override val elementType: IElementType
|
||||||
get() = lighterASTNode.tokenType
|
get() = lighterASTNode.tokenType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We can create a [FirLightSourceElement] from a [FirPsiSourceElement] by using [FirPsiSourceElement.lighterASTNode];
|
||||||
|
* [unwrapToFirPsiSourceElement] allows to get original [FirPsiSourceElement] in such case.
|
||||||
|
*
|
||||||
|
* If it is `pure` [FirLightSourceElement], i.e, compiler created it in light tree mode, then return [unwrapToFirPsiSourceElement] `null`.
|
||||||
|
* Otherwise, return some not-null result.
|
||||||
|
*/
|
||||||
|
fun unwrapToFirPsiSourceElement(): FirPsiSourceElement<*>? {
|
||||||
|
if (treeStructure !is FirPsiSourceElement.WrappedTreeStructure) return null
|
||||||
|
val node = treeStructure.unwrap(lighterASTNode)
|
||||||
|
return node.psi?.toFirPsiSourceElement(kind)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val FirSourceElement?.psi: PsiElement? get() = (this as? FirPsiSourceElement<*>)?.psi
|
val FirSourceElement?.psi: PsiElement? get() = (this as? FirPsiSourceElement<*>)?.psi
|
||||||
|
|||||||
+47
-17
@@ -5,29 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics
|
package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.SessionConfiguration
|
import org.jetbrains.kotlin.fir.SessionConfiguration
|
||||||
import org.jetbrains.kotlin.fir.analysis.CheckersComponent
|
import org.jetbrains.kotlin.fir.analysis.CheckersComponent
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.PersistentCheckerContext
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.CheckerRunningDiagnosticCollectorVisitor
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.*
|
import org.jetbrains.kotlin.fir.analysis.collectors.components.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
|
import org.jetbrains.kotlin.fir.checkers.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
|
||||||
import org.jetbrains.kotlin.fir.checkers.CommonDeclarationCheckers
|
|
||||||
import org.jetbrains.kotlin.fir.checkers.CommonExpressionCheckers
|
|
||||||
import org.jetbrains.kotlin.fir.checkers.ExtendedDeclarationCheckers
|
|
||||||
import org.jetbrains.kotlin.fir.checkers.ExtendedExpressionCheckers
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.ImplicitBodyResolveComputationSession
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.createReturnTypeCalculatorForIDE
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.element.builder.FirIdeDesignatedBodyResolveTransformerForReturnTypeCalculator
|
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.checkCanceled
|
|
||||||
|
|
||||||
internal abstract class AbstractFirIdeDiagnosticsCollector(
|
internal abstract class AbstractFirIdeDiagnosticsCollector(
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
@@ -53,9 +42,16 @@ internal abstract class AbstractFirIdeDiagnosticsCollector(
|
|||||||
|
|
||||||
private inner class Reporter : DiagnosticReporter() {
|
private inner class Reporter : DiagnosticReporter() {
|
||||||
override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) {
|
override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) {
|
||||||
if (diagnostic !is FirPsiDiagnostic<*>) return
|
if (diagnostic == null) return
|
||||||
if (context.isDiagnosticSuppressed(diagnostic)) return
|
if (context.isDiagnosticSuppressed(diagnostic)) return
|
||||||
onDiagnostic(diagnostic)
|
|
||||||
|
val psiDiagnostic = when (diagnostic) {
|
||||||
|
is FirPsiDiagnostic<*> -> diagnostic
|
||||||
|
is FirLightDiagnostic -> diagnostic.toPsiDiagnostic()
|
||||||
|
else -> error("Unknown diagnostic type ${diagnostic::class.simpleName}")
|
||||||
|
}
|
||||||
|
|
||||||
|
onDiagnostic(psiDiagnostic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +68,40 @@ internal abstract class AbstractFirIdeDiagnosticsCollector(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirLightDiagnostic.toPsiDiagnostic(): FirPsiDiagnostic<*> {
|
||||||
|
val psiSourceElement = element.unwrapToFirPsiSourceElement()
|
||||||
|
?: error("Diagnostic should be created from PSI in IDE")
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return when (this) {
|
||||||
|
is FirLightSimpleDiagnostic -> FirPsiSimpleDiagnostic(
|
||||||
|
psiSourceElement,
|
||||||
|
severity,
|
||||||
|
factory as FirDiagnosticFactory0<PsiElement>
|
||||||
|
)
|
||||||
|
|
||||||
|
is FirLightDiagnosticWithParameters1<*> -> FirPsiDiagnosticWithParameters1(
|
||||||
|
psiSourceElement,
|
||||||
|
a,
|
||||||
|
severity,
|
||||||
|
factory as FirDiagnosticFactory1<PsiElement, Any>
|
||||||
|
)
|
||||||
|
|
||||||
|
is FirLightDiagnosticWithParameters2<*, *> -> FirPsiDiagnosticWithParameters2(
|
||||||
|
psiSourceElement,
|
||||||
|
a, b,
|
||||||
|
severity,
|
||||||
|
factory as FirDiagnosticFactory2<PsiElement, Any, Any>
|
||||||
|
)
|
||||||
|
|
||||||
|
is FirLightDiagnosticWithParameters3<*, *, *> -> FirPsiDiagnosticWithParameters3(
|
||||||
|
psiSourceElement,
|
||||||
|
a, b, c,
|
||||||
|
severity,
|
||||||
|
factory as FirDiagnosticFactory3<PsiElement, Any, Any, Any>
|
||||||
|
)
|
||||||
|
else -> error("Unknown diagnostic type ${this::class.simpleName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private object CheckersFactory {
|
private object CheckersFactory {
|
||||||
private val extendedDeclarationCheckers = createDeclarationCheckers(ExtendedDeclarationCheckers)
|
private val extendedDeclarationCheckers = createDeclarationCheckers(ExtendedDeclarationCheckers)
|
||||||
|
|||||||
Reference in New Issue
Block a user