[FIR] Add CheckerContext to DiagnosticReporter and refactor diagnostic reporting
Refactoring includes replacing `Diagnostic.report` extensions in checkers with `DiagnosticReporter.reportOn` extension declared in DiagnosticReporter.kt
This commit is contained in:
+4
-2
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.cfa
|
package org.jetbrains.kotlin.fir.analysis.cfa
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.CFGNode
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.CFGNode
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
||||||
@@ -15,6 +16,7 @@ abstract class AbstractFirPropertyInitializationChecker {
|
|||||||
graph: ControlFlowGraph,
|
graph: ControlFlowGraph,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
||||||
properties: Set<FirPropertySymbol>
|
properties: Set<FirPropertySymbol>,
|
||||||
|
context: CheckerContext
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-6
@@ -43,7 +43,7 @@ import kotlin.contracts.contract
|
|||||||
|
|
||||||
object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
||||||
|
|
||||||
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, checkerContext: CheckerContext) {
|
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||||
val function = (graph.declaration as? FirFunction<*>) ?: return
|
val function = (graph.declaration as? FirFunction<*>) ?: return
|
||||||
if (function !is FirContractDescriptionOwner) return
|
if (function !is FirContractDescriptionOwner) return
|
||||||
if (function.contractDescription.coneEffects?.any { it is ConeCallsEffectDeclaration } != true) return
|
if (function.contractDescription.coneEffects?.any { it is ConeCallsEffectDeclaration } != true) return
|
||||||
@@ -73,10 +73,10 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
|||||||
|
|
||||||
for ((symbol, leakedPlaces) in leakedSymbols) {
|
for ((symbol, leakedPlaces) in leakedSymbols) {
|
||||||
function.contractDescription.source?.let {
|
function.contractDescription.source?.let {
|
||||||
reporter.report(FirErrors.LEAKED_IN_PLACE_LAMBDA.on(it, symbol))
|
reporter.report(FirErrors.LEAKED_IN_PLACE_LAMBDA.on(it, symbol), context)
|
||||||
}
|
}
|
||||||
leakedPlaces.forEach {
|
leakedPlaces.forEach {
|
||||||
reporter.report(FirErrors.LEAKED_IN_PLACE_LAMBDA.on(it, symbol))
|
reporter.report(FirErrors.LEAKED_IN_PLACE_LAMBDA.on(it, symbol), context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
|||||||
val requiredRange = effectDeclaration.kind
|
val requiredRange = effectDeclaration.kind
|
||||||
val pathAwareInfo = invocationData.getValue(node)
|
val pathAwareInfo = invocationData.getValue(node)
|
||||||
for (info in pathAwareInfo.values) {
|
for (info in pathAwareInfo.values) {
|
||||||
if (investigate(info, symbol, requiredRange, function, reporter)) {
|
if (investigate(info, symbol, requiredRange, function, reporter, context)) {
|
||||||
// To avoid duplicate reports, stop investigating remaining paths once reported.
|
// To avoid duplicate reports, stop investigating remaining paths once reported.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -105,12 +105,13 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
|||||||
symbol: AbstractFirBasedSymbol<*>,
|
symbol: AbstractFirBasedSymbol<*>,
|
||||||
requiredRange: EventOccurrencesRange,
|
requiredRange: EventOccurrencesRange,
|
||||||
function: FirContractDescriptionOwner,
|
function: FirContractDescriptionOwner,
|
||||||
reporter: DiagnosticReporter
|
reporter: DiagnosticReporter,
|
||||||
|
context: CheckerContext
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val foundRange = info[symbol] ?: EventOccurrencesRange.ZERO
|
val foundRange = info[symbol] ?: EventOccurrencesRange.ZERO
|
||||||
if (foundRange !in requiredRange) {
|
if (foundRange !in requiredRange) {
|
||||||
function.contractDescription.source?.let {
|
function.contractDescription.source?.let {
|
||||||
reporter.report(FirErrors.WRONG_INVOCATION_KIND.on(it, symbol, requiredRange, foundRange))
|
reporter.report(FirErrors.WRONG_INVOCATION_KIND.on(it, symbol, requiredRange, foundRange), context)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-6
@@ -29,27 +29,32 @@ class FirControlFlowAnalyzer(session: FirSession) {
|
|||||||
|
|
||||||
cfaCheckers.forEach { it.analyze(graph, reporter, context) }
|
cfaCheckers.forEach { it.analyze(graph, reporter, context) }
|
||||||
if (context.containingDeclarations.any { it is FirProperty || it is FirFunction<*> }) return
|
if (context.containingDeclarations.any { it is FirProperty || it is FirFunction<*> }) return
|
||||||
runAssignmentCfaCheckers(graph, reporter)
|
runAssignmentCfaCheckers(graph, reporter, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun analyzePropertyInitializer(property: FirProperty, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) {
|
fun analyzePropertyInitializer(property: FirProperty, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (graph.owner != null) return
|
if (graph.owner != null) return
|
||||||
|
|
||||||
cfaCheckers.forEach { it.analyze(graph, reporter, context) }
|
cfaCheckers.forEach { it.analyze(graph, reporter, context) }
|
||||||
runAssignmentCfaCheckers(graph, reporter)
|
runAssignmentCfaCheckers(graph, reporter, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun analyzePropertyAccessor(accessor: FirPropertyAccessor, graph: ControlFlowGraph, context: CheckerContext, reporter: DiagnosticReporter) {
|
fun analyzePropertyAccessor(
|
||||||
|
accessor: FirPropertyAccessor,
|
||||||
|
graph: ControlFlowGraph,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
if (graph.owner != null) return
|
if (graph.owner != null) return
|
||||||
|
|
||||||
cfaCheckers.forEach { it.analyze(graph, reporter, context) }
|
cfaCheckers.forEach { it.analyze(graph, reporter, context) }
|
||||||
runAssignmentCfaCheckers(graph, reporter)
|
runAssignmentCfaCheckers(graph, reporter, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runAssignmentCfaCheckers(graph: ControlFlowGraph, reporter: DiagnosticReporter) {
|
private fun runAssignmentCfaCheckers(graph: ControlFlowGraph, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||||
val properties = LocalPropertyCollector.collect(graph)
|
val properties = LocalPropertyCollector.collect(graph)
|
||||||
if (properties.isEmpty()) return
|
if (properties.isEmpty()) return
|
||||||
val data = PropertyInitializationInfoCollector(properties).getData(graph)
|
val data = PropertyInitializationInfoCollector(properties).getData(graph)
|
||||||
variableAssignmentCheckers.forEach { it.analyze(graph, reporter, data, properties) }
|
variableAssignmentCheckers.forEach { it.analyze(graph, reporter, data, properties, context) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.cfa
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||||
import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited
|
import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.isLateInit
|
import org.jetbrains.kotlin.fir.declarations.isLateInit
|
||||||
@@ -23,7 +24,8 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
|
|||||||
graph: ControlFlowGraph,
|
graph: ControlFlowGraph,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
||||||
properties: Set<FirPropertySymbol>
|
properties: Set<FirPropertySymbol>,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
val localData = data.filter {
|
val localData = data.filter {
|
||||||
val symbolFir = (it.key.fir as? FirVariableSymbol<*>)?.fir
|
val symbolFir = (it.key.fir as? FirVariableSymbol<*>)?.fir
|
||||||
@@ -32,14 +34,15 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
|
|||||||
|
|
||||||
val localProperties = properties.filter { it.fir.initializer == null && it.fir.delegate == null }.toSet()
|
val localProperties = properties.filter { it.fir.initializer == null && it.fir.delegate == null }.toSet()
|
||||||
|
|
||||||
val reporterVisitor = UninitializedPropertyReporter(localData, localProperties, reporter)
|
val reporterVisitor = UninitializedPropertyReporter(localData, localProperties, reporter, context)
|
||||||
graph.traverse(TraverseDirection.Forward, reporterVisitor)
|
graph.traverse(TraverseDirection.Forward, reporterVisitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UninitializedPropertyReporter(
|
private class UninitializedPropertyReporter(
|
||||||
val data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
val data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
||||||
val localProperties: Set<FirPropertySymbol>,
|
val localProperties: Set<FirPropertySymbol>,
|
||||||
val reporter: DiagnosticReporter
|
val reporter: DiagnosticReporter,
|
||||||
|
val context: CheckerContext
|
||||||
) : ControlFlowGraphVisitorVoid() {
|
) : ControlFlowGraphVisitorVoid() {
|
||||||
override fun visitNode(node: CFGNode<*>) {}
|
override fun visitNode(node: CFGNode<*>) {}
|
||||||
|
|
||||||
@@ -61,7 +64,7 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
|
|||||||
val kind = info[symbol] ?: EventOccurrencesRange.ZERO
|
val kind = info[symbol] ?: EventOccurrencesRange.ZERO
|
||||||
if (!kind.isDefinitelyVisited()) {
|
if (!kind.isDefinitelyVisited()) {
|
||||||
node.fir.source?.let {
|
node.fir.source?.let {
|
||||||
reporter.report(FirErrors.UNINITIALIZED_VARIABLE.on(it, symbol))
|
reporter.report(FirErrors.UNINITIALIZED_VARIABLE.on(it, symbol), context)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
|||||||
|
|
||||||
object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
|
object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
|
||||||
|
|
||||||
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, checkerContext: CheckerContext) {
|
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||||
val function = graph.declaration as? FirFunction<*> ?: return
|
val function = graph.declaration as? FirFunction<*> ?: return
|
||||||
val graphRef = function.controlFlowGraphReference as FirControlFlowGraphReferenceImpl
|
val graphRef = function.controlFlowGraphReference as FirControlFlowGraphReferenceImpl
|
||||||
val dataFlowInfo = graphRef.dataFlowInfo
|
val dataFlowInfo = graphRef.dataFlowInfo
|
||||||
@@ -62,7 +62,7 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
|
|||||||
|
|
||||||
if (wrongCondition) {
|
if (wrongCondition) {
|
||||||
function.contractDescription.source?.let {
|
function.contractDescription.source?.let {
|
||||||
reporter.report(FirErrors.WRONG_IMPLIES_CONDITION.on(it))
|
reporter.report(FirErrors.WRONG_IMPLIES_CONDITION.on(it), context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,4 +215,4 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
|
|||||||
private fun FirFunction<*>.getParameterSymbol(index: Int): AbstractFirBasedSymbol<*> {
|
private fun FirFunction<*>.getParameterSymbol(index: Int): AbstractFirBasedSymbol<*> {
|
||||||
return if (index == -1) this.symbol else this.valueParameters[index].symbol
|
return if (index == -1) this.symbol else this.valueParameters[index].symbol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -10,5 +10,5 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
|||||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
|
||||||
|
|
||||||
abstract class FirControlFlowChecker {
|
abstract class FirControlFlowChecker {
|
||||||
abstract fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, checkerContext: CheckerContext)
|
abstract fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, context: CheckerContext)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-20
@@ -5,21 +5,24 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
|
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
import org.jetbrains.kotlin.fir.*
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -36,8 +39,8 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
|||||||
for ((arg, _) in declarationOfAnnotation.argumentMapping ?: continue) {
|
for ((arg, _) in declarationOfAnnotation.argumentMapping ?: continue) {
|
||||||
val expression = (arg as? FirNamedArgumentExpression)?.expression ?: arg
|
val expression = (arg as? FirNamedArgumentExpression)?.expression ?: arg
|
||||||
|
|
||||||
checkAnnotationArgumentWithSubElements(expression, context.session, reporter)
|
checkAnnotationArgumentWithSubElements(expression, context.session, reporter, context)
|
||||||
?.let { reporter.report(expression.source, it) }
|
?.let { reporter.reportOn(expression.source, it, context) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +48,8 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
|||||||
private fun checkAnnotationArgumentWithSubElements(
|
private fun checkAnnotationArgumentWithSubElements(
|
||||||
expression: FirExpression,
|
expression: FirExpression,
|
||||||
session: FirSession,
|
session: FirSession,
|
||||||
reporter: DiagnosticReporter
|
reporter: DiagnosticReporter,
|
||||||
|
context: CheckerContext
|
||||||
): FirDiagnosticFactory0<FirSourceElement, KtExpression>? {
|
): FirDiagnosticFactory0<FirSourceElement, KtExpression>? {
|
||||||
when (expression) {
|
when (expression) {
|
||||||
is FirArrayOfCall -> {
|
is FirArrayOfCall -> {
|
||||||
@@ -54,13 +58,13 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
|||||||
for (arg in expression.argumentList.arguments) {
|
for (arg in expression.argumentList.arguments) {
|
||||||
val sourceForReport = arg.source
|
val sourceForReport = arg.source
|
||||||
|
|
||||||
when (val err = checkAnnotationArgumentWithSubElements(arg, session, reporter)) {
|
when (val err = checkAnnotationArgumentWithSubElements(arg, session, reporter, context)) {
|
||||||
null -> {
|
null -> {
|
||||||
//DO NOTHING
|
//DO NOTHING
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
if (err != FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL) usedNonConst = true
|
if (err != FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL) usedNonConst = true
|
||||||
reporter.report(sourceForReport, err)
|
reporter.reportOn(sourceForReport, err, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,8 +73,8 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
is FirVarargArgumentsExpression -> {
|
is FirVarargArgumentsExpression -> {
|
||||||
for (arg in expression.arguments)
|
for (arg in expression.arguments)
|
||||||
checkAnnotationArgumentWithSubElements(arg, session, reporter)
|
checkAnnotationArgumentWithSubElements(arg, session, reporter, context)
|
||||||
?.let { reporter.report(arg.source, it) }
|
?.let { reporter.reportOn(arg.source, it, context) }
|
||||||
}
|
}
|
||||||
else ->
|
else ->
|
||||||
return checkAnnotationArgument(expression, session)
|
return checkAnnotationArgument(expression, session)
|
||||||
@@ -224,14 +228,7 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
|||||||
?.toSymbol(session)
|
?.toSymbol(session)
|
||||||
?.fir
|
?.fir
|
||||||
|
|
||||||
private inline fun <reified T : FirSourceElement, P : PsiElement> DiagnosticReporter.report(
|
|
||||||
source: T?,
|
|
||||||
factory: FirDiagnosticFactory0<T, P>
|
|
||||||
) {
|
|
||||||
source?.let { report(factory.on(it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val CONVERSION_NAMES = listOf(
|
private val CONVERSION_NAMES = listOf(
|
||||||
"toInt", "toLong", "toShort", "toByte", "toFloat", "toDouble", "toChar", "toBoolean"
|
"toInt", "toLong", "toShort", "toByte", "toFloat", "toDouble", "toChar", "toBoolean"
|
||||||
).mapTo(hashSetOf()) { Name.identifier(it) }
|
).mapTo(hashSetOf()) { Name.identifier(it) }
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-21
@@ -5,28 +5,26 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import org.jetbrains.kotlin.KtNodeTypes.FUN
|
||||||
|
import org.jetbrains.kotlin.KtNodeTypes.VALUE_PARAMETER
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind.ANNOTATION_CLASS
|
import org.jetbrains.kotlin.descriptors.ClassKind.ANNOTATION_CLASS
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind.ENUM_CLASS
|
import org.jetbrains.kotlin.descriptors.ClassKind.ENUM_CLASS
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds.primitiveArrayTypeByElementType
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds.primitiveArrayTypeByElementType
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds.primitiveTypes
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds.primitiveTypes
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds.unsignedTypes
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds.unsignedTypes
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.KtNodeTypes.FUN
|
|
||||||
import org.jetbrains.kotlin.KtNodeTypes.VALUE_PARAMETER
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (declaration.classKind != ANNOTATION_CLASS) return
|
if (declaration.classKind != ANNOTATION_CLASS) return
|
||||||
if (declaration.isLocal) reporter.report(declaration.source, FirErrors.LOCAL_ANNOTATION_CLASS_ERROR)
|
if (declaration.isLocal) reporter.reportOn(declaration.source, FirErrors.LOCAL_ANNOTATION_CLASS_ERROR, context)
|
||||||
|
|
||||||
for (it in declaration.declarations) {
|
for (it in declaration.declarations) {
|
||||||
when {
|
when {
|
||||||
@@ -34,9 +32,9 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
|||||||
for (parameter in it.valueParameters) {
|
for (parameter in it.valueParameters) {
|
||||||
val source = parameter.source ?: continue
|
val source = parameter.source ?: continue
|
||||||
if (!source.hasValOrVar()) {
|
if (!source.hasValOrVar()) {
|
||||||
reporter.report(source, FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER)
|
reporter.reportOn(source, FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER, context)
|
||||||
} else if (source.hasVar()) {
|
} else if (source.hasVar()) {
|
||||||
reporter.report(source, FirErrors.VAR_ANNOTATION_PARAMETER)
|
reporter.reportOn(source, FirErrors.VAR_ANNOTATION_PARAMETER, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
val typeRef = parameter.returnTypeRef
|
val typeRef = parameter.returnTypeRef
|
||||||
@@ -48,7 +46,7 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
|||||||
// TODO: replace with UNRESOLVED_REFERENCE check
|
// TODO: replace with UNRESOLVED_REFERENCE check
|
||||||
}
|
}
|
||||||
coneType.isNullable -> {
|
coneType.isNullable -> {
|
||||||
reporter.report(typeRef.source, FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER)
|
reporter.reportOn(typeRef.source, FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER, context)
|
||||||
}
|
}
|
||||||
classId in primitiveTypes -> {
|
classId in primitiveTypes -> {
|
||||||
// DO NOTHING: primitives are allowed as annotation class parameter
|
// DO NOTHING: primitives are allowed as annotation class parameter
|
||||||
@@ -67,13 +65,13 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
|||||||
}
|
}
|
||||||
classId == StandardClassIds.Array -> {
|
classId == StandardClassIds.Array -> {
|
||||||
if (!isAllowedArray(typeRef, context.session))
|
if (!isAllowedArray(typeRef, context.session))
|
||||||
reporter.report(typeRef.source, FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER)
|
reporter.reportOn(typeRef.source, FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER, context)
|
||||||
}
|
}
|
||||||
isAllowedClassKind(coneType, context.session) -> {
|
isAllowedClassKind(coneType, context.session) -> {
|
||||||
// DO NOTHING: annotation or enum classes are allowed
|
// DO NOTHING: annotation or enum classes are allowed
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
reporter.report(typeRef.source, FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER)
|
reporter.reportOn(typeRef.source, FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +87,7 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
|||||||
// TODO: replace with origin check
|
// TODO: replace with origin check
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
reporter.report(it.source, FirErrors.ANNOTATION_CLASS_MEMBER)
|
reporter.reportOn(it.source, FirErrors.ANNOTATION_CLASS_MEMBER, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,11 +132,4 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T : FirSourceElement, P : PsiElement> DiagnosticReporter.report(
|
|
||||||
source: T?,
|
|
||||||
factory: FirDiagnosticFactory0<T, P>
|
|
||||||
) {
|
|
||||||
source?.let { report(factory.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-18
@@ -6,10 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||||
@@ -47,9 +47,9 @@ object FirCommonConstructorDelegationIssuesChecker : FirRegularClassChecker() {
|
|||||||
for (it in otherConstructors) {
|
for (it in otherConstructors) {
|
||||||
if (it.delegatedConstructor?.isThis != true) {
|
if (it.delegatedConstructor?.isThis != true) {
|
||||||
if (it.delegatedConstructor?.source != null) {
|
if (it.delegatedConstructor?.source != null) {
|
||||||
reporter.reportPrimaryConstructorDelegationCallExpected(it.delegatedConstructor?.source)
|
reporter.reportOn(it.delegatedConstructor?.source, FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED, context)
|
||||||
} else {
|
} else {
|
||||||
reporter.reportPrimaryConstructorDelegationCallExpected(it.source)
|
reporter.reportOn(it.source, FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,13 +62,13 @@ object FirCommonConstructorDelegationIssuesChecker : FirRegularClassChecker() {
|
|||||||
callee is FirErrorNamedReference && callee.diagnostic is ConeAmbiguityError &&
|
callee is FirErrorNamedReference && callee.diagnostic is ConeAmbiguityError &&
|
||||||
it.delegatedConstructor?.source?.kind is FirFakeSourceElementKind
|
it.delegatedConstructor?.source?.kind is FirFakeSourceElementKind
|
||||||
) {
|
) {
|
||||||
reporter.reportExplicitDelegationCallRequired(it.source)
|
reporter.reportOn(it.source, FirErrors.EXPLICIT_DELEGATION_CALL_REQUIRED, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cyclicConstructors.forEach {
|
cyclicConstructors.forEach {
|
||||||
reporter.reportCyclicConstructorDelegationCall(it.delegatedConstructor?.source)
|
reporter.reportOn(it.delegatedConstructor?.source, FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,16 +95,4 @@ object FirCommonConstructorDelegationIssuesChecker : FirRegularClassChecker() {
|
|||||||
?.calleeReference.safeAs<FirResolvedNamedReference>()
|
?.calleeReference.safeAs<FirResolvedNamedReference>()
|
||||||
?.resolvedSymbol
|
?.resolvedSymbol
|
||||||
?.fir.safeAs()
|
?.fir.safeAs()
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.reportCyclicConstructorDelegationCall(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.CYCLIC_CONSTRUCTOR_DELEGATION_CALL.on(it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportPrimaryConstructorDelegationCallExpected(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED.on(it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportExplicitDelegationCallRequired(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.EXPLICIT_DELEGATION_CALL_REQUIRED.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-12
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
@@ -35,7 +35,7 @@ object FirConflictingProjectionChecker : FirBasicDeclarationChecker() {
|
|||||||
is FirTypeAlias -> {
|
is FirTypeAlias -> {
|
||||||
for (it in declaration.typeParameters) {
|
for (it in declaration.typeParameters) {
|
||||||
if (it.variance != Variance.INVARIANT) {
|
if (it.variance != Variance.INVARIANT) {
|
||||||
reporter.reportVarianceNotAllowed(it.source)
|
reporter.reportOn(it.source, FirErrors.VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkTypeRef(declaration.expandedTypeRef, context, reporter)
|
checkTypeRef(declaration.expandedTypeRef, context, reporter)
|
||||||
@@ -70,17 +70,9 @@ object FirConflictingProjectionChecker : FirBasicDeclarationChecker() {
|
|||||||
actual is ConeKotlinTypeProjectionIn && protoVariance == Variance.OUT_VARIANCE ||
|
actual is ConeKotlinTypeProjectionIn && protoVariance == Variance.OUT_VARIANCE ||
|
||||||
actual is ConeKotlinTypeProjectionOut && protoVariance == Variance.IN_VARIANCE
|
actual is ConeKotlinTypeProjectionOut && protoVariance == Variance.IN_VARIANCE
|
||||||
) {
|
) {
|
||||||
reporter.reportConflictingProjections(typeRef.source, typeRef.coneType.toString())
|
reporter.reportOn(typeRef.source, FirErrors.CONFLICTING_PROJECTION, typeRef.coneType.toString(), context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.reportConflictingProjections(source: FirSourceElement?, desiredProjection: String) {
|
|
||||||
source?.let { report(FirErrors.CONFLICTING_PROJECTION.on(it, desiredProjection)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportVarianceNotAllowed(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-11
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector
|
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
@@ -25,11 +25,11 @@ object FirConflictsChecker : FirBasicDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inspector.functionDeclarations.forEachNonSingle { it, hint ->
|
inspector.functionDeclarations.forEachNonSingle { it, hint ->
|
||||||
reporter.reportConflictingOverloads(it.source, hint)
|
reporter.reportOn(it.source, FirErrors.CONFLICTING_OVERLOADS, hint, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
inspector.otherDeclarations.forEachNonSingle { it, hint ->
|
inspector.otherDeclarations.forEachNonSingle { it, hint ->
|
||||||
reporter.reportConflictingDeclarations(it.source, hint)
|
reporter.reportOn(it.source, FirErrors.REDECLARATION, hint, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,12 +56,4 @@ object FirConflictsChecker : FirBasicDeclarationChecker() {
|
|||||||
inspector.collect(it)
|
inspector.collect(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportConflictingOverloads(source: FirSourceElement?, declarations: String) {
|
|
||||||
source?.let { report(FirErrors.CONFLICTING_OVERLOADS.on(it, declarations)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportConflictingDeclarations(source: FirSourceElement?, declarations: String) {
|
|
||||||
source?.let { report(FirErrors.REDECLARATION.on(it, declarations)) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-15
@@ -5,16 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
|
||||||
object FirConstructorAllowedChecker : FirConstructorChecker() {
|
object FirConstructorAllowedChecker : FirConstructorChecker() {
|
||||||
@@ -26,27 +24,20 @@ object FirConstructorAllowedChecker : FirConstructorChecker() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
when (containingClass.classKind) {
|
when (containingClass.classKind) {
|
||||||
ClassKind.OBJECT -> reporter.report(source, FirErrors.CONSTRUCTOR_IN_OBJECT)
|
ClassKind.OBJECT -> reporter.reportOn(source, FirErrors.CONSTRUCTOR_IN_OBJECT, context)
|
||||||
ClassKind.INTERFACE -> reporter.report(source, FirErrors.CONSTRUCTOR_IN_INTERFACE)
|
ClassKind.INTERFACE -> reporter.reportOn(source, FirErrors.CONSTRUCTOR_IN_INTERFACE, context)
|
||||||
ClassKind.ENUM_ENTRY -> reporter.report(source, FirErrors.CONSTRUCTOR_IN_OBJECT)
|
ClassKind.ENUM_ENTRY -> reporter.reportOn(source, FirErrors.CONSTRUCTOR_IN_OBJECT, context)
|
||||||
ClassKind.ENUM_CLASS -> if (declaration.visibility != Visibilities.Private) {
|
ClassKind.ENUM_CLASS -> if (declaration.visibility != Visibilities.Private) {
|
||||||
reporter.report(source, FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM)
|
reporter.reportOn(source, FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_ENUM, context)
|
||||||
}
|
}
|
||||||
ClassKind.CLASS -> if (containingClass is FirRegularClass && containingClass.modality == Modality.SEALED &&
|
ClassKind.CLASS -> if (containingClass is FirRegularClass && containingClass.modality == Modality.SEALED &&
|
||||||
declaration.visibility != Visibilities.Private
|
declaration.visibility != Visibilities.Private
|
||||||
) {
|
) {
|
||||||
reporter.report(source, FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED)
|
reporter.reportOn(source, FirErrors.NON_PRIVATE_CONSTRUCTOR_IN_SEALED, context)
|
||||||
}
|
}
|
||||||
ClassKind.ANNOTATION_CLASS -> {
|
ClassKind.ANNOTATION_CLASS -> {
|
||||||
// DO NOTHING
|
// DO NOTHING
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T : FirSourceElement, P : PsiElement> DiagnosticReporter.report(
|
|
||||||
source: T?,
|
|
||||||
factory: FirDiagnosticFactory0<T, P>
|
|
||||||
) {
|
|
||||||
source?.let { report(factory.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.hasPrimaryConstructor
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.hasPrimaryConstructor
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isInterface
|
import org.jetbrains.kotlin.fir.declarations.isInterface
|
||||||
|
|
||||||
@@ -20,11 +20,7 @@ object FirConstructorInInterfaceChecker : FirRegularClassChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (declaration.source?.hasPrimaryConstructor() == true) {
|
if (declaration.source?.hasPrimaryConstructor() == true) {
|
||||||
reporter.report(declaration.source)
|
reporter.reportOn(declaration.source, FirErrors.CONSTRUCTOR_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.CONSTRUCTOR_IN_INTERFACE.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+18
-16
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
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.extended.report
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||||
@@ -25,14 +25,15 @@ internal fun checkExpectDeclarationVisibilityAndBody(
|
|||||||
declaration: FirMemberDeclaration,
|
declaration: FirMemberDeclaration,
|
||||||
source: FirSourceElement,
|
source: FirSourceElement,
|
||||||
modifierList: FirModifierList?,
|
modifierList: FirModifierList?,
|
||||||
reporter: DiagnosticReporter
|
reporter: DiagnosticReporter,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
if (declaration.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true) {
|
if (declaration.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true) {
|
||||||
if (Visibilities.isPrivate(declaration.visibility)) {
|
if (Visibilities.isPrivate(declaration.visibility)) {
|
||||||
reporter.report(source, FirErrors.EXPECTED_PRIVATE_DECLARATION)
|
reporter.reportOn(source, FirErrors.EXPECTED_PRIVATE_DECLARATION, context)
|
||||||
}
|
}
|
||||||
if (declaration is FirSimpleFunction && declaration.hasBody) {
|
if (declaration is FirSimpleFunction && declaration.hasBody) {
|
||||||
reporter.report(source, FirErrors.EXPECTED_DECLARATION_WITH_BODY)
|
reporter.reportOn(source, FirErrors.EXPECTED_DECLARATION_WITH_BODY, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,7 +41,8 @@ internal fun checkExpectDeclarationVisibilityAndBody(
|
|||||||
internal fun checkPropertyInitializer(
|
internal fun checkPropertyInitializer(
|
||||||
containingClass: FirRegularClass?,
|
containingClass: FirRegularClass?,
|
||||||
property: FirProperty,
|
property: FirProperty,
|
||||||
reporter: DiagnosticReporter
|
reporter: DiagnosticReporter,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
val inInterface = containingClass?.isInterface == true
|
val inInterface = containingClass?.isInterface == true
|
||||||
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
|
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
|
||||||
@@ -51,7 +53,7 @@ internal fun checkPropertyInitializer(
|
|||||||
if (isAbstract) {
|
if (isAbstract) {
|
||||||
if (property.initializer == null && property.delegate == null && property.returnTypeRef is FirImplicitTypeRef) {
|
if (property.initializer == null && property.delegate == null && property.returnTypeRef is FirImplicitTypeRef) {
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
reporter.report(it, FirErrors.PROPERTY_WITH_NO_TYPE_NO_INITIALIZER)
|
reporter.reportOn(it, FirErrors.PROPERTY_WITH_NO_TYPE_NO_INITIALIZER, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -61,7 +63,7 @@ internal fun checkPropertyInitializer(
|
|||||||
val backingFieldRequired = property.hasBackingField
|
val backingFieldRequired = property.hasBackingField
|
||||||
if (inInterface && backingFieldRequired && property.hasAccessorImplementation) {
|
if (inInterface && backingFieldRequired && property.hasAccessorImplementation) {
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
// reporter.report(it, FirErrors.BACKING_FIELD_IN_INTERFACE)
|
// reporter.reportOn(it, FirErrors.BACKING_FIELD_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,16 +74,16 @@ internal fun checkPropertyInitializer(
|
|||||||
property.initializer?.source?.let {
|
property.initializer?.source?.let {
|
||||||
when {
|
when {
|
||||||
inInterface -> {
|
inInterface -> {
|
||||||
reporter.report(it, FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE)
|
reporter.reportOn(it, FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
isExpect -> {
|
isExpect -> {
|
||||||
reporter.report(it, FirErrors.EXPECTED_PROPERTY_INITIALIZER)
|
reporter.reportOn(it, FirErrors.EXPECTED_PROPERTY_INITIALIZER, context)
|
||||||
}
|
}
|
||||||
!backingFieldRequired -> {
|
!backingFieldRequired -> {
|
||||||
// reporter.report(it, FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD)
|
// reporter.reportOn(it, FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD, context)
|
||||||
}
|
}
|
||||||
property.receiverTypeRef != null -> {
|
property.receiverTypeRef != null -> {
|
||||||
// reporter.report(it, FirErrors.EXTENSION_PROPERTY_WITH_BACKING_FIELD)
|
// reporter.reportOn(it, FirErrors.EXTENSION_PROPERTY_WITH_BACKING_FIELD, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,10 +92,10 @@ internal fun checkPropertyInitializer(
|
|||||||
property.delegate?.source?.let {
|
property.delegate?.source?.let {
|
||||||
when {
|
when {
|
||||||
inInterface -> {
|
inInterface -> {
|
||||||
reporter.report(it, FirErrors.DELEGATED_PROPERTY_IN_INTERFACE)
|
reporter.reportOn(it, FirErrors.DELEGATED_PROPERTY_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
isExpect -> {
|
isExpect -> {
|
||||||
reporter.report(it, FirErrors.EXPECTED_DELEGATED_PROPERTY)
|
reporter.reportOn(it, FirErrors.EXPECTED_DELEGATED_PROPERTY, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,12 +107,12 @@ internal fun checkPropertyInitializer(
|
|||||||
if (backingFieldRequired && !inInterface && !property.isLateInit && !isExpect && isUninitialized && !isExternal) {
|
if (backingFieldRequired && !inInterface && !property.isLateInit && !isExpect && isUninitialized && !isExternal) {
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
if (property.receiverTypeRef != null && !property.hasAccessorImplementation) {
|
if (property.receiverTypeRef != null && !property.hasAccessorImplementation) {
|
||||||
// reporter.report(it, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT)
|
// reporter.reportOn(it, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, context)
|
||||||
} else {
|
} else {
|
||||||
if (containingClass != null || property.hasAccessorImplementation) {
|
if (containingClass != null || property.hasAccessorImplementation) {
|
||||||
// reporter.report(it, FirErrors.MUST_BE_INITIALIZED)
|
// reporter.reportOn(it, FirErrors.MUST_BE_INITIALIZED, context)
|
||||||
} else {
|
} else {
|
||||||
// reporter.report(it, FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT)
|
// reporter.reportOn(it, FirErrors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -6,10 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isInterface
|
import org.jetbrains.kotlin.fir.declarations.isInterface
|
||||||
|
|
||||||
@@ -22,12 +22,8 @@ object FirDelegationInInterfaceChecker : FirRegularClassChecker() {
|
|||||||
for (superTypeRef in declaration.superTypeRefs) {
|
for (superTypeRef in declaration.superTypeRefs) {
|
||||||
val source = superTypeRef.source ?: continue
|
val source = superTypeRef.source ?: continue
|
||||||
if (source.treeStructure.getParent(source.lighterASTNode)?.tokenType == KtNodeTypes.DELEGATED_SUPER_TYPE_ENTRY) {
|
if (source.treeStructure.getParent(source.lighterASTNode)?.tokenType == KtNodeTypes.DELEGATED_SUPER_TYPE_ENTRY) {
|
||||||
reporter.report(source)
|
reporter.reportOn(source, FirErrors.DELEGATION_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.DELEGATION_IN_INTERFACE.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-7
@@ -6,10 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isEnumClass
|
import org.jetbrains.kotlin.fir.declarations.isEnumClass
|
||||||
@@ -26,12 +26,8 @@ object FirDelegationSuperCallInEnumConstructorChecker : FirRegularClassChecker()
|
|||||||
it.delegatedConstructor?.isThis == false &&
|
it.delegatedConstructor?.isThis == false &&
|
||||||
it.delegatedConstructor?.source?.kind !is FirFakeSourceElementKind
|
it.delegatedConstructor?.source?.kind !is FirFakeSourceElementKind
|
||||||
) {
|
) {
|
||||||
reporter.report(it.delegatedConstructor?.source)
|
reporter.reportOn(it.delegatedConstructor?.source, FirErrors.DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.DELEGATION_SUPER_CALL_IN_ENUM_CONSTRUCTOR.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+15
-7
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
|||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
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.extended.report
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||||
@@ -36,7 +36,7 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
|||||||
assert(declaration.name.isSpecial && declaration.name.asString() == "<destruct>") {
|
assert(declaration.name.isSpecial && declaration.name.asString() == "<destruct>") {
|
||||||
"Unexpected name: ${declaration.name.asString()} for destructuring declaration"
|
"Unexpected name: ${declaration.name.asString()} for destructuring declaration"
|
||||||
}
|
}
|
||||||
checkInitializer(source, declaration.initializer, reporter)
|
checkInitializer(source, declaration.initializer, reporter, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,8 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
|||||||
originalDestructuringDeclarationOrInitializerSource,
|
originalDestructuringDeclarationOrInitializerSource,
|
||||||
diagnostic.name,
|
diagnostic.name,
|
||||||
originalDestructuringDeclarationType
|
originalDestructuringDeclarationType
|
||||||
)
|
),
|
||||||
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is ConeAmbiguityError -> {
|
is ConeAmbiguityError -> {
|
||||||
@@ -91,7 +92,8 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
|||||||
originalDestructuringDeclarationOrInitializerSource,
|
originalDestructuringDeclarationOrInitializerSource,
|
||||||
diagnostic.name,
|
diagnostic.name,
|
||||||
diagnostic.candidates
|
diagnostic.candidates
|
||||||
)
|
),
|
||||||
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is ConeInapplicableCandidateError -> {
|
is ConeInapplicableCandidateError -> {
|
||||||
@@ -100,7 +102,8 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
|||||||
FirErrors.COMPONENT_FUNCTION_ON_NULLABLE.on(
|
FirErrors.COMPONENT_FUNCTION_ON_NULLABLE.on(
|
||||||
originalDestructuringDeclarationOrInitializerSource,
|
originalDestructuringDeclarationOrInitializerSource,
|
||||||
(diagnostic.candidateSymbol.fir as FirSimpleFunction).name
|
(diagnostic.candidateSymbol.fir as FirSimpleFunction).name
|
||||||
)
|
),
|
||||||
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,7 +111,12 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkInitializer(source: FirSourceElement, initializer: FirExpression?, reporter: DiagnosticReporter) {
|
private fun checkInitializer(
|
||||||
|
source: FirSourceElement,
|
||||||
|
initializer: FirExpression?,
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
context: CheckerContext
|
||||||
|
) {
|
||||||
val needToReport =
|
val needToReport =
|
||||||
when (initializer) {
|
when (initializer) {
|
||||||
null -> true
|
null -> true
|
||||||
@@ -116,7 +124,7 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
if (needToReport) {
|
if (needToReport) {
|
||||||
reporter.report(source, FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION)
|
reporter.reportOn(source, FirErrors.INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-12
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
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.findNonInterfaceSupertype
|
import org.jetbrains.kotlin.fir.analysis.checkers.findNonInterfaceSupertype
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isEnumClass
|
import org.jetbrains.kotlin.fir.declarations.isEnumClass
|
||||||
|
|
||||||
@@ -20,19 +20,11 @@ object FirEnumClassSimpleChecker : FirRegularClassChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declaration.findNonInterfaceSupertype(context)?.let {
|
declaration.findNonInterfaceSupertype(context)?.let {
|
||||||
reporter.reportClassInSupertypeForEnum(it.source)
|
reporter.reportOn(it.source, FirErrors.CLASS_IN_SUPERTYPE_FOR_ENUM, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declaration.typeParameters.isNotEmpty()) {
|
if (declaration.typeParameters.isNotEmpty()) {
|
||||||
reporter.reportTypeParametersInEnum(declaration.typeParameters.firstOrNull()?.source)
|
reporter.reportOn(declaration.typeParameters.firstOrNull()?.source, FirErrors.TYPE_PARAMETERS_IN_ENUM, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.reportClassInSupertypeForEnum(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.CLASS_IN_SUPERTYPE_FOR_ENUM.on(it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportTypeParametersInEnum(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.TYPE_PARAMETERS_IN_ENUM.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+32
-43
@@ -5,15 +5,16 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.FirEffectiveVisibility
|
||||||
|
import org.jetbrains.kotlin.fir.FirEffectiveVisibilityImpl
|
||||||
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.toRegularClass
|
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory3
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.getEffectiveVisibility
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
|
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
|
||||||
@@ -51,12 +52,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
val restricting = supertype.findVisibilityExposure(context, classVisibility)
|
val restricting = supertype.findVisibilityExposure(context, classVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
reporter.reportExposure(
|
reporter.reportOn(
|
||||||
|
supertypeRef.source ?: declaration.source,
|
||||||
if (isInterface) FirErrors.EXPOSED_SUPER_INTERFACE else FirErrors.EXPOSED_SUPER_CLASS,
|
if (isInterface) FirErrors.EXPOSED_SUPER_INTERFACE else FirErrors.EXPOSED_SUPER_CLASS,
|
||||||
restricting,
|
|
||||||
classVisibility,
|
classVisibility,
|
||||||
|
restricting,
|
||||||
restricting.getEffectiveVisibility(context),
|
restricting.getEffectiveVisibility(context),
|
||||||
supertypeRef.source ?: declaration.source
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,12 +72,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
for (bound in parameter.symbol.fir.bounds) {
|
for (bound in parameter.symbol.fir.bounds) {
|
||||||
val restricting = bound.coneType.findVisibilityExposure(context, classVisibility)
|
val restricting = bound.coneType.findVisibilityExposure(context, classVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
reporter.reportExposure(
|
reporter.reportOn(
|
||||||
|
bound.source,
|
||||||
FirErrors.EXPOSED_TYPE_PARAMETER_BOUND,
|
FirErrors.EXPOSED_TYPE_PARAMETER_BOUND,
|
||||||
restricting,
|
|
||||||
classVisibility,
|
classVisibility,
|
||||||
|
restricting,
|
||||||
restricting.getEffectiveVisibility(context),
|
restricting.getEffectiveVisibility(context),
|
||||||
bound.source
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,12 +92,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
if (typeAliasVisibility == FirEffectiveVisibilityImpl.Local) return
|
if (typeAliasVisibility == FirEffectiveVisibilityImpl.Local) return
|
||||||
val restricting = expandedType?.findVisibilityExposure(context, typeAliasVisibility)
|
val restricting = expandedType?.findVisibilityExposure(context, typeAliasVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
reporter.reportExposure(
|
reporter.reportOn(
|
||||||
|
declaration.source,
|
||||||
FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE,
|
FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE,
|
||||||
restricting,
|
|
||||||
typeAliasVisibility,
|
typeAliasVisibility,
|
||||||
|
restricting,
|
||||||
restricting.getEffectiveVisibility(context),
|
restricting.getEffectiveVisibility(context),
|
||||||
declaration.source
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,12 +111,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
val restricting = declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
val restricting = declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||||
?.findVisibilityExposure(context, functionVisibility)
|
?.findVisibilityExposure(context, functionVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
reporter.reportExposure(
|
reporter.reportOn(
|
||||||
|
declaration.source,
|
||||||
FirErrors.EXPOSED_FUNCTION_RETURN_TYPE,
|
FirErrors.EXPOSED_FUNCTION_RETURN_TYPE,
|
||||||
restricting,
|
|
||||||
functionVisibility,
|
functionVisibility,
|
||||||
|
restricting,
|
||||||
restricting.getEffectiveVisibility(context),
|
restricting.getEffectiveVisibility(context),
|
||||||
declaration.source
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,12 +127,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||||
?.findVisibilityExposure(context, functionVisibility)
|
?.findVisibilityExposure(context, functionVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
reporter.reportExposure(
|
reporter.reportOn(
|
||||||
|
valueParameter.source,
|
||||||
FirErrors.EXPOSED_PARAMETER_TYPE,
|
FirErrors.EXPOSED_PARAMETER_TYPE,
|
||||||
restricting,
|
|
||||||
functionVisibility,
|
functionVisibility,
|
||||||
|
restricting,
|
||||||
restricting.getEffectiveVisibility(context),
|
restricting.getEffectiveVisibility(context),
|
||||||
valueParameter.source
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,12 +149,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||||
?.findVisibilityExposure(context, propertyVisibility)
|
?.findVisibilityExposure(context, propertyVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
reporter.reportExposure(
|
reporter.reportOn(
|
||||||
|
declaration.source,
|
||||||
FirErrors.EXPOSED_PROPERTY_TYPE,
|
FirErrors.EXPOSED_PROPERTY_TYPE,
|
||||||
restricting,
|
|
||||||
propertyVisibility,
|
propertyVisibility,
|
||||||
|
restricting,
|
||||||
restricting.getEffectiveVisibility(context),
|
restricting.getEffectiveVisibility(context),
|
||||||
declaration.source
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
checkMemberReceiver(declaration.receiverTypeRef, declaration, reporter, context)
|
checkMemberReceiver(declaration.receiverTypeRef, declaration, reporter, context)
|
||||||
@@ -167,12 +174,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
if (memberVisibility == FirEffectiveVisibilityImpl.Local) return
|
if (memberVisibility == FirEffectiveVisibilityImpl.Local) return
|
||||||
val restricting = receiverParameterType.findVisibilityExposure(context, memberVisibility)
|
val restricting = receiverParameterType.findVisibilityExposure(context, memberVisibility)
|
||||||
if (restricting != null) {
|
if (restricting != null) {
|
||||||
reporter.reportExposure(
|
reporter.reportOn(
|
||||||
|
typeRef.source,
|
||||||
FirErrors.EXPOSED_RECEIVER_TYPE,
|
FirErrors.EXPOSED_RECEIVER_TYPE,
|
||||||
restricting,
|
|
||||||
memberVisibility,
|
memberVisibility,
|
||||||
|
restricting,
|
||||||
restricting.getEffectiveVisibility(context),
|
restricting.getEffectiveVisibility(context),
|
||||||
typeRef.source
|
context
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -207,25 +215,6 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified E : FirSourceElement, P : PsiElement> DiagnosticReporter.reportExposure(
|
|
||||||
error: FirDiagnosticFactory3<E, P, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>,
|
|
||||||
restrictingDeclaration: FirMemberDeclaration,
|
|
||||||
elementVisibility: FirEffectiveVisibility,
|
|
||||||
restrictingVisibility: FirEffectiveVisibility,
|
|
||||||
source: FirSourceElement?
|
|
||||||
) {
|
|
||||||
source?.let {
|
|
||||||
report(
|
|
||||||
error.on(
|
|
||||||
it as E,
|
|
||||||
elementVisibility,
|
|
||||||
restrictingDeclaration,
|
|
||||||
restrictingVisibility
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirMemberDeclaration.getEffectiveVisibility(context: CheckerContext) =
|
private fun FirMemberDeclaration.getEffectiveVisibility(context: CheckerContext) =
|
||||||
getEffectiveVisibility(context.session, context.containingDeclarations, context.sessionHolder.scopeSession)
|
getEffectiveVisibility(context.session, context.containingDeclarations, context.sessionHolder.scopeSession)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
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.extended.report
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
@@ -23,7 +23,7 @@ object FirFunctionNameChecker : FirFunctionChecker() {
|
|||||||
val containingDeclaration = context.containingDeclarations.lastOrNull()
|
val containingDeclaration = context.containingDeclarations.lastOrNull()
|
||||||
val isNonLocal = containingDeclaration is FirFile || containingDeclaration is FirClass<*>
|
val isNonLocal = containingDeclaration is FirFile || containingDeclaration is FirClass<*>
|
||||||
if (declaration is FirSimpleFunction && declaration.name == SpecialNames.NO_NAME_PROVIDED && isNonLocal) {
|
if (declaration is FirSimpleFunction && declaration.name == SpecialNames.NO_NAME_PROVIDED && isNonLocal) {
|
||||||
reporter.report(source, FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME)
|
reporter.reportOn(source, FirErrors.FUNCTION_DECLARATION_WITH_NO_NAME, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -10,7 +10,8 @@ import org.jetbrains.kotlin.fir.FirSourceElement
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.isLateInit
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
import org.jetbrains.kotlin.fir.types.ConeTypeParameterType
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
@@ -40,28 +41,28 @@ object FirInapplicableLateinitChecker : FirPropertyChecker() {
|
|||||||
|
|
||||||
when {
|
when {
|
||||||
declaration.isVal ->
|
declaration.isVal ->
|
||||||
reporter.report(declaration.source, "is allowed only on mutable properties")
|
reporter.reportOn(declaration.source, "is allowed only on mutable properties", context)
|
||||||
|
|
||||||
declaration.initializer != null -> if (declaration.isLocal) {
|
declaration.initializer != null -> if (declaration.isLocal) {
|
||||||
reporter.report(declaration.source, "is not allowed on local variables with initializer")
|
reporter.reportOn(declaration.source, "is not allowed on local variables with initializer", context)
|
||||||
} else {
|
} else {
|
||||||
reporter.report(declaration.source, "is not allowed on properties with initializer")
|
reporter.reportOn(declaration.source, "is not allowed on properties with initializer", context)
|
||||||
}
|
}
|
||||||
|
|
||||||
declaration.delegate != null ->
|
declaration.delegate != null ->
|
||||||
reporter.report(declaration.source, "is not allowed on delegated properties")
|
reporter.reportOn(declaration.source, "is not allowed on delegated properties", context)
|
||||||
|
|
||||||
declaration.isNullable() ->
|
declaration.isNullable() ->
|
||||||
reporter.report(declaration.source, "is not allowed on properties of a type with nullable upper bound")
|
reporter.reportOn(declaration.source, "is not allowed on properties of a type with nullable upper bound", context)
|
||||||
|
|
||||||
declaration.returnTypeRef.coneType in getPrimitiveTypes(context) -> if (declaration.isLocal) {
|
declaration.returnTypeRef.coneType in getPrimitiveTypes(context) -> if (declaration.isLocal) {
|
||||||
reporter.report(declaration.source, "is not allowed on local variables of primitive types")
|
reporter.reportOn(declaration.source, "is not allowed on local variables of primitive types", context)
|
||||||
} else {
|
} else {
|
||||||
reporter.report(declaration.source, "is not allowed on properties of primitive types")
|
reporter.reportOn(declaration.source, "is not allowed on properties of primitive types", context)
|
||||||
}
|
}
|
||||||
|
|
||||||
declaration.hasGetter() || declaration.hasSetter() ->
|
declaration.hasGetter() || declaration.hasSetter() ->
|
||||||
reporter.report(declaration.source, "is not allowed on properties with a custom getter or setter")
|
reporter.reportOn(declaration.source, "is not allowed on properties with a custom getter or setter", context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ object FirInapplicableLateinitChecker : FirPropertyChecker() {
|
|||||||
private fun FirProperty.hasGetter() = getter != null && getter?.source != null && getter?.source?.kind !is FirFakeSourceElementKind
|
private fun FirProperty.hasGetter() = getter != null && getter?.source != null && getter?.source?.kind !is FirFakeSourceElementKind
|
||||||
private fun FirProperty.hasSetter() = setter != null && setter?.source != null && setter?.source?.kind !is FirFakeSourceElementKind
|
private fun FirProperty.hasSetter() = setter != null && setter?.source != null && setter?.source?.kind !is FirFakeSourceElementKind
|
||||||
|
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?, target: String) {
|
private fun DiagnosticReporter.reportOn(source: FirSourceElement?, target: String, context: CheckerContext) {
|
||||||
source?.let { report(FirErrors.INAPPLICABLE_LATEINIT_MODIFIER.on(it, target)) }
|
source?.let { report(FirErrors.INAPPLICABLE_LATEINIT_MODIFIER.on(it, target), context) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
@@ -18,12 +18,12 @@ object FirInfixFunctionDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (declaration is FirSimpleFunction && declaration.isInfix) {
|
if (declaration is FirSimpleFunction && declaration.isInfix) {
|
||||||
if (declaration.valueParameters.size != 1 || !hasExtensionOrDispatchReceiver(declaration, context)) {
|
if (declaration.valueParameters.size != 1 || !hasExtensionOrDispatchReceiver(declaration, context)) {
|
||||||
reporter.report(declaration.source)
|
reporter.reportOn(declaration.source, FirErrors.INAPPLICABLE_INFIX_MODIFIER, context)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (declaration.isInfix) {
|
if (declaration.isInfix) {
|
||||||
reporter.report(declaration.source)
|
reporter.reportOn(declaration.source, FirErrors.INAPPLICABLE_INFIX_MODIFIER, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,8 +34,4 @@ object FirInfixFunctionDeclarationChecker : FirMemberDeclarationChecker() {
|
|||||||
if (function.receiverTypeRef != null) return true
|
if (function.receiverTypeRef != null) return true
|
||||||
return context.containingDeclarations.lastOrNull() is FirClass<*>
|
return context.containingDeclarations.lastOrNull() is FirClass<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.INAPPLICABLE_INFIX_MODIFIER.on(it, "Inapplicable infix modifier")) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
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.findNonInterfaceSupertype
|
import org.jetbrains.kotlin.fir.analysis.checkers.findNonInterfaceSupertype
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isInterface
|
import org.jetbrains.kotlin.fir.declarations.isInterface
|
||||||
|
|
||||||
@@ -20,11 +20,7 @@ object FirInterfaceWithSuperclassChecker : FirRegularClassChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declaration.findNonInterfaceSupertype(context)?.let {
|
declaration.findNonInterfaceSupertype(context)?.let {
|
||||||
reporter.report(it.source)
|
reporter.reportOn(it.source, FirErrors.INTERFACE_WITH_SUPERCLASS, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.INTERFACE_WITH_SUPERCLASS.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-12
@@ -6,15 +6,14 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isCompanion
|
import org.jetbrains.kotlin.fir.declarations.isCompanion
|
||||||
import org.jetbrains.kotlin.fir.declarations.visibility
|
import org.jetbrains.kotlin.fir.declarations.visibility
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
|
|
||||||
object FirLocalEntityNotAllowedChecker : FirRegularClassChecker() {
|
object FirLocalEntityNotAllowedChecker : FirRegularClassChecker() {
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
@@ -24,19 +23,11 @@ object FirLocalEntityNotAllowedChecker : FirRegularClassChecker() {
|
|||||||
|
|
||||||
when {
|
when {
|
||||||
declaration.classKind == ClassKind.OBJECT && !declaration.isCompanion ->
|
declaration.classKind == ClassKind.OBJECT && !declaration.isCompanion ->
|
||||||
reporter.reportLocalObjectNotAllowed(declaration.source, declaration.name)
|
reporter.reportOn(declaration.source, FirErrors.LOCAL_OBJECT_NOT_ALLOWED, declaration.name, context)
|
||||||
declaration.classKind == ClassKind.INTERFACE ->
|
declaration.classKind == ClassKind.INTERFACE ->
|
||||||
reporter.reportLocalInterfaceNotAllowed(declaration.source, declaration.name)
|
reporter.reportOn(declaration.source, FirErrors.LOCAL_INTERFACE_NOT_ALLOWED, declaration.name, context)
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportLocalObjectNotAllowed(source: FirSourceElement?, name: Name) {
|
|
||||||
source?.let { report(FirErrors.LOCAL_OBJECT_NOT_ALLOWED.on(it, name)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportLocalInterfaceNotAllowed(source: FirSourceElement?, name: Name) {
|
|
||||||
source?.let { report(FirErrors.LOCAL_INTERFACE_NOT_ALLOWED.on(it, name)) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isCompanion
|
import org.jetbrains.kotlin.fir.declarations.isCompanion
|
||||||
|
|
||||||
@@ -19,14 +19,10 @@ object FirManyCompanionObjectsChecker : FirRegularClassChecker() {
|
|||||||
for (it in declaration.declarations) {
|
for (it in declaration.declarations) {
|
||||||
if (it is FirRegularClass && it.isCompanion) {
|
if (it is FirRegularClass && it.isCompanion) {
|
||||||
if (hasCompanion) {
|
if (hasCompanion) {
|
||||||
reporter.report(it.source)
|
reporter.reportOn(it.source, FirErrors.MANY_COMPANION_OBJECTS, context)
|
||||||
}
|
}
|
||||||
hasCompanion = true
|
hasCompanion = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.MANY_COMPANION_OBJECTS.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+10
-8
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
|||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
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.extended.report
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
@@ -39,10 +39,13 @@ object FirMemberFunctionChecker : FirRegularClassChecker() {
|
|||||||
val isAbstract = function.isAbstract || hasAbstractModifier
|
val isAbstract = function.isAbstract || hasAbstractModifier
|
||||||
if (isAbstract) {
|
if (isAbstract) {
|
||||||
if (!containingDeclaration.canHaveAbstractDeclaration) {
|
if (!containingDeclaration.canHaveAbstractDeclaration) {
|
||||||
reporter.report(FirErrors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(source, function, containingDeclaration))
|
reporter.report(
|
||||||
|
FirErrors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(source, function, containingDeclaration),
|
||||||
|
context
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (function.hasBody) {
|
if (function.hasBody) {
|
||||||
reporter.report(FirErrors.ABSTRACT_FUNCTION_WITH_BODY.on(source, function))
|
reporter.report(FirErrors.ABSTRACT_FUNCTION_WITH_BODY.on(source, function), context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val isInsideExpectClass = isInsideExpectClass(containingDeclaration, context)
|
val isInsideExpectClass = isInsideExpectClass(containingDeclaration, context)
|
||||||
@@ -51,17 +54,16 @@ object FirMemberFunctionChecker : FirRegularClassChecker() {
|
|||||||
if (!function.hasBody) {
|
if (!function.hasBody) {
|
||||||
if (containingDeclaration.isInterface) {
|
if (containingDeclaration.isInterface) {
|
||||||
if (Visibilities.isPrivate(function.visibility)) {
|
if (Visibilities.isPrivate(function.visibility)) {
|
||||||
reporter.report(FirErrors.PRIVATE_FUNCTION_WITH_NO_BODY.on(source, function))
|
reporter.reportOn(source, FirErrors.PRIVATE_FUNCTION_WITH_NO_BODY, function, context)
|
||||||
}
|
}
|
||||||
if (!isInsideExpectClass && !hasAbstractModifier && hasOpenModifier) {
|
if (!isInsideExpectClass && !hasAbstractModifier && hasOpenModifier) {
|
||||||
reporter.report(source, FirErrors.REDUNDANT_OPEN_IN_INTERFACE)
|
reporter.reportOn(source, FirErrors.REDUNDANT_OPEN_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
} else if (!isInsideExpectClass && !hasAbstractModifier && !isExternal) {
|
} else if (!isInsideExpectClass && !hasAbstractModifier && !isExternal) {
|
||||||
reporter.report(FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(source, function))
|
reporter.reportOn(source, FirErrors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, function, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExpectDeclarationVisibilityAndBody(function, source, modifierList, reporter)
|
checkExpectDeclarationVisibilityAndBody(function, source, modifierList, reporter, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-12
@@ -9,9 +9,9 @@ import org.jetbrains.kotlin.descriptors.Visibilities
|
|||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
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.extended.report
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
@@ -47,37 +47,43 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
|
|||||||
(property.getter == null || property.getter is FirDefaultPropertyAccessor)
|
(property.getter == null || property.getter is FirDefaultPropertyAccessor)
|
||||||
) {
|
) {
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
reporter.report(it, FirErrors.PRIVATE_PROPERTY_IN_INTERFACE)
|
reporter.reportOn(it, FirErrors.PRIVATE_PROPERTY_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAbstract) {
|
if (isAbstract) {
|
||||||
if (!containingDeclaration.canHaveAbstractDeclaration) {
|
if (!containingDeclaration.canHaveAbstractDeclaration) {
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
reporter.report(FirErrors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(it, property, containingDeclaration))
|
reporter.reportOn(
|
||||||
|
it,
|
||||||
|
FirErrors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS,
|
||||||
|
property,
|
||||||
|
containingDeclaration,
|
||||||
|
context
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
property.initializer?.source?.let {
|
property.initializer?.source?.let {
|
||||||
reporter.report(it, FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER)
|
reporter.reportOn(it, FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER, context)
|
||||||
}
|
}
|
||||||
property.delegate?.source?.let {
|
property.delegate?.source?.let {
|
||||||
reporter.report(it, FirErrors.ABSTRACT_DELEGATED_PROPERTY)
|
reporter.reportOn(it, FirErrors.ABSTRACT_DELEGATED_PROPERTY, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAccessor(property.getter, property.delegate) { src, _ ->
|
checkAccessor(property.getter, property.delegate) { src, _ ->
|
||||||
reporter.report(src, FirErrors.ABSTRACT_PROPERTY_WITH_GETTER)
|
reporter.reportOn(src, FirErrors.ABSTRACT_PROPERTY_WITH_GETTER, context)
|
||||||
}
|
}
|
||||||
checkAccessor(property.setter, property.delegate) { src, symbol ->
|
checkAccessor(property.setter, property.delegate) { src, symbol ->
|
||||||
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
|
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
|
||||||
reporter.report(src, FirErrors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY)
|
reporter.reportOn(src, FirErrors.PRIVATE_SETTER_FOR_ABSTRACT_PROPERTY, context)
|
||||||
} else {
|
} else {
|
||||||
reporter.report(src, FirErrors.ABSTRACT_PROPERTY_WITH_SETTER)
|
reporter.reportOn(src, FirErrors.ABSTRACT_PROPERTY_WITH_SETTER, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPropertyInitializer(containingDeclaration, property, reporter)
|
checkPropertyInitializer(containingDeclaration, property, reporter, context)
|
||||||
|
|
||||||
val hasOpenModifier = modifierList?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true
|
val hasOpenModifier = modifierList?.modifiers?.any { it.token == KtTokens.OPEN_KEYWORD } == true
|
||||||
if (hasOpenModifier &&
|
if (hasOpenModifier &&
|
||||||
@@ -87,19 +93,19 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
|
|||||||
!isInsideExpectClass(containingDeclaration, context)
|
!isInsideExpectClass(containingDeclaration, context)
|
||||||
) {
|
) {
|
||||||
property.source?.let {
|
property.source?.let {
|
||||||
reporter.report(it, FirErrors.REDUNDANT_OPEN_IN_INTERFACE)
|
reporter.reportOn(it, FirErrors.REDUNDANT_OPEN_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val isOpen = property.isOpen || hasOpenModifier
|
val isOpen = property.isOpen || hasOpenModifier
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
checkAccessor(property.setter, property.delegate) { src, symbol ->
|
checkAccessor(property.setter, property.delegate) { src, symbol ->
|
||||||
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
|
if (symbol.fir.visibility == Visibilities.Private && property.visibility != Visibilities.Private) {
|
||||||
reporter.report(src, FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY)
|
reporter.reportOn(src, FirErrors.PRIVATE_SETTER_FOR_OPEN_PROPERTY, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter)
|
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkAccessor(
|
private fun checkAccessor(
|
||||||
|
|||||||
+3
-7
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector
|
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationPresenter
|
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationPresenter
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -64,12 +64,8 @@ object FirMethodOfAnyImplementedInInterfaceChecker : FirRegularClassChecker(), F
|
|||||||
val inspector = getInspector(context)
|
val inspector = getInspector(context)
|
||||||
|
|
||||||
if (it is FirSimpleFunction && inspector.contains(it) && it.body != null && it.isOverride) {
|
if (it is FirSimpleFunction && inspector.contains(it) && it.body != null && it.isOverride) {
|
||||||
reporter.report(it.source)
|
reporter.reportOn(it.source, FirErrors.ANY_METHOD_IMPLEMENTED_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.ANY_METHOD_IMPLEMENTED_IN_INTERFACE.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+22
-20
@@ -6,7 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
@@ -103,7 +103,8 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
|||||||
secondModifier: FirModifier<*>,
|
secondModifier: FirModifier<*>,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
reportedNodes: MutableSet<FirModifier<*>>,
|
reportedNodes: MutableSet<FirModifier<*>>,
|
||||||
owner: FirDeclaration?
|
owner: FirDeclaration?,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
val firstToken = firstModifier.token
|
val firstToken = firstModifier.token
|
||||||
val secondToken = secondModifier.token
|
val secondToken = secondModifier.token
|
||||||
@@ -111,21 +112,21 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
|||||||
CompatibilityType.COMPATIBLE -> {
|
CompatibilityType.COMPATIBLE -> {
|
||||||
}
|
}
|
||||||
CompatibilityType.REPEATED ->
|
CompatibilityType.REPEATED ->
|
||||||
if (reportedNodes.add(secondModifier)) reporter.reportRepeatedModifier(secondModifier, secondToken)
|
if (reportedNodes.add(secondModifier)) reporter.reportRepeatedModifier(secondModifier, secondToken, context)
|
||||||
CompatibilityType.REDUNDANT_2_TO_1 ->
|
CompatibilityType.REDUNDANT_2_TO_1 ->
|
||||||
reporter.reportRedundantModifier(secondModifier, secondToken, firstToken)
|
reporter.reportRedundantModifier(secondModifier, secondToken, firstToken, context)
|
||||||
CompatibilityType.REDUNDANT_1_TO_2 ->
|
CompatibilityType.REDUNDANT_1_TO_2 ->
|
||||||
reporter.reportRedundantModifier(firstModifier, firstToken, secondToken)
|
reporter.reportRedundantModifier(firstModifier, firstToken, secondToken, context)
|
||||||
CompatibilityType.DEPRECATED -> {
|
CompatibilityType.DEPRECATED -> {
|
||||||
reporter.reportDeprecatedModifierPair(firstModifier, firstToken, secondToken)
|
reporter.reportDeprecatedModifierPair(firstModifier, firstToken, secondToken, context)
|
||||||
reporter.reportDeprecatedModifierPair(secondModifier, secondToken, firstToken)
|
reporter.reportDeprecatedModifierPair(secondModifier, secondToken, firstToken, context)
|
||||||
}
|
}
|
||||||
CompatibilityType.INCOMPATIBLE, CompatibilityType.COMPATIBLE_FOR_CLASSES -> {
|
CompatibilityType.INCOMPATIBLE, CompatibilityType.COMPATIBLE_FOR_CLASSES -> {
|
||||||
if (compatibilityType == CompatibilityType.COMPATIBLE_FOR_CLASSES && owner is FirClass<*>) {
|
if (compatibilityType == CompatibilityType.COMPATIBLE_FOR_CLASSES && owner is FirClass<*>) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (reportedNodes.add(firstModifier)) reporter.reportIncompatibleModifiers(firstModifier, firstToken, secondToken)
|
if (reportedNodes.add(firstModifier)) reporter.reportIncompatibleModifiers(firstModifier, firstToken, secondToken, context)
|
||||||
if (reportedNodes.add(secondModifier)) reporter.reportIncompatibleModifiers(secondModifier, secondToken, firstToken)
|
if (reportedNodes.add(secondModifier)) reporter.reportIncompatibleModifiers(secondModifier, secondToken, firstToken, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,7 +134,8 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
|||||||
private fun checkModifiers(
|
private fun checkModifiers(
|
||||||
list: FirModifierList,
|
list: FirModifierList,
|
||||||
owner: FirDeclaration,
|
owner: FirDeclaration,
|
||||||
reporter: DiagnosticReporter
|
reporter: DiagnosticReporter,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
// general strategy: report no more than one error and any number of warnings
|
// general strategy: report no more than one error and any number of warnings
|
||||||
// therefore, a track of nodes with already reported errors should be kept
|
// therefore, a track of nodes with already reported errors should be kept
|
||||||
@@ -145,7 +147,7 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
|||||||
if (firstModifier == secondModifier) {
|
if (firstModifier == secondModifier) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
checkCompatibilityType(firstModifier, secondModifier, reporter, reportedNodes, owner)
|
checkCompatibilityType(firstModifier, secondModifier, reporter, reportedNodes, owner, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,30 +170,30 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
|||||||
if (context.containingDeclarations.last() is FirDefaultPropertyAccessor) return
|
if (context.containingDeclarations.last() is FirDefaultPropertyAccessor) return
|
||||||
|
|
||||||
val modifierList = with(FirModifierList) { source.getModifierList() }
|
val modifierList = with(FirModifierList) { source.getModifierList() }
|
||||||
modifierList?.let { checkModifiers(it, declaration, reporter) }
|
modifierList?.let { checkModifiers(it, declaration, reporter, context) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportRepeatedModifier(
|
private fun DiagnosticReporter.reportRepeatedModifier(
|
||||||
modifier: FirModifier<*>, keyword: KtModifierKeywordToken
|
modifier: FirModifier<*>, keyword: KtModifierKeywordToken, context: CheckerContext
|
||||||
) {
|
) {
|
||||||
report(FirErrors.REPEATED_MODIFIER.on(modifier.source, keyword))
|
report(FirErrors.REPEATED_MODIFIER.on(modifier.source, keyword), context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportRedundantModifier(
|
private fun DiagnosticReporter.reportRedundantModifier(
|
||||||
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken
|
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken, context: CheckerContext
|
||||||
) {
|
) {
|
||||||
report(FirErrors.REDUNDANT_MODIFIER.on(modifier.source, firstKeyword, secondKeyword))
|
report(FirErrors.REDUNDANT_MODIFIER.on(modifier.source, firstKeyword, secondKeyword), context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportDeprecatedModifierPair(
|
private fun DiagnosticReporter.reportDeprecatedModifierPair(
|
||||||
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken
|
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken, context: CheckerContext
|
||||||
) {
|
) {
|
||||||
report(FirErrors.DEPRECATED_MODIFIER_PAIR.on(modifier.source, firstKeyword, secondKeyword))
|
report(FirErrors.DEPRECATED_MODIFIER_PAIR.on(modifier.source, firstKeyword, secondKeyword), context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportIncompatibleModifiers(
|
private fun DiagnosticReporter.reportIncompatibleModifiers(
|
||||||
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken
|
modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken, context: CheckerContext
|
||||||
) {
|
) {
|
||||||
report(FirErrors.INCOMPATIBLE_MODIFIERS.on(modifier.source, firstKeyword, secondKeyword))
|
report(FirErrors.INCOMPATIBLE_MODIFIERS.on(modifier.source, firstKeyword, secondKeyword), context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-32
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.Modality
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.containingClass
|
import org.jetbrains.kotlin.fir.containingClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||||
@@ -106,6 +107,7 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
private fun FirCallableMemberDeclaration<*>.checkVisibility(
|
private fun FirCallableMemberDeclaration<*>.checkVisibility(
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
overriddenSymbols: List<FirCallableSymbol<*>>,
|
overriddenSymbols: List<FirCallableSymbol<*>>,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
val visibilities = overriddenSymbols.mapNotNull {
|
val visibilities = overriddenSymbols.mapNotNull {
|
||||||
if (it.fir !is FirMemberDeclaration) return@mapNotNull null
|
if (it.fir !is FirMemberDeclaration) return@mapNotNull null
|
||||||
@@ -122,7 +124,7 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
// reporter.reportCannotChangeAccessPrivilege(this, overridden.fir)
|
// reporter.reportCannotChangeAccessPrivilege(this, overridden.fir)
|
||||||
return
|
return
|
||||||
} else if (compare < 0) {
|
} else if (compare < 0) {
|
||||||
reporter.reportCannotWeakenAccessPrivilege(this, overridden.fir)
|
reporter.reportCannotWeakenAccessPrivilege(this, overridden.fir, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,15 +171,15 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
val overriddenFunctionSymbols = firTypeScope.retrieveDirectOverriddenOf(function)
|
val overriddenFunctionSymbols = firTypeScope.retrieveDirectOverriddenOf(function)
|
||||||
|
|
||||||
if (overriddenFunctionSymbols.isEmpty()) {
|
if (overriddenFunctionSymbols.isEmpty()) {
|
||||||
reporter.reportNothingToOverride(function)
|
reporter.reportNothingToOverride(function, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
checkModality(overriddenFunctionSymbols)?.let {
|
checkModality(overriddenFunctionSymbols)?.let {
|
||||||
reporter.reportOverridingFinalMember(function, it)
|
reporter.reportOverridingFinalMember(function, it, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
function.checkVisibility(reporter, overriddenFunctionSymbols)
|
function.checkVisibility(reporter, overriddenFunctionSymbols, context)
|
||||||
|
|
||||||
val restriction = function.checkReturnType(
|
val restriction = function.checkReturnType(
|
||||||
overriddenSymbols = overriddenFunctionSymbols,
|
overriddenSymbols = overriddenFunctionSymbols,
|
||||||
@@ -186,7 +188,7 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
restriction?.let {
|
restriction?.let {
|
||||||
reporter.reportReturnTypeMismatchOnFunction(function, it)
|
reporter.reportReturnTypeMismatchOnFunction(function, it, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,19 +206,19 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
val overriddenPropertySymbols = firTypeScope.retrieveDirectOverriddenOf(property)
|
val overriddenPropertySymbols = firTypeScope.retrieveDirectOverriddenOf(property)
|
||||||
|
|
||||||
if (overriddenPropertySymbols.isEmpty()) {
|
if (overriddenPropertySymbols.isEmpty()) {
|
||||||
reporter.reportNothingToOverride(property)
|
reporter.reportNothingToOverride(property, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
checkModality(overriddenPropertySymbols)?.let {
|
checkModality(overriddenPropertySymbols)?.let {
|
||||||
reporter.reportOverridingFinalMember(property, it)
|
reporter.reportOverridingFinalMember(property, it, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
property.checkMutability(overriddenPropertySymbols)?.let {
|
property.checkMutability(overriddenPropertySymbols)?.let {
|
||||||
reporter.reportVarOverriddenByVal(property, it)
|
reporter.reportVarOverriddenByVal(property, it, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
property.checkVisibility(reporter, overriddenPropertySymbols)
|
property.checkVisibility(reporter, overriddenPropertySymbols, context)
|
||||||
|
|
||||||
val restriction = property.checkReturnType(
|
val restriction = property.checkReturnType(
|
||||||
overriddenSymbols = overriddenPropertySymbols,
|
overriddenSymbols = overriddenPropertySymbols,
|
||||||
@@ -226,76 +228,91 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
|
|
||||||
restriction?.let {
|
restriction?.let {
|
||||||
if (property.isVar) {
|
if (property.isVar) {
|
||||||
reporter.reportTypeMismatchOnVariable(property, it)
|
reporter.reportTypeMismatchOnVariable(property, it, context)
|
||||||
} else {
|
} else {
|
||||||
reporter.reportTypeMismatchOnProperty(property, it)
|
reporter.reportTypeMismatchOnProperty(property, it, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportNothingToOverride(declaration: FirMemberDeclaration) {
|
private fun DiagnosticReporter.reportNothingToOverride(declaration: FirMemberDeclaration, context: CheckerContext) {
|
||||||
// TODO: not ready yet, e.g., Collections
|
// TODO: not ready yet, e.g., Collections
|
||||||
// declaration.source?.let { report(FirErrors.NOTHING_TO_OVERRIDE.on(it, declaration)) }
|
// reportOn(declaration.source, FirErrors.NOTHING_TO_OVERRIDE, declaration, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportOverridingFinalMember(
|
private fun DiagnosticReporter.reportOverridingFinalMember(
|
||||||
overriding: FirMemberDeclaration,
|
overriding: FirMemberDeclaration,
|
||||||
overridden: FirCallableDeclaration<*>,
|
overridden: FirCallableDeclaration<*>,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
overriding.source?.let { source ->
|
overriding.source?.let { source ->
|
||||||
overridden.containingClass()?.let { containingClass ->
|
overridden.containingClass()?.let { containingClass ->
|
||||||
report(FirErrors.OVERRIDING_FINAL_MEMBER.on(source, overridden, containingClass.name))
|
report(FirErrors.OVERRIDING_FINAL_MEMBER.on(source, overridden, containingClass.name), context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportVarOverriddenByVal(
|
private fun DiagnosticReporter.reportVarOverriddenByVal(
|
||||||
overriding: FirMemberDeclaration,
|
overriding: FirMemberDeclaration,
|
||||||
overridden: FirMemberDeclaration
|
overridden: FirMemberDeclaration,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
overriding.source?.let { report(FirErrors.VAR_OVERRIDDEN_BY_VAL.on(it, overriding, overridden)) }
|
overriding.source?.let { report(FirErrors.VAR_OVERRIDDEN_BY_VAL.on(it, overriding, overridden), context) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportCannotWeakenAccessPrivilege(
|
private fun DiagnosticReporter.reportCannotWeakenAccessPrivilege(
|
||||||
overriding: FirMemberDeclaration,
|
overriding: FirMemberDeclaration,
|
||||||
overridden: FirCallableDeclaration<*>,
|
overridden: FirCallableDeclaration<*>,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
overriding.source?.let { source ->
|
val containingClass = overridden.containingClass() ?: return
|
||||||
overridden.containingClass()?.let { containingClass ->
|
reportOn(
|
||||||
report(FirErrors.CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(source, overriding.visibility, overridden, containingClass.name))
|
overriding.source,
|
||||||
}
|
FirErrors.CANNOT_WEAKEN_ACCESS_PRIVILEGE,
|
||||||
}
|
overriding.visibility,
|
||||||
|
overridden,
|
||||||
|
containingClass.name,
|
||||||
|
context
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportCannotChangeAccessPrivilege(
|
private fun DiagnosticReporter.reportCannotChangeAccessPrivilege(
|
||||||
overriding: FirMemberDeclaration,
|
overriding: FirMemberDeclaration,
|
||||||
overridden: FirCallableDeclaration<*>,
|
overridden: FirCallableDeclaration<*>,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
overriding.source?.let { source ->
|
val containingClass = overridden.containingClass() ?: return
|
||||||
overridden.containingClass()?.let { containingClass ->
|
reportOn(
|
||||||
report(FirErrors.CANNOT_CHANGE_ACCESS_PRIVILEGE.on(source, overriding.visibility, overridden, containingClass.name))
|
overriding.source,
|
||||||
}
|
FirErrors.CANNOT_CHANGE_ACCESS_PRIVILEGE,
|
||||||
}
|
overriding.visibility,
|
||||||
|
overridden,
|
||||||
|
containingClass.name,
|
||||||
|
context
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportReturnTypeMismatchOnFunction(
|
private fun DiagnosticReporter.reportReturnTypeMismatchOnFunction(
|
||||||
overriding: FirMemberDeclaration,
|
overriding: FirMemberDeclaration,
|
||||||
overridden: FirMemberDeclaration
|
overridden: FirMemberDeclaration,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
overriding.source?.let { report(FirErrors.RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(it, overriding, overridden)) }
|
reportOn(overriding.source, FirErrors.RETURN_TYPE_MISMATCH_ON_OVERRIDE, overriding, overridden, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportTypeMismatchOnProperty(
|
private fun DiagnosticReporter.reportTypeMismatchOnProperty(
|
||||||
overriding: FirMemberDeclaration,
|
overriding: FirMemberDeclaration,
|
||||||
overridden: FirMemberDeclaration
|
overridden: FirMemberDeclaration,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
overriding.source?.let { report(FirErrors.PROPERTY_TYPE_MISMATCH_ON_OVERRIDE.on(it, overriding, overridden)) }
|
reportOn(overriding.source, FirErrors.PROPERTY_TYPE_MISMATCH_ON_OVERRIDE, overriding, overridden, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportTypeMismatchOnVariable(
|
private fun DiagnosticReporter.reportTypeMismatchOnVariable(
|
||||||
overriding: FirMemberDeclaration,
|
overriding: FirMemberDeclaration,
|
||||||
overridden: FirMemberDeclaration
|
overridden: FirMemberDeclaration,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
overriding.source?.let { report(FirErrors.VAR_TYPE_MISMATCH_ON_OVERRIDE.on(it, overriding, overridden)) }
|
reportOn(overriding.source, FirErrors.VAR_TYPE_MISMATCH_ON_OVERRIDE, overriding, overridden, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -6,10 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isData
|
import org.jetbrains.kotlin.fir.declarations.isData
|
||||||
@@ -23,11 +23,7 @@ object FirPrimaryConstructorRequiredForDataClassChecker : FirRegularClassChecker
|
|||||||
val hasPrimaryConstructor = declaration.declarations.any { it is FirConstructor && it.isPrimary }
|
val hasPrimaryConstructor = declaration.declarations.any { it is FirConstructor && it.isPrimary }
|
||||||
|
|
||||||
if (!hasPrimaryConstructor) {
|
if (!hasPrimaryConstructor) {
|
||||||
reporter.report(declaration.source)
|
reporter.reportOn(declaration.source, FirErrors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+5
-13
@@ -6,10 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
@@ -55,7 +55,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
|||||||
?: continue
|
?: continue
|
||||||
|
|
||||||
if (fir.status.modality == Modality.SEALED && classId.outerClassId != null) {
|
if (fir.status.modality == Modality.SEALED && classId.outerClassId != null) {
|
||||||
reporter.report(it.source)
|
reporter.reportOn(it.source, FirErrors.SEALED_SUPERTYPE, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,7 +77,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
|||||||
?: continue
|
?: continue
|
||||||
|
|
||||||
if (fir.status.modality == Modality.SEALED) {
|
if (fir.status.modality == Modality.SEALED) {
|
||||||
reporter.reportInLocal(it.source)
|
reporter.reportOn(it.source, FirErrors.SEALED_SUPERTYPE_IN_LOCAL_CLASS, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,17 +99,9 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
|||||||
?: continue
|
?: continue
|
||||||
|
|
||||||
if (fir.status.modality == Modality.SEALED && !context.containingDeclarations.contains(fir)) {
|
if (fir.status.modality == Modality.SEALED && !context.containingDeclarations.contains(fir)) {
|
||||||
reporter.report(it.source)
|
reporter.reportOn(it.source, FirErrors.SEALED_SUPERTYPE, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.SEALED_SUPERTYPE.on(it)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DiagnosticReporter.reportInLocal(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.SEALED_SUPERTYPE_IN_LOCAL_CLASS.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-7
@@ -6,10 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isInterface
|
import org.jetbrains.kotlin.fir.declarations.isInterface
|
||||||
|
|
||||||
@@ -22,12 +22,8 @@ object FirSupertypeInitializedInInterfaceChecker : FirRegularClassChecker() {
|
|||||||
for (superTypeRef in declaration.superTypeRefs) {
|
for (superTypeRef in declaration.superTypeRefs) {
|
||||||
val source = superTypeRef.source ?: continue
|
val source = superTypeRef.source ?: continue
|
||||||
if (source.treeStructure.getParent(source.lighterASTNode)?.tokenType == KtNodeTypes.CONSTRUCTOR_CALLEE) {
|
if (source.treeStructure.getParent(source.lighterASTNode)?.tokenType == KtNodeTypes.CONSTRUCTOR_CALLEE) {
|
||||||
reporter.report(source)
|
reporter.reportOn(source, FirErrors.SUPERTYPE_INITIALIZED_IN_INTERFACE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.SUPERTYPE_INITIALIZED_IN_INTERFACE.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+2
-6
@@ -6,10 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.isInterface
|
import org.jetbrains.kotlin.fir.declarations.isInterface
|
||||||
@@ -27,12 +27,8 @@ object FirSupertypeInitializedWithoutPrimaryConstructor : FirRegularClassChecker
|
|||||||
for (superTypeRef in declaration.superTypeRefs) {
|
for (superTypeRef in declaration.superTypeRefs) {
|
||||||
val source = superTypeRef.source ?: continue
|
val source = superTypeRef.source ?: continue
|
||||||
if (source.treeStructure.getParent(source.lighterASTNode)?.tokenType == KtNodeTypes.CONSTRUCTOR_CALLEE) {
|
if (source.treeStructure.getParent(source.lighterASTNode)?.tokenType == KtNodeTypes.CONSTRUCTOR_CALLEE) {
|
||||||
reporter.report(declaration.source)
|
reporter.reportOn(declaration.source, FirErrors.SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-4
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
|
||||||
@@ -17,12 +18,12 @@ object FirTopLevelFunctionChecker : FirFileChecker() {
|
|||||||
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
for (topLevelDeclaration in declaration.declarations) {
|
for (topLevelDeclaration in declaration.declarations) {
|
||||||
if (topLevelDeclaration is FirSimpleFunction) {
|
if (topLevelDeclaration is FirSimpleFunction) {
|
||||||
checkFunction(topLevelDeclaration, reporter)
|
checkFunction(topLevelDeclaration, reporter, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkFunction(function: FirSimpleFunction, reporter: DiagnosticReporter) {
|
private fun checkFunction(function: FirSimpleFunction, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||||
val source = function.source ?: return
|
val source = function.source ?: return
|
||||||
if (source.kind is FirFakeSourceElementKind) return
|
if (source.kind is FirFakeSourceElementKind) return
|
||||||
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
|
// If multiple (potentially conflicting) modality modifiers are specified, not all modifiers are recorded at `status`.
|
||||||
@@ -32,9 +33,9 @@ object FirTopLevelFunctionChecker : FirFileChecker() {
|
|||||||
if (function.isExternal || modifierList?.modifiers?.any { it.token == KtTokens.EXTERNAL_KEYWORD } == true) return
|
if (function.isExternal || modifierList?.modifiers?.any { it.token == KtTokens.EXTERNAL_KEYWORD } == true) return
|
||||||
val isExpect = function.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true
|
val isExpect = function.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true
|
||||||
if (!function.hasBody && !isExpect) {
|
if (!function.hasBody && !isExpect) {
|
||||||
reporter.report(FirErrors.NON_MEMBER_FUNCTION_NO_BODY.on(source, function))
|
reporter.reportOn(source, FirErrors.NON_MEMBER_FUNCTION_NO_BODY, function, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExpectDeclarationVisibilityAndBody(function, source, modifierList, reporter)
|
checkExpectDeclarationVisibilityAndBody(function, source, modifierList, reporter, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -16,17 +16,17 @@ object FirTopLevelPropertyChecker : FirFileChecker() {
|
|||||||
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
for (topLevelDeclaration in declaration.declarations) {
|
for (topLevelDeclaration in declaration.declarations) {
|
||||||
if (topLevelDeclaration is FirProperty) {
|
if (topLevelDeclaration is FirProperty) {
|
||||||
checkProperty(topLevelDeclaration, reporter)
|
checkProperty(topLevelDeclaration, reporter, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkProperty(property: FirProperty, reporter: DiagnosticReporter) {
|
private fun checkProperty(property: FirProperty, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||||
val source = property.source ?: return
|
val source = property.source ?: return
|
||||||
if (source.kind is FirFakeSourceElementKind) return
|
if (source.kind is FirFakeSourceElementKind) return
|
||||||
val modifierList = with(FirModifierList) { source.getModifierList() }
|
val modifierList = with(FirModifierList) { source.getModifierList() }
|
||||||
|
|
||||||
checkPropertyInitializer(null, property, reporter)
|
checkPropertyInitializer(null, property, reporter, context)
|
||||||
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter)
|
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -6,10 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
|
||||||
object FirTypeParametersInObjectChecker : FirRegularClassChecker() {
|
object FirTypeParametersInObjectChecker : FirRegularClassChecker() {
|
||||||
@@ -19,11 +19,7 @@ object FirTypeParametersInObjectChecker : FirRegularClassChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (declaration.typeParameters.isNotEmpty()) {
|
if (declaration.typeParameters.isNotEmpty()) {
|
||||||
reporter.report(declaration.source)
|
reporter.reportOn(declaration.source, FirErrors.TYPE_PARAMETERS_IN_OBJECT, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.TYPE_PARAMETERS_IN_OBJECT.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-9
@@ -7,12 +7,12 @@ package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
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.getContainingClass
|
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getDeclaration
|
import org.jetbrains.kotlin.fir.analysis.checkers.getDeclaration
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.modality
|
import org.jetbrains.kotlin.fir.declarations.modality
|
||||||
@@ -42,14 +42,8 @@ object FirAbstractSuperCallChecker : FirQualifiedAccessChecker() {
|
|||||||
declaration.modality == Modality.ABSTRACT &&
|
declaration.modality == Modality.ABSTRACT &&
|
||||||
item.modality == Modality.ABSTRACT
|
item.modality == Modality.ABSTRACT
|
||||||
) {
|
) {
|
||||||
reporter.report(expression.calleeReference.source)
|
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let {
|
|
||||||
report(FirErrors.ABSTRACT_SUPER_CALL.on(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-3
@@ -6,9 +6,9 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
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.extended.report
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
|
|
||||||
@@ -20,10 +20,10 @@ object FirAnonymousFunctionChecker : FirExpressionChecker<FirStatement>() {
|
|||||||
for (valueParameter in expression.valueParameters) {
|
for (valueParameter in expression.valueParameters) {
|
||||||
val source = valueParameter.source ?: continue
|
val source = valueParameter.source ?: continue
|
||||||
if (valueParameter.defaultValue != null) {
|
if (valueParameter.defaultValue != null) {
|
||||||
reporter.report(source, FirErrors.ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE)
|
reporter.reportOn(source, FirErrors.ANONYMOUS_FUNCTION_PARAMETER_WITH_DEFAULT_VALUE, context)
|
||||||
}
|
}
|
||||||
if (valueParameter.isVararg) {
|
if (valueParameter.isVararg) {
|
||||||
reporter.report(source, FirErrors.USELESS_VARARG_ON_PARAMETER)
|
reporter.reportOn(source, FirErrors.USELESS_VARARG_ON_PARAMETER, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -28,7 +28,7 @@ object FirCatchParameterChecker : FirTryExpressionChecker() {
|
|||||||
val catchParameter = catchEntry.parameter
|
val catchParameter = catchEntry.parameter
|
||||||
|
|
||||||
if (catchParameter.defaultValue != null)
|
if (catchParameter.defaultValue != null)
|
||||||
catchParameter.source?.let { reporter.report(FirErrors.CATCH_PARAMETER_WITH_DEFAULT_VALUE.on(it)) }
|
catchParameter.source?.let { reporter.report(FirErrors.CATCH_PARAMETER_WITH_DEFAULT_VALUE.on(it), context) }
|
||||||
|
|
||||||
val typeRef = catchParameter.returnTypeRef
|
val typeRef = catchParameter.returnTypeRef
|
||||||
if (typeRef !is FirResolvedTypeRef) return
|
if (typeRef !is FirResolvedTypeRef) return
|
||||||
@@ -38,17 +38,17 @@ object FirCatchParameterChecker : FirTryExpressionChecker() {
|
|||||||
val isReified = coneType.lookupTag.typeParameterSymbol.fir.isReified
|
val isReified = coneType.lookupTag.typeParameterSymbol.fir.isReified
|
||||||
|
|
||||||
if (isReified) {
|
if (isReified) {
|
||||||
catchParameter.source?.let { reporter.report(FirErrors.REIFIED_TYPE_IN_CATCH_CLAUSE.on(it)) }
|
catchParameter.source?.let { reporter.report(FirErrors.REIFIED_TYPE_IN_CATCH_CLAUSE.on(it), context) }
|
||||||
} else {
|
} else {
|
||||||
catchParameter.source?.let { reporter.report(FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE.on(it)) }
|
catchParameter.source?.let { reporter.report(FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE.on(it), context) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!coneType.isThrowable(context.session))
|
if (!coneType.isThrowable(context.session))
|
||||||
catchParameter.source?.let { reporter.report(FirErrors.TYPE_MISMATCH.on(it, throwable, coneType)) }
|
catchParameter.source?.let { reporter.report(FirErrors.TYPE_MISMATCH.on(it, throwable, coneType), context) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConeKotlinType.isThrowable(session: FirSession) =
|
private fun ConeKotlinType.isThrowable(session: FirSession) =
|
||||||
throwable.isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session))
|
throwable.isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session))
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-8
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
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.isSupertypeOf
|
import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
|
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
@@ -29,7 +29,7 @@ object FirNotASupertypeChecker : FirQualifiedAccessChecker() {
|
|||||||
|
|
||||||
val surrounding = context.findClosestClass(superReference.labelName) ?: return
|
val surrounding = context.findClosestClass(superReference.labelName) ?: return
|
||||||
if (!targetClass.isSupertypeOf(surrounding)) {
|
if (!targetClass.isSupertypeOf(surrounding)) {
|
||||||
reporter.report(expression.source)
|
reporter.reportOn(expression.source, FirErrors.NOT_A_SUPERTYPE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,10 +51,4 @@ object FirNotASupertypeChecker : FirQualifiedAccessChecker() {
|
|||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let {
|
|
||||||
report(FirErrors.NOT_A_SUPERTYPE.on(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-10
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.types.FirStarProjection
|
import org.jetbrains.kotlin.fir.types.FirStarProjection
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
|
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
|
||||||
@@ -18,19 +18,13 @@ object FirProjectionsOnNonClassTypeArgumentChecker : FirQualifiedAccessChecker()
|
|||||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
for (it in expression.typeArguments) {
|
for (it in expression.typeArguments) {
|
||||||
when (it) {
|
when (it) {
|
||||||
is FirStarProjection -> reporter.report(it.source)
|
is FirStarProjection -> reporter.reportOn(it.source, FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, context)
|
||||||
is FirTypeProjectionWithVariance -> {
|
is FirTypeProjectionWithVariance -> {
|
||||||
if (it.variance != Variance.INVARIANT) {
|
if (it.variance != Variance.INVARIANT) {
|
||||||
reporter.report(it.source)
|
reporter.reportOn(it.source, FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let {
|
|
||||||
report(FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+7
-8
@@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
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.findClosestClassOrObject
|
import org.jetbrains.kotlin.fir.analysis.checkers.findClosestClassOrObject
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.followAllAlias
|
import org.jetbrains.kotlin.fir.analysis.checkers.followAllAlias
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf
|
import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||||
@@ -61,13 +61,12 @@ object FirQualifiedSupertypeExtendedByOtherSupertypeChecker : FirQualifiedAccess
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (count >= 2 && candidate != null) {
|
if (count >= 2 && candidate != null) {
|
||||||
reporter.report(superReference.superTypeRef.source, candidate)
|
reporter.reportOn(
|
||||||
}
|
superReference.superTypeRef.source,
|
||||||
}
|
FirErrors.QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE,
|
||||||
|
candidate,
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?, candidate: FirClass<*>) {
|
context
|
||||||
source?.let {
|
)
|
||||||
report(FirErrors.QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE.on(it, candidate))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -6,10 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
@@ -33,11 +33,7 @@ object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() {
|
|||||||
?: return
|
?: return
|
||||||
|
|
||||||
if (typeFir.status.modality == Modality.SEALED) {
|
if (typeFir.status.modality == Modality.SEALED) {
|
||||||
reporter.report(expression.calleeReference.source)
|
reporter.reportOn(expression.calleeReference.source, FirErrors.SEALED_CLASS_CONSTRUCTOR_CALL, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let { report(FirErrors.SEALED_CLASS_CONSTRUCTOR_CALL.on(it)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+2
-8
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||||
@@ -23,13 +23,7 @@ object FirSuperNotAvailableChecker : FirQualifiedAccessChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isInsideClass) {
|
if (!isInsideClass) {
|
||||||
reporter.report(expression.source)
|
reporter.reportOn(expression.source, FirErrors.SUPER_NOT_AVAILABLE, context)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let {
|
|
||||||
report(FirErrors.SUPER_NOT_AVAILABLE.on(it))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-8
@@ -6,11 +6,11 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
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.getContainingClass
|
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
@@ -34,7 +34,7 @@ object FirSuperclassNotAccessibleFromInterfaceChecker : FirQualifiedAccessChecke
|
|||||||
?: return
|
?: return
|
||||||
|
|
||||||
if (origin.source != null && origin.classKind == ClassKind.CLASS) {
|
if (origin.source != null && origin.classKind == ClassKind.CLASS) {
|
||||||
reporter.report(expression.explicitReceiver?.source)
|
reporter.reportOn(expression.explicitReceiver?.source, FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,10 +46,4 @@ object FirSuperclassNotAccessibleFromInterfaceChecker : FirQualifiedAccessChecke
|
|||||||
private fun getClassLikeDeclaration(functionCall: FirQualifiedAccessExpression, context: CheckerContext): FirClassLikeDeclaration<*>? {
|
private fun getClassLikeDeclaration(functionCall: FirQualifiedAccessExpression, context: CheckerContext): FirClassLikeDeclaration<*>? {
|
||||||
return functionCall.calleeReference.safeAs<FirResolvedNamedReference>()?.resolvedSymbol?.fir?.getContainingClass(context)
|
return functionCall.calleeReference.safeAs<FirResolvedNamedReference>()?.resolvedSymbol?.fir?.getContainingClass(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let {
|
|
||||||
report(FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE.on(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-9
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
|
||||||
|
|
||||||
@@ -20,15 +20,9 @@ object FirTypeArgumentsNotAllowedExpressionChecker : FirQualifiedAccessChecker()
|
|||||||
|
|
||||||
if (explicitReceiver is FirResolvedQualifier && explicitReceiver.symbol == null) {
|
if (explicitReceiver is FirResolvedQualifier && explicitReceiver.symbol == null) {
|
||||||
if (explicitReceiver.typeArguments.isNotEmpty()) {
|
if (explicitReceiver.typeArguments.isNotEmpty()) {
|
||||||
reporter.report(explicitReceiver.source)
|
reporter.reportOn(explicitReceiver.source, FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
|
||||||
source?.let {
|
|
||||||
report(FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.on(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+14
-9
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
|
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
|
||||||
@@ -74,7 +75,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
|
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
|
||||||
reporter.report(actual.source, proto, actual.type)
|
reporter.reportOn(actual.source, proto, actual.type, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +99,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
// typealias A<G> = B<List<G>>
|
// typealias A<G> = B<List<G>>
|
||||||
// val a = A<Int>()
|
// val a = A<Int>()
|
||||||
when (calleeFir) {
|
when (calleeFir) {
|
||||||
is FirConstructor -> analyzeConstructorCall(expression, substitutor, typeCheckerContext, reporter)
|
is FirConstructor -> analyzeConstructorCall(expression, substitutor, typeCheckerContext, reporter, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +107,8 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
functionCall: FirQualifiedAccessExpression,
|
functionCall: FirQualifiedAccessExpression,
|
||||||
callSiteSubstitutor: ConeSubstitutor,
|
callSiteSubstitutor: ConeSubstitutor,
|
||||||
typeCheckerContext: AbstractTypeCheckerContext,
|
typeCheckerContext: AbstractTypeCheckerContext,
|
||||||
reporter: DiagnosticReporter
|
reporter: DiagnosticReporter,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
// holds Collection<Number> bound.
|
// holds Collection<Number> bound.
|
||||||
// note that if B used another type parameter here,
|
// note that if B used another type parameter here,
|
||||||
@@ -168,7 +170,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
val satisfiesBounds = AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
|
val satisfiesBounds = AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
|
||||||
|
|
||||||
if (!satisfiesBounds) {
|
if (!satisfiesBounds) {
|
||||||
reporter.report(functionCall.source, proto, actual)
|
reporter.reportOn(functionCall.source, proto, actual, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,7 +220,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
parameterPairs.forEach { (proto, actual) ->
|
parameterPairs.forEach { (proto, actual) ->
|
||||||
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
|
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
|
||||||
// should report on the parameter instead!
|
// should report on the parameter instead!
|
||||||
reporter.report(reportTarget, proto, actual)
|
reporter.reportOn(reportTarget, proto, actual, context)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,9 +252,12 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
return AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
|
return AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DiagnosticReporter.report(source: FirSourceElement?, proto: FirTypeParameterSymbol, actual: ConeKotlinType) {
|
private fun DiagnosticReporter.reportOn(
|
||||||
source?.let {
|
source: FirSourceElement?,
|
||||||
report(FirErrors.UPPER_BOUND_VIOLATED.on(it, proto, actual))
|
proto: FirTypeParameterSymbol,
|
||||||
}
|
actual: ConeKotlinType,
|
||||||
|
context: CheckerContext
|
||||||
|
) {
|
||||||
|
reportOn(source, FirErrors.UPPER_BOUND_VIOLATED, proto, actual, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
|
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirOperation
|
import org.jetbrains.kotlin.fir.expressions.FirOperation
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
@@ -27,6 +28,6 @@ object ArrayEqualityCanBeReplacedWithEquals : FirBasicExpressionChecker() {
|
|||||||
if (left.typeRef.coneType.classId != StandardClassIds.Array) return
|
if (left.typeRef.coneType.classId != StandardClassIds.Array) return
|
||||||
if (right.typeRef.coneType.classId != StandardClassIds.Array) return
|
if (right.typeRef.coneType.classId != StandardClassIds.Array) return
|
||||||
|
|
||||||
reporter.report(expression.source, ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS)
|
reporter.reportOn(expression.source, ARRAY_EQUALITY_OPERATOR_CAN_BE_REPLACED_WITH_EQUALS, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirVariableAssignme
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||||
@@ -58,7 +59,7 @@ object CanBeReplacedWithOperatorAssignmentChecker : FirVariableAssignmentChecker
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (needToReport) {
|
if (needToReport) {
|
||||||
reporter.report(expression.source, FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT)
|
reporter.reportOn(expression.source, FirErrors.CAN_BE_REPLACED_WITH_OPERATOR_ASSIGNMENT, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-6
@@ -7,11 +7,17 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.FirFakeSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.cfa.*
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.PathAwarePropertyInitializationInfo
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.TraverseDirection
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.cfa.traverse
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
@@ -21,7 +27,8 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
|
|||||||
graph: ControlFlowGraph,
|
graph: ControlFlowGraph,
|
||||||
reporter: DiagnosticReporter,
|
reporter: DiagnosticReporter,
|
||||||
data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
||||||
properties: Set<FirPropertySymbol>
|
properties: Set<FirPropertySymbol>,
|
||||||
|
context: CheckerContext
|
||||||
) {
|
) {
|
||||||
val unprocessedProperties = mutableSetOf<FirPropertySymbol>()
|
val unprocessedProperties = mutableSetOf<FirPropertySymbol>()
|
||||||
val propertiesCharacteristics = mutableMapOf<FirPropertySymbol, EventOccurrencesRange>()
|
val propertiesCharacteristics = mutableMapOf<FirPropertySymbol, EventOccurrencesRange>()
|
||||||
@@ -51,14 +58,14 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
|
|||||||
if (lastDestructuringSource != null) {
|
if (lastDestructuringSource != null) {
|
||||||
// if this is the last variable in destructuring declaration and destructuringCanBeVal == true and it can be val
|
// if this is the last variable in destructuring declaration and destructuringCanBeVal == true and it can be val
|
||||||
if (lastDestructuredVariables == 1 && destructuringCanBeVal && canBeVal(symbol, value)) {
|
if (lastDestructuredVariables == 1 && destructuringCanBeVal && canBeVal(symbol, value)) {
|
||||||
reporter.report(lastDestructuringSource, FirErrors.CAN_BE_VAL)
|
reporter.reportOn(lastDestructuringSource, FirErrors.CAN_BE_VAL, context)
|
||||||
lastDestructuringSource = null
|
lastDestructuringSource = null
|
||||||
} else if (!canBeVal(symbol, value)) {
|
} else if (!canBeVal(symbol, value)) {
|
||||||
destructuringCanBeVal = false
|
destructuringCanBeVal = false
|
||||||
}
|
}
|
||||||
lastDestructuredVariables--
|
lastDestructuredVariables--
|
||||||
} else if (canBeVal(symbol, value) && symbol.fir.delegate == null) {
|
} else if (canBeVal(symbol, value) && symbol.fir.delegate == null) {
|
||||||
reporter.report(source, FirErrors.CAN_BE_VAL)
|
reporter.reportOn(source, FirErrors.CAN_BE_VAL, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,4 +117,4 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
|
|||||||
EventOccurrencesRange.AT_MOST_ONCE,
|
EventOccurrencesRange.AT_MOST_ONCE,
|
||||||
EventOccurrencesRange.ZERO
|
EventOccurrencesRange.ZERO
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
@@ -36,8 +37,7 @@ object EmptyRangeChecker : FirBasicExpressionChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (needReport) {
|
if (needReport) {
|
||||||
reporter.report(expression.source, FirErrors.EMPTY_RANGE)
|
reporter.reportOn(expression.source, FirErrors.EMPTY_RANGE, context)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
@@ -31,7 +32,7 @@ object RedundantCallOfConversionMethod : FirQualifiedAccessChecker() {
|
|||||||
val qualifiedType = targetClassMap[functionName] ?: return
|
val qualifiedType = targetClassMap[functionName] ?: return
|
||||||
|
|
||||||
if (expression.explicitReceiver?.isRedundant(qualifiedType) == true) {
|
if (expression.explicitReceiver?.isRedundant(qualifiedType) == true) {
|
||||||
reporter.report(expression.source, FirErrors.REDUNDANT_CALL_OF_CONVERSION_METHOD)
|
reporter.reportOn(expression.source, FirErrors.REDUNDANT_CALL_OF_CONVERSION_METHOD, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,4 +65,4 @@ object RedundantCallOfConversionMethod : FirQualifiedAccessChecker() {
|
|||||||
"toUShort" to StandardClassIds.UShort,
|
"toUShort" to StandardClassIds.UShort,
|
||||||
"toUByte" to StandardClassIds.UByte
|
"toUByte" to StandardClassIds.UByte
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||||
@@ -84,7 +85,7 @@ object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
|
|||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
|
|
||||||
reporter.report(declaration.returnTypeRef.source, FirErrors.REDUNDANT_EXPLICIT_TYPE)
|
reporter.reportOn(declaration.returnTypeRef.source, FirErrors.REDUNDANT_EXPLICIT_TYPE, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConeKotlinType.isSame(other: ClassId?): Boolean {
|
private fun ConeKotlinType.isSame(other: ClassId?): Boolean {
|
||||||
@@ -95,4 +96,4 @@ object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
|
|||||||
|
|
||||||
private fun ConeKotlinType.hasSameNameWithoutModifiers(name: Name): Boolean =
|
private fun ConeKotlinType.hasSameNameWithoutModifiers(name: Name): Boolean =
|
||||||
this is ConeClassLikeType && lookupTag.name == name && typeArguments.isEmpty() && !isMarkedNullable
|
this is ConeClassLikeType && lookupTag.name == name && typeArguments.isEmpty() && !isMarkedNullable
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.implicitModality
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODALITY_MODIFIER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.modality
|
import org.jetbrains.kotlin.fir.declarations.modality
|
||||||
@@ -33,6 +34,6 @@ object RedundantModalityModifierChecker : FirMemberDeclarationChecker() {
|
|||||||
val implicitModality = declaration.implicitModality(context)
|
val implicitModality = declaration.implicitModality(context)
|
||||||
if (modality != implicitModality) return
|
if (modality != implicitModality) return
|
||||||
|
|
||||||
reporter.report(source, REDUNDANT_MODALITY_MODIFIER)
|
reporter.reportOn(source, REDUNDANT_MODALITY_MODIFIER, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
||||||
@@ -25,8 +26,8 @@ object RedundantReturnUnitType : FirBasicDeclarationChecker() {
|
|||||||
if (returnType.annotations.isNotEmpty()) return
|
if (returnType.annotations.isNotEmpty()) return
|
||||||
|
|
||||||
if (returnType.isUnit) {
|
if (returnType.isUnit) {
|
||||||
reporter.report(declaration.returnTypeRef.source, FirErrors.REDUNDANT_RETURN_UNIT_TYPE)
|
reporter.reportOn(declaration.returnTypeRef.source, FirErrors.REDUNDANT_RETURN_UNIT_TYPE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SETTER_PARAMETER_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SETTER_PARAMETER_TYPE
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||||
@@ -23,7 +24,7 @@ object RedundantSetterParameterTypeChecker : FirMemberDeclarationChecker() {
|
|||||||
val setterParameterTypeSource = valueParameter.returnTypeRef.source ?: return
|
val setterParameterTypeSource = valueParameter.returnTypeRef.source ?: return
|
||||||
|
|
||||||
if (setterParameterTypeSource != propertyTypeSource) {
|
if (setterParameterTypeSource != propertyTypeSource) {
|
||||||
reporter.report(setterParameterTypeSource, REDUNDANT_SETTER_PARAMETER_TYPE)
|
reporter.reportOn(setterParameterTypeSource, REDUNDANT_SETTER_PARAMETER_TYPE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirBasicExpressionC
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
import org.jetbrains.kotlin.fir.analysis.checkers.getChildren
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
@@ -32,7 +33,7 @@ object RedundantSingleExpressionStringTemplateChecker : FirBasicExpressionChecke
|
|||||||
expression.explicitReceiver?.typeRef?.coneType?.classId == StandardClassIds.String
|
expression.explicitReceiver?.typeRef?.coneType?.classId == StandardClassIds.String
|
||||||
&& expression.stringParentChildrenCount() == 1 // there is no more children in original string template
|
&& expression.stringParentChildrenCount() == 1 // there is no more children in original string template
|
||||||
) {
|
) {
|
||||||
reporter.report(expression.source, REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE)
|
reporter.reportOn(expression.source, REDUNDANT_SINGLE_EXPRESSION_STRING_TEMPLATE, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-7
@@ -7,17 +7,14 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
|
import org.jetbrains.kotlin.fir.FirFakeSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.*
|
import org.jetbrains.kotlin.fir.analysis.checkers.*
|
||||||
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.declaration.FirBasicDeclarationChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
|
|
||||||
@@ -53,7 +50,7 @@ object RedundantVisibilityModifierChecker : FirBasicDeclarationChecker() {
|
|||||||
&& declaration.setter?.visibility == Visibilities.Public
|
&& declaration.setter?.visibility == Visibilities.Public
|
||||||
) return
|
) return
|
||||||
|
|
||||||
reporter.report(source, FirErrors.REDUNDANT_VISIBILITY_MODIFIER)
|
reporter.reportOn(source, FirErrors.REDUNDANT_VISIBILITY_MODIFIER, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirDeclaration.implicitVisibility(context: CheckerContext): Visibility {
|
private fun FirDeclaration.implicitVisibility(context: CheckerContext): Visibility {
|
||||||
|
|||||||
-18
@@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2020 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.extended
|
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
|
||||||
|
|
||||||
inline fun <reified T : FirSourceElement, P : PsiElement> DiagnosticReporter.report(
|
|
||||||
source: T?,
|
|
||||||
factory: FirDiagnosticFactory0<T, P>
|
|
||||||
) {
|
|
||||||
source?.let { report(factory.on(it)) }
|
|
||||||
}
|
|
||||||
+11
-9
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.isIterator
|
import org.jetbrains.kotlin.fir.analysis.checkers.isIterator
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
|
||||||
@@ -30,21 +31,22 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
|||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
|
||||||
object UnusedChecker : FirControlFlowChecker() {
|
object UnusedChecker : FirControlFlowChecker() {
|
||||||
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, checkerContext: CheckerContext) {
|
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||||
if ((graph.declaration as? FirSymbolOwner<*>)?.getContainingClass(checkerContext)?.takeIf {
|
if ((graph.declaration as? FirSymbolOwner<*>)?.getContainingClass(context)?.takeIf {
|
||||||
!it.symbol.classId.isLocal
|
!it.symbol.classId.isLocal
|
||||||
} != null
|
} != null
|
||||||
) return
|
) return
|
||||||
val properties = LocalPropertyCollector.collect(graph)
|
val properties = LocalPropertyCollector.collect(graph)
|
||||||
if (properties.isEmpty()) return
|
if (properties.isEmpty()) return
|
||||||
|
|
||||||
val data = ValueWritesWithoutReading(checkerContext.session, properties).getData(graph)
|
val data = ValueWritesWithoutReading(context.session, properties).getData(graph)
|
||||||
graph.traverse(TraverseDirection.Backward, CfaVisitor(data, reporter))
|
graph.traverse(TraverseDirection.Backward, CfaVisitor(data, reporter, context))
|
||||||
}
|
}
|
||||||
|
|
||||||
class CfaVisitor(
|
class CfaVisitor(
|
||||||
val data: Map<CFGNode<*>, PathAwareVariableStatusInfo>,
|
val data: Map<CFGNode<*>, PathAwareVariableStatusInfo>,
|
||||||
val reporter: DiagnosticReporter
|
val reporter: DiagnosticReporter,
|
||||||
|
val context: CheckerContext
|
||||||
) : ControlFlowGraphVisitorVoid() {
|
) : ControlFlowGraphVisitorVoid() {
|
||||||
override fun visitNode(node: CFGNode<*>) {}
|
override fun visitNode(node: CFGNode<*>) {}
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ object UnusedChecker : FirControlFlowChecker() {
|
|||||||
if (data == VariableStatus.ONLY_WRITTEN_NEVER_READ) {
|
if (data == VariableStatus.ONLY_WRITTEN_NEVER_READ) {
|
||||||
// todo: report case like "a += 1" where `a` `doesn't writes` different way (special for Idea)
|
// todo: report case like "a += 1" where `a` `doesn't writes` different way (special for Idea)
|
||||||
val source = node.fir.lValue.source
|
val source = node.fir.lValue.source
|
||||||
reporter.report(source, FirErrors.ASSIGNED_VALUE_IS_NEVER_READ)
|
reporter.reportOn(source, FirErrors.ASSIGNED_VALUE_IS_NEVER_READ, context)
|
||||||
// To avoid duplicate reports, stop investigating remaining paths once reported.
|
// To avoid duplicate reports, stop investigating remaining paths once reported.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -74,17 +76,17 @@ object UnusedChecker : FirControlFlowChecker() {
|
|||||||
when {
|
when {
|
||||||
data == VariableStatus.UNUSED -> {
|
data == VariableStatus.UNUSED -> {
|
||||||
if ((node.fir.initializer as? FirFunctionCall)?.isIterator != true) {
|
if ((node.fir.initializer as? FirFunctionCall)?.isIterator != true) {
|
||||||
reporter.report(variableSource, FirErrors.UNUSED_VARIABLE)
|
reporter.reportOn(variableSource, FirErrors.UNUSED_VARIABLE, context)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data.isRedundantInit -> {
|
data.isRedundantInit -> {
|
||||||
val source = variableSymbol.fir.initializer?.source
|
val source = variableSymbol.fir.initializer?.source
|
||||||
reporter.report(source, FirErrors.VARIABLE_INITIALIZER_IS_REDUNDANT)
|
reporter.reportOn(source, FirErrors.VARIABLE_INITIALIZER_IS_REDUNDANT, context)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
data == VariableStatus.ONLY_WRITTEN_NEVER_READ -> {
|
data == VariableStatus.ONLY_WRITTEN_NEVER_READ -> {
|
||||||
reporter.report(variableSource, FirErrors.VARIABLE_NEVER_READ)
|
reporter.reportOn(variableSource, FirErrors.VARIABLE_NEVER_READ, context)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
+3
-2
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
@@ -28,7 +29,7 @@ object UselessCallOnNotNullChecker : FirQualifiedAccessChecker() {
|
|||||||
if ("$calleePackageName.$calleeName" !in triggerOn) return
|
if ("$calleePackageName.$calleeName" !in triggerOn) return
|
||||||
|
|
||||||
if (calleeOn.getNullability() == ConeNullability.NOT_NULL) {
|
if (calleeOn.getNullability() == ConeNullability.NOT_NULL) {
|
||||||
reporter.report(expression.source, FirErrors.USELESS_CALL_ON_NOT_NULL)
|
reporter.reportOn(expression.source, FirErrors.USELESS_CALL_ON_NOT_NULL, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,4 +54,4 @@ object UselessCallOnNotNullChecker : FirQualifiedAccessChecker() {
|
|||||||
"kotlin.orEmpty"
|
"kotlin.orEmpty"
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-9
@@ -10,7 +10,10 @@ import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
|||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.*
|
import org.jetbrains.kotlin.fir.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind.*
|
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind.*
|
||||||
@@ -27,37 +30,42 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|||||||
class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||||
override fun visitErrorLoop(errorLoop: FirErrorLoop, data: CheckerContext) {
|
override fun visitErrorLoop(errorLoop: FirErrorLoop, data: CheckerContext) {
|
||||||
val source = errorLoop.source ?: return
|
val source = errorLoop.source ?: return
|
||||||
reportFirDiagnostic(errorLoop.diagnostic, source, reporter)
|
reportFirDiagnostic(errorLoop.diagnostic, source, reporter, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: CheckerContext) {
|
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: CheckerContext) {
|
||||||
val source = errorTypeRef.source ?: return
|
val source = errorTypeRef.source ?: return
|
||||||
reportFirDiagnostic(errorTypeRef.diagnostic, source, reporter)
|
reportFirDiagnostic(errorTypeRef.diagnostic, source, reporter, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference, data: CheckerContext) {
|
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference, data: CheckerContext) {
|
||||||
val source = errorNamedReference.source ?: return
|
val source = errorNamedReference.source ?: return
|
||||||
// Don't report duplicated unresolved reference on annotation entry (already reported on its type)
|
// Don't report duplicated unresolved reference on annotation entry (already reported on its type)
|
||||||
if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && errorNamedReference.diagnostic is ConeUnresolvedNameError) return
|
if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && errorNamedReference.diagnostic is ConeUnresolvedNameError) return
|
||||||
reportFirDiagnostic(errorNamedReference.diagnostic, source, reporter)
|
reportFirDiagnostic(errorNamedReference.diagnostic, source, reporter, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitErrorExpression(errorExpression: FirErrorExpression, data: CheckerContext) {
|
override fun visitErrorExpression(errorExpression: FirErrorExpression, data: CheckerContext) {
|
||||||
val source = errorExpression.source ?: return
|
val source = errorExpression.source ?: return
|
||||||
reportFirDiagnostic(errorExpression.diagnostic, source, reporter)
|
reportFirDiagnostic(errorExpression.diagnostic, source, reporter, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitErrorFunction(errorFunction: FirErrorFunction, data: CheckerContext) {
|
override fun visitErrorFunction(errorFunction: FirErrorFunction, data: CheckerContext) {
|
||||||
val source = errorFunction.source ?: return
|
val source = errorFunction.source ?: return
|
||||||
reportFirDiagnostic(errorFunction.diagnostic, source, reporter)
|
reportFirDiagnostic(errorFunction.diagnostic, source, reporter, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitErrorResolvedQualifier(errorResolvedQualifier: FirErrorResolvedQualifier, data: CheckerContext) {
|
override fun visitErrorResolvedQualifier(errorResolvedQualifier: FirErrorResolvedQualifier, data: CheckerContext) {
|
||||||
val source = errorResolvedQualifier.source ?: return
|
val source = errorResolvedQualifier.source ?: return
|
||||||
reportFirDiagnostic(errorResolvedQualifier.diagnostic, source, reporter)
|
reportFirDiagnostic(errorResolvedQualifier.diagnostic, source, reporter, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun reportFirDiagnostic(diagnostic: ConeDiagnostic, source: FirSourceElement, reporter: DiagnosticReporter) {
|
private fun reportFirDiagnostic(
|
||||||
|
diagnostic: ConeDiagnostic,
|
||||||
|
source: FirSourceElement,
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
context: CheckerContext
|
||||||
|
) {
|
||||||
// Will be handled by [FirDestructuringDeclarationChecker]
|
// Will be handled by [FirDestructuringDeclarationChecker]
|
||||||
if (source.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY) {
|
if (source.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION_ENTRY) {
|
||||||
// TODO: if all diagnostics are supported, we don't need the following check, and will bail out based on element type.
|
// TODO: if all diagnostics are supported, we don't need the following check, and will bail out based on element type.
|
||||||
@@ -97,7 +105,7 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
|
|||||||
is ConeIntermediateDiagnostic -> null
|
is ConeIntermediateDiagnostic -> null
|
||||||
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${diagnostic.javaClass}")
|
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${diagnostic.javaClass}")
|
||||||
}
|
}
|
||||||
reporter.report(coneDiagnostic)
|
reporter.report(coneDiagnostic, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConeKotlinType.isEffectivelyNotNull(): Boolean {
|
private fun ConeKotlinType.isEffectivelyNotNull(): Boolean {
|
||||||
|
|||||||
+45
-3
@@ -5,15 +5,57 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
|
||||||
abstract class DiagnosticReporter {
|
abstract class DiagnosticReporter {
|
||||||
abstract fun report(diagnostic: FirDiagnostic<*>?)
|
abstract fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : FirSourceElement, P : PsiElement> DiagnosticReporter.reportOn(
|
||||||
|
source: T?,
|
||||||
|
factory: FirDiagnosticFactory0<T, P>,
|
||||||
|
context: CheckerContext
|
||||||
|
) {
|
||||||
|
source?.let { report(factory.on(it), context) }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : FirSourceElement, P : PsiElement, A : Any> DiagnosticReporter.reportOn(
|
||||||
|
source: T?,
|
||||||
|
factory: FirDiagnosticFactory1<T, P, A>,
|
||||||
|
a: A,
|
||||||
|
context: CheckerContext
|
||||||
|
) {
|
||||||
|
source?.let { report(factory.on(it, a), context) }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : FirSourceElement, P : PsiElement, A : Any, B : Any> DiagnosticReporter.reportOn(
|
||||||
|
source: T?,
|
||||||
|
factory: FirDiagnosticFactory2<T, P, A, B>,
|
||||||
|
a: A,
|
||||||
|
b: B,
|
||||||
|
context: CheckerContext
|
||||||
|
) {
|
||||||
|
source?.let { report(factory.on(it, a, b), context) }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : FirSourceElement, P : PsiElement, A : Any, B : Any, C : Any> DiagnosticReporter.reportOn(
|
||||||
|
source: T?,
|
||||||
|
factory: FirDiagnosticFactory3<T, P, A, B, C>,
|
||||||
|
a: A,
|
||||||
|
b: B,
|
||||||
|
c: C,
|
||||||
|
context: CheckerContext
|
||||||
|
) {
|
||||||
|
source?.let { report(factory.on(it, a, b, c), context) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimpleDiagnosticReporter : DiagnosticReporter() {
|
class SimpleDiagnosticReporter : DiagnosticReporter() {
|
||||||
val diagnostics: MutableList<FirDiagnostic<*>> = mutableListOf()
|
val diagnostics: MutableList<FirDiagnostic<*>> = mutableListOf()
|
||||||
|
|
||||||
override fun report(diagnostic: FirDiagnostic<*>?) {
|
override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) {
|
||||||
if (diagnostic == null) return
|
if (diagnostic == null) return
|
||||||
diagnostics += diagnostic
|
diagnostics += diagnostic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -288,7 +288,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Modifiers
|
// Modifiers
|
||||||
map.put(INAPPLICABLE_INFIX_MODIFIER, "''infix'' modifier is inapplicable on this function: {0}", TO_STRING)
|
map.put(INAPPLICABLE_INFIX_MODIFIER, "''infix'' modifier is inapplicable on this function")
|
||||||
map.put(REPEATED_MODIFIER, "Repeated ''{0}''", TO_STRING)
|
map.put(REPEATED_MODIFIER, "Repeated ''{0}''", TO_STRING)
|
||||||
map.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING)
|
map.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING)
|
||||||
map.put(DEPRECATED_MODIFIER_PAIR, "Modifier ''{0}'' is deprecated in presence of ''{1}''", TO_STRING, TO_STRING)
|
map.put(DEPRECATED_MODIFIER_PAIR, "Modifier ''{0}'' is deprecated in presence of ''{1}''", TO_STRING, TO_STRING)
|
||||||
|
|||||||
+4
-2
@@ -15,7 +15,9 @@ import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -104,7 +106,7 @@ object FirErrors {
|
|||||||
val EXPOSED_TYPE_PARAMETER_BOUND by error3<FirSourceElement, KtTypeReference, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
|
val EXPOSED_TYPE_PARAMETER_BOUND by error3<FirSourceElement, KtTypeReference, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
|
||||||
|
|
||||||
// Modifiers
|
// Modifiers
|
||||||
val INAPPLICABLE_INFIX_MODIFIER by existing1<FirSourceElement, PsiElement, String>()
|
val INAPPLICABLE_INFIX_MODIFIER by error0<FirSourceElement, PsiElement>()
|
||||||
val REPEATED_MODIFIER by error1<FirSourceElement, PsiElement, KtModifierKeywordToken>()
|
val REPEATED_MODIFIER by error1<FirSourceElement, PsiElement, KtModifierKeywordToken>()
|
||||||
val REDUNDANT_MODIFIER by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
|
val REDUNDANT_MODIFIER by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
|
||||||
val DEPRECATED_MODIFIER_PAIR by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
|
val DEPRECATED_MODIFIER_PAIR by error2<FirSourceElement, PsiElement, KtModifierKeywordToken, KtModifierKeywordToken>()
|
||||||
|
|||||||
+2
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.diagnostics
|
|||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||||
import org.jetbrains.kotlin.fir.analysis.collectors.registerAllComponents
|
import org.jetbrains.kotlin.fir.analysis.collectors.registerAllComponents
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
@@ -39,7 +40,7 @@ internal abstract class AbstractFirIdeDiagnosticsCollector(
|
|||||||
|
|
||||||
|
|
||||||
private inner class Reporter : DiagnosticReporter() {
|
private inner class Reporter : DiagnosticReporter() {
|
||||||
override fun report(diagnostic: FirDiagnostic<*>?) {
|
override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) {
|
||||||
if (diagnostic !is FirPsiDiagnostic<*>) return
|
if (diagnostic !is FirPsiDiagnostic<*>) return
|
||||||
if (diagnostic.element.psi !is KtElement) return
|
if (diagnostic.element.psi !is KtElement) return
|
||||||
onDiagnostic(diagnostic)
|
onDiagnostic(diagnostic)
|
||||||
|
|||||||
+2
-3
@@ -7,8 +7,7 @@ package org.jetbrains.kotlin.fir.plugin.checkers
|
|||||||
|
|
||||||
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.declaration.FirMemberDeclarationChecker
|
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMemberDeclarationChecker
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
|
||||||
@@ -16,7 +15,7 @@ object DummyNameChecker : FirMemberDeclarationChecker() {
|
|||||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (declaration !is FirSimpleFunction) return
|
if (declaration !is FirSimpleFunction) return
|
||||||
if (declaration.name.asString() == "dummy") {
|
if (declaration.name.asString() == "dummy") {
|
||||||
declaration.source?.let { reporter.report(FirErrors.SYNTAX.on(it)) }
|
reporter.reportOn(declaration.source, FirErrors.SYNTAX, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user