From fa3f8055738f9b112cad36cf1d721e7434c1694e Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Tue, 17 Nov 2020 18:05:30 +0300 Subject: [PATCH] Support FirDiagnostic.isValid properly Diagnostic is considered valid in this commit if it's reported on a syntactically non-erroneous element without erroneous last child --- .../fir/analysis/diagnostics/FirDiagnostic.kt | 2 +- .../diagnostics/FirDiagnosticFactory.kt | 5 ++++ .../LightTreePositioningStrategy.kt | 28 ++++++++++++++++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt index 96cb228f5ba..d319a2d32c1 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnostic.kt @@ -25,7 +25,7 @@ sealed class FirDiagnostic : Diagnostic { get() = factory.getTextRanges(this) override val isValid: Boolean - get() = true + get() = factory.isValid(this) } sealed class FirSimpleDiagnostic : FirDiagnostic() { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt index e8dae007b45..d8428c7053a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticFactory.kt @@ -29,6 +29,11 @@ sealed class AbstractFirDiagnosticFactory): List = positioningStrategy.markDiagnostic(diagnostic) + + fun isValid(diagnostic: FirDiagnostic<*>): Boolean { + val element = diagnostic.element + return positioningStrategy.isValid(element.lighterASTNode, element.treeStructure) + } } class FirDiagnosticFactory0( diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategy.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategy.kt index 6e6bdf7bbe2..a234035a711 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategy.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategy.kt @@ -6,9 +6,13 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics import com.intellij.lang.LighterASTNode +import com.intellij.openapi.util.Ref import com.intellij.openapi.util.TextRange +import com.intellij.psi.TokenType import com.intellij.util.diff.FlyweightCapableTreeStructure -import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.lexer.KtSingleValueToken +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.lexer.KtTokens.WHITE_SPACE open class LightTreePositioningStrategy { open fun markDiagnostic(diagnostic: FirDiagnostic<*>): List { @@ -20,6 +24,10 @@ open class LightTreePositioningStrategy { return markElement(node, tree) } + open fun isValid(node: LighterASTNode, tree: FlyweightCapableTreeStructure): Boolean { + return !hasSyntaxErrors(node, tree) + } + companion object { val DEFAULT = LightTreePositioningStrategies.DEFAULT } @@ -32,3 +40,21 @@ fun markElement(node: LighterASTNode, tree: FlyweightCapableTreeStructure): List { return listOf(TextRange(tree.getStartOffset(from), tree.getEndOffset(to))) } + +private val DOC_AND_COMMENT_TOKENS = setOf( + WHITE_SPACE, KtTokens.IDENTIFIER, + KtTokens.EOL_COMMENT, KtTokens.BLOCK_COMMENT, KtTokens.SHEBANG_COMMENT, KtTokens.DOC_COMMENT +) + +private fun hasSyntaxErrors(node: LighterASTNode, tree: FlyweightCapableTreeStructure): Boolean { + if (node.tokenType == TokenType.ERROR_ELEMENT) return true + + val childrenRef = Ref>() + tree.getChildren(node, childrenRef) + val children = childrenRef.get() + return children.lastOrNull { + val tokenType = it.tokenType + tokenType !is KtSingleValueToken && tokenType !in DOC_AND_COMMENT_TOKENS + }?.let { hasSyntaxErrors(it, tree) } == true +} +