diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/AbstractFirIdeDiagnosticsCollector.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/AbstractFirIdeDiagnosticsCollector.kt index 5f0983a2aae..21e27a318ed 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/AbstractFirIdeDiagnosticsCollector.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostics/AbstractFirIdeDiagnosticsCollector.kt @@ -62,6 +62,7 @@ private object CheckersFactory { add(ExpressionCheckersDiagnosticComponent(session, reporter, expressionCheckers)) add(TypeCheckersDiagnosticComponent(session, reporter, typeCheckers)) add(ControlFlowAnalysisDiagnosticComponent(session, reporter, declarationCheckers)) + add(ReportCommitterDiagnosticComponent(session, reporter)) } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt index 4d5953d780b..4f77541da94 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt @@ -172,7 +172,7 @@ object FirKotlinToJvmBytecodeCompiler { val renderDiagnosticNames = moduleConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) - val diagnosticsReporter = DiagnosticReporterFactory.createReporter() + val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() val firResult = runFrontend(allSources, diagnosticsReporter).also { performanceManager?.notifyAnalysisFinished() } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt index fb84838f425..41333b65051 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt @@ -120,7 +120,7 @@ fun compileModulesUsingFrontendIrAndLightTree( } val renderDiagnosticName = moduleConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) - val diagnosticsReporter = DiagnosticReporterFactory.createReporter() + val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() val compilerInput = ModuleCompilerInput( TargetId(module), diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.kt b/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.kt index ce429d1f164..b32b51fc938 100644 --- a/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.kt +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.kt @@ -1,20 +1,20 @@ const val x = "123" - @Suppress("CONST_VAL_WITH_GETTER") - get() = field + @Suppress("CONST_VAL_WITH_GETTER") + get() = field val y = "789" -const val z = @Suppress("CONST_VAL_WITH_NON_CONST_INITIALIZER") y +const val z = @Suppress("CONST_VAL_WITH_NON_CONST_INITIALIZER") y @Target(AnnotationTarget.TYPE) annotation class Ann -fun foo(): @Suppress("REPEATED_ANNOTATION") @Ann @Ann Int = 42 +fun foo(): @Suppress("REPEATED_ANNOTATION") @Ann @Ann Int = 42 -typealias Alias = @Suppress("TYPEALIAS_SHOULD_EXPAND_TO_CLASS") T +typealias Alias = @Suppress("TYPEALIAS_SHOULD_EXPAND_TO_CLASS") T interface A -interface B : @Suppress("SUPERTYPE_INITIALIZED_IN_INTERFACE") A() +interface B : @Suppress("SUPERTYPE_INITIALIZED_IN_INTERFACE") A() -data class D @Suppress("DATA_CLASS_VARARG_PARAMETER") constructor(vararg val x: String) +data class D @Suppress("DATA_CLASS_VARARG_PARAMETER") constructor(vararg val x: String) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/CheckerRunningDiagnosticCollectorVisitor.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/CheckerRunningDiagnosticCollectorVisitor.kt index 868b66a068f..6f2d15fdcba 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/CheckerRunningDiagnosticCollectorVisitor.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/CheckerRunningDiagnosticCollectorVisitor.kt @@ -8,6 +8,8 @@ package org.jetbrains.kotlin.fir.analysis.collectors import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirFile open class CheckerRunningDiagnosticCollectorVisitor( context: CheckerContext, @@ -19,4 +21,11 @@ open class CheckerRunningDiagnosticCollectorVisitor( element.accept(it, context) } } + + override fun onDeclarationExit(declaration: FirDeclaration) { + if (declaration !is FirFile) return + components.forEach { + it.endOfFile(declaration) + } + } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/AbstractDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/AbstractDiagnosticCollectorComponent.kt index 530fa7afa00..3dc84adc295 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/AbstractDiagnosticCollectorComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/AbstractDiagnosticCollectorComponent.kt @@ -5,10 +5,13 @@ package org.jetbrains.kotlin.fir.analysis.collectors.components +import org.jetbrains.kotlin.diagnostics.DiagnosticContext import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.impl.PendingDiagnosticsCollectorWithSuppress +import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.visitors.FirVisitor abstract class AbstractDiagnosticCollectorComponent( @@ -16,4 +19,13 @@ abstract class AbstractDiagnosticCollectorComponent( protected val reporter: DiagnosticReporter, ) : FirVisitor() { override fun visitElement(element: FirElement, data: CheckerContext) {} + + protected fun checkAndCommitReportsOn(element: FirElement, context: DiagnosticContext?) { + if (reporter is PendingDiagnosticsCollectorWithSuppress) { + val source = element.source ?: return + reporter.checkAndCommitReportsOn(source, context, context == null) + } + } + + open fun endOfFile(file: FirFile) {} } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt index ce3511f370d..514b8d50f0c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DeclarationCheckersDiagnosticComponent.kt @@ -22,69 +22,68 @@ class DeclarationCheckersDiagnosticComponent( ) : AbstractDiagnosticCollectorComponent(session, reporter) { override fun visitFile(file: FirFile, data: CheckerContext) { - checkers.allFileCheckers.check(file, data, reporter) + checkers.allFileCheckers.check(file, data) } override fun visitProperty(property: FirProperty, data: CheckerContext) { - checkers.allPropertyCheckers.check(property, data, reporter) + checkers.allPropertyCheckers.check(property, data) } override fun visitClass(klass: FirClass, data: CheckerContext) { - checkers.allClassCheckers.check(klass, data, reporter) + checkers.allClassCheckers.check(klass, data) } override fun visitRegularClass(regularClass: FirRegularClass, data: CheckerContext) { - checkers.allRegularClassCheckers.check(regularClass, data, reporter) + checkers.allRegularClassCheckers.check(regularClass, data) } override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: CheckerContext) { - checkers.allSimpleFunctionCheckers.check(simpleFunction, data, reporter) + checkers.allSimpleFunctionCheckers.check(simpleFunction, data) } override fun visitTypeAlias(typeAlias: FirTypeAlias, data: CheckerContext) { - checkers.allTypeAliasCheckers.check(typeAlias, data, reporter) + checkers.allTypeAliasCheckers.check(typeAlias, data) } override fun visitConstructor(constructor: FirConstructor, data: CheckerContext) { - checkers.allConstructorCheckers.check(constructor, data, reporter) + checkers.allConstructorCheckers.check(constructor, data) } override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: CheckerContext) { - checkers.allAnonymousFunctionCheckers.check(anonymousFunction, data, reporter) + checkers.allAnonymousFunctionCheckers.check(anonymousFunction, data) } override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: CheckerContext) { - checkers.allPropertyAccessorCheckers.check(propertyAccessor, data, reporter) + checkers.allPropertyAccessorCheckers.check(propertyAccessor, data) } override fun visitBackingField(backingField: FirBackingField, data: CheckerContext) { - checkers.allBackingFieldCheckers.check(backingField, data, reporter) + checkers.allBackingFieldCheckers.check(backingField, data) } override fun visitValueParameter(valueParameter: FirValueParameter, data: CheckerContext) { - checkers.allValueParameterCheckers.check(valueParameter, data, reporter) + checkers.allValueParameterCheckers.check(valueParameter, data) } override fun visitTypeParameter(typeParameter: FirTypeParameter, data: CheckerContext) { - checkers.allTypeParameterCheckers.check(typeParameter, data, reporter) + checkers.allTypeParameterCheckers.check(typeParameter, data) } override fun visitEnumEntry(enumEntry: FirEnumEntry, data: CheckerContext) { - checkers.allEnumEntryCheckers.check(enumEntry, data, reporter) + checkers.allEnumEntryCheckers.check(enumEntry, data) } override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: CheckerContext) { - checkers.allAnonymousObjectCheckers.check(anonymousObject, data, reporter) + checkers.allAnonymousObjectCheckers.check(anonymousObject, data) } override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: CheckerContext) { - checkers.allAnonymousInitializerCheckers.check(anonymousInitializer, data, reporter) + checkers.allAnonymousInitializerCheckers.check(anonymousInitializer, data) } private fun Collection>.check( declaration: D, - context: CheckerContext, - reporter: DiagnosticReporter + context: CheckerContext ) { for (checker in this) { checker.check(declaration, context, reporter) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DiagnosticComponentsFactory.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DiagnosticComponentsFactory.kt index 1c86494b960..3c5263d827c 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DiagnosticComponentsFactory.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/DiagnosticComponentsFactory.kt @@ -16,6 +16,7 @@ object DiagnosticComponentsFactory { TypeCheckersDiagnosticComponent(session, reporter), ErrorNodeDiagnosticCollectorComponent(session, reporter), ControlFlowAnalysisDiagnosticComponent(session, reporter), + ReportCommitterDiagnosticComponent(session, reporter) ) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt index a5927ca1187..d5006e4beeb 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt @@ -32,12 +32,12 @@ class ErrorNodeDiagnosticCollectorComponent( ) : AbstractDiagnosticCollectorComponent(session, reporter) { override fun visitErrorLoop(errorLoop: FirErrorLoop, data: CheckerContext) { val source = errorLoop.source ?: return - reportFirDiagnostic(errorLoop.diagnostic, source, reporter, data) + reportFirDiagnostic(errorLoop.diagnostic, source, data) } override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: CheckerContext) { val source = errorTypeRef.source ?: return - reportFirDiagnostic(errorTypeRef.diagnostic, source, reporter, data) + reportFirDiagnostic(errorTypeRef.diagnostic, source, data) } override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: CheckerContext) { @@ -71,7 +71,7 @@ class ErrorNodeDiagnosticCollectorComponent( ) return } - reportFirDiagnostic(errorNamedReference.diagnostic, source, reporter, data, qualifiedAccessOrAnnotationCall?.source) + reportFirDiagnostic(errorNamedReference.diagnostic, source, data, qualifiedAccessOrAnnotationCall?.source) } private fun FirExpression?.cannotBeResolved(): Boolean { @@ -86,28 +86,27 @@ class ErrorNodeDiagnosticCollectorComponent( override fun visitErrorExpression(errorExpression: FirErrorExpression, data: CheckerContext) { val source = errorExpression.source ?: return - reportFirDiagnostic(errorExpression.diagnostic, source, reporter, data) + reportFirDiagnostic(errorExpression.diagnostic, source, data) } override fun visitErrorFunction(errorFunction: FirErrorFunction, data: CheckerContext) { val source = errorFunction.source ?: return - reportFirDiagnostic(errorFunction.diagnostic, source, reporter, data) + reportFirDiagnostic(errorFunction.diagnostic, source, data) } override fun visitErrorResolvedQualifier(errorResolvedQualifier: FirErrorResolvedQualifier, data: CheckerContext) { val source = errorResolvedQualifier.source ?: return - reportFirDiagnostic(errorResolvedQualifier.diagnostic, source, reporter, data) + reportFirDiagnostic(errorResolvedQualifier.diagnostic, source, data) } override fun visitErrorImport(errorImport: FirErrorImport, data: CheckerContext) { val source = errorImport.source ?: return - reportFirDiagnostic(errorImport.diagnostic, source, reporter, data) + reportFirDiagnostic(errorImport.diagnostic, source, data) } private fun reportFirDiagnostic( diagnostic: ConeDiagnostic, source: KtSourceElement, - reporter: DiagnosticReporter, context: CheckerContext, qualifiedAccessSource: KtSourceElement? = null ) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt index 6353c808370..56ff3cd0c08 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt @@ -21,137 +21,136 @@ class ExpressionCheckersDiagnosticComponent( private val checkers: ExpressionCheckers = session.checkersComponent.expressionCheckers, ) : AbstractDiagnosticCollectorComponent(session, reporter) { override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall, data: CheckerContext) { - checkers.allTypeOperatorCallCheckers.check(typeOperatorCall, data, reporter) + checkers.allTypeOperatorCallCheckers.check(typeOperatorCall, data) } override fun visitConstExpression(constExpression: FirConstExpression, data: CheckerContext) { - checkers.allConstExpressionCheckers.check(constExpression, data, reporter) + checkers.allConstExpressionCheckers.check(constExpression, data) } override fun visitAnnotation(annotation: FirAnnotation, data: CheckerContext) { - checkers.allAnnotationCheckers.check(annotation, data, reporter) + checkers.allAnnotationCheckers.check(annotation, data) } override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: CheckerContext) { - checkers.allAnnotationCallCheckers.check(annotationCall, data, reporter) + checkers.allAnnotationCallCheckers.check(annotationCall, data) } override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: CheckerContext) { - checkers.allQualifiedAccessExpressionCheckers.check(qualifiedAccessExpression, data, reporter) + checkers.allQualifiedAccessExpressionCheckers.check(qualifiedAccessExpression, data) } override fun visitPropertyAccessExpression(propertyAccessExpression: FirPropertyAccessExpression, data: CheckerContext) { - checkers.allQualifiedAccessExpressionCheckers.check(propertyAccessExpression, data, reporter) + checkers.allQualifiedAccessExpressionCheckers.check(propertyAccessExpression, data) } override fun visitFunctionCall(functionCall: FirFunctionCall, data: CheckerContext) { - checkers.allFunctionCallCheckers.check(functionCall, data, reporter) + checkers.allFunctionCallCheckers.check(functionCall, data) } override fun visitIntegerLiteralOperatorCall(integerLiteralOperatorCall: FirIntegerLiteralOperatorCall, data: CheckerContext) { - checkers.allIntegerLiteralOperatorCallCheckers.check(integerLiteralOperatorCall, data, reporter) + checkers.allIntegerLiteralOperatorCallCheckers.check(integerLiteralOperatorCall, data) } override fun visitImplicitInvokeCall(implicitInvokeCall: FirImplicitInvokeCall, data: CheckerContext) { - checkers.allFunctionCallCheckers.check(implicitInvokeCall, data, reporter) + checkers.allFunctionCallCheckers.check(implicitInvokeCall, data) } override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: CheckerContext) { - checkers.allCallableReferenceAccessCheckers.check(callableReferenceAccess, data, reporter) + checkers.allCallableReferenceAccessCheckers.check(callableReferenceAccess, data) } override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression, data: CheckerContext) { - checkers.allThisReceiverExpressionCheckers.check(thisReceiverExpression, data, reporter) + checkers.allThisReceiverExpressionCheckers.check(thisReceiverExpression, data) } override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: CheckerContext) { - checkers.allResolvedQualifierCheckers.check(resolvedQualifier, data, reporter) + checkers.allResolvedQualifierCheckers.check(resolvedQualifier, data) } override fun visitWhenExpression(whenExpression: FirWhenExpression, data: CheckerContext) { - checkers.allWhenExpressionCheckers.check(whenExpression, data, reporter) + checkers.allWhenExpressionCheckers.check(whenExpression, data) } override fun visitWhileLoop(whileLoop: FirWhileLoop, data: CheckerContext) { - checkers.allWhileLoopCheckers.check(whileLoop, data, reporter) + checkers.allWhileLoopCheckers.check(whileLoop, data) } override fun visitDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: CheckerContext) { - checkers.allDoWhileLoopCheckers.check(doWhileLoop, data, reporter) + checkers.allDoWhileLoopCheckers.check(doWhileLoop, data) } override fun visitErrorLoop(errorLoop: FirErrorLoop, data: CheckerContext) { - checkers.allLoopExpressionCheckers.check(errorLoop, data, reporter) + checkers.allLoopExpressionCheckers.check(errorLoop, data) } override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: CheckerContext) { - checkers.allLogicExpressionCheckers.check(binaryLogicExpression, data, reporter) + checkers.allLogicExpressionCheckers.check(binaryLogicExpression, data) } override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall, data: CheckerContext) { - checkers.allArrayOfCallCheckers.check(arrayOfCall, data, reporter) + checkers.allArrayOfCallCheckers.check(arrayOfCall, data) } override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall, data: CheckerContext) { - checkers.allStringConcatenationCallCheckers.check(stringConcatenationCall, data, reporter) + checkers.allStringConcatenationCallCheckers.check(stringConcatenationCall, data) } override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall, data: CheckerContext) { - checkers.allCheckNotNullCallCheckers.check(checkNotNullCall, data, reporter) + checkers.allCheckNotNullCallCheckers.check(checkNotNullCall, data) } override fun visitElvisExpression(elvisExpression: FirElvisExpression, data: CheckerContext) { - checkers.allElvisExpressionCheckers.check(elvisExpression, data, reporter) + checkers.allElvisExpressionCheckers.check(elvisExpression, data) } override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: CheckerContext) { - checkers.allSafeCallExpressionCheckers.check(safeCallExpression, data, reporter) + checkers.allSafeCallExpressionCheckers.check(safeCallExpression, data) } override fun visitTryExpression(tryExpression: FirTryExpression, data: CheckerContext) { - checkers.allTryExpressionCheckers.check(tryExpression, data, reporter) + checkers.allTryExpressionCheckers.check(tryExpression, data) } override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression, data: CheckerContext) { - checkers.allClassReferenceExpressionCheckers.check(classReferenceExpression, data, reporter) + checkers.allClassReferenceExpressionCheckers.check(classReferenceExpression, data) } override fun visitGetClassCall(getClassCall: FirGetClassCall, data: CheckerContext) { - checkers.allGetClassCallCheckers.check(getClassCall, data, reporter) + checkers.allGetClassCallCheckers.check(getClassCall, data) } override fun visitEqualityOperatorCall(equalityOperatorCall: FirEqualityOperatorCall, data: CheckerContext) { - checkers.allEqualityOperatorCallCheckers.check(equalityOperatorCall, data, reporter) + checkers.allEqualityOperatorCallCheckers.check(equalityOperatorCall, data) } override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: CheckerContext) { - checkers.allVariableAssignmentCheckers.check(variableAssignment, data, reporter) + checkers.allVariableAssignmentCheckers.check(variableAssignment, data) } override fun visitReturnExpression(returnExpression: FirReturnExpression, data: CheckerContext) { - checkers.allReturnExpressionCheckers.check(returnExpression, data, reporter) + checkers.allReturnExpressionCheckers.check(returnExpression, data) } override fun visitBreakExpression(breakExpression: FirBreakExpression, data: CheckerContext) { - checkers.allLoopJumpCheckers.check(breakExpression, data, reporter) + checkers.allLoopJumpCheckers.check(breakExpression, data) } override fun visitContinueExpression(continueExpression: FirContinueExpression, data: CheckerContext) { - checkers.allLoopJumpCheckers.check(continueExpression, data, reporter) + checkers.allLoopJumpCheckers.check(continueExpression, data) } override fun visitBlock(block: FirBlock, data: CheckerContext) { - checkers.allBlockCheckers.check(block, data, reporter) + checkers.allBlockCheckers.check(block, data) } override fun visitDelegatedConstructorCall(delegatedConstructorCall: FirDelegatedConstructorCall, data: CheckerContext) { - checkers.allCallCheckers.check(delegatedConstructorCall, data, reporter) + checkers.allCallCheckers.check(delegatedConstructorCall, data) } private fun Collection>.check( expression: E, - context: CheckerContext, - reporter: DiagnosticReporter + context: CheckerContext ) { for (checker in this) { checker.check(expression, context, reporter) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ReportCommiterDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ReportCommiterDiagnosticComponent.kt new file mode 100644 index 00000000000..2d34c21e3fa --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ReportCommiterDiagnosticComponent.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2022 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.collectors.components + +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.declarations.FirFile + +class ReportCommitterDiagnosticComponent( + session: FirSession, + reporter: DiagnosticReporter +) : AbstractDiagnosticCollectorComponent(session, reporter) { + override fun visitElement(element: FirElement, data: CheckerContext) { + checkAndCommitReportsOn(element, data) + } + + override fun endOfFile(file: FirFile) { + checkAndCommitReportsOn(file, null) + } +} \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/TypeCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/TypeCheckersDiagnosticComponent.kt index b8790cf3db3..d11952c1ff1 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/TypeCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/TypeCheckersDiagnosticComponent.kt @@ -22,41 +22,40 @@ class TypeCheckersDiagnosticComponent( ) : AbstractDiagnosticCollectorComponent(session, reporter) { override fun visitDynamicTypeRef(dynamicTypeRef: FirDynamicTypeRef, data: CheckerContext) { - checkers.allTypeRefCheckers.check(dynamicTypeRef, data, reporter) + checkers.allTypeRefCheckers.check(dynamicTypeRef, data) } override fun visitFunctionTypeRef(functionTypeRef: FirFunctionTypeRef, data: CheckerContext) { - checkers.allTypeRefCheckers.check(functionTypeRef, data, reporter) + checkers.allTypeRefCheckers.check(functionTypeRef, data) } override fun visitUserTypeRef(userTypeRef: FirUserTypeRef, data: CheckerContext) { - checkers.allTypeRefCheckers.check(userTypeRef, data, reporter) + checkers.allTypeRefCheckers.check(userTypeRef, data) } override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: CheckerContext) { - checkers.allTypeRefCheckers.check(resolvedTypeRef, data, reporter) + checkers.allTypeRefCheckers.check(resolvedTypeRef, data) } override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: CheckerContext) { - checkers.allTypeRefCheckers.check(errorTypeRef, data, reporter) + checkers.allTypeRefCheckers.check(errorTypeRef, data) } override fun visitTypeRefWithNullability(typeRefWithNullability: FirTypeRefWithNullability, data: CheckerContext) { - checkers.allTypeRefCheckers.check(typeRefWithNullability, data, reporter) + checkers.allTypeRefCheckers.check(typeRefWithNullability, data) } override fun visitImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: CheckerContext) { - checkers.allTypeRefCheckers.check(implicitTypeRef, data, reporter) + checkers.allTypeRefCheckers.check(implicitTypeRef, data) } override fun visitTypeRef(typeRef: FirTypeRef, data: CheckerContext) { - checkers.allTypeRefCheckers.check(typeRef, data, reporter) + checkers.allTypeRefCheckers.check(typeRef, data) } private fun Collection>.check( typeRef: T, - context: CheckerContext, - reporter: DiagnosticReporter + context: CheckerContext ) { for (checker in this) { checker.check(typeRef, context, reporter) diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt index 6368e561513..814858e13af 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/analyse.kt @@ -6,8 +6,6 @@ package org.jetbrains.kotlin.fir.pipeline import org.jetbrains.kotlin.diagnostics.DiagnosticReporter -import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory -import org.jetbrains.kotlin.diagnostics.KtDiagnostic import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.collectors.FirDiagnosticsCollector import org.jetbrains.kotlin.fir.declarations.FirFile @@ -20,19 +18,6 @@ fun FirSession.runResolution(firFiles: List): Pair): Map> { - val collector = FirDiagnosticsCollector.create(this, scopeSession) - return buildMap { - for (file in firFiles) { - val reporter = DiagnosticReporterFactory.createReporter() - collector.collectDiagnostics(file, reporter) - put(file, reporter.diagnostics) - } - } -} - -@OptIn(ExperimentalStdlibApi::class) fun FirSession.runCheckers(scopeSession: ScopeSession, firFiles: List, reporter: DiagnosticReporter) { val collector = FirDiagnosticsCollector.create(this, scopeSession) for (file in firFiles) { diff --git a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt index fbada38623f..c9775ef74f2 100644 --- a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt +++ b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt @@ -337,7 +337,7 @@ class FirCheckersRunnerTransformer(private val diagnosticCollector: AbstractDiag } override fun transformFile(file: FirFile, data: Nothing?): FirFile { - val reporter = DiagnosticReporterFactory.createReporter() + val reporter = DiagnosticReporterFactory.createPendingReporter() diagnosticCollector.collectDiagnostics(file, reporter) return file } diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/DiagnosticReporterFactory.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/DiagnosticReporterFactory.kt index 20dc034b2a8..050f1e6b2cb 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/DiagnosticReporterFactory.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/DiagnosticReporterFactory.kt @@ -6,15 +6,19 @@ package org.jetbrains.kotlin.diagnostics import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector -import org.jetbrains.kotlin.diagnostics.impl.DiagnosticsCollectorWithSuppress +import org.jetbrains.kotlin.diagnostics.impl.PendingDiagnosticsCollectorWithSuppress import org.jetbrains.kotlin.diagnostics.impl.SimpleDiagnosticsCollector +import org.jetbrains.kotlin.diagnostics.impl.SimpleDiagnosticsCollectorWithSuppress object DiagnosticReporterFactory { fun createReporter(disableSuppress: Boolean = false): BaseDiagnosticsCollector { return if (disableSuppress) { SimpleDiagnosticsCollector() } else { - DiagnosticsCollectorWithSuppress() + SimpleDiagnosticsCollectorWithSuppress() } } + + fun createPendingReporter(): PendingDiagnosticsCollectorWithSuppress = + PendingDiagnosticsCollectorWithSuppress() } \ No newline at end of file diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/PendingDiagnosticsCollectorWithSuppress.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/PendingDiagnosticsCollectorWithSuppress.kt new file mode 100644 index 00000000000..68953603f7b --- /dev/null +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/PendingDiagnosticsCollectorWithSuppress.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.diagnostics.impl + +import org.jetbrains.kotlin.AbstractKtSourceElement +import org.jetbrains.kotlin.diagnostics.DiagnosticContext +import org.jetbrains.kotlin.diagnostics.KtDiagnostic +import org.jetbrains.kotlin.diagnostics.Severity + +class PendingDiagnosticsCollectorWithSuppress : BaseDiagnosticsCollector() { + private val pendingDiagnosticsByFilePath: MutableMap> = mutableMapOf() + private val _diagnosticsByFilePath: MutableMap> = mutableMapOf() + override val diagnostics: List + get() = _diagnosticsByFilePath.flatMap { it.value } + override val diagnosticsByFilePath: Map> + get() = _diagnosticsByFilePath + + override var hasErrors = false + private set + + override fun report(diagnostic: KtDiagnostic?, context: DiagnosticContext) { + if (diagnostic != null && !context.isDiagnosticSuppressed(diagnostic)) { + pendingDiagnosticsByFilePath.getOrPut(context.containingFilePath) { mutableListOf() }.run { + add(diagnostic) + } + } + } + + fun checkAndCommitReportsOn( + element: AbstractKtSourceElement, + context: DiagnosticContext?, + commitEverything: Boolean + ) { + for ((path, pendingList) in pendingDiagnosticsByFilePath) { + val committedList = _diagnosticsByFilePath.getOrPut(path) { mutableListOf() } + val iterator = pendingList.iterator() + while (iterator.hasNext()) { + val diagnostic = iterator.next() + when { + context?.isDiagnosticSuppressed(diagnostic) == true -> { + if (diagnostic.element == element || + diagnostic.element.startOffset >= element.startOffset && diagnostic.element.endOffset <= element.endOffset + ) { + iterator.remove() + } + } + diagnostic.element == element || commitEverything -> { + iterator.remove() + committedList += diagnostic + if (!hasErrors && diagnostic.severity == Severity.ERROR) { + hasErrors = true + } + } + } + } + } + } +} diff --git a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/DiagnosticsCollectorWithSuppress.kt b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/SimpleDiagnosticsCollectorWithSuppress.kt similarity index 94% rename from compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/DiagnosticsCollectorWithSuppress.kt rename to compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/SimpleDiagnosticsCollectorWithSuppress.kt index f92fcd6018d..7e8b0b01734 100644 --- a/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/DiagnosticsCollectorWithSuppress.kt +++ b/compiler/frontend.common/src/org/jetbrains/kotlin/diagnostics/impl/SimpleDiagnosticsCollectorWithSuppress.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticContext import org.jetbrains.kotlin.diagnostics.KtDiagnostic import org.jetbrains.kotlin.diagnostics.Severity -class DiagnosticsCollectorWithSuppress : BaseDiagnosticsCollector() { +class SimpleDiagnosticsCollectorWithSuppress : BaseDiagnosticsCollector() { private val _diagnosticsByFilePath: MutableMap> = mutableMapOf() override val diagnostics: List get() = _diagnosticsByFilePath.flatMap { it.value } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt index 3ba413afe6c..081158f5298 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt @@ -188,7 +188,7 @@ class IncrementalFirJvmCompilerRunner( else allPlatformSourceFiles.add(file) } - val diagnosticsReporter = DiagnosticReporterFactory.createReporter() + val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() val performanceManager = configuration[CLIConfigurationKeys.PERF_MANAGER] val compilerEnvironment = ModuleCompilerEnvironment(projectEnvironment, diagnosticsReporter) diff --git a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/functionWithNonTailRecursions.kt b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/functionWithNonTailRecursions.kt index 28494340c1b..dcc9f5fd489 100644 --- a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/functionWithNonTailRecursions.kt +++ b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/functionWithNonTailRecursions.kt @@ -3,7 +3,6 @@ // IGNORE_BACKEND: JS_IR_ES6 // TODO: muted automatically, investigate should it be ran for JS or not // IGNORE_BACKEND: JS -// IGNORE_FIR_DIAGNOSTICS_DIFF tailrec fun badTails(x : Int) : Int { if (x < 50 && x != 10 && x > 0) { diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt index d867d81c62f..fdda0142292 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt @@ -270,7 +270,7 @@ abstract class AbstractKtDiagnosticsTest : AbstractFirBaseDiagnosticsTest() { for (firFile in firFiles) { val session = firFile.moduleData.session val collector = collectors.computeIfAbsent(session) { createCollector(session) } - val reporter = DiagnosticReporterFactory.createReporter() + val reporter = DiagnosticReporterFactory.createPendingReporter() collector.collectDiagnostics(firFile, reporter) result[firFile] = reporter.diagnostics } diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt index bacadd7af85..77bd93d7b60 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt @@ -93,7 +93,7 @@ class FirAnalyzerFacade( val collector = FirDiagnosticsCollector.create(session, scopeSession) collectedDiagnostics = buildMap { for (file in firFiles!!) { - val reporter = DiagnosticReporterFactory.createReporter() + val reporter = DiagnosticReporterFactory.createPendingReporter() collector.collectDiagnostics(file, reporter) put(file, reporter.diagnostics) }