[FIR] Remove not used FirRedundantLabelChecker
This commit is contained in:
-163
@@ -1,163 +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.fir.analysis.checkers.syntax
|
||||
|
||||
import com.intellij.lang.LighterASTNode
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
import org.jetbrains.kotlin.*
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.findChildByType
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.diagnostics.unwrapParenthesesLabelsAndAnnotations
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.buildChildSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
object FirRedundantLabelChecker : FirDeclarationSyntaxChecker<FirDeclaration, PsiElement>() {
|
||||
override fun checkLightTree(
|
||||
element: FirDeclaration,
|
||||
source: KtLightSourceElement,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
// Local declarations are already checked when the containing declaration is checked.
|
||||
if (!isRootLabelContainer(element)) return
|
||||
|
||||
val allTraversalRoots = mutableSetOf<KtSourceElement>()
|
||||
|
||||
// First collect all labels in the declaration
|
||||
element.accept(object : FirVisitorVoid() {
|
||||
override fun visitElement(element: FirElement) {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitBlock(block: FirBlock) {
|
||||
markTraversalRoot(block)
|
||||
super.visitBlock(block)
|
||||
}
|
||||
|
||||
override fun visitProperty(property: FirProperty) {
|
||||
markTraversalRoot(property)
|
||||
super.visitProperty(property)
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
|
||||
markTraversalRoot(simpleFunction)
|
||||
super.visitFunction(simpleFunction)
|
||||
}
|
||||
|
||||
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
|
||||
markTraversalRoot(propertyAccessor)
|
||||
super.visitPropertyAccessor(propertyAccessor)
|
||||
}
|
||||
|
||||
override fun visitConstructor(constructor: FirConstructor) {
|
||||
markTraversalRoot(constructor)
|
||||
super.visitConstructor(constructor)
|
||||
}
|
||||
|
||||
private fun markTraversalRoot(elem: FirElement) {
|
||||
val elemSource = elem.source
|
||||
if (elemSource?.kind is KtRealSourceElementKind) {
|
||||
allTraversalRoots.add(elemSource)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
for (root in allTraversalRoots) {
|
||||
root.treeStructure.reportRedundantLabels(reporter, context, root as KtLightSourceElement, allTraversalRoots)
|
||||
}
|
||||
}
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.reportRedundantLabels(
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext,
|
||||
source: KtLightSourceElement,
|
||||
allTraversalRoots: Set<KtSourceElement>,
|
||||
isChildNode: Boolean = false,
|
||||
) {
|
||||
if (isChildNode && source in allTraversalRoots) return // Prevent double traversal
|
||||
val node = source.lighterASTNode
|
||||
if (node.tokenType == KtNodeTypes.LABELED_EXPRESSION) {
|
||||
val labelQualifier = findChildByType(node, KtNodeTypes.LABEL_QUALIFIER)
|
||||
if (labelQualifier != null) {
|
||||
findChildByType(labelQualifier, KtNodeTypes.LABEL)?.let { labelNode ->
|
||||
when (unwrapParenthesesLabelsAndAnnotations(node).tokenType) {
|
||||
KtNodeTypes.LAMBDA_EXPRESSION, KtNodeTypes.FOR, KtNodeTypes.WHILE, KtNodeTypes.DO_WHILE, KtNodeTypes.FUN -> {}
|
||||
else -> reporter.reportOn(
|
||||
source.buildChildSourceElement(labelNode),
|
||||
FirErrors.REDUNDANT_LABEL_WARNING,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val childrenRef = Ref.create<Array<LighterASTNode?>>(null)
|
||||
getChildren(node, childrenRef)
|
||||
for (child in childrenRef.get() ?: return) {
|
||||
if (child == null) continue
|
||||
reportRedundantLabels(reporter, context, source.buildChildSourceElement(child), allTraversalRoots, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun checkPsi(
|
||||
element: FirDeclaration,
|
||||
source: KtPsiSourceElement,
|
||||
psi: PsiElement,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
// Local declarations are already checked when the containing declaration is checked.
|
||||
if (!isRootLabelContainer(element)) return
|
||||
|
||||
// First collect all labels in the declaration
|
||||
source.psi.accept(object : KtTreeVisitorVoid() {
|
||||
override fun visitLabeledExpression(expression: KtLabeledExpression) {
|
||||
val labelNameExpression = expression.getTargetLabel()
|
||||
|
||||
if (labelNameExpression != null) {
|
||||
val deparenthesizedBaseExpression = KtPsiUtil.deparenthesize(expression)
|
||||
if (deparenthesizedBaseExpression !is KtLambdaExpression &&
|
||||
deparenthesizedBaseExpression !is KtLoopExpression &&
|
||||
deparenthesizedBaseExpression !is KtNamedFunction
|
||||
) {
|
||||
reporter.reportOn(labelNameExpression.toKtPsiSourceElement(), FirErrors.REDUNDANT_LABEL_WARNING, context)
|
||||
}
|
||||
}
|
||||
super.visitLabeledExpression(expression)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun isRootLabelContainer(element: FirDeclaration): Boolean {
|
||||
if (element.source?.kind is KtFakeSourceElementKind) return false
|
||||
if (element is FirCallableDeclaration && element.effectiveVisibility == EffectiveVisibility.Local) return false
|
||||
return when (element) {
|
||||
is FirAnonymousFunction -> false
|
||||
is FirFunction -> true
|
||||
is FirProperty -> true
|
||||
// Consider class initializer of non local class as root label container.
|
||||
is FirAnonymousInitializer -> {
|
||||
val parentVisibility =
|
||||
(element.getContainingClassSymbol(element.moduleData.session) as? FirRegularClassSymbol)?.effectiveVisibility
|
||||
parentVisibility != null && parentVisibility != EffectiveVisibility.Local
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user