[FIR] Report deprecations in qualified expressions
This commit is contained in:
committed by
TeamCityServer
parent
98bd6f5d3e
commit
8a0941a85a
+1
@@ -121,6 +121,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
get() = setOf(
|
||||
FirStandaloneQualifierChecker,
|
||||
FirOptInUsageQualifierChecker,
|
||||
FirDeprecatedQualifierChecker,
|
||||
)
|
||||
|
||||
override val equalityOperatorCallCheckers: Set<FirEqualityOperatorCallChecker>
|
||||
|
||||
+10
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.collectEnumEntries
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirDeprecationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
@@ -37,6 +38,7 @@ object FirImportsChecker : FirFileChecker() {
|
||||
checkOperatorRename(import, context, reporter)
|
||||
}
|
||||
}
|
||||
checkDeprecatedImport(import, context, reporter)
|
||||
}
|
||||
checkConflictingImports(declaration.imports, context, reporter)
|
||||
}
|
||||
@@ -175,4 +177,12 @@ object FirImportsChecker : FirFileChecker() {
|
||||
|
||||
return hasStatic || !hasIllegal
|
||||
}
|
||||
|
||||
private fun checkDeprecatedImport(import: FirImport, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val importedFqName = import.importedFqName ?: return
|
||||
if (importedFqName.isRoot || importedFqName.shortName().asString().isEmpty()) return
|
||||
val classId = (import as? FirResolvedImport)?.resolvedClassId ?: ClassId.topLevel(importedFqName)
|
||||
val classLike: FirRegularClassSymbol = classId.resolveToClass(context) ?: return
|
||||
FirDeprecationChecker.reportDeprecationIfNeeded(import.source, classLike, null, context, reporter)
|
||||
}
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.expression
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDeprecated
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
|
||||
object FirDeprecatedQualifierChecker : FirResolvedQualifierChecker() {
|
||||
override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
expression.nonFatalDiagnostics.filterIsInstance<ConeDeprecated>().forEach { diagnostic ->
|
||||
FirDeprecationChecker.reportDeprecation(diagnostic.source, diagnostic.symbol, diagnostic.deprecation, reporter, context)
|
||||
}
|
||||
if (expression.resolvedToCompanionObject) {
|
||||
val companionSymbol = (expression.symbol as? FirRegularClassSymbol)?.companionObjectSymbol ?: return
|
||||
FirDeprecationChecker.reportDeprecationIfNeeded(expression.source, companionSymbol, null, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-3
@@ -17,9 +17,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.Deprecation
|
||||
import org.jetbrains.kotlin.fir.declarations.DeprecationLevelValue
|
||||
import org.jetbrains.kotlin.fir.declarations.getDeprecation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
@@ -50,6 +48,16 @@ object FirDeprecationChecker : FirBasicExpressionChecker() {
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
val deprecation = getWorstDeprecation(callSite, referencedSymbol, context) ?: return
|
||||
reportDeprecation(source, referencedSymbol, deprecation, reporter, context)
|
||||
}
|
||||
|
||||
internal fun reportDeprecation(
|
||||
source: FirSourceElement?,
|
||||
referencedSymbol: FirBasedSymbol<*>,
|
||||
deprecation: Deprecation,
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val diagnostic = when (deprecation.level) {
|
||||
DeprecationLevelValue.ERROR, DeprecationLevelValue.HIDDEN -> FirErrors.DEPRECATION_ERROR
|
||||
DeprecationLevelValue.WARNING -> FirErrors.DEPRECATION
|
||||
|
||||
+36
-30
@@ -527,36 +527,42 @@ object LightTreePositioningStrategies {
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
if (node.tokenType == KtNodeTypes.CALL_EXPRESSION || node.tokenType == KtNodeTypes.CONSTRUCTOR_DELEGATION_CALL) {
|
||||
return markElement(tree.referenceExpression(node, locateReferencedName) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
if (node.tokenType == KtNodeTypes.PROPERTY_DELEGATE) {
|
||||
return markElement(tree.findExpressionDeep(node) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
if (node.tokenType == KtNodeTypes.ANNOTATION_ENTRY) {
|
||||
return markElement(
|
||||
tree.findDescendantByType(node, KtNodeTypes.CONSTRUCTOR_CALLEE) ?: node,
|
||||
startOffset,
|
||||
endOffset,
|
||||
tree,
|
||||
node
|
||||
)
|
||||
}
|
||||
if (node.tokenType in nodeTypesWithOperation) {
|
||||
return markElement(tree.operationReference(node) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
if (node.tokenType == KtNodeTypes.TYPE_REFERENCE) {
|
||||
val nodeToMark =
|
||||
tree.findChildByType(node, KtNodeTypes.NULLABLE_TYPE)
|
||||
?.let { tree.findChildByType(it, KtNodeTypes.USER_TYPE) }
|
||||
?: node
|
||||
return markElement(nodeToMark, startOffset, endOffset, tree, node)
|
||||
}
|
||||
if (node.tokenType != KtNodeTypes.DOT_QUALIFIED_EXPRESSION &&
|
||||
node.tokenType != KtNodeTypes.SAFE_ACCESS_EXPRESSION &&
|
||||
node.tokenType != KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION
|
||||
) {
|
||||
return super.mark(node, startOffset, endOffset, tree)
|
||||
when {
|
||||
node.tokenType == KtNodeTypes.CALL_EXPRESSION || node.tokenType == KtNodeTypes.CONSTRUCTOR_DELEGATION_CALL -> {
|
||||
return markElement(tree.referenceExpression(node, locateReferencedName) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
node.tokenType == KtNodeTypes.PROPERTY_DELEGATE -> {
|
||||
return markElement(tree.findExpressionDeep(node) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
node.tokenType == KtNodeTypes.ANNOTATION_ENTRY -> {
|
||||
return markElement(
|
||||
tree.findDescendantByType(node, KtNodeTypes.CONSTRUCTOR_CALLEE) ?: node,
|
||||
startOffset,
|
||||
endOffset,
|
||||
tree,
|
||||
node
|
||||
)
|
||||
}
|
||||
node.tokenType in nodeTypesWithOperation -> {
|
||||
return markElement(tree.operationReference(node) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
node.tokenType == KtNodeTypes.TYPE_REFERENCE -> {
|
||||
val nodeToMark =
|
||||
tree.findChildByType(node, KtNodeTypes.NULLABLE_TYPE)
|
||||
?.let { tree.findChildByType(it, KtNodeTypes.USER_TYPE) }
|
||||
?: node
|
||||
return markElement(nodeToMark, startOffset, endOffset, tree, node)
|
||||
}
|
||||
node.tokenType == KtNodeTypes.IMPORT_DIRECTIVE -> {
|
||||
val nodeToMark = tree.findChildByType(node, KtStubElementTypes.INSIDE_DIRECTIVE_EXPRESSIONS) ?: node
|
||||
return markElement(nodeToMark, startOffset, endOffset, tree, node)
|
||||
}
|
||||
node.tokenType != KtNodeTypes.DOT_QUALIFIED_EXPRESSION &&
|
||||
node.tokenType != KtNodeTypes.SAFE_ACCESS_EXPRESSION &&
|
||||
node.tokenType != KtNodeTypes.CALLABLE_REFERENCE_EXPRESSION
|
||||
-> {
|
||||
return super.mark(node, startOffset, endOffset, tree)
|
||||
}
|
||||
}
|
||||
val selector = tree.selector(node)
|
||||
if (selector != null) {
|
||||
|
||||
Reference in New Issue
Block a user