From ebced14db2ef71e3460d03d0cd741716cd884fc9 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Mon, 1 Feb 2021 18:34:03 +0300 Subject: [PATCH] [FIR] Implement suppressing diagnostics with @Suppress --- ...TouchedTilContractsPhaseTestGenerated.java | 33 +++++ .../resolve/suppress/allWarnings.fir.txt | 10 ++ .../testData/resolve/suppress/allWarnings.kt | 6 + .../resolve/suppress/multipleWarnings.fir.txt | 10 ++ .../resolve/suppress/multipleWarnings.kt | 7 ++ .../resolve/suppress/singleError.fir.txt | 6 + .../testData/resolve/suppress/singleError.kt | 6 + .../resolve/suppress/singleWarning.fir.txt | 3 + .../resolve/suppress/singleWarning.kt | 4 + .../runners/FirDiagnosticTestGenerated.java | 34 +++++ ...DiagnosticsWithLightTreeTestGenerated.java | 35 ++++++ .../checkers/context/CheckerContext.kt | 54 +++++++- .../collectors/AbstractDiagnosticCollector.kt | 119 ++++++++++++++---- .../collectors/SimpleDiagnosticsCollector.kt | 18 ++- .../diagnostics/DiagnosticReporter.kt | 8 -- .../impl/BaseDiagnosticReporter.kt | 13 ++ .../impl/DiagnosticReporterWithSuppress.kt | 30 +++++ .../impl/SimpleDiagnosticReporter.kt | 20 +++ .../kotlin/fir/symbols/StandardClassIds.kt | 2 + .../private/privateClassExtensionLambda.kt | 1 - 20 files changed, 376 insertions(+), 43 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/suppress/singleError.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/suppress/singleError.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.kt create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/BaseDiagnosticReporter.kt create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/DiagnosticReporterWithSuppress.kt create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/SimpleDiagnosticReporter.kt diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index bc3dcee379d..e1a9a0eccf1 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -3103,6 +3103,39 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract } } + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/suppress") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Suppress extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInSuppress() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/suppress"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("allWarnings.kt") + public void testAllWarnings() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.kt"); + } + + @TestMetadata("multipleWarnings.kt") + public void testMultipleWarnings() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.kt"); + } + + @TestMetadata("singleError.kt") + public void testSingleError() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/singleError.kt"); + } + + @TestMetadata("singleWarning.kt") + public void testSingleWarning() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.kt"); + } + } + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/types") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.fir.txt b/compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.fir.txt new file mode 100644 index 00000000000..6c20e88a786 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.fir.txt @@ -0,0 +1,10 @@ +FILE: allWarnings.kt + @R|kotlin/Suppress|(vararg(String(warnings))) public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + public final fun foo(): R|kotlin/Unit| { + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.kt b/compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.kt new file mode 100644 index 00000000000..b3390930d71 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.kt @@ -0,0 +1,6 @@ +// WITH_EXTENDED_CHECKERS + +@Suppress("warnings") +public class A { + final fun foo() {} +} diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.fir.txt b/compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.fir.txt new file mode 100644 index 00000000000..b34ddd212ea --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.fir.txt @@ -0,0 +1,10 @@ +FILE: multipleWarnings.kt + @R|kotlin/Suppress|(vararg(String(REDUNDANT_VISIBILITY_MODIFIER))) public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + @R|kotlin/Suppress|(vararg(String(REDUNDANT_MODALITY_MODIFIER))) public final fun foo(): R|kotlin/Unit| { + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.kt b/compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.kt new file mode 100644 index 00000000000..ecc7612bc2b --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.kt @@ -0,0 +1,7 @@ +// WITH_EXTENDED_CHECKERS + +@Suppress("REDUNDANT_VISIBILITY_MODIFIER") +public class A { + @Suppress("REDUNDANT_MODALITY_MODIFIER") + public final fun foo() {} +} diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/singleError.fir.txt b/compiler/fir/analysis-tests/testData/resolve/suppress/singleError.fir.txt new file mode 100644 index 00000000000..1baaf30ee06 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/singleError.fir.txt @@ -0,0 +1,6 @@ +FILE: singleError.kt + public final fun foo(x: R|kotlin/String|): R|kotlin/Unit| { + } + @R|kotlin/Suppress|(vararg(String(INAPPLICABLE_CANDIDATE))) public final fun bar(): R|kotlin/Unit| { + #(Int(10)) + } diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/singleError.kt b/compiler/fir/analysis-tests/testData/resolve/suppress/singleError.kt new file mode 100644 index 00000000000..d80a4283953 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/singleError.kt @@ -0,0 +1,6 @@ +fun foo(x: String) {} + +@Suppress("INAPPLICABLE_CANDIDATE") +fun bar() { + foo(10) +} diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.fir.txt b/compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.fir.txt new file mode 100644 index 00000000000..60a8e07837b --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.fir.txt @@ -0,0 +1,3 @@ +FILE: singleWarning.kt + @R|kotlin/Suppress|(vararg(String(REDUNDANT_VISIBILITY_MODIFIER))) public final fun foo(): R|kotlin/Unit| { + } diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.kt b/compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.kt new file mode 100644 index 00000000000..259808b63ca --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.kt @@ -0,0 +1,4 @@ +// WITH_EXTENDED_CHECKERS + +@Suppress("REDUNDANT_VISIBILITY_MODIFIER") +public fun foo() {} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 0961d597acc..66fd5afefef 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -3474,6 +3474,40 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { } } + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/suppress") + @TestDataPath("$PROJECT_ROOT") + public class Suppress extends AbstractFirDiagnosticTest { + @Test + public void testAllFilesPresentInSuppress() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/suppress"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("allWarnings.kt") + public void testAllWarnings() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.kt"); + } + + @Test + @TestMetadata("multipleWarnings.kt") + public void testMultipleWarnings() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.kt"); + } + + @Test + @TestMetadata("singleError.kt") + public void testSingleError() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/singleError.kt"); + } + + @Test + @TestMetadata("singleWarning.kt") + public void testSingleWarning() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.kt"); + } + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolve/types") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index b6c7ad201aa..2940ede7b8f 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -3520,6 +3520,41 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos } } + @Nested + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/suppress") + @TestDataPath("$PROJECT_ROOT") + @Execution(ExecutionMode.SAME_THREAD) + public class Suppress extends AbstractFirDiagnosticsWithLightTreeTest { + @Test + public void testAllFilesPresentInSuppress() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/suppress"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("allWarnings.kt") + public void testAllWarnings() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/allWarnings.kt"); + } + + @Test + @TestMetadata("multipleWarnings.kt") + public void testMultipleWarnings() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/multipleWarnings.kt"); + } + + @Test + @TestMetadata("singleError.kt") + public void testSingleError() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/singleError.kt"); + } + + @Test + @TestMetadata("singleWarning.kt") + public void testSingleWarning() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/suppress/singleWarning.kt"); + } + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolve/types") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt index 4f67ab4df9b..50f8ae30f35 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/context/CheckerContext.kt @@ -6,13 +6,16 @@ package org.jetbrains.kotlin.fir.analysis.checkers.context import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.PersistentSet import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.persistentSetOf import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue +import org.jetbrains.kotlin.fir.resolve.calls.InapplicableArgumentDiagnostic import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.name.Name @@ -21,6 +24,10 @@ abstract class CheckerContext { abstract val containingDeclarations: List abstract val sessionHolder: SessionHolder abstract val returnTypeCalculator: ReturnTypeCalculator + abstract val suppressedDiagnostics: Set + abstract val allInfosSuppressed: Boolean + abstract val allWarningsSuppressed: Boolean + abstract val allErrorsSuppressed: Boolean val session: FirSession get() = sessionHolder.session @@ -38,17 +45,25 @@ abstract class CheckerContext { } } -class PersistentCheckerContext( - override val implicitReceiverStack: PersistentImplicitReceiverStack = PersistentImplicitReceiverStack(), - override val containingDeclarations: PersistentList = persistentListOf(), +class PersistentCheckerContext private constructor( + override val implicitReceiverStack: PersistentImplicitReceiverStack, + override val containingDeclarations: PersistentList, override val sessionHolder: SessionHolder, override val returnTypeCalculator: ReturnTypeCalculator, + override val suppressedDiagnostics: PersistentSet, + override val allInfosSuppressed: Boolean, + override val allWarningsSuppressed: Boolean, + override val allErrorsSuppressed: Boolean ) : CheckerContext() { constructor(sessionHolder: SessionHolder, returnTypeCalculator: ReturnTypeCalculator) : this( PersistentImplicitReceiverStack(), persistentListOf(), sessionHolder, - returnTypeCalculator + returnTypeCalculator, + persistentSetOf(), + allInfosSuppressed = false, + allWarningsSuppressed = false, + allErrorsSuppressed = false ) fun addImplicitReceiver(name: Name?, value: ImplicitReceiverValue<*>): PersistentCheckerContext { @@ -56,7 +71,11 @@ class PersistentCheckerContext( implicitReceiverStack.add(name, value), containingDeclarations, sessionHolder, - returnTypeCalculator + returnTypeCalculator, + suppressedDiagnostics, + allInfosSuppressed, + allWarningsSuppressed, + allErrorsSuppressed ) } @@ -65,7 +84,30 @@ class PersistentCheckerContext( implicitReceiverStack, containingDeclarations.add(declaration), sessionHolder, - returnTypeCalculator + returnTypeCalculator, + suppressedDiagnostics, + allInfosSuppressed, + allWarningsSuppressed, + allErrorsSuppressed + ) + } + + fun addSuppressedDiagnostics( + diagnosticNames: Collection, + allInfosSuppressed: Boolean, + allWarningsSuppressed: Boolean, + allErrorsSuppressed: Boolean + ): PersistentCheckerContext { + if (diagnosticNames.isEmpty()) return this + return PersistentCheckerContext( + implicitReceiverStack, + containingDeclarations, + sessionHolder, + returnTypeCalculator, + suppressedDiagnostics.addAll(diagnosticNames), + this.allInfosSuppressed || allInfosSuppressed, + this.allWarningsSuppressed || allWarningsSuppressed, + this.allErrorsSuppressed || allErrorsSuppressed ) } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt index 79cbafe8f2d..8591c9865dd 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/AbstractDiagnosticCollector.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.collectors +import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirSession @@ -21,11 +22,9 @@ import org.jetbrains.kotlin.fir.resolve.collectImplicitReceivers import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef -import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.symbols.StandardClassIds +import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef -import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.name.Name @@ -34,6 +33,12 @@ abstract class AbstractDiagnosticCollector( override val scopeSession: ScopeSession = ScopeSession(), returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve() ) : SessionHolder { + companion object { + private const val SUPPRESS_ALL_INFOS = "infos" + private const val SUPPRESS_ALL_WARNINGS = "warnings" + private const val SUPPRESS_ALL_ERRORS = "errors" + } + fun collectDiagnostics(firFile: FirFile): List> { if (!componentsInitialized) { throw IllegalStateException("Components are not initialized") @@ -74,13 +79,26 @@ abstract class AbstractDiagnosticCollector( } override fun visitElement(element: FirElement, data: Nothing?) { + if (element is FirAnnotationContainer) { + visitAnnotationContainer(element, data) + return + } element.runComponents() element.acceptChildren(this, null) } + override fun visitAnnotationContainer(annotationContainer: FirAnnotationContainer, data: Nothing?) { + withSuppressedDiagnostics(annotationContainer) { + annotationContainer.runComponents() + annotationContainer.acceptChildren(this, null) + } + } + private fun visitJump(loopJump: FirLoopJump) { - loopJump.runComponents() - loopJump.target.labeledElement.takeIf { it is FirErrorLoop }?.accept(this, null) + withSuppressedDiagnostics(loopJump) { + loopJump.runComponents() + loopJump.target.labeledElement.takeIf { it is FirErrorLoop }?.accept(this, null) + } } override fun visitBreakExpression(breakExpression: FirBreakExpression, data: Nothing?) { @@ -96,55 +114,74 @@ abstract class AbstractDiagnosticCollector( this.type = type } visitWithDeclarationAndReceiver(klass, (klass as? FirRegularClass)?.name, typeRef) - } override fun visitRegularClass(regularClass: FirRegularClass, data: Nothing?) { - visitClassAndChildren(regularClass, regularClass.defaultType()) + withSuppressedDiagnostics(regularClass) { + visitClassAndChildren(regularClass, regularClass.defaultType()) + } } override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Nothing?) { - visitClassAndChildren(anonymousObject, anonymousObject.defaultType()) + withSuppressedDiagnostics(anonymousObject) { + visitClassAndChildren(anonymousObject, anonymousObject.defaultType()) + } } override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Nothing?) { - visitWithDeclarationAndReceiver(simpleFunction, simpleFunction.name, simpleFunction.receiverTypeRef) + withSuppressedDiagnostics(simpleFunction) { + visitWithDeclarationAndReceiver(simpleFunction, simpleFunction.name, simpleFunction.receiverTypeRef) + } } override fun visitConstructor(constructor: FirConstructor, data: Nothing?) { - visitWithDeclaration(constructor) + withSuppressedDiagnostics(constructor) { + visitWithDeclaration(constructor) + } } override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: Nothing?) { - val labelName = anonymousFunction.label?.name?.let { Name.identifier(it) } - visitWithDeclarationAndReceiver( - anonymousFunction, - labelName, - anonymousFunction.receiverTypeRef - ) + withSuppressedDiagnostics(anonymousFunction) { + val labelName = anonymousFunction.label?.name?.let { Name.identifier(it) } + visitWithDeclarationAndReceiver( + anonymousFunction, + labelName, + anonymousFunction.receiverTypeRef + ) + } } override fun visitProperty(property: FirProperty, data: Nothing?) { - visitWithDeclaration(property) + withSuppressedDiagnostics(property) { + visitWithDeclaration(property) + } } override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Nothing?) { if (propertyAccessor !is FirDefaultPropertyAccessor) { val property = context.containingDeclarations.last() as FirProperty - visitWithDeclarationAndReceiver(propertyAccessor, property.name, property.receiverTypeRef) + withSuppressedDiagnostics(propertyAccessor) { + visitWithDeclarationAndReceiver(propertyAccessor, property.name, property.receiverTypeRef) + } } } override fun visitValueParameter(valueParameter: FirValueParameter, data: Nothing?) { - visitWithDeclaration(valueParameter) + withSuppressedDiagnostics(valueParameter) { + visitWithDeclaration(valueParameter) + } } override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Nothing?) { - visitWithDeclaration(enumEntry) + withSuppressedDiagnostics(enumEntry) { + visitWithDeclaration(enumEntry) + } } override fun visitFile(file: FirFile, data: Nothing?) { - visitWithDeclaration(file) + withSuppressedDiagnostics(file) { + visitWithDeclaration(file) + } } override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: Nothing?) { @@ -152,12 +189,17 @@ abstract class AbstractDiagnosticCollector( } override fun visitBlock(block: FirBlock, data: Nothing?) { - visitExpression(block, data) + withSuppressedDiagnostics(block) { + visitExpression(block, data) + } } override fun visitTypeRef(typeRef: FirTypeRef, data: Nothing?) { if (typeRef.source != null && typeRef.source?.kind !is FirFakeSourceElementKind) { - super.visitTypeRef(typeRef, null) + withSuppressedDiagnostics(typeRef) { + typeRef.runComponents() + typeRef.acceptChildren(this, data) + } } } @@ -233,6 +275,35 @@ abstract class AbstractDiagnosticCollector( } } + private inline fun withSuppressedDiagnostics(annotationContainer: FirAnnotationContainer, block: () -> R): R { + val existingContext = context + addSuppressedDiagnosticsToContext(annotationContainer) + return try { + block() + } finally { + context = existingContext + } + } + + private fun addSuppressedDiagnosticsToContext(annotationContainer: FirAnnotationContainer) { + val annotations = annotationContainer.annotations.filter { + val type = it.annotationTypeRef.coneType as? ConeClassLikeType ?: return@filter false + type.lookupTag.classId == StandardClassIds.Suppress + } + if (annotations.isEmpty()) return + val arguments = annotations.flatMap { annotationCall -> + annotationCall.arguments.filterIsInstance().flatMap { varargArgument -> + varargArgument.arguments.mapNotNull { (it as? FirConstExpression<*>)?.value as? String? } + } + } + context = context.addSuppressedDiagnostics( + arguments, + allInfosSuppressed = SUPPRESS_ALL_INFOS in arguments, + allWarningsSuppressed = SUPPRESS_ALL_WARNINGS in arguments, + allErrorsSuppressed = SUPPRESS_ALL_ERRORS in arguments + ) + } + private inline fun withDiagnosticsAction(action: DiagnosticCollectorDeclarationAction, block: () -> R): R { val oldAction = currentAction currentAction = action diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/SimpleDiagnosticsCollector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/SimpleDiagnosticsCollector.kt index 0f5e62de345..d71e63942ba 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/SimpleDiagnosticsCollector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/SimpleDiagnosticsCollector.kt @@ -7,14 +7,24 @@ package org.jetbrains.kotlin.fir.analysis.collectors import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic -import org.jetbrains.kotlin.fir.analysis.diagnostics.SimpleDiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.BaseDiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.DiagnosticReporterWithSuppress +import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.SimpleDiagnosticReporter -class SimpleDiagnosticsCollector(session: FirSession) : AbstractDiagnosticCollector(session) { - override var reporter = SimpleDiagnosticReporter() +class SimpleDiagnosticsCollector(session: FirSession, private val disableSuppress: Boolean = false) : AbstractDiagnosticCollector(session) { + override var reporter = createDiagnosticReporter() private set + private fun createDiagnosticReporter(): BaseDiagnosticReporter { + return if (disableSuppress) { + SimpleDiagnosticReporter() + } else { + DiagnosticReporterWithSuppress() + } + } + override fun initializeCollector() { - reporter = SimpleDiagnosticReporter() + reporter = createDiagnosticReporter() } override fun getCollectedDiagnostics(): List> { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporter.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporter.kt index de84018cfd2..f52c0b4b5a0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporter.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/DiagnosticReporter.kt @@ -51,11 +51,3 @@ inline fun > = mutableListOf() - - override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) { - if (diagnostic == null) return - diagnostics += diagnostic - } -} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/BaseDiagnosticReporter.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/BaseDiagnosticReporter.kt new file mode 100644 index 00000000000..63ceeb2da50 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/BaseDiagnosticReporter.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.diagnostics.impl + +import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic + +abstract class BaseDiagnosticReporter : DiagnosticReporter() { + abstract val diagnostics: List> +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/DiagnosticReporterWithSuppress.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/DiagnosticReporterWithSuppress.kt new file mode 100644 index 00000000000..fde5767a9b2 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/DiagnosticReporterWithSuppress.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.diagnostics.impl + +import org.jetbrains.kotlin.diagnostics.Severity +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic + +class DiagnosticReporterWithSuppress : BaseDiagnosticReporter() { + private val _diagnostics: MutableList> = mutableListOf() + override val diagnostics: List> + get() = _diagnostics + + override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) { + if (diagnostic == null) return + val factory = diagnostic.factory + val name = factory.name + val suppressedByAll = when (factory.severity) { + Severity.INFO -> context.allInfosSuppressed + Severity.WARNING -> context.allWarningsSuppressed + Severity.ERROR -> context.allErrorsSuppressed + } + + if (suppressedByAll || name in context.suppressedDiagnostics) return + _diagnostics += diagnostic + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/SimpleDiagnosticReporter.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/SimpleDiagnosticReporter.kt new file mode 100644 index 00000000000..eb7af3a7aa6 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/impl/SimpleDiagnosticReporter.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.analysis.diagnostics.impl + +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic + +class SimpleDiagnosticReporter : BaseDiagnosticReporter() { + private val _diagnostics: MutableList> = mutableListOf() + override val diagnostics: List> + get() = _diagnostics + + override fun report(diagnostic: FirDiagnostic<*>?, context: CheckerContext) { + if (diagnostic == null) return + _diagnostics += diagnostic + } +} diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/StandardClassIds.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/StandardClassIds.kt index bc5d111157c..96e5e4c2d4e 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/StandardClassIds.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/symbols/StandardClassIds.kt @@ -83,6 +83,8 @@ object StandardClassIds { fun FunctionN(n: Int): ClassId { return "Function$n".baseId() } + + val Suppress = "Suppress".baseId() } private fun Map.inverseMap() = entries.associate { (k, v) -> v to k } diff --git a/compiler/testData/codegen/boxInline/private/privateClassExtensionLambda.kt b/compiler/testData/codegen/boxInline/private/privateClassExtensionLambda.kt index 10be051585b..03a5c694d58 100644 --- a/compiler/testData/codegen/boxInline/private/privateClassExtensionLambda.kt +++ b/compiler/testData/codegen/boxInline/private/privateClassExtensionLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_FIR_DIAGNOSTICS // FILE: 1.kt package test -- GitLab