FIR IDE: fix collecting diagnostics multiple times for the same declaration
^KT-45199 fixed
This commit is contained in:
+16
-16
@@ -58,7 +58,7 @@ abstract class AbstractDiagnosticCollector(
|
|||||||
|
|
||||||
@Suppress("LeakingThis")
|
@Suppress("LeakingThis")
|
||||||
private var context = PersistentCheckerContext(this, returnTypeCalculator)
|
private var context = PersistentCheckerContext(this, returnTypeCalculator)
|
||||||
private var currentAction = DiagnosticCollectorDeclarationAction.CHECK_CURRENT_DECLARATION_AND_CHECK_NESTED
|
private var currentAction = DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
|
|
||||||
fun initializeComponents(vararg components: AbstractDiagnosticCollectorComponent) {
|
fun initializeComponents(vararg components: AbstractDiagnosticCollectorComponent) {
|
||||||
if (componentsInitialized) {
|
if (componentsInitialized) {
|
||||||
@@ -72,9 +72,11 @@ abstract class AbstractDiagnosticCollector(
|
|||||||
|
|
||||||
private inner class Visitor : FirDefaultVisitor<Unit, Nothing?>() {
|
private inner class Visitor : FirDefaultVisitor<Unit, Nothing?>() {
|
||||||
private fun <T : FirElement> T.runComponents() {
|
private fun <T : FirElement> T.runComponents() {
|
||||||
components.forEach {
|
if (currentAction.checkInCurrentDeclaration) {
|
||||||
beforeCollecting()
|
components.forEach {
|
||||||
this.accept(it, context)
|
beforeCollecting()
|
||||||
|
this.accept(it, context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,13 +222,11 @@ abstract class AbstractDiagnosticCollector(
|
|||||||
declaration: FirDeclaration,
|
declaration: FirDeclaration,
|
||||||
block: () -> Unit = { declaration.acceptChildren(this, null) }
|
block: () -> Unit = { declaration.acceptChildren(this, null) }
|
||||||
) {
|
) {
|
||||||
if (!currentAction.checkNested) return
|
if (!currentAction.lookupForNestedDeclaration) return
|
||||||
|
|
||||||
val action = onDeclarationEnter(declaration)
|
val action = getDeclarationActionOnDeclarationEnter(declaration)
|
||||||
if (action.checkCurrentDeclaration) {
|
|
||||||
declaration.runComponents()
|
|
||||||
}
|
|
||||||
withDiagnosticsAction(action) {
|
withDiagnosticsAction(action) {
|
||||||
|
declaration.runComponents()
|
||||||
withDeclaration(declaration) {
|
withDeclaration(declaration) {
|
||||||
block()
|
block()
|
||||||
}
|
}
|
||||||
@@ -258,8 +258,8 @@ abstract class AbstractDiagnosticCollector(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun onDeclarationEnter(declaration: FirDeclaration): DiagnosticCollectorDeclarationAction =
|
protected open fun getDeclarationActionOnDeclarationEnter(declaration: FirDeclaration): DiagnosticCollectorDeclarationAction =
|
||||||
DiagnosticCollectorDeclarationAction.CHECK_CURRENT_DECLARATION_AND_CHECK_NESTED
|
DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
|
|
||||||
protected open fun onDeclarationExit(declaration: FirDeclaration) {}
|
protected open fun onDeclarationExit(declaration: FirDeclaration) {}
|
||||||
|
|
||||||
@@ -334,11 +334,11 @@ abstract class AbstractDiagnosticCollector(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class DiagnosticCollectorDeclarationAction(val checkCurrentDeclaration: Boolean, val checkNested: Boolean) {
|
enum class DiagnosticCollectorDeclarationAction(val checkInCurrentDeclaration: Boolean, val lookupForNestedDeclaration: Boolean) {
|
||||||
CHECK_CURRENT_DECLARATION_AND_CHECK_NESTED(checkCurrentDeclaration = true, checkNested = true),
|
CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED(checkInCurrentDeclaration = true, lookupForNestedDeclaration = true),
|
||||||
CHECK_CURRENT_DECLARATION_AND_SKIP_NESTED(checkCurrentDeclaration = true, checkNested = false),
|
CHECK_IN_CURRENT_DECLARATION_AND_DO_NOT_LOOKUP_FOR_NESTED(checkInCurrentDeclaration = true, lookupForNestedDeclaration = false),
|
||||||
SKIP_CURRENT_DECLARATION_AND_CHECK_NESTED(checkCurrentDeclaration = false, checkNested = true),
|
DO_NOT_CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED(checkInCurrentDeclaration = false, lookupForNestedDeclaration = true),
|
||||||
SKIP(checkCurrentDeclaration = false, checkNested = false),
|
SKIP(checkInCurrentDeclaration = false, lookupForNestedDeclaration = false),
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AbstractDiagnosticCollector.registerAllComponents() {
|
fun AbstractDiagnosticCollector.registerAllComponents() {
|
||||||
|
|||||||
+1
@@ -10,6 +10,7 @@ import com.intellij.util.SmartList
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirPsiDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DiagnosticCheckerFilter
|
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DiagnosticCheckerFilter
|
||||||
|
import org.jetbrains.kotlin.idea.fir.low.level.api.file.structure.FileStructureElement
|
||||||
|
|
||||||
internal class FileStructureElementDiagnostics(
|
internal class FileStructureElementDiagnostics(
|
||||||
private val firFile: FirFile,
|
private val firFile: FirFile,
|
||||||
|
|||||||
+1
-1
@@ -49,7 +49,7 @@ internal class FileStructureElementDiagnosticsCollector private constructor(priv
|
|||||||
result.addValueFor(diagnostic.psiElement, diagnostic)
|
result.addValueFor(diagnostic.psiElement, diagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDeclarationEnter(
|
override fun getDeclarationActionOnDeclarationEnter(
|
||||||
declaration: FirDeclaration,
|
declaration: FirDeclaration,
|
||||||
): DiagnosticCollectorDeclarationAction =
|
): DiagnosticCollectorDeclarationAction =
|
||||||
onDeclarationEnter.invoke(declaration)
|
onDeclarationEnter.invoke(declaration)
|
||||||
|
|||||||
+9
-9
@@ -60,10 +60,10 @@ internal sealed class ReanalyzableStructureElement<KT : KtDeclaration>(firFile:
|
|||||||
when {
|
when {
|
||||||
firDeclaration == declaration -> {
|
firDeclaration == declaration -> {
|
||||||
inCurrentDeclaration = true
|
inCurrentDeclaration = true
|
||||||
DiagnosticCollectorDeclarationAction.CHECK_CURRENT_DECLARATION_AND_CHECK_NESTED
|
DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
}
|
}
|
||||||
inCurrentDeclaration -> DiagnosticCollectorDeclarationAction.CHECK_CURRENT_DECLARATION_AND_CHECK_NESTED
|
inCurrentDeclaration -> DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
else -> DiagnosticCollectorDeclarationAction.SKIP_CURRENT_DECLARATION_AND_CHECK_NESTED
|
else -> DiagnosticCollectorDeclarationAction.DO_NOT_CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDeclarationExit = { firDeclaration ->
|
onDeclarationExit = { firDeclaration ->
|
||||||
@@ -176,19 +176,19 @@ internal class NonReanalyzableDeclarationStructureElement(
|
|||||||
// Some generated declaration contains structures that we need to check. For example the FIR representation of an
|
// Some generated declaration contains structures that we need to check. For example the FIR representation of an
|
||||||
// enum entry initializer, when present, is a generated anonymous object of kind `ENUM_ENTRY`.
|
// enum entry initializer, when present, is a generated anonymous object of kind `ENUM_ENTRY`.
|
||||||
firDeclaration.isGeneratedDeclaration ->
|
firDeclaration.isGeneratedDeclaration ->
|
||||||
DiagnosticCollectorDeclarationAction.SKIP_CURRENT_DECLARATION_AND_CHECK_NESTED
|
DiagnosticCollectorDeclarationAction.DO_NOT_CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
firDeclaration is FirFile -> DiagnosticCollectorDeclarationAction.CHECK_CURRENT_DECLARATION_AND_CHECK_NESTED
|
firDeclaration is FirFile -> DiagnosticCollectorDeclarationAction.DO_NOT_CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
firDeclaration == fir -> {
|
firDeclaration == fir -> {
|
||||||
inCurrentDeclaration = true
|
inCurrentDeclaration = true
|
||||||
DiagnosticCollectorDeclarationAction.CHECK_CURRENT_DECLARATION_AND_CHECK_NESTED
|
DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
}
|
}
|
||||||
FileElementFactory.isReanalyzableContainer(firDeclaration.ktDeclaration) -> {
|
FileElementFactory.isReanalyzableContainer(firDeclaration.ktDeclaration) -> {
|
||||||
DiagnosticCollectorDeclarationAction.SKIP
|
DiagnosticCollectorDeclarationAction.SKIP
|
||||||
}
|
}
|
||||||
inCurrentDeclaration -> {
|
inCurrentDeclaration -> {
|
||||||
DiagnosticCollectorDeclarationAction.CHECK_CURRENT_DECLARATION_AND_CHECK_NESTED
|
DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
}
|
}
|
||||||
else -> DiagnosticCollectorDeclarationAction.SKIP_CURRENT_DECLARATION_AND_CHECK_NESTED
|
else -> DiagnosticCollectorDeclarationAction.DO_NOT_CHECK_IN_CURRENT_DECLARATION_AND_LOOKUP_FOR_NESTED
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDeclarationExit = { firDeclaration ->
|
onDeclarationExit = { firDeclaration ->
|
||||||
@@ -233,7 +233,7 @@ internal class RootStructureElement(
|
|||||||
private object DiagnosticRetriever : FileStructureElementDiagnosticRetriever() {
|
private object DiagnosticRetriever : FileStructureElementDiagnosticRetriever() {
|
||||||
override fun retrieve(firFile: FirFile, collector: FileStructureElementDiagnosticsCollector): FileStructureElementDiagnosticList {
|
override fun retrieve(firFile: FirFile, collector: FileStructureElementDiagnosticsCollector): FileStructureElementDiagnosticList {
|
||||||
return collector.collectForStructureElement(firFile) { firDeclaration ->
|
return collector.collectForStructureElement(firFile) { firDeclaration ->
|
||||||
if (firDeclaration is FirFile) DiagnosticCollectorDeclarationAction.CHECK_CURRENT_DECLARATION_AND_SKIP_NESTED
|
if (firDeclaration is FirFile) DiagnosticCollectorDeclarationAction.CHECK_IN_CURRENT_DECLARATION_AND_DO_NOT_LOOKUP_FOR_NESTED
|
||||||
else DiagnosticCollectorDeclarationAction.SKIP
|
else DiagnosticCollectorDeclarationAction.SKIP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user