[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
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
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.ControlFlowGraph
|
||||
@@ -15,6 +16,7 @@ abstract class AbstractFirPropertyInitializationChecker {
|
||||
graph: ControlFlowGraph,
|
||||
reporter: DiagnosticReporter,
|
||||
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() {
|
||||
|
||||
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
|
||||
if (function !is FirContractDescriptionOwner) return
|
||||
if (function.contractDescription.coneEffects?.any { it is ConeCallsEffectDeclaration } != true) return
|
||||
@@ -73,10 +73,10 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
||||
|
||||
for ((symbol, leakedPlaces) in leakedSymbols) {
|
||||
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 {
|
||||
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 pathAwareInfo = invocationData.getValue(node)
|
||||
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.
|
||||
break
|
||||
}
|
||||
@@ -105,12 +105,13 @@ object FirCallsEffectAnalyzer : FirControlFlowChecker() {
|
||||
symbol: AbstractFirBasedSymbol<*>,
|
||||
requiredRange: EventOccurrencesRange,
|
||||
function: FirContractDescriptionOwner,
|
||||
reporter: DiagnosticReporter
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
): Boolean {
|
||||
val foundRange = info[symbol] ?: EventOccurrencesRange.ZERO
|
||||
if (foundRange !in requiredRange) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
+11
-6
@@ -29,27 +29,32 @@ class FirControlFlowAnalyzer(session: FirSession) {
|
||||
|
||||
cfaCheckers.forEach { it.analyze(graph, reporter, context) }
|
||||
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) {
|
||||
if (graph.owner != null) return
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
if (properties.isEmpty()) return
|
||||
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.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.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.isLateInit
|
||||
@@ -23,7 +24,8 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
|
||||
graph: ControlFlowGraph,
|
||||
reporter: DiagnosticReporter,
|
||||
data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
||||
properties: Set<FirPropertySymbol>
|
||||
properties: Set<FirPropertySymbol>,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val localData = data.filter {
|
||||
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 reporterVisitor = UninitializedPropertyReporter(localData, localProperties, reporter)
|
||||
val reporterVisitor = UninitializedPropertyReporter(localData, localProperties, reporter, context)
|
||||
graph.traverse(TraverseDirection.Forward, reporterVisitor)
|
||||
}
|
||||
|
||||
private class UninitializedPropertyReporter(
|
||||
val data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
||||
val localProperties: Set<FirPropertySymbol>,
|
||||
val reporter: DiagnosticReporter
|
||||
val reporter: DiagnosticReporter,
|
||||
val context: CheckerContext
|
||||
) : ControlFlowGraphVisitorVoid() {
|
||||
override fun visitNode(node: CFGNode<*>) {}
|
||||
|
||||
@@ -61,7 +64,7 @@ object FirPropertyInitializationAnalyzer : AbstractFirPropertyInitializationChec
|
||||
val kind = info[symbol] ?: EventOccurrencesRange.ZERO
|
||||
if (!kind.isDefinitelyVisited()) {
|
||||
node.fir.source?.let {
|
||||
reporter.report(FirErrors.UNINITIALIZED_VARIABLE.on(it, symbol))
|
||||
reporter.report(FirErrors.UNINITIALIZED_VARIABLE.on(it, symbol), context)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
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 graphRef = function.controlFlowGraphReference as FirControlFlowGraphReferenceImpl
|
||||
val dataFlowInfo = graphRef.dataFlowInfo
|
||||
@@ -62,7 +62,7 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
|
||||
|
||||
if (wrongCondition) {
|
||||
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<*> {
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
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.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.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.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
|
||||
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.types.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -36,8 +39,8 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
||||
for ((arg, _) in declarationOfAnnotation.argumentMapping ?: continue) {
|
||||
val expression = (arg as? FirNamedArgumentExpression)?.expression ?: arg
|
||||
|
||||
checkAnnotationArgumentWithSubElements(expression, context.session, reporter)
|
||||
?.let { reporter.report(expression.source, it) }
|
||||
checkAnnotationArgumentWithSubElements(expression, context.session, reporter, context)
|
||||
?.let { reporter.reportOn(expression.source, it, context) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +48,8 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
||||
private fun checkAnnotationArgumentWithSubElements(
|
||||
expression: FirExpression,
|
||||
session: FirSession,
|
||||
reporter: DiagnosticReporter
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
): FirDiagnosticFactory0<FirSourceElement, KtExpression>? {
|
||||
when (expression) {
|
||||
is FirArrayOfCall -> {
|
||||
@@ -54,13 +58,13 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
||||
for (arg in expression.argumentList.arguments) {
|
||||
val sourceForReport = arg.source
|
||||
|
||||
when (val err = checkAnnotationArgumentWithSubElements(arg, session, reporter)) {
|
||||
when (val err = checkAnnotationArgumentWithSubElements(arg, session, reporter, context)) {
|
||||
null -> {
|
||||
//DO NOTHING
|
||||
}
|
||||
else -> {
|
||||
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 -> {
|
||||
for (arg in expression.arguments)
|
||||
checkAnnotationArgumentWithSubElements(arg, session, reporter)
|
||||
?.let { reporter.report(arg.source, it) }
|
||||
checkAnnotationArgumentWithSubElements(arg, session, reporter, context)
|
||||
?.let { reporter.reportOn(arg.source, it, context) }
|
||||
}
|
||||
else ->
|
||||
return checkAnnotationArgument(expression, session)
|
||||
@@ -224,14 +228,7 @@ object FirAnnotationArgumentChecker : FirBasicDeclarationChecker() {
|
||||
?.toSymbol(session)
|
||||
?.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(
|
||||
"toInt", "toLong", "toShort", "toByte", "toFloat", "toDouble", "toChar", "toBoolean"
|
||||
).mapTo(hashSetOf()) { Name.identifier(it) }
|
||||
}
|
||||
}
|
||||
|
||||
+12
-21
@@ -5,28 +5,26 @@
|
||||
|
||||
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.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.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.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds.primitiveArrayTypeByElementType
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds.primitiveTypes
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds.unsignedTypes
|
||||
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
|
||||
|
||||
object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
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) {
|
||||
when {
|
||||
@@ -34,9 +32,9 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
||||
for (parameter in it.valueParameters) {
|
||||
val source = parameter.source ?: continue
|
||||
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()) {
|
||||
reporter.report(source, FirErrors.VAR_ANNOTATION_PARAMETER)
|
||||
reporter.reportOn(source, FirErrors.VAR_ANNOTATION_PARAMETER, context)
|
||||
}
|
||||
|
||||
val typeRef = parameter.returnTypeRef
|
||||
@@ -48,7 +46,7 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
||||
// TODO: replace with UNRESOLVED_REFERENCE check
|
||||
}
|
||||
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 -> {
|
||||
// DO NOTHING: primitives are allowed as annotation class parameter
|
||||
@@ -67,13 +65,13 @@ object FirAnnotationClassDeclarationChecker : FirRegularClassChecker() {
|
||||
}
|
||||
classId == StandardClassIds.Array -> {
|
||||
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) -> {
|
||||
// DO NOTHING: annotation or enum classes are allowed
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
@@ -47,9 +47,9 @@ object FirCommonConstructorDelegationIssuesChecker : FirRegularClassChecker() {
|
||||
for (it in otherConstructors) {
|
||||
if (it.delegatedConstructor?.isThis != true) {
|
||||
if (it.delegatedConstructor?.source != null) {
|
||||
reporter.reportPrimaryConstructorDelegationCallExpected(it.delegatedConstructor?.source)
|
||||
reporter.reportOn(it.delegatedConstructor?.source, FirErrors.PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED, context)
|
||||
} 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 &&
|
||||
it.delegatedConstructor?.source?.kind is FirFakeSourceElementKind
|
||||
) {
|
||||
reporter.reportExplicitDelegationCallRequired(it.source)
|
||||
reporter.reportOn(it.source, FirErrors.EXPLICIT_DELEGATION_CALL_REQUIRED, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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>()
|
||||
?.resolvedSymbol
|
||||
?.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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -35,7 +35,7 @@ object FirConflictingProjectionChecker : FirBasicDeclarationChecker() {
|
||||
is FirTypeAlias -> {
|
||||
for (it in declaration.typeParameters) {
|
||||
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)
|
||||
@@ -70,17 +70,9 @@ object FirConflictingProjectionChecker : FirBasicDeclarationChecker() {
|
||||
actual is ConeKotlinTypeProjectionIn && protoVariance == Variance.OUT_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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
@@ -25,11 +25,11 @@ object FirConflictsChecker : FirBasicDeclarationChecker() {
|
||||
}
|
||||
|
||||
inspector.functionDeclarations.forEachNonSingle { it, hint ->
|
||||
reporter.reportConflictingOverloads(it.source, hint)
|
||||
reporter.reportOn(it.source, FirErrors.CONFLICTING_OVERLOADS, hint, context)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
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.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
|
||||
object FirConstructorAllowedChecker : FirConstructorChecker() {
|
||||
@@ -26,27 +24,20 @@ object FirConstructorAllowedChecker : FirConstructorChecker() {
|
||||
return
|
||||
}
|
||||
when (containingClass.classKind) {
|
||||
ClassKind.OBJECT -> reporter.report(source, FirErrors.CONSTRUCTOR_IN_OBJECT)
|
||||
ClassKind.INTERFACE -> reporter.report(source, FirErrors.CONSTRUCTOR_IN_INTERFACE)
|
||||
ClassKind.ENUM_ENTRY -> reporter.report(source, FirErrors.CONSTRUCTOR_IN_OBJECT)
|
||||
ClassKind.OBJECT -> reporter.reportOn(source, FirErrors.CONSTRUCTOR_IN_OBJECT, context)
|
||||
ClassKind.INTERFACE -> reporter.reportOn(source, FirErrors.CONSTRUCTOR_IN_INTERFACE, context)
|
||||
ClassKind.ENUM_ENTRY -> reporter.reportOn(source, FirErrors.CONSTRUCTOR_IN_OBJECT, context)
|
||||
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 &&
|
||||
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 -> {
|
||||
// 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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
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.isInterface
|
||||
|
||||
@@ -20,11 +20,7 @@ object FirConstructorInInterfaceChecker : FirRegularClassChecker() {
|
||||
}
|
||||
|
||||
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.fir.FirSourceElement
|
||||
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.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
@@ -25,14 +25,15 @@ internal fun checkExpectDeclarationVisibilityAndBody(
|
||||
declaration: FirMemberDeclaration,
|
||||
source: FirSourceElement,
|
||||
modifierList: FirModifierList?,
|
||||
reporter: DiagnosticReporter
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
) {
|
||||
if (declaration.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true) {
|
||||
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) {
|
||||
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(
|
||||
containingClass: FirRegularClass?,
|
||||
property: FirProperty,
|
||||
reporter: DiagnosticReporter
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val inInterface = containingClass?.isInterface == true
|
||||
// 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 (property.initializer == null && property.delegate == null && property.returnTypeRef is FirImplicitTypeRef) {
|
||||
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
|
||||
@@ -61,7 +63,7 @@ internal fun checkPropertyInitializer(
|
||||
val backingFieldRequired = property.hasBackingField
|
||||
if (inInterface && backingFieldRequired && property.hasAccessorImplementation) {
|
||||
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 {
|
||||
when {
|
||||
inInterface -> {
|
||||
reporter.report(it, FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE)
|
||||
reporter.reportOn(it, FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE, context)
|
||||
}
|
||||
isExpect -> {
|
||||
reporter.report(it, FirErrors.EXPECTED_PROPERTY_INITIALIZER)
|
||||
reporter.reportOn(it, FirErrors.EXPECTED_PROPERTY_INITIALIZER, context)
|
||||
}
|
||||
!backingFieldRequired -> {
|
||||
// reporter.report(it, FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD)
|
||||
// reporter.reportOn(it, FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD, context)
|
||||
}
|
||||
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 {
|
||||
when {
|
||||
inInterface -> {
|
||||
reporter.report(it, FirErrors.DELEGATED_PROPERTY_IN_INTERFACE)
|
||||
reporter.reportOn(it, FirErrors.DELEGATED_PROPERTY_IN_INTERFACE, context)
|
||||
}
|
||||
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) {
|
||||
property.source?.let {
|
||||
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 {
|
||||
if (containingClass != null || property.hasAccessorImplementation) {
|
||||
// reporter.report(it, FirErrors.MUST_BE_INITIALIZED)
|
||||
// reporter.reportOn(it, FirErrors.MUST_BE_INITIALIZED, context)
|
||||
} 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
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.isInterface
|
||||
|
||||
@@ -22,12 +22,8 @@ object FirDelegationInInterfaceChecker : FirRegularClassChecker() {
|
||||
for (superTypeRef in declaration.superTypeRefs) {
|
||||
val source = superTypeRef.source ?: continue
|
||||
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
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.isEnumClass
|
||||
@@ -26,12 +26,8 @@ object FirDelegationSuperCallInEnumConstructorChecker : FirRegularClassChecker()
|
||||
it.delegatedConstructor?.isThis == false &&
|
||||
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.fir.FirSourceElement
|
||||
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.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
@@ -36,7 +36,7 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
||||
assert(declaration.name.isSpecial && declaration.name.asString() == "<destruct>") {
|
||||
"Unexpected name: ${declaration.name.asString()} for destructuring declaration"
|
||||
}
|
||||
checkInitializer(source, declaration.initializer, reporter)
|
||||
checkInitializer(source, declaration.initializer, reporter, context)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -82,7 +82,8 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
||||
originalDestructuringDeclarationOrInitializerSource,
|
||||
diagnostic.name,
|
||||
originalDestructuringDeclarationType
|
||||
)
|
||||
),
|
||||
context
|
||||
)
|
||||
}
|
||||
is ConeAmbiguityError -> {
|
||||
@@ -91,7 +92,8 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
||||
originalDestructuringDeclarationOrInitializerSource,
|
||||
diagnostic.name,
|
||||
diagnostic.candidates
|
||||
)
|
||||
),
|
||||
context
|
||||
)
|
||||
}
|
||||
is ConeInapplicableCandidateError -> {
|
||||
@@ -100,7 +102,8 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
||||
FirErrors.COMPONENT_FUNCTION_ON_NULLABLE.on(
|
||||
originalDestructuringDeclarationOrInitializerSource,
|
||||
(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 =
|
||||
when (initializer) {
|
||||
null -> true
|
||||
@@ -116,7 +124,7 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() {
|
||||
else -> false
|
||||
}
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.findNonInterfaceSupertype
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.isEnumClass
|
||||
|
||||
@@ -20,19 +20,11 @@ object FirEnumClassSimpleChecker : FirRegularClassChecker() {
|
||||
}
|
||||
|
||||
declaration.findNonInterfaceSupertype(context)?.let {
|
||||
reporter.reportClassInSupertypeForEnum(it.source)
|
||||
reporter.reportOn(it.source, FirErrors.CLASS_IN_SUPERTYPE_FOR_ENUM, context)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
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.toRegularClass
|
||||
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.reportOn
|
||||
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.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
|
||||
@@ -51,12 +52,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
}
|
||||
val restricting = supertype.findVisibilityExposure(context, classVisibility)
|
||||
if (restricting != null) {
|
||||
reporter.reportExposure(
|
||||
reporter.reportOn(
|
||||
supertypeRef.source ?: declaration.source,
|
||||
if (isInterface) FirErrors.EXPOSED_SUPER_INTERFACE else FirErrors.EXPOSED_SUPER_CLASS,
|
||||
restricting,
|
||||
classVisibility,
|
||||
restricting,
|
||||
restricting.getEffectiveVisibility(context),
|
||||
supertypeRef.source ?: declaration.source
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -70,12 +72,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
for (bound in parameter.symbol.fir.bounds) {
|
||||
val restricting = bound.coneType.findVisibilityExposure(context, classVisibility)
|
||||
if (restricting != null) {
|
||||
reporter.reportExposure(
|
||||
reporter.reportOn(
|
||||
bound.source,
|
||||
FirErrors.EXPOSED_TYPE_PARAMETER_BOUND,
|
||||
restricting,
|
||||
classVisibility,
|
||||
restricting,
|
||||
restricting.getEffectiveVisibility(context),
|
||||
bound.source
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -89,12 +92,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
if (typeAliasVisibility == FirEffectiveVisibilityImpl.Local) return
|
||||
val restricting = expandedType?.findVisibilityExposure(context, typeAliasVisibility)
|
||||
if (restricting != null) {
|
||||
reporter.reportExposure(
|
||||
reporter.reportOn(
|
||||
declaration.source,
|
||||
FirErrors.EXPOSED_TYPEALIAS_EXPANDED_TYPE,
|
||||
restricting,
|
||||
typeAliasVisibility,
|
||||
restricting,
|
||||
restricting.getEffectiveVisibility(context),
|
||||
declaration.source
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -107,12 +111,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
val restricting = declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||
?.findVisibilityExposure(context, functionVisibility)
|
||||
if (restricting != null) {
|
||||
reporter.reportExposure(
|
||||
reporter.reportOn(
|
||||
declaration.source,
|
||||
FirErrors.EXPOSED_FUNCTION_RETURN_TYPE,
|
||||
restricting,
|
||||
functionVisibility,
|
||||
restricting,
|
||||
restricting.getEffectiveVisibility(context),
|
||||
declaration.source
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -122,12 +127,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||
?.findVisibilityExposure(context, functionVisibility)
|
||||
if (restricting != null) {
|
||||
reporter.reportExposure(
|
||||
reporter.reportOn(
|
||||
valueParameter.source,
|
||||
FirErrors.EXPOSED_PARAMETER_TYPE,
|
||||
restricting,
|
||||
functionVisibility,
|
||||
restricting,
|
||||
restricting.getEffectiveVisibility(context),
|
||||
valueParameter.source
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -143,12 +149,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()
|
||||
?.findVisibilityExposure(context, propertyVisibility)
|
||||
if (restricting != null) {
|
||||
reporter.reportExposure(
|
||||
reporter.reportOn(
|
||||
declaration.source,
|
||||
FirErrors.EXPOSED_PROPERTY_TYPE,
|
||||
restricting,
|
||||
propertyVisibility,
|
||||
restricting,
|
||||
restricting.getEffectiveVisibility(context),
|
||||
declaration.source
|
||||
context
|
||||
)
|
||||
}
|
||||
checkMemberReceiver(declaration.receiverTypeRef, declaration, reporter, context)
|
||||
@@ -167,12 +174,13 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
if (memberVisibility == FirEffectiveVisibilityImpl.Local) return
|
||||
val restricting = receiverParameterType.findVisibilityExposure(context, memberVisibility)
|
||||
if (restricting != null) {
|
||||
reporter.reportExposure(
|
||||
reporter.reportOn(
|
||||
typeRef.source,
|
||||
FirErrors.EXPOSED_RECEIVER_TYPE,
|
||||
restricting,
|
||||
memberVisibility,
|
||||
restricting,
|
||||
restricting.getEffectiveVisibility(context),
|
||||
typeRef.source
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -207,25 +215,6 @@ object FirExposedVisibilityDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
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) =
|
||||
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.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.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
@@ -23,7 +23,7 @@ object FirFunctionNameChecker : FirFunctionChecker() {
|
||||
val containingDeclaration = context.containingDeclarations.lastOrNull()
|
||||
val isNonLocal = containingDeclaration is FirFile || containingDeclaration is FirClass<*>
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.ConeTypeParameterType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
@@ -40,28 +41,28 @@ object FirInapplicableLateinitChecker : FirPropertyChecker() {
|
||||
|
||||
when {
|
||||
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) {
|
||||
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 {
|
||||
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 ->
|
||||
reporter.report(declaration.source, "is not allowed on delegated properties")
|
||||
reporter.reportOn(declaration.source, "is not allowed on delegated properties", context)
|
||||
|
||||
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) {
|
||||
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 {
|
||||
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() ->
|
||||
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.hasSetter() = setter != null && setter?.source != null && setter?.source?.kind !is FirFakeSourceElementKind
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?, target: String) {
|
||||
source?.let { report(FirErrors.INAPPLICABLE_LATEINIT_MODIFIER.on(it, target)) }
|
||||
private fun DiagnosticReporter.reportOn(source: FirSourceElement?, target: String, context: CheckerContext) {
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
@@ -18,12 +18,12 @@ object FirInfixFunctionDeclarationChecker : FirMemberDeclarationChecker() {
|
||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration is FirSimpleFunction && declaration.isInfix) {
|
||||
if (declaration.valueParameters.size != 1 || !hasExtensionOrDispatchReceiver(declaration, context)) {
|
||||
reporter.report(declaration.source)
|
||||
reporter.reportOn(declaration.source, FirErrors.INAPPLICABLE_INFIX_MODIFIER, context)
|
||||
}
|
||||
return
|
||||
}
|
||||
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
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.findNonInterfaceSupertype
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.isInterface
|
||||
|
||||
@@ -20,11 +20,7 @@ object FirInterfaceWithSuperclassChecker : FirRegularClassChecker() {
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.isCompanion
|
||||
import org.jetbrains.kotlin.fir.declarations.visibility
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
object FirLocalEntityNotAllowedChecker : FirRegularClassChecker() {
|
||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -24,19 +23,11 @@ object FirLocalEntityNotAllowedChecker : FirRegularClassChecker() {
|
||||
|
||||
when {
|
||||
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 ->
|
||||
reporter.reportLocalInterfaceNotAllowed(declaration.source, declaration.name)
|
||||
reporter.reportOn(declaration.source, FirErrors.LOCAL_INTERFACE_NOT_ALLOWED, declaration.name, context)
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.isCompanion
|
||||
|
||||
@@ -19,14 +19,10 @@ object FirManyCompanionObjectsChecker : FirRegularClassChecker() {
|
||||
for (it in declaration.declarations) {
|
||||
if (it is FirRegularClass && it.isCompanion) {
|
||||
if (hasCompanion) {
|
||||
reporter.report(it.source)
|
||||
reporter.reportOn(it.source, FirErrors.MANY_COMPANION_OBJECTS, context)
|
||||
}
|
||||
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.fir.FirFakeSourceElementKind
|
||||
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.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
|
||||
@@ -39,10 +39,13 @@ object FirMemberFunctionChecker : FirRegularClassChecker() {
|
||||
val isAbstract = function.isAbstract || hasAbstractModifier
|
||||
if (isAbstract) {
|
||||
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) {
|
||||
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)
|
||||
@@ -51,17 +54,16 @@ object FirMemberFunctionChecker : FirRegularClassChecker() {
|
||||
if (!function.hasBody) {
|
||||
if (containingDeclaration.isInterface) {
|
||||
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) {
|
||||
reporter.report(source, FirErrors.REDUNDANT_OPEN_IN_INTERFACE)
|
||||
reporter.reportOn(source, FirErrors.REDUNDANT_OPEN_IN_INTERFACE, context)
|
||||
}
|
||||
} 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.FirSourceElement
|
||||
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.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
@@ -47,37 +47,43 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
|
||||
(property.getter == null || property.getter is FirDefaultPropertyAccessor)
|
||||
) {
|
||||
property.source?.let {
|
||||
reporter.report(it, FirErrors.PRIVATE_PROPERTY_IN_INTERFACE)
|
||||
reporter.reportOn(it, FirErrors.PRIVATE_PROPERTY_IN_INTERFACE, context)
|
||||
}
|
||||
}
|
||||
|
||||
if (isAbstract) {
|
||||
if (!containingDeclaration.canHaveAbstractDeclaration) {
|
||||
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
|
||||
}
|
||||
}
|
||||
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 {
|
||||
reporter.report(it, FirErrors.ABSTRACT_DELEGATED_PROPERTY)
|
||||
reporter.reportOn(it, FirErrors.ABSTRACT_DELEGATED_PROPERTY, context)
|
||||
}
|
||||
|
||||
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 ->
|
||||
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 {
|
||||
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
|
||||
if (hasOpenModifier &&
|
||||
@@ -87,19 +93,19 @@ object FirMemberPropertyChecker : FirRegularClassChecker() {
|
||||
!isInsideExpectClass(containingDeclaration, context)
|
||||
) {
|
||||
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
|
||||
if (isOpen) {
|
||||
checkAccessor(property.setter, property.delegate) { src, symbol ->
|
||||
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(
|
||||
|
||||
+3
-7
@@ -5,12 +5,12 @@
|
||||
|
||||
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.FirDeclarationPresenter
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -64,12 +64,8 @@ object FirMethodOfAnyImplementedInInterfaceChecker : FirRegularClassChecker(), F
|
||||
val inspector = getInspector(context)
|
||||
|
||||
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
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
@@ -103,7 +103,8 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
||||
secondModifier: FirModifier<*>,
|
||||
reporter: DiagnosticReporter,
|
||||
reportedNodes: MutableSet<FirModifier<*>>,
|
||||
owner: FirDeclaration?
|
||||
owner: FirDeclaration?,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val firstToken = firstModifier.token
|
||||
val secondToken = secondModifier.token
|
||||
@@ -111,21 +112,21 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
||||
CompatibilityType.COMPATIBLE -> {
|
||||
}
|
||||
CompatibilityType.REPEATED ->
|
||||
if (reportedNodes.add(secondModifier)) reporter.reportRepeatedModifier(secondModifier, secondToken)
|
||||
if (reportedNodes.add(secondModifier)) reporter.reportRepeatedModifier(secondModifier, secondToken, context)
|
||||
CompatibilityType.REDUNDANT_2_TO_1 ->
|
||||
reporter.reportRedundantModifier(secondModifier, secondToken, firstToken)
|
||||
reporter.reportRedundantModifier(secondModifier, secondToken, firstToken, context)
|
||||
CompatibilityType.REDUNDANT_1_TO_2 ->
|
||||
reporter.reportRedundantModifier(firstModifier, firstToken, secondToken)
|
||||
reporter.reportRedundantModifier(firstModifier, firstToken, secondToken, context)
|
||||
CompatibilityType.DEPRECATED -> {
|
||||
reporter.reportDeprecatedModifierPair(firstModifier, firstToken, secondToken)
|
||||
reporter.reportDeprecatedModifierPair(secondModifier, secondToken, firstToken)
|
||||
reporter.reportDeprecatedModifierPair(firstModifier, firstToken, secondToken, context)
|
||||
reporter.reportDeprecatedModifierPair(secondModifier, secondToken, firstToken, context)
|
||||
}
|
||||
CompatibilityType.INCOMPATIBLE, CompatibilityType.COMPATIBLE_FOR_CLASSES -> {
|
||||
if (compatibilityType == CompatibilityType.COMPATIBLE_FOR_CLASSES && owner is FirClass<*>) {
|
||||
return
|
||||
}
|
||||
if (reportedNodes.add(firstModifier)) reporter.reportIncompatibleModifiers(firstModifier, firstToken, secondToken)
|
||||
if (reportedNodes.add(secondModifier)) reporter.reportIncompatibleModifiers(secondModifier, secondToken, firstToken)
|
||||
if (reportedNodes.add(firstModifier)) reporter.reportIncompatibleModifiers(firstModifier, firstToken, secondToken, context)
|
||||
if (reportedNodes.add(secondModifier)) reporter.reportIncompatibleModifiers(secondModifier, secondToken, firstToken, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,7 +134,8 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
||||
private fun checkModifiers(
|
||||
list: FirModifierList,
|
||||
owner: FirDeclaration,
|
||||
reporter: DiagnosticReporter
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
) {
|
||||
// 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
|
||||
@@ -145,7 +147,7 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
||||
if (firstModifier == secondModifier) {
|
||||
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
|
||||
|
||||
val modifierList = with(FirModifierList) { source.getModifierList() }
|
||||
modifierList?.let { checkModifiers(it, declaration, reporter) }
|
||||
modifierList?.let { checkModifiers(it, declaration, reporter, context) }
|
||||
}
|
||||
|
||||
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(
|
||||
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(
|
||||
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(
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.declarations.*
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
@@ -106,6 +107,7 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
||||
private fun FirCallableMemberDeclaration<*>.checkVisibility(
|
||||
reporter: DiagnosticReporter,
|
||||
overriddenSymbols: List<FirCallableSymbol<*>>,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val visibilities = overriddenSymbols.mapNotNull {
|
||||
if (it.fir !is FirMemberDeclaration) return@mapNotNull null
|
||||
@@ -122,7 +124,7 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
||||
// reporter.reportCannotChangeAccessPrivilege(this, overridden.fir)
|
||||
return
|
||||
} else if (compare < 0) {
|
||||
reporter.reportCannotWeakenAccessPrivilege(this, overridden.fir)
|
||||
reporter.reportCannotWeakenAccessPrivilege(this, overridden.fir, context)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -169,15 +171,15 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
||||
val overriddenFunctionSymbols = firTypeScope.retrieveDirectOverriddenOf(function)
|
||||
|
||||
if (overriddenFunctionSymbols.isEmpty()) {
|
||||
reporter.reportNothingToOverride(function)
|
||||
reporter.reportNothingToOverride(function, context)
|
||||
return
|
||||
}
|
||||
|
||||
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(
|
||||
overriddenSymbols = overriddenFunctionSymbols,
|
||||
@@ -186,7 +188,7 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
||||
)
|
||||
|
||||
restriction?.let {
|
||||
reporter.reportReturnTypeMismatchOnFunction(function, it)
|
||||
reporter.reportReturnTypeMismatchOnFunction(function, it, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,19 +206,19 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
||||
val overriddenPropertySymbols = firTypeScope.retrieveDirectOverriddenOf(property)
|
||||
|
||||
if (overriddenPropertySymbols.isEmpty()) {
|
||||
reporter.reportNothingToOverride(property)
|
||||
reporter.reportNothingToOverride(property, context)
|
||||
return
|
||||
}
|
||||
|
||||
checkModality(overriddenPropertySymbols)?.let {
|
||||
reporter.reportOverridingFinalMember(property, it)
|
||||
reporter.reportOverridingFinalMember(property, it, context)
|
||||
}
|
||||
|
||||
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(
|
||||
overriddenSymbols = overriddenPropertySymbols,
|
||||
@@ -226,76 +228,91 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
||||
|
||||
restriction?.let {
|
||||
if (property.isVar) {
|
||||
reporter.reportTypeMismatchOnVariable(property, it)
|
||||
reporter.reportTypeMismatchOnVariable(property, it, context)
|
||||
} 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
|
||||
// declaration.source?.let { report(FirErrors.NOTHING_TO_OVERRIDE.on(it, declaration)) }
|
||||
// reportOn(declaration.source, FirErrors.NOTHING_TO_OVERRIDE, declaration, context)
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.reportOverridingFinalMember(
|
||||
overriding: FirMemberDeclaration,
|
||||
overridden: FirCallableDeclaration<*>,
|
||||
context: CheckerContext
|
||||
) {
|
||||
overriding.source?.let { source ->
|
||||
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(
|
||||
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(
|
||||
overriding: FirMemberDeclaration,
|
||||
overridden: FirCallableDeclaration<*>,
|
||||
context: CheckerContext
|
||||
) {
|
||||
overriding.source?.let { source ->
|
||||
overridden.containingClass()?.let { containingClass ->
|
||||
report(FirErrors.CANNOT_WEAKEN_ACCESS_PRIVILEGE.on(source, overriding.visibility, overridden, containingClass.name))
|
||||
}
|
||||
}
|
||||
val containingClass = overridden.containingClass() ?: return
|
||||
reportOn(
|
||||
overriding.source,
|
||||
FirErrors.CANNOT_WEAKEN_ACCESS_PRIVILEGE,
|
||||
overriding.visibility,
|
||||
overridden,
|
||||
containingClass.name,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.reportCannotChangeAccessPrivilege(
|
||||
overriding: FirMemberDeclaration,
|
||||
overridden: FirCallableDeclaration<*>,
|
||||
context: CheckerContext
|
||||
) {
|
||||
overriding.source?.let { source ->
|
||||
overridden.containingClass()?.let { containingClass ->
|
||||
report(FirErrors.CANNOT_CHANGE_ACCESS_PRIVILEGE.on(source, overriding.visibility, overridden, containingClass.name))
|
||||
}
|
||||
}
|
||||
val containingClass = overridden.containingClass() ?: return
|
||||
reportOn(
|
||||
overriding.source,
|
||||
FirErrors.CANNOT_CHANGE_ACCESS_PRIVILEGE,
|
||||
overriding.visibility,
|
||||
overridden,
|
||||
containingClass.name,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.reportReturnTypeMismatchOnFunction(
|
||||
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(
|
||||
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(
|
||||
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
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.isData
|
||||
@@ -23,11 +23,7 @@ object FirPrimaryConstructorRequiredForDataClassChecker : FirRegularClassChecker
|
||||
val hasPrimaryConstructor = declaration.declarations.any { it is FirConstructor && it.isPrimary }
|
||||
|
||||
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
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
@@ -55,7 +55,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
||||
?: continue
|
||||
|
||||
if (fir.status.modality == Modality.SEALED && classId.outerClassId != null) {
|
||||
reporter.report(it.source)
|
||||
reporter.reportOn(it.source, FirErrors.SEALED_SUPERTYPE, context)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
||||
?: continue
|
||||
|
||||
if (fir.status.modality == Modality.SEALED) {
|
||||
reporter.reportInLocal(it.source)
|
||||
reporter.reportOn(it.source, FirErrors.SEALED_SUPERTYPE_IN_LOCAL_CLASS, context)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -99,17 +99,9 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
||||
?: continue
|
||||
|
||||
if (fir.status.modality == Modality.SEALED && !context.containingDeclarations.contains(fir)) {
|
||||
reporter.report(it.source)
|
||||
reporter.reportOn(it.source, FirErrors.SEALED_SUPERTYPE, context)
|
||||
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
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.isInterface
|
||||
|
||||
@@ -22,12 +22,8 @@ object FirSupertypeInitializedInInterfaceChecker : FirRegularClassChecker() {
|
||||
for (superTypeRef in declaration.superTypeRefs) {
|
||||
val source = superTypeRef.source ?: continue
|
||||
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
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.isInterface
|
||||
@@ -27,12 +27,8 @@ object FirSupertypeInitializedWithoutPrimaryConstructor : FirRegularClassChecker
|
||||
for (superTypeRef in declaration.superTypeRefs) {
|
||||
val source = superTypeRef.source ?: continue
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.lexer.KtTokens
|
||||
|
||||
@@ -17,12 +18,12 @@ object FirTopLevelFunctionChecker : FirFileChecker() {
|
||||
override fun check(declaration: FirFile, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
for (topLevelDeclaration in declaration.declarations) {
|
||||
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
|
||||
if (source.kind is FirFakeSourceElementKind) return
|
||||
// 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
|
||||
val isExpect = function.isExpect || modifierList?.modifiers?.any { it.token == KtTokens.EXPECT_KEYWORD } == true
|
||||
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) {
|
||||
for (topLevelDeclaration in declaration.declarations) {
|
||||
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
|
||||
if (source.kind is FirFakeSourceElementKind) return
|
||||
val modifierList = with(FirModifierList) { source.getModifierList() }
|
||||
|
||||
checkPropertyInitializer(null, property, reporter)
|
||||
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter)
|
||||
checkPropertyInitializer(null, property, reporter, context)
|
||||
checkExpectDeclarationVisibilityAndBody(property, source, modifierList, reporter, context)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-7
@@ -6,10 +6,10 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
|
||||
object FirTypeParametersInObjectChecker : FirRegularClassChecker() {
|
||||
@@ -19,11 +19,7 @@ object FirTypeParametersInObjectChecker : FirRegularClassChecker() {
|
||||
}
|
||||
|
||||
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.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getDeclaration
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.modality
|
||||
@@ -42,14 +42,8 @@ object FirAbstractSuperCallChecker : FirQualifiedAccessChecker() {
|
||||
declaration.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
|
||||
|
||||
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.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
|
||||
@@ -20,10 +20,10 @@ object FirAnonymousFunctionChecker : FirExpressionChecker<FirStatement>() {
|
||||
for (valueParameter in expression.valueParameters) {
|
||||
val source = valueParameter.source ?: continue
|
||||
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) {
|
||||
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
|
||||
|
||||
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
|
||||
if (typeRef !is FirResolvedTypeRef) return
|
||||
@@ -38,17 +38,17 @@ object FirCatchParameterChecker : FirTryExpressionChecker() {
|
||||
val isReified = coneType.lookupTag.typeParameterSymbol.fir.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 {
|
||||
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))
|
||||
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) =
|
||||
throwable.isSupertypeOf(session.typeCheckerContext, this.fullyExpandedType(session))
|
||||
}
|
||||
}
|
||||
|
||||
+2
-8
@@ -5,12 +5,12 @@
|
||||
|
||||
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.isSupertypeOf
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
@@ -29,7 +29,7 @@ object FirNotASupertypeChecker : FirQualifiedAccessChecker() {
|
||||
|
||||
val surrounding = context.findClosestClass(superReference.labelName) ?: return
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.types.FirStarProjection
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
|
||||
@@ -18,19 +18,13 @@ object FirProjectionsOnNonClassTypeArgumentChecker : FirQualifiedAccessChecker()
|
||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
for (it in expression.typeArguments) {
|
||||
when (it) {
|
||||
is FirStarProjection -> reporter.report(it.source)
|
||||
is FirStarProjection -> reporter.reportOn(it.source, FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, context)
|
||||
is FirTypeProjectionWithVariance -> {
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.findClosestClassOrObject
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.followAllAlias
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
@@ -61,13 +61,12 @@ object FirQualifiedSupertypeExtendedByOtherSupertypeChecker : FirQualifiedAccess
|
||||
}
|
||||
|
||||
if (count >= 2 && candidate != null) {
|
||||
reporter.report(superReference.superTypeRef.source, candidate)
|
||||
}
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?, candidate: FirClass<*>) {
|
||||
source?.let {
|
||||
report(FirErrors.QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE.on(it, candidate))
|
||||
reporter.reportOn(
|
||||
superReference.superTypeRef.source,
|
||||
FirErrors.QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE,
|
||||
candidate,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-7
@@ -6,10 +6,10 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
@@ -33,11 +33,7 @@ object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() {
|
||||
?: return
|
||||
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
@@ -23,13 +23,7 @@ object FirSuperNotAvailableChecker : FirQualifiedAccessChecker() {
|
||||
}
|
||||
|
||||
if (!isInsideClass) {
|
||||
reporter.report(expression.source)
|
||||
}
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
||||
source?.let {
|
||||
report(FirErrors.SUPER_NOT_AVAILABLE.on(it))
|
||||
reporter.reportOn(expression.source, FirErrors.SUPER_NOT_AVAILABLE, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-8
@@ -6,11 +6,11 @@
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||
|
||||
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.getContainingClass
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
@@ -34,7 +34,7 @@ object FirSuperclassNotAccessibleFromInterfaceChecker : FirQualifiedAccessChecke
|
||||
?: return
|
||||
|
||||
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<*>? {
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.FirResolvedQualifier
|
||||
|
||||
@@ -20,15 +20,9 @@ object FirTypeArgumentsNotAllowedExpressionChecker : FirQualifiedAccessChecker()
|
||||
|
||||
if (explicitReceiver is FirResolvedQualifier && explicitReceiver.symbol == null) {
|
||||
if (explicitReceiver.typeArguments.isNotEmpty()) {
|
||||
reporter.report(explicitReceiver.source)
|
||||
reporter.reportOn(explicitReceiver.source, FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED, context)
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.originalForSubstitutionOverride
|
||||
@@ -74,7 +75,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
||||
}
|
||||
|
||||
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
|
||||
reporter.report(actual.source, proto, actual.type)
|
||||
reporter.reportOn(actual.source, proto, actual.type, context)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -98,7 +99,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
||||
// typealias A<G> = B<List<G>>
|
||||
// val a = A<Int>()
|
||||
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,
|
||||
callSiteSubstitutor: ConeSubstitutor,
|
||||
typeCheckerContext: AbstractTypeCheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
) {
|
||||
// holds Collection<Number> bound.
|
||||
// note that if B used another type parameter here,
|
||||
@@ -168,7 +170,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
||||
val satisfiesBounds = AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
|
||||
|
||||
if (!satisfiesBounds) {
|
||||
reporter.report(functionCall.source, proto, actual)
|
||||
reporter.reportOn(functionCall.source, proto, actual, context)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -218,7 +220,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
||||
parameterPairs.forEach { (proto, actual) ->
|
||||
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
|
||||
// should report on the parameter instead!
|
||||
reporter.report(reportTarget, proto, actual)
|
||||
reporter.reportOn(reportTarget, proto, actual, context)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -250,9 +252,12 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
||||
return AbstractTypeChecker.isSubtypeOf(typeCheckerContext, target, intersection)
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?, proto: FirTypeParameterSymbol, actual: ConeKotlinType) {
|
||||
source?.let {
|
||||
report(FirErrors.UPPER_BOUND_VIOLATED.on(it, proto, actual))
|
||||
}
|
||||
private fun DiagnosticReporter.reportOn(
|
||||
source: FirSourceElement?,
|
||||
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.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.reportOn
|
||||
import org.jetbrains.kotlin.fir.expressions.FirEqualityOperatorCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirOperation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
@@ -27,6 +28,6 @@ object ArrayEqualityCanBeReplacedWithEquals : FirBasicExpressionChecker() {
|
||||
if (left.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.diagnostics.DiagnosticReporter
|
||||
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.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
@@ -58,7 +59,7 @@ object CanBeReplacedWithOperatorAssignmentChecker : FirVariableAssignmentChecker
|
||||
}
|
||||
|
||||
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.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.cfa.*
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElement
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
@@ -21,7 +27,8 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
|
||||
graph: ControlFlowGraph,
|
||||
reporter: DiagnosticReporter,
|
||||
data: Map<CFGNode<*>, PathAwarePropertyInitializationInfo>,
|
||||
properties: Set<FirPropertySymbol>
|
||||
properties: Set<FirPropertySymbol>,
|
||||
context: CheckerContext
|
||||
) {
|
||||
val unprocessedProperties = mutableSetOf<FirPropertySymbol>()
|
||||
val propertiesCharacteristics = mutableMapOf<FirPropertySymbol, EventOccurrencesRange>()
|
||||
@@ -51,14 +58,14 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
|
||||
if (lastDestructuringSource != null) {
|
||||
// if this is the last variable in destructuring declaration and destructuringCanBeVal == true and it can be val
|
||||
if (lastDestructuredVariables == 1 && destructuringCanBeVal && canBeVal(symbol, value)) {
|
||||
reporter.report(lastDestructuringSource, FirErrors.CAN_BE_VAL)
|
||||
reporter.reportOn(lastDestructuringSource, FirErrors.CAN_BE_VAL, context)
|
||||
lastDestructuringSource = null
|
||||
} else if (!canBeVal(symbol, value)) {
|
||||
destructuringCanBeVal = false
|
||||
}
|
||||
lastDestructuredVariables--
|
||||
} 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.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.diagnostics.DiagnosticReporter
|
||||
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.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
@@ -36,8 +37,7 @@ object EmptyRangeChecker : FirBasicExpressionChecker() {
|
||||
}
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
@@ -31,7 +32,7 @@ object RedundantCallOfConversionMethod : FirQualifiedAccessChecker() {
|
||||
val qualifiedType = targetClassMap[functionName] ?: return
|
||||
|
||||
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,
|
||||
"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.diagnostics.DiagnosticReporter
|
||||
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.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||
@@ -84,7 +85,7 @@ object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
|
||||
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 {
|
||||
@@ -95,4 +96,4 @@ object RedundantExplicitTypeChecker : FirMemberDeclarationChecker() {
|
||||
|
||||
private fun ConeKotlinType.hasSameNameWithoutModifiers(name: Name): Boolean =
|
||||
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.FirErrors.REDUNDANT_MODALITY_MODIFIER
|
||||
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.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.modality
|
||||
@@ -33,6 +34,6 @@ object RedundantModalityModifierChecker : FirMemberDeclarationChecker() {
|
||||
val implicitModality = declaration.implicitModality(context)
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
||||
@@ -25,8 +26,8 @@ object RedundantReturnUnitType : FirBasicDeclarationChecker() {
|
||||
if (returnType.annotations.isNotEmpty()) return
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
@@ -23,7 +24,7 @@ object RedundantSetterParameterTypeChecker : FirMemberDeclarationChecker() {
|
||||
val setterParameterTypeSource = valueParameter.returnTypeRef.source ?: return
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirStatement
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
@@ -32,7 +33,7 @@ object RedundantSingleExpressionStringTemplateChecker : FirBasicExpressionChecke
|
||||
expression.explicitReceiver?.typeRef?.coneType?.classId == StandardClassIds.String
|
||||
&& 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.Modality
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElement
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
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.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
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.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
|
||||
@@ -53,7 +50,7 @@ object RedundantVisibilityModifierChecker : FirBasicDeclarationChecker() {
|
||||
&& declaration.setter?.visibility == Visibilities.Public
|
||||
) return
|
||||
|
||||
reporter.report(source, FirErrors.REDUNDANT_VISIBILITY_MODIFIER)
|
||||
reporter.reportOn(source, FirErrors.REDUNDANT_VISIBILITY_MODIFIER, context)
|
||||
}
|
||||
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirFunctionCall
|
||||
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
|
||||
|
||||
object UnusedChecker : FirControlFlowChecker() {
|
||||
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, checkerContext: CheckerContext) {
|
||||
if ((graph.declaration as? FirSymbolOwner<*>)?.getContainingClass(checkerContext)?.takeIf {
|
||||
override fun analyze(graph: ControlFlowGraph, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||
if ((graph.declaration as? FirSymbolOwner<*>)?.getContainingClass(context)?.takeIf {
|
||||
!it.symbol.classId.isLocal
|
||||
} != null
|
||||
) return
|
||||
val properties = LocalPropertyCollector.collect(graph)
|
||||
if (properties.isEmpty()) return
|
||||
|
||||
val data = ValueWritesWithoutReading(checkerContext.session, properties).getData(graph)
|
||||
graph.traverse(TraverseDirection.Backward, CfaVisitor(data, reporter))
|
||||
val data = ValueWritesWithoutReading(context.session, properties).getData(graph)
|
||||
graph.traverse(TraverseDirection.Backward, CfaVisitor(data, reporter, context))
|
||||
}
|
||||
|
||||
class CfaVisitor(
|
||||
val data: Map<CFGNode<*>, PathAwareVariableStatusInfo>,
|
||||
val reporter: DiagnosticReporter
|
||||
val reporter: DiagnosticReporter,
|
||||
val context: CheckerContext
|
||||
) : ControlFlowGraphVisitorVoid() {
|
||||
override fun visitNode(node: CFGNode<*>) {}
|
||||
|
||||
@@ -56,7 +58,7 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
if (data == VariableStatus.ONLY_WRITTEN_NEVER_READ) {
|
||||
// todo: report case like "a += 1" where `a` `doesn't writes` different way (special for Idea)
|
||||
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.
|
||||
break
|
||||
}
|
||||
@@ -74,17 +76,17 @@ object UnusedChecker : FirControlFlowChecker() {
|
||||
when {
|
||||
data == VariableStatus.UNUSED -> {
|
||||
if ((node.fir.initializer as? FirFunctionCall)?.isIterator != true) {
|
||||
reporter.report(variableSource, FirErrors.UNUSED_VARIABLE)
|
||||
reporter.reportOn(variableSource, FirErrors.UNUSED_VARIABLE, context)
|
||||
break
|
||||
}
|
||||
}
|
||||
data.isRedundantInit -> {
|
||||
val source = variableSymbol.fir.initializer?.source
|
||||
reporter.report(source, FirErrors.VARIABLE_INITIALIZER_IS_REDUNDANT)
|
||||
reporter.reportOn(source, FirErrors.VARIABLE_INITIALIZER_IS_REDUNDANT, context)
|
||||
break
|
||||
}
|
||||
data == VariableStatus.ONLY_WRITTEN_NEVER_READ -> {
|
||||
reporter.report(variableSource, FirErrors.VARIABLE_NEVER_READ)
|
||||
reporter.reportOn(variableSource, FirErrors.VARIABLE_NEVER_READ, context)
|
||||
break
|
||||
}
|
||||
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.diagnostics.DiagnosticReporter
|
||||
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.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
@@ -28,7 +29,7 @@ object UselessCallOnNotNullChecker : FirQualifiedAccessChecker() {
|
||||
if ("$calleePackageName.$calleeName" !in triggerOn) return
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+17
-9
@@ -10,7 +10,10 @@ 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.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.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind.*
|
||||
@@ -27,37 +30,42 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
override fun visitErrorLoop(errorLoop: FirErrorLoop, data: CheckerContext) {
|
||||
val source = errorLoop.source ?: return
|
||||
reportFirDiagnostic(errorLoop.diagnostic, source, reporter)
|
||||
reportFirDiagnostic(errorLoop.diagnostic, source, reporter, data)
|
||||
}
|
||||
|
||||
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: CheckerContext) {
|
||||
val source = errorTypeRef.source ?: return
|
||||
reportFirDiagnostic(errorTypeRef.diagnostic, source, reporter)
|
||||
reportFirDiagnostic(errorTypeRef.diagnostic, source, reporter, data)
|
||||
}
|
||||
|
||||
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference, data: CheckerContext) {
|
||||
val source = errorNamedReference.source ?: return
|
||||
// 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
|
||||
reportFirDiagnostic(errorNamedReference.diagnostic, source, reporter)
|
||||
reportFirDiagnostic(errorNamedReference.diagnostic, source, reporter, data)
|
||||
}
|
||||
|
||||
override fun visitErrorExpression(errorExpression: FirErrorExpression, data: CheckerContext) {
|
||||
val source = errorExpression.source ?: return
|
||||
reportFirDiagnostic(errorExpression.diagnostic, source, reporter)
|
||||
reportFirDiagnostic(errorExpression.diagnostic, source, reporter, data)
|
||||
}
|
||||
|
||||
override fun visitErrorFunction(errorFunction: FirErrorFunction, data: CheckerContext) {
|
||||
val source = errorFunction.source ?: return
|
||||
reportFirDiagnostic(errorFunction.diagnostic, source, reporter)
|
||||
reportFirDiagnostic(errorFunction.diagnostic, source, reporter, data)
|
||||
}
|
||||
|
||||
override fun visitErrorResolvedQualifier(errorResolvedQualifier: FirErrorResolvedQualifier, data: CheckerContext) {
|
||||
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]
|
||||
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.
|
||||
@@ -97,7 +105,7 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect
|
||||
is ConeIntermediateDiagnostic -> null
|
||||
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${diagnostic.javaClass}")
|
||||
}
|
||||
reporter.report(coneDiagnostic)
|
||||
reporter.report(coneDiagnostic, context)
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.isEffectivelyNotNull(): Boolean {
|
||||
|
||||
+45
-3
@@ -5,15 +5,57 @@
|
||||
|
||||
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 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() {
|
||||
val diagnostics: MutableList<FirDiagnostic<*>> = mutableListOf()
|
||||
|
||||
override fun report(diagnostic: FirDiagnostic<*>?) {
|
||||
override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) {
|
||||
if (diagnostic == null) return
|
||||
diagnostics += diagnostic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -288,7 +288,7 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
)
|
||||
|
||||
// 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(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)
|
||||
|
||||
+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.FirMemberDeclaration
|
||||
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.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -104,7 +106,7 @@ object FirErrors {
|
||||
val EXPOSED_TYPE_PARAMETER_BOUND by error3<FirSourceElement, KtTypeReference, FirEffectiveVisibility, FirMemberDeclaration, FirEffectiveVisibility>()
|
||||
|
||||
// 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 REDUNDANT_MODIFIER 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 org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
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.registerAllComponents
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
@@ -39,7 +40,7 @@ internal abstract class AbstractFirIdeDiagnosticsCollector(
|
||||
|
||||
|
||||
private inner class Reporter : DiagnosticReporter() {
|
||||
override fun report(diagnostic: FirDiagnostic<*>?) {
|
||||
override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) {
|
||||
if (diagnostic !is FirPsiDiagnostic<*>) return
|
||||
if (diagnostic.element.psi !is KtElement) return
|
||||
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.declaration.FirMemberDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
|
||||
@@ -16,7 +15,7 @@ object DummyNameChecker : FirMemberDeclarationChecker() {
|
||||
override fun check(declaration: FirMemberDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (declaration !is FirSimpleFunction) return
|
||||
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