From b7d8e879a65c1c621ad58254cc204857159d7e80 Mon Sep 17 00:00:00 2001 From: FenstonSingel Date: Fri, 27 Mar 2020 02:10:26 +0300 Subject: [PATCH] [FIR] Support 4 diagnostics for pairs of modifiers In particular, this commit includes: * Attempt to abstract access to FirSourceElement via FirModifier * Add more visit functions to DeclarationCheckersDiagnosticComponent * Add messages+factories for 4 modifier-related errors and warnings * Introduce FirModifierChecker --- .../diagnostics/incompatibleModifiers.kt | 31 +++ .../diagnostics/incompatibleModifiers.txt | 147 +++++++++++++ .../resolve/diagnostics/redundantModifier.kt | 2 + .../resolve/diagnostics/redundantModifier.txt | 13 ++ .../resolve/diagnostics/repeatedModifier.kt | 17 ++ .../resolve/diagnostics/repeatedModifier.txt | 54 +++++ .../fir/FirDiagnosticsTestGenerated.java | 15 ++ ...DiagnosticsWithLightTreeTestGenerated.java | 15 ++ .../declaration/DeclarationCheckers.kt | 4 +- .../declaration/FirModifierChecker.kt | 199 ++++++++++++++++++ .../DeclarationCheckersDiagnosticComponent.kt | 14 +- .../diagnostics/FirDefaultErrorMessages.kt | 10 + .../diagnostics/FirDiagnosticRenderers.kt | 2 + .../fir/analysis/diagnostics/FirErrors.kt | 6 + .../jetbrains/kotlin/fir/FirModifierList.kt | 28 ++- .../cannotOverrideInvisibleMember.fir.kt | 2 +- .../tests/dataClasses/dataInheritance.fir.kt | 2 +- .../tests/dataClasses/innerDataClass.fir.kt | 3 - .../tests/dataClasses/innerDataClass.kt | 1 + .../dataClasses/innerOuterDataClass.fir.kt | 2 +- .../tests/dataClasses/sealedDataClass.fir.kt | 4 - .../tests/dataClasses/sealedDataClass.kt | 1 + .../inlineClassDeclarationCheck.fir.kt | 2 +- .../tests/modifiers/IllegalModifiers.fir.kt | 70 +++--- .../modifiers/const/applicability.fir.kt | 6 +- .../incompatibleVarianceModifiers.fir.kt | 8 +- .../tests/modifiers/inlineParameters.fir.kt | 6 +- .../modifierOnParameterInFunctionType.fir.kt | 34 +-- .../tests/modifiers/openInInterface.fir.kt | 4 +- .../tests/modifiers/privateInInterface.fir.kt | 2 +- .../tests/modifiers/repeatedModifiers.fir.kt | 38 ++-- .../tests/multiplatform/incompatibles.fir.kt | 12 +- ...kt4204-completeNestedCallsForInvoke.fir.kt | 6 +- .../scopes/VisibilityInheritModifier.fir.kt | 2 +- .../diagnostics/tests/scopes/kt151.fir.kt | 2 +- .../tests/sealed/NeverFinal.fir.kt | 3 - .../diagnostics/tests/sealed/NeverFinal.kt | 1 + .../diagnostics/tests/sealed/NeverOpen.fir.kt | 3 - .../diagnostics/tests/sealed/NeverOpen.kt | 1 + .../tests/sealed/RedundantAbstract.fir.kt | 3 - .../tests/sealed/RedundantAbstract.kt | 1 + .../noDataClassInheritance.fir.kt | 2 +- 42 files changed, 656 insertions(+), 122 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.txt create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt delete mode 100644 compiler/testData/diagnostics/tests/dataClasses/innerDataClass.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/dataClasses/sealedDataClass.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/NeverFinal.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/NeverOpen.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/sealed/RedundantAbstract.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt new file mode 100644 index 00000000000..f450767bb03 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt @@ -0,0 +1,31 @@ +class A<in out T> { } + +private public class B +protected internal class C + +final abstract class D +final open class E +final sealed class F +open sealed class G + +inline fun foo( + crossinline noinline first: () -> Unit, + second: () -> Unit +) { } + +open abstract data class H(val i: Int) +sealed data class I(val i: Int) +inline data class J(val i: Int) + +abstract class K { + private open val i1: Int = 0 + private abstract val i2: Int +} + +private open class L : K() +private abstract class M : K() + +class X { + inner data class Y(val i: Int) + sealed inner class Z +} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.txt new file mode 100644 index 00000000000..1b5b65f4a30 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.txt @@ -0,0 +1,147 @@ +FILE: incompatibleModifiers.kt + public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + } + private final class B : R|kotlin/Any| { + public[private] constructor(): R|B| { + super() + } + + } + protected final class C : R|kotlin/Any| { + public[protected] constructor(): R|C| { + super() + } + + } + public final class D : R|kotlin/Any| { + public constructor(): R|D| { + super() + } + + } + public final class E : R|kotlin/Any| { + public constructor(): R|E| { + super() + } + + } + public final class F : R|kotlin/Any| { + private constructor(): R|F| { + super() + } + + } + public sealed class G : R|kotlin/Any| { + private constructor(): R|G| { + super() + } + + } + public final inline fun foo(crossinline noinline first: R|() -> kotlin/Unit|, second: R|() -> kotlin/Unit|): R|kotlin/Unit| { + } + public abstract data class H : R|kotlin/Any| { + public constructor(i: R|kotlin/Int|): R|H| { + super() + } + + public final val i: R|kotlin/Int| = R|/i| + public get(): R|kotlin/Int| + + public final fun component1(): R|kotlin/Int| { + ^component1 this@R|/H|.R|/H.i| + } + + public final fun copy(i: R|kotlin/Int| = this@R|/H|.R|/H.i|): R|H| { + } + + } + public sealed data class I : R|kotlin/Any| { + private constructor(i: R|kotlin/Int|): R|I| { + super() + } + + public final val i: R|kotlin/Int| = R|/i| + public get(): R|kotlin/Int| + + public final fun component1(): R|kotlin/Int| { + ^component1 this@R|/I|.R|/I.i| + } + + public final fun copy(i: R|kotlin/Int| = this@R|/I|.R|/I.i|): R|I| { + } + + } + public final data inline class J : R|kotlin/Any| { + public constructor(i: R|kotlin/Int|): R|J| { + super() + } + + public final val i: R|kotlin/Int| = R|/i| + public get(): R|kotlin/Int| + + public final fun component1(): R|kotlin/Int| { + ^component1 this@R|/J|.R|/J.i| + } + + public final fun copy(i: R|kotlin/Int| = this@R|/J|.R|/J.i|): R|J| { + } + + } + public abstract class K : R|kotlin/Any| { + public constructor(): R|K| { + super() + } + + private open val i1: R|kotlin/Int| = Int(0) + private get(): R|kotlin/Int| + + private abstract val i2: R|kotlin/Int| + private get(): R|kotlin/Int| + + } + private open class L : R|K| { + public[private] constructor(): R|L| { + super() + } + + } + private abstract class M : R|K| { + public[private] constructor(): R|M| { + super() + } + + } + public final class X : R|kotlin/Any| { + public constructor(): R|X| { + super() + } + + public final inner data class Y : R|kotlin/Any| { + public constructor(i: R|kotlin/Int|): R|X.Y| { + super() + } + + public final val i: R|kotlin/Int| = R|/i| + public get(): R|kotlin/Int| + + public final fun component1(): R|kotlin/Int| { + ^component1 this@R|/X.Y|.R|/X.Y.i| + } + + public final fun copy(i: R|kotlin/Int| = this@R|/X.Y|.R|/X.Y.i|): R|X.Y| { + } + + } + + public sealed inner class Z : R|kotlin/Any| { + private constructor(): R|X.Z| { + super() + } + + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.kt new file mode 100644 index 00000000000..184d9b91e71 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.kt @@ -0,0 +1,2 @@ +open abstract class A +abstract sealed class B \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.txt new file mode 100644 index 00000000000..d2716c234c6 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.txt @@ -0,0 +1,13 @@ +FILE: redundantModifier.kt + public abstract class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + } + public sealed class B : R|kotlin/Any| { + private constructor(): R|B| { + super() + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.kt new file mode 100644 index 00000000000..6095c967cc3 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.kt @@ -0,0 +1,17 @@ +open open class A + +internal internal object B + +enum enum class C { + VALUE1, VALUE2; + + protected protected companion object { + private private val D = 5 + } + + inline inline fun foo(f: (Int) -> Int) = f(8) +} + +open class E(private private val int: Int = 5) { + protected protected var double = int + 8.0 +} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.txt new file mode 100644 index 00000000000..8e246a8b308 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.txt @@ -0,0 +1,54 @@ +FILE: repeatedModifier.kt + public open class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + } + internal final object B : R|kotlin/Any| { + private constructor(): R|B| { + super() + } + + } + public final enum class C : R|kotlin/Enum| { + private constructor(): R|C| { + super|>() + } + + public final static enum entry VALUE1: R|C| + public final static enum entry VALUE2: R|C| + protected final companion object Companion : R|kotlin/Any| { + private constructor(): R|C.Companion| { + super() + } + + private final val D: R|kotlin/Int| = Int(5) + private get(): R|kotlin/Int| + + } + + public final inline fun foo(f: R|(kotlin/Int) -> kotlin/Int|): R|kotlin/Int| { + ^foo R|/f|.R|FakeOverride|(Int(8)) + } + + public final static fun values(): R|kotlin/Array| { + } + + public final static fun valueOf(value: R|kotlin/String|): R|C| { + } + + } + public open class E : R|kotlin/Any| { + public constructor(int: R|kotlin/Int| = Int(5)): R|E| { + super() + } + + private final val int: R|kotlin/Int| = R|/int| + private get(): R|kotlin/Int| + + protected final var double: R|kotlin/Double| = R|/int|.R|kotlin/Int.plus|(Double(8.0)) + protected get(): R|kotlin/Double| + protected set(value: R|kotlin/Double|): R|kotlin/Unit| + + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index b29f2841409..7732cdd80c7 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -740,11 +740,26 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @TestMetadata("incompatibleModifiers.kt") + public void testIncompatibleModifiers() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt"); + } + @TestMetadata("infixFunctions.kt") public void testInfixFunctions() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt"); } + @TestMetadata("redundantModifier.kt") + public void testRedundantModifier() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.kt"); + } + + @TestMetadata("repeatedModifier.kt") + public void testRepeatedModifier() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.kt"); + } + @TestMetadata("superIsNotAnExpression.kt") public void testSuperIsNotAnExpression() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 943218b55a5..49c5aa6c09c 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -740,11 +740,26 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @TestMetadata("incompatibleModifiers.kt") + public void testIncompatibleModifiers() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/incompatibleModifiers.kt"); + } + @TestMetadata("infixFunctions.kt") public void testInfixFunctions() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt"); } + @TestMetadata("redundantModifier.kt") + public void testRedundantModifier() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.kt"); + } + + @TestMetadata("repeatedModifier.kt") + public void testRepeatedModifier() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/repeatedModifier.kt"); + } + @TestMetadata("superIsNotAnExpression.kt") public void testSuperIsNotAnExpression() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt"); diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt index 404b5770704..a778cd983e6 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/DeclarationCheckers.kt @@ -9,7 +9,9 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration object DeclarationCheckers { - val DECLARATIONS: List> = listOf() + val DECLARATIONS: List> = listOf( + FirModifierChecker + ) val MEMBER_DECLARATIONS: List> = DECLARATIONS + listOf( FirInfixFunctionDeclarationChecker ) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt new file mode 100644 index 00000000000..0c278237b24 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirModifierChecker.kt @@ -0,0 +1,199 @@ +/* + * 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.declaration + +import org.jetbrains.kotlin.KtNodeTypes +import org.jetbrains.kotlin.fir.* +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.impl.FirDefaultPropertyAccessor +import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.lexer.KtTokens.* + +object FirModifierChecker : FirDeclarationChecker() { + + private enum class CompatibilityType { + COMPATIBLE, + COMPATIBLE_FOR_CLASSES, // for functions and properties: error + REDUNDANT_1_TO_2, // first is redundant to second: warning + REDUNDANT_2_TO_1, // second is redundant to first: warning + DEPRECATED, // pair is deprecated and will soon become incompatible: warning + REPEATED, // first and second are the same: error + INCOMPATIBLE, // pair is incompatible: error + } + + // first modifier in pair should also be first in spelling order and declaration's modifier list + private val compatibilityTypeMap = hashMapOf, CompatibilityType>() + + private fun recordCompatibilityType(compatibilityType: CompatibilityType, vararg list: KtModifierKeywordToken) { + for (firstKeyword in list) { + for (secondKeyword in list) { + if (firstKeyword != secondKeyword) { + compatibilityTypeMap[Pair(firstKeyword, secondKeyword)] = compatibilityType + } + } + } + } + + private fun recordPairsCompatibleForClasses(vararg list: KtModifierKeywordToken) { + recordCompatibilityType(CompatibilityType.COMPATIBLE_FOR_CLASSES, *list) + } + + private fun recordDeprecatedPairs(vararg list: KtModifierKeywordToken) { + recordCompatibilityType(CompatibilityType.DEPRECATED, *list) + } + + private fun recordIncompatiblePairs(vararg list: KtModifierKeywordToken) { + recordCompatibilityType(CompatibilityType.INCOMPATIBLE, *list) + } + + // note that order matters: the first argument is redundant to the second, not the other way around + private fun recordRedundantPairs(redundantKeyword: KtModifierKeywordToken, sufficientKeyword: KtModifierKeywordToken) { + compatibilityTypeMap[Pair(redundantKeyword, sufficientKeyword)] = CompatibilityType.REDUNDANT_1_TO_2 + compatibilityTypeMap[Pair(sufficientKeyword, redundantKeyword)] = CompatibilityType.REDUNDANT_2_TO_1 + } + + // building the compatibility type mapping + init { + recordIncompatiblePairs(IN_KEYWORD, OUT_KEYWORD) // Variance + recordIncompatiblePairs(PRIVATE_KEYWORD, PROTECTED_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD) // Visibilities + recordIncompatiblePairs(HEADER_KEYWORD, EXPECT_KEYWORD, IMPL_KEYWORD, ACTUAL_KEYWORD) + recordIncompatiblePairs(FINAL_KEYWORD, ABSTRACT_KEYWORD) + recordIncompatiblePairs(FINAL_KEYWORD, OPEN_KEYWORD, SEALED_KEYWORD) + recordIncompatiblePairs(CROSSINLINE_KEYWORD, NOINLINE_KEYWORD) + + recordIncompatiblePairs(DATA_KEYWORD, OPEN_KEYWORD) + recordIncompatiblePairs(DATA_KEYWORD, INNER_KEYWORD) + recordIncompatiblePairs(DATA_KEYWORD, ABSTRACT_KEYWORD) + recordIncompatiblePairs(DATA_KEYWORD, SEALED_KEYWORD) + recordIncompatiblePairs(DATA_KEYWORD, INLINE_KEYWORD) + + recordIncompatiblePairs(CONST_KEYWORD, ABSTRACT_KEYWORD) + recordIncompatiblePairs(CONST_KEYWORD, OPEN_KEYWORD) + recordIncompatiblePairs(CONST_KEYWORD, OVERRIDE_KEYWORD) + + recordIncompatiblePairs(PRIVATE_KEYWORD, OVERRIDE_KEYWORD) + recordPairsCompatibleForClasses(PRIVATE_KEYWORD, OPEN_KEYWORD) + recordPairsCompatibleForClasses(PRIVATE_KEYWORD, ABSTRACT_KEYWORD) + + // 1. subclasses contained inside a sealed class can not be instantiated, because their constructors needs + // an instance of an outer sealed (effectively abstract) class + // 2. subclasses of a non-top-level sealed class must be declared inside the class + // (see the KEEP https://github.com/Kotlin/KEEP/blob/master/proposals/sealed-class-inheritance.md) + recordIncompatiblePairs(SEALED_KEYWORD, INNER_KEYWORD) + + recordRedundantPairs(OPEN_KEYWORD, ABSTRACT_KEYWORD) + recordRedundantPairs(ABSTRACT_KEYWORD, SEALED_KEYWORD) + } + + private fun deduceCompatibilityType(firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken): CompatibilityType = + if (firstKeyword == secondKeyword) { + CompatibilityType.REPEATED + } else { + compatibilityTypeMap[Pair(firstKeyword, secondKeyword)] ?: CompatibilityType.COMPATIBLE + } + + private fun checkCompatibilityType( + firstModifier: FirModifier<*>, + secondModifier: FirModifier<*>, + reporter: DiagnosticReporter, + reportedNodes: MutableSet>, + owner: FirDeclaration? + ) { + val firstToken = firstModifier.token + val secondToken = secondModifier.token + when (val compatibilityType = deduceCompatibilityType(firstToken, secondToken)) { + CompatibilityType.COMPATIBLE -> {} + CompatibilityType.REPEATED -> + if (reportedNodes.add(secondModifier)) reporter.reportRepeatedModifier(secondModifier, secondToken) + CompatibilityType.REDUNDANT_2_TO_1 -> + reporter.reportRedundantModifier(secondModifier, secondToken, firstToken) + CompatibilityType.REDUNDANT_1_TO_2 -> + reporter.reportRedundantModifier(firstModifier, firstToken, secondToken) + CompatibilityType.DEPRECATED -> { + reporter.reportDeprecatedModifierPair(firstModifier, firstToken, secondToken) + reporter.reportDeprecatedModifierPair(secondModifier, secondToken, firstToken) + } + 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) + } + } + } + + private fun checkModifiers( + list: FirModifierList, + owner: FirDeclaration, + reporter: DiagnosticReporter + ) { + // 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 + val reportedNodes = hashSetOf>() + + val modifiers = list.modifiers + for (secondModifier in modifiers) { + for (firstModifier in modifiers) { + if (firstModifier == secondModifier) { + break + } + checkCompatibilityType(firstModifier, secondModifier, reporter, reportedNodes, owner) + } + } + } + + private fun isDeclarationMappedToSourceCorrectly(declaration: FirDeclaration, source: FirSourceElement): Boolean = + when (source.elementType) { + KtNodeTypes.CLASS -> declaration is FirClass<*> + KtNodeTypes.OBJECT_DECLARATION -> declaration is FirClass<*> + KtNodeTypes.PROPERTY -> declaration is FirProperty + KtNodeTypes.VALUE_PARAMETER -> declaration is FirValueParameter + // TODO more FIR-PSI relations possibly have to be added + else -> true + } + + override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { + val source = declaration.source ?: return + if (!isDeclarationMappedToSourceCorrectly(declaration, source)) return + if (context.containingDeclarations.last() is FirDefaultPropertyAccessor) return + + val modifierList = source.getModifierList() + modifierList?.let { checkModifiers(it, declaration, reporter) } + } + + private fun DiagnosticReporter.reportRepeatedModifier( + modifier: FirModifier<*>, keyword: KtModifierKeywordToken + ) { + val source = modifier.source + source?.let { report(FirErrors.REPEATED_MODIFIER.on(it, keyword)) } + } + + private fun DiagnosticReporter.reportRedundantModifier( + modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken + ) { + val source = modifier.source + source?.let { report(FirErrors.REDUNDANT_MODIFIER.on(it, firstKeyword, secondKeyword)) } + } + + private fun DiagnosticReporter.reportDeprecatedModifierPair( + modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken + ) { + val source = modifier.source + source?.let { report(FirErrors.DEPRECATED_MODIFIER_PAIR.on(it, firstKeyword, secondKeyword)) } + } + + private fun DiagnosticReporter.reportIncompatibleModifiers( + modifier: FirModifier<*>, firstKeyword: KtModifierKeywordToken, secondKeyword: KtModifierKeywordToken + ) { + val source = modifier.source + source?.let { report(FirErrors.INCOMPATIBLE_MODIFIERS.on(it, firstKeyword, secondKeyword)) } + } + +} \ No newline at end of file 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 3e2032ecd84..bbdc0bedcb1 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 @@ -21,6 +21,10 @@ class DeclarationCheckersDiagnosticComponent(collector: AbstractDiagnosticCollec runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(regularClass, data, it) } } + override fun visitSealedClass(sealedClass: FirSealedClass, data: CheckerContext) { + runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(sealedClass, data, it) } + } + override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: CheckerContext) { runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(simpleFunction, data, it) } } @@ -45,11 +49,19 @@ class DeclarationCheckersDiagnosticComponent(collector: AbstractDiagnosticCollec runCheck { DeclarationCheckers.DECLARATIONS.check(valueParameter, data, it) } } + override fun visitTypeParameter(typeParameter: FirTypeParameter, data: CheckerContext) { + runCheck { DeclarationCheckers.DECLARATIONS.check(typeParameter, data, it) } + } + override fun visitEnumEntry(enumEntry: FirEnumEntry, data: CheckerContext) { runCheck { DeclarationCheckers.DECLARATIONS.check(enumEntry, data, it) } } - private fun List>.check(declaration: D, context: CheckerContext, reporter: DiagnosticReporter) { + private fun List>.check( + declaration: D, + context: CheckerContext, + reporter: DiagnosticReporter + ) { for (checker in this) { checker.check(declaration, context, reporter) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 9e4081e3511..f92ad4994bd 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -9,18 +9,23 @@ import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NULLABLE_STRING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.TO_STRING import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUITY import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGN_OPERATOR_AMBIGUITY +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_MODIFIER_PAIR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ENUM_AS_SUPERTYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_FROM_JAVA_RESOLUTION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXPRESSION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_CANDIDATE +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INCOMPATIBLE_MODIFIERS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_SUPERTYPE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OTHER_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_IMPLICIT_TYPES import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_SUPERTYPES +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REDUNDANT_MODIFIER +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.REPEATED_MODIFIER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPER_IS_NOT_AN_EXPRESSION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SYNTAX_ERROR import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_SUPERTYPE @@ -52,6 +57,11 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { map.put(ERROR_FROM_JAVA_RESOLUTION, "Java resolution error") map.put(OTHER_ERROR, "Unknown (other) error") map.put(SUPER_IS_NOT_AN_EXPRESSION, "Super cannot be a callee") + + 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) + map.put(INCOMPATIBLE_MODIFIERS, "Modifier ''{0}'' is incompatible with ''{1}''", TO_STRING, TO_STRING) } } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt index 61f126f7cc4..828f5ddb4a8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDiagnosticRenderers.kt @@ -22,4 +22,6 @@ object FirDiagnosticRenderers { } } } + + val TO_STRING = Renderer { it.toString() } } \ No newline at end of file diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index b2933f7040d..da12ce7193b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.lexer.KtModifierKeywordToken object FirErrors { val UNRESOLVED_REFERENCE by error1() @@ -34,4 +35,9 @@ object FirErrors { val SUPER_IS_NOT_AN_EXPRESSION by error0() val INAPPLICABLE_INFIX_MODIFIER by existing(Errors.INAPPLICABLE_INFIX_MODIFIER) + + val REPEATED_MODIFIER by error1() + val REDUNDANT_MODIFIER by error2() + val DEPRECATED_MODIFIER_PAIR by error2() + val INCOMPATIBLE_MODIFIERS by error2() } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirModifierList.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirModifierList.kt index 46268dc48da..7e9c3c052b5 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirModifierList.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirModifierList.kt @@ -37,14 +37,34 @@ class FirLightModifierList(val modifierList: LighterASTNode, val tree: Flyweight val modifierNodes = kidsRef.get() return modifierNodes.filterNotNull() .filter { it.tokenType is KtModifierKeywordToken } - .map { FirLightModifier(it, it.tokenType as KtModifierKeywordToken) } + .map { FirLightModifier(it, it.tokenType as KtModifierKeywordToken, tree) } } } sealed class FirModifier(val node: Node, val token: KtModifierKeywordToken) -class FirPsiModifier(node: ASTNode, token: KtModifierKeywordToken) : FirModifier(node, token) +class FirPsiModifier( + node: ASTNode, + token: KtModifierKeywordToken +) : FirModifier(node, token) -class FirLightModifier(node: LighterASTNode, token: KtModifierKeywordToken) : FirModifier(node, token) +class FirLightModifier( + node: LighterASTNode, + token: KtModifierKeywordToken, + val tree: FlyweightCapableTreeStructure +) : FirModifier(node, token) -val FirModifier<*>.psi: PsiElement? get() = (this as? FirPsiModifier)?.node?.psi \ No newline at end of file +val FirModifier<*>.psi: PsiElement? get() = (this as? FirPsiModifier)?.node?.psi + +val FirModifier<*>.lightNode: LighterASTNode? get() = (this as? FirLightModifier)?.node + +val FirModifier<*>.source: FirSourceElement? + get() = when (this) { + is FirPsiModifier -> this.psi?.toFirSourceElement() + is FirLightModifier -> { + // TODO pretty sure I got offsets wrong here + val startOffset = tree.getStartOffset(node) + val endOffset = tree.getEndOffset(node) + FirLightSourceElement(node, startOffset, endOffset, tree) + } + } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/rendering/cannotOverrideInvisibleMember.fir.kt b/compiler/testData/diagnostics/tests/annotations/rendering/cannotOverrideInvisibleMember.fir.kt index ae412ba8eb7..2b454317472 100644 --- a/compiler/testData/diagnostics/tests/annotations/rendering/cannotOverrideInvisibleMember.fir.kt +++ b/compiler/testData/diagnostics/tests/annotations/rendering/cannotOverrideInvisibleMember.fir.kt @@ -7,7 +7,7 @@ annotation class A @A open class B1 { @A - private open fun foo() {} + private open fun foo() {} } class D1 : B1() { diff --git a/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.fir.kt b/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.fir.kt index c65cabe764d..04d17f7f1ca 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.fir.kt +++ b/compiler/testData/diagnostics/tests/dataClasses/dataInheritance.fir.kt @@ -2,7 +2,7 @@ interface SuperInterface open class SuperClass -abstract data class Base(val x: Int) +abstract data class Base(val x: Int) class Derived: Base(42) diff --git a/compiler/testData/diagnostics/tests/dataClasses/innerDataClass.fir.kt b/compiler/testData/diagnostics/tests/dataClasses/innerDataClass.fir.kt deleted file mode 100644 index 18c9b2307af..00000000000 --- a/compiler/testData/diagnostics/tests/dataClasses/innerDataClass.fir.kt +++ /dev/null @@ -1,3 +0,0 @@ -class Outer { - inner data class Inner(val x: Int) -} diff --git a/compiler/testData/diagnostics/tests/dataClasses/innerDataClass.kt b/compiler/testData/diagnostics/tests/dataClasses/innerDataClass.kt index 840b4bb62aa..ffd48b509f2 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/innerDataClass.kt +++ b/compiler/testData/diagnostics/tests/dataClasses/innerDataClass.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL class Outer { inner data class Inner(val x: Int) } diff --git a/compiler/testData/diagnostics/tests/dataClasses/innerOuterDataClass.fir.kt b/compiler/testData/diagnostics/tests/dataClasses/innerOuterDataClass.fir.kt index 496921194f8..a7a16e75490 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/innerOuterDataClass.fir.kt +++ b/compiler/testData/diagnostics/tests/dataClasses/innerOuterDataClass.fir.kt @@ -1 +1 @@ -inner data class Outer(val x: Int) \ No newline at end of file +inner data class Outer(val x: Int) \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/dataClasses/sealedDataClass.fir.kt b/compiler/testData/diagnostics/tests/dataClasses/sealedDataClass.fir.kt deleted file mode 100644 index 8899146b396..00000000000 --- a/compiler/testData/diagnostics/tests/dataClasses/sealedDataClass.fir.kt +++ /dev/null @@ -1,4 +0,0 @@ -sealed data class My(val x: Int) { - object Your: My(1) - class His(y: Int): My(y) -} diff --git a/compiler/testData/diagnostics/tests/dataClasses/sealedDataClass.kt b/compiler/testData/diagnostics/tests/dataClasses/sealedDataClass.kt index cc65d11e001..1b69cce9a20 100644 --- a/compiler/testData/diagnostics/tests/dataClasses/sealedDataClass.kt +++ b/compiler/testData/diagnostics/tests/dataClasses/sealedDataClass.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed data class My(val x: Int) { object Your: My(1) class His(y: Int): My(y) diff --git a/compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.fir.kt b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.fir.kt index 1dc1d59e16d..a16404c9a45 100644 --- a/compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/inlineClasses/inlineClassDeclarationCheck.fir.kt @@ -30,4 +30,4 @@ open inline class D1(val x: Int) abstract inline class D2(val x: Int) sealed inline class D3(val x: Int) -inline data class D4(val x: String) +inline data class D4(val x: String) diff --git a/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt b/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt index 39c44dd2189..4f47b9e219a 100644 --- a/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/IllegalModifiers.fir.kt @@ -2,9 +2,9 @@ package illegal_modifiers abstract class A() { - abstract final fun f() - abstract open fun g() - final open fun h() {} + abstract final fun f() + abstract open fun g() + final open fun h() {} open var r: String get @@ -21,8 +21,8 @@ class FinalClass() { open set(v: Int) {} } -private public class C -private public object D +private public class C +private public object D //A sample annotation to check annotation usage in parameters. annotation class annotated(val text: String = "not given") @@ -32,8 +32,8 @@ class LegalModifier(val a: Int, @annotated private var b: String, @annotated var //Check illegal modifier in constructor parameters class IllegalModifiers1( - in - out + in + out reified enum private @@ -41,7 +41,7 @@ class IllegalModifiers1( a: Int) //Check multiple illegal modifiers in constructor -class IllegalModifiers2(private abstract a: Int) +class IllegalModifiers2(private abstract a: Int) //Check annotations with illegal modifiers in constructor @@ -65,10 +65,10 @@ abstract class IllegalModifiers5() { private fun qux() { //Check illegal modifier in catch block - try {} catch (in out reified enum public e: Exception) {} + try {} catch (in out reified enum public e: Exception) {} //Check multiple illegal modifiers in catch block - try {} catch (in out reified enum abstract public e: Exception) {} + try {} catch (in out reified enum abstract public e: Exception) {} //Check annotations with illegal modifiers try {} catch (@annotated("a text") abstract public e: Exception) {} @@ -92,24 +92,24 @@ abstract class IllegalModifiers6() { // strange inappropriate modifiers usages override -out -in +out +in vararg reified class IllegalModifiers7() { enum inner annotation - out - in + out + in vararg reified val x = 1 enum inner annotation - out - in + out + in vararg reified const @@ -118,46 +118,46 @@ class IllegalModifiers7() { // Secondary constructors class IllegalModifiers8 { - abstract + abstract enum - open + open inner annotation - override - out - in - final + override + out + in + final vararg reified - const + const constructor() {} - constructor(private enum abstract x: Int) {} + constructor(private enum abstract x: Int) {} } class IllegalModifiers9 { - private protected constructor() {} - private internal constructor(x: Int) {} + private protected constructor() {} + private internal constructor(x: Int) {} } // Illegal modifiers on primary constructor class IllegalModifiers10 -abstract +abstract enum -open +open inner annotation -override -out -in -final +override +out +in +final vararg reified -const constructor() +const constructor() -class IllegalModifiers11 private protected constructor() +class IllegalModifiers11 private protected constructor() class Outer { - inner sealed class Inner + inner sealed class Inner } diff --git a/compiler/testData/diagnostics/tests/modifiers/const/applicability.fir.kt b/compiler/testData/diagnostics/tests/modifiers/const/applicability.fir.kt index 3c7e9b95872..1d828a3b8ae 100644 --- a/compiler/testData/diagnostics/tests/modifiers/const/applicability.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/const/applicability.fir.kt @@ -15,9 +15,9 @@ object A { class B(const val constructor: Int = 5) abstract class C { - open const val x: Int = 6 + open const val x: Int = 6 - abstract const val y: Int = 7 + abstract const val y: Int = 7 companion object { const val inCompaionObject = 8 @@ -25,7 +25,7 @@ abstract class C { } object D : C() { - override const val x: Int = 9 + override const val x: Int = 9 const val inObject = 10 diff --git a/compiler/testData/diagnostics/tests/modifiers/incompatibleVarianceModifiers.fir.kt b/compiler/testData/diagnostics/tests/modifiers/incompatibleVarianceModifiers.fir.kt index 960ca254855..28ea9b366b4 100644 --- a/compiler/testData/diagnostics/tests/modifiers/incompatibleVarianceModifiers.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/incompatibleVarianceModifiers.fir.kt @@ -1,8 +1,8 @@ // !DIAGNOSTICS: -UNUSED_VARIABLE interface Foo -interface Foo1 -interface Foo2 +interface Foo1<in out T> +interface Foo2in T> fun test1(foo: Foo) = foo fun test2(): Foo = throw Exception() @@ -10,11 +10,11 @@ fun test2(): Foo = throw Exception() fun test3() { val f: Foo - class Bzz + class Bzzin T> } class A { - fun bar() { + fun out T> bar() { } } diff --git a/compiler/testData/diagnostics/tests/modifiers/inlineParameters.fir.kt b/compiler/testData/diagnostics/tests/modifiers/inlineParameters.fir.kt index 311f939d9ff..b2058c75f90 100644 --- a/compiler/testData/diagnostics/tests/modifiers/inlineParameters.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/inlineParameters.fir.kt @@ -8,13 +8,13 @@ fun gav(noinline x: (Int) -> Unit, crossinline y: (String) -> Int) {} inline fun correct(noinline x: (Int) -> Unit, crossinline y: (String) -> Int) {} -inline fun incompatible(noinline crossinline x: () -> String) {} +inline fun incompatible(noinline crossinline x: () -> String) {} class FunctionSubtype : () -> Unit { override fun invoke() {} } inline fun functionSubtype( - noinline f: FunctionSubtype, - crossinline g: FunctionSubtype + noinline f: FunctionSubtype, + crossinline g: FunctionSubtype ) { } diff --git a/compiler/testData/diagnostics/tests/modifiers/modifierOnParameterInFunctionType.fir.kt b/compiler/testData/diagnostics/tests/modifiers/modifierOnParameterInFunctionType.fir.kt index ae1ccc95eb6..158233f2142 100644 --- a/compiler/testData/diagnostics/tests/modifiers/modifierOnParameterInFunctionType.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/modifierOnParameterInFunctionType.fir.kt @@ -19,30 +19,30 @@ class A : (vararg Int)->Unit { get(): (vararg x: Int)->Unit = {} } -val allProhibited: (abstract +val allProhibited: (abstract annotation companion - const - crossinline - data + const + crossinline + data enum external - final - in - inline - inner - internal + final + in + inline + inner + internal lateinit - noinline - open + noinline + open operator - out - override - private - protected - public + out + override + private + protected + public reified - sealed + sealed tailrec vararg diff --git a/compiler/testData/diagnostics/tests/modifiers/openInInterface.fir.kt b/compiler/testData/diagnostics/tests/modifiers/openInInterface.fir.kt index 8c9497d874f..b3124a6f394 100644 --- a/compiler/testData/diagnostics/tests/modifiers/openInInterface.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/openInInterface.fir.kt @@ -1,10 +1,10 @@ interface My { open fun foo() open fun bar() {} - open abstract fun baz(): Int + open abstract fun baz(): Int open val x: Int open val y: String get() = "" - open abstract val z: Double + open abstract val z: Double } diff --git a/compiler/testData/diagnostics/tests/modifiers/privateInInterface.fir.kt b/compiler/testData/diagnostics/tests/modifiers/privateInInterface.fir.kt index 75878595978..0dbf6aec924 100644 --- a/compiler/testData/diagnostics/tests/modifiers/privateInInterface.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/privateInInterface.fir.kt @@ -1,6 +1,6 @@ interface My { private val x: Int - private abstract val xx: Int + private abstract val xx: Int private val xxx: Int get() = 0 final val y: Int diff --git a/compiler/testData/diagnostics/tests/modifiers/repeatedModifiers.fir.kt b/compiler/testData/diagnostics/tests/modifiers/repeatedModifiers.fir.kt index 0ae92441676..9646ac9c216 100644 --- a/compiler/testData/diagnostics/tests/modifiers/repeatedModifiers.fir.kt +++ b/compiler/testData/diagnostics/tests/modifiers/repeatedModifiers.fir.kt @@ -1,41 +1,41 @@ -abstract abstract class Foo -public public class Bar -open open final class Baz { - private private fun foo() {} +abstract abstract class Foo +public public class Bar +open open final class Baz { + private private fun foo() {} } -class Bzz(public public val q: Int = 1) { - public public val x: Int = 2 +class Bzz(public public val q: Int = 1) { + public public val x: Int = 2 public val y: Int - public public get() = 3 + public public get() = 3 val z: Int - open final get() = 4 + open final get() = 4 - public public class B(public public val z: Int = 1) { - public public val y: Int = 2 + public public class B(public public val z: Int = 1) { + public public val y: Int = 2 public val x: Int - public public get() = 3 + public public get() = 3 } - public public object C { - public public val y: Int = 1 - public public fun z(): Int = 1 + public public object C { + public public val y: Int = 1 + public public fun z(): Int = 1 } } -public public val bar: Int = 1 +public public val bar: Int = 1 -public public fun foo(): Int = 1 +public public fun foo(): Int = 1 fun test() { - public public class B(public public val z: Int = 1) { - public public val y: Int = 2 + public public class B(public public val z: Int = 1) { + public public val y: Int = 2 public val x: Int - public public get() = 3 + public public get() = 3 } } diff --git a/compiler/testData/diagnostics/tests/multiplatform/incompatibles.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/incompatibles.fir.kt index 3c6b058712a..07688479da5 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/incompatibles.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/incompatibles.fir.kt @@ -1,13 +1,13 @@ // !LANGUAGE: +MultiPlatformProjects -header impl class First +header impl class First -header expect class Second +header expect class Second -header actual class Third +header actual class Third -impl expect class Fourth +impl expect class Fourth -impl actual class Fifth +impl actual class Fifth -expect actual class Sixth \ No newline at end of file +expect actual class Sixth \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/kt4204-completeNestedCallsForInvoke.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/kt4204-completeNestedCallsForInvoke.fir.kt index 874d9c980f1..0bf25a44277 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/kt4204-completeNestedCallsForInvoke.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/kt4204-completeNestedCallsForInvoke.fir.kt @@ -11,7 +11,7 @@ public abstract class TestBug1() { position(m1().second) } - private abstract fun m1(): Pair + private abstract fun m1(): Pair private fun position(p: Int) {} @@ -19,6 +19,6 @@ public abstract class TestBug1() { //from library public class Pair ( - public val first: A, - public val second: B + public val first: A, + public val second: B ) diff --git a/compiler/testData/diagnostics/tests/scopes/VisibilityInheritModifier.fir.kt b/compiler/testData/diagnostics/tests/scopes/VisibilityInheritModifier.fir.kt index ac6bd941f1c..74a068dd880 100644 --- a/compiler/testData/diagnostics/tests/scopes/VisibilityInheritModifier.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/VisibilityInheritModifier.fir.kt @@ -14,7 +14,7 @@ class C : A() { //------------ open class D { - private open fun self() : D = this + private open fun self() : D = this } class E : D() { diff --git a/compiler/testData/diagnostics/tests/scopes/kt151.fir.kt b/compiler/testData/diagnostics/tests/scopes/kt151.fir.kt index 01a0da63151..00e6dc84c85 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt151.fir.kt +++ b/compiler/testData/diagnostics/tests/scopes/kt151.fir.kt @@ -32,7 +32,7 @@ class E : C(), T { } class F : C(), T { - private override fun foo() {} + private override fun foo() {} } class G : C(), T { diff --git a/compiler/testData/diagnostics/tests/sealed/NeverFinal.fir.kt b/compiler/testData/diagnostics/tests/sealed/NeverFinal.fir.kt deleted file mode 100644 index 13fb5481e51..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/NeverFinal.fir.kt +++ /dev/null @@ -1,3 +0,0 @@ -final sealed class Base { - -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/sealed/NeverFinal.kt b/compiler/testData/diagnostics/tests/sealed/NeverFinal.kt index 8dc1fad9a32..b44393c6524 100644 --- a/compiler/testData/diagnostics/tests/sealed/NeverFinal.kt +++ b/compiler/testData/diagnostics/tests/sealed/NeverFinal.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL final sealed class Base { } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/sealed/NeverOpen.fir.kt b/compiler/testData/diagnostics/tests/sealed/NeverOpen.fir.kt deleted file mode 100644 index 34e4caa6ed7..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/NeverOpen.fir.kt +++ /dev/null @@ -1,3 +0,0 @@ -open sealed class Base { - -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/sealed/NeverOpen.kt b/compiler/testData/diagnostics/tests/sealed/NeverOpen.kt index 6b92d13dbbc..358c9fff507 100644 --- a/compiler/testData/diagnostics/tests/sealed/NeverOpen.kt +++ b/compiler/testData/diagnostics/tests/sealed/NeverOpen.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL open sealed class Base { } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/sealed/RedundantAbstract.fir.kt b/compiler/testData/diagnostics/tests/sealed/RedundantAbstract.fir.kt deleted file mode 100644 index 4a90ee701d2..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/RedundantAbstract.fir.kt +++ /dev/null @@ -1,3 +0,0 @@ -abstract sealed class Base { - -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/sealed/RedundantAbstract.kt b/compiler/testData/diagnostics/tests/sealed/RedundantAbstract.kt index c4ee1cfbb91..0e51cfff002 100644 --- a/compiler/testData/diagnostics/tests/sealed/RedundantAbstract.kt +++ b/compiler/testData/diagnostics/tests/sealed/RedundantAbstract.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL abstract sealed class Base { } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.fir.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.fir.kt index 4a83ee84a13..b8133554e39 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.fir.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/noDataClassInheritance.fir.kt @@ -4,7 +4,7 @@ interface Allowed open class NotAllowed -abstract data class Base(val x: Int) +abstract data class Base(val x: Int) class Derived: Base(42)