K2 Scripting: deprecate top level script inner classes
no LT support yet
This commit is contained in:
committed by
Space Team
parent
7484ccb9ee
commit
70d2fcd9c4
+12
@@ -253,6 +253,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.INNER_ON_TOP_LEVEL_SCRIPT_CLASS.errorFactory) { firDiagnostic ->
|
||||||
|
InnerOnTopLevelScriptClassErrorImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.INNER_ON_TOP_LEVEL_SCRIPT_CLASS.warningFactory) { firDiagnostic ->
|
||||||
|
InnerOnTopLevelScriptClassWarningImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.INVISIBLE_REFERENCE) { firDiagnostic ->
|
add(FirErrors.INVISIBLE_REFERENCE) { firDiagnostic ->
|
||||||
InvisibleReferenceImpl(
|
InvisibleReferenceImpl(
|
||||||
firSymbolBuilder.buildSymbol(firDiagnostic.a),
|
firSymbolBuilder.buildSymbol(firDiagnostic.a),
|
||||||
|
|||||||
+8
@@ -217,6 +217,14 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
val callableId: CallableId
|
val callableId: CallableId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface InnerOnTopLevelScriptClassError : KtFirDiagnostic<PsiElement> {
|
||||||
|
override val diagnosticClass get() = InnerOnTopLevelScriptClassError::class
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InnerOnTopLevelScriptClassWarning : KtFirDiagnostic<PsiElement> {
|
||||||
|
override val diagnosticClass get() = InnerOnTopLevelScriptClassWarning::class
|
||||||
|
}
|
||||||
|
|
||||||
interface InvisibleReference : KtFirDiagnostic<PsiElement> {
|
interface InvisibleReference : KtFirDiagnostic<PsiElement> {
|
||||||
override val diagnosticClass get() = InvisibleReference::class
|
override val diagnosticClass get() = InvisibleReference::class
|
||||||
val reference: KtSymbol
|
val reference: KtSymbol
|
||||||
|
|||||||
+10
@@ -246,6 +246,16 @@ internal class InvisibleSetterImpl(
|
|||||||
token: KtLifetimeToken,
|
token: KtLifetimeToken,
|
||||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.InvisibleSetter
|
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.InvisibleSetter
|
||||||
|
|
||||||
|
internal class InnerOnTopLevelScriptClassErrorImpl(
|
||||||
|
firDiagnostic: KtPsiDiagnostic,
|
||||||
|
token: KtLifetimeToken,
|
||||||
|
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.InnerOnTopLevelScriptClassError
|
||||||
|
|
||||||
|
internal class InnerOnTopLevelScriptClassWarningImpl(
|
||||||
|
firDiagnostic: KtPsiDiagnostic,
|
||||||
|
token: KtLifetimeToken,
|
||||||
|
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.InnerOnTopLevelScriptClassWarning
|
||||||
|
|
||||||
internal class InvisibleReferenceImpl(
|
internal class InvisibleReferenceImpl(
|
||||||
override val reference: KtSymbol,
|
override val reference: KtSymbol,
|
||||||
override val visible: Visibility,
|
override val visible: Visibility,
|
||||||
|
|||||||
+12
@@ -29134,6 +29134,18 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/script/imports.kts");
|
runTest("compiler/testData/diagnostics/tests/script/imports.kts");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("innerClassError.kts")
|
||||||
|
public void testInnerClassError() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/script/innerClassError.kts");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("innerClassWarning.kts")
|
||||||
|
public void testInnerClassWarning() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/script/innerClassWarning.kts");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("LateInit.kts")
|
@TestMetadata("LateInit.kts")
|
||||||
public void testLateInit() throws Exception {
|
public void testLateInit() throws Exception {
|
||||||
|
|||||||
+1
@@ -99,6 +99,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
parameter<Visibility>("visibility")
|
parameter<Visibility>("visibility")
|
||||||
parameter<CallableId>("callableId")
|
parameter<CallableId>("callableId")
|
||||||
}
|
}
|
||||||
|
val INNER_ON_TOP_LEVEL_SCRIPT_CLASS by deprecationError<PsiElement>(LanguageFeature.ProhibitScriptTopLevelInnerClasses)
|
||||||
}
|
}
|
||||||
|
|
||||||
val UNRESOLVED by object : DiagnosticGroup("Unresolved") {
|
val UNRESOLVED by object : DiagnosticGroup("Unresolved") {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.config.LanguageFeature.ProhibitCyclesInAnnotations
|
|||||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitImplementingVarByInheritedVal
|
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitImplementingVarByInheritedVal
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitInvisibleAbstractMethodsInSuperclasses
|
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitInvisibleAbstractMethodsInSuperclasses
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments
|
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitScriptTopLevelInnerClasses
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitUseSiteTargetAnnotationsOnSuperTypes
|
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitUseSiteTargetAnnotationsOnSuperTypes
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.RestrictRetentionForExpressionAnnotations
|
import org.jetbrains.kotlin.config.LanguageFeature.RestrictRetentionForExpressionAnnotations
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature.RestrictionOfValReassignmentViaBackingField
|
import org.jetbrains.kotlin.config.LanguageFeature.RestrictionOfValReassignmentViaBackingField
|
||||||
@@ -146,6 +147,7 @@ object FirErrors {
|
|||||||
val VAL_OR_VAR_ON_CATCH_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
|
val VAL_OR_VAR_ON_CATCH_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
|
||||||
val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
|
val VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER by error1<KtParameter, KtKeywordToken>(SourceElementPositioningStrategies.VAL_OR_VAR_NODE)
|
||||||
val INVISIBLE_SETTER by error3<PsiElement, FirPropertySymbol, Visibility, CallableId>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
|
val INVISIBLE_SETTER by error3<PsiElement, FirPropertySymbol, Visibility, CallableId>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
|
||||||
|
val INNER_ON_TOP_LEVEL_SCRIPT_CLASS by deprecationError0<PsiElement>(ProhibitScriptTopLevelInnerClasses)
|
||||||
|
|
||||||
// Unresolved
|
// Unresolved
|
||||||
val INVISIBLE_REFERENCE by error3<PsiElement, FirBasedSymbol<*>, Visibility, ClassId?>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val INVISIBLE_REFERENCE by error3<PsiElement, FirBasedSymbol<*>, Visibility, ClassId?>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
|||||||
+11
-7
@@ -262,13 +262,17 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
|
|||||||
val possibleParentPredicate = possibleParentTargetPredicateMap[modifierToken] ?: return true
|
val possibleParentPredicate = possibleParentTargetPredicateMap[modifierToken] ?: return true
|
||||||
if (actualParents.any { possibleParentPredicate.isAllowed(it, context.session.languageVersionSettings) }) return true
|
if (actualParents.any { possibleParentPredicate.isAllowed(it, context.session.languageVersionSettings) }) return true
|
||||||
|
|
||||||
reporter.reportOn(
|
if (modifierToken == KtTokens.INNER_KEYWORD && parent is FirScript) {
|
||||||
modifierSource,
|
reporter.reportOn(modifierSource, FirErrors.INNER_ON_TOP_LEVEL_SCRIPT_CLASS, context)
|
||||||
FirErrors.WRONG_MODIFIER_CONTAINING_DECLARATION,
|
} else {
|
||||||
modifierToken,
|
reporter.reportOn(
|
||||||
actualParents.firstOrThis(),
|
modifierSource,
|
||||||
context
|
FirErrors.WRONG_MODIFIER_CONTAINING_DECLARATION,
|
||||||
)
|
modifierToken,
|
||||||
|
actualParents.firstOrThis(),
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -301,6 +301,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INLINE_SUSPEND_FU
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_CONSTRUCTOR_NO_RECEIVER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_CONSTRUCTOR_NO_RECEIVER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_INSIDE_VALUE_CLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_INSIDE_VALUE_CLASS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_ON_TOP_LEVEL_SCRIPT_CLASS
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_AS_FUNCTION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_AS_FUNCTION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SUPERCLASS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SUPERCLASS
|
||||||
@@ -714,6 +715,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
VISIBILITY,
|
VISIBILITY,
|
||||||
NAME_OF_CONTAINING_DECLARATION_OR_FILE
|
NAME_OF_CONTAINING_DECLARATION_OR_FILE
|
||||||
)
|
)
|
||||||
|
map.put(INNER_ON_TOP_LEVEL_SCRIPT_CLASS, "Top level script class cannot be inner.")
|
||||||
map.put(UNRESOLVED_REFERENCE, "Unresolved reference: {0}", NULLABLE_STRING)
|
map.put(UNRESOLVED_REFERENCE, "Unresolved reference: {0}", NULLABLE_STRING)
|
||||||
map.put(UNRESOLVED_IMPORT, "Unresolved reference: {0}", NULLABLE_STRING) // &
|
map.put(UNRESOLVED_IMPORT, "Unresolved reference: {0}", NULLABLE_STRING) // &
|
||||||
map.put(UNRESOLVED_LABEL, "Unresolved label")
|
map.put(UNRESOLVED_LABEL, "Unresolved label")
|
||||||
|
|||||||
+5
-4
@@ -1023,7 +1023,7 @@ open class PsiRawFirBuilder(
|
|||||||
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility(), Modality.FINAL).apply {
|
val status = FirDeclarationStatusImpl(explicitVisibility ?: defaultVisibility(), Modality.FINAL).apply {
|
||||||
isExpect = this@toFirConstructor?.hasExpectModifier() == true || this@PsiRawFirBuilder.context.containerIsExpect
|
isExpect = this@toFirConstructor?.hasExpectModifier() == true || this@PsiRawFirBuilder.context.containerIsExpect
|
||||||
isActual = this@toFirConstructor?.hasActualModifier() == true
|
isActual = this@toFirConstructor?.hasActualModifier() == true
|
||||||
isInner = owner.hasModifier(INNER_KEYWORD)
|
isInner = owner.parent.parent !is KtScript && owner.hasModifier(INNER_KEYWORD) // a warning about inner script class is reported on the class itself
|
||||||
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.Private
|
isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.Private
|
||||||
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
|
isFromEnumClass = owner.hasModifier(ENUM_KEYWORD)
|
||||||
}
|
}
|
||||||
@@ -1244,6 +1244,7 @@ open class PsiRawFirBuilder(
|
|||||||
// NB: enum entry nested classes are considered local by FIR design (see discussion in KT-45115)
|
// NB: enum entry nested classes are considered local by FIR design (see discussion in KT-45115)
|
||||||
val isLocal = classOrObject.isLocal || classOrObject.getStrictParentOfType<KtEnumEntry>() != null
|
val isLocal = classOrObject.isLocal || classOrObject.getStrictParentOfType<KtEnumEntry>() != null
|
||||||
val classIsExpect = classOrObject.hasExpectModifier() || context.containerIsExpect
|
val classIsExpect = classOrObject.hasExpectModifier() || context.containerIsExpect
|
||||||
|
val sourceElement = classOrObject.toFirSourceElement()
|
||||||
return withChildClassName(
|
return withChildClassName(
|
||||||
classOrObject.nameAsSafeName,
|
classOrObject.nameAsSafeName,
|
||||||
isExpect = classIsExpect,
|
isExpect = classIsExpect,
|
||||||
@@ -1265,7 +1266,7 @@ open class PsiRawFirBuilder(
|
|||||||
).apply {
|
).apply {
|
||||||
isExpect = classIsExpect
|
isExpect = classIsExpect
|
||||||
isActual = classOrObject.hasActualModifier()
|
isActual = classOrObject.hasActualModifier()
|
||||||
isInner = classOrObject.hasModifier(INNER_KEYWORD)
|
isInner = classOrObject.hasModifier(INNER_KEYWORD) && classOrObject.parent.parent !is KtScript
|
||||||
isCompanion = (classOrObject as? KtObjectDeclaration)?.isCompanion() == true
|
isCompanion = (classOrObject as? KtObjectDeclaration)?.isCompanion() == true
|
||||||
isData = classOrObject.hasModifier(DATA_KEYWORD)
|
isData = classOrObject.hasModifier(DATA_KEYWORD)
|
||||||
isInline = classOrObject.hasModifier(INLINE_KEYWORD) || classOrObject.hasModifier(VALUE_KEYWORD)
|
isInline = classOrObject.hasModifier(INLINE_KEYWORD) || classOrObject.hasModifier(VALUE_KEYWORD)
|
||||||
@@ -1273,10 +1274,10 @@ open class PsiRawFirBuilder(
|
|||||||
isExternal = classOrObject.hasModifier(EXTERNAL_KEYWORD)
|
isExternal = classOrObject.hasModifier(EXTERNAL_KEYWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
withCapturedTypeParameters(status.isInner || isLocal, classOrObject.toFirSourceElement(), listOf()) {
|
withCapturedTypeParameters(status.isInner || isLocal, sourceElement, listOf()) {
|
||||||
var delegatedFieldsMap: Map<Int, FirFieldSymbol>?
|
var delegatedFieldsMap: Map<Int, FirFieldSymbol>?
|
||||||
buildRegularClass {
|
buildRegularClass {
|
||||||
source = classOrObject.toFirSourceElement()
|
source = sourceElement
|
||||||
moduleData = baseModuleData
|
moduleData = baseModuleData
|
||||||
origin = FirDeclarationOrigin.Source
|
origin = FirDeclarationOrigin.Source
|
||||||
name = classOrObject.nameAsSafeName
|
name = classOrObject.nameAsSafeName
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Nested {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>inner<!> class Inner {
|
<!INNER_ON_TOP_LEVEL_SCRIPT_CLASS_WARNING!>inner<!> class Inner {
|
||||||
fun innerFun() = function()
|
fun innerFun() = function()
|
||||||
val innerProp = property
|
val innerProp = property
|
||||||
fun innerThisFun() = this<!UNRESOLVED_LABEL!>@NestedInnerClass<!>.function()
|
fun innerThisFun() = this<!UNRESOLVED_LABEL!>@NestedInnerClass<!>.function()
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// !LANGUAGE: +ProhibitScriptTopLevelInnerClasses
|
||||||
|
|
||||||
|
<!INNER_ON_TOP_LEVEL_SCRIPT_CLASS_ERROR!>inner<!> class A
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
|
||||||
|
inner class A
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// !LANGUAGE: -ProhibitScriptTopLevelInnerClasses
|
||||||
|
|
||||||
|
<!INNER_ON_TOP_LEVEL_SCRIPT_CLASS_WARNING!>inner<!> class A
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
|
||||||
|
inner class A
|
||||||
Generated
+12
@@ -29972,6 +29972,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/script/imports.kts");
|
runTest("compiler/testData/diagnostics/tests/script/imports.kts");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("innerClassError.kts")
|
||||||
|
public void testInnerClassError() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/script/innerClassError.kts");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("innerClassWarning.kts")
|
||||||
|
public void testInnerClassWarning() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/script/innerClassWarning.kts");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("LateInit.kts")
|
@TestMetadata("LateInit.kts")
|
||||||
public void testLateInit() throws Exception {
|
public void testLateInit() throws Exception {
|
||||||
|
|||||||
@@ -332,6 +332,11 @@ enum class LanguageFeature(
|
|||||||
// When this feature is enabled, no such errors are reported.
|
// When this feature is enabled, no such errors are reported.
|
||||||
NoAdditionalErrorsInK1DiagnosticReporter(sinceVersion = null, kind = OTHER),
|
NoAdditionalErrorsInK1DiagnosticReporter(sinceVersion = null, kind = OTHER),
|
||||||
|
|
||||||
|
// top-level script inner classes never made any sense, but used for some time to overcome the capturing logic limitations
|
||||||
|
// Now capturing logic works properly, therefore the warning is reported in K2
|
||||||
|
// this feature will eventually switch this warning to an error
|
||||||
|
ProhibitScriptTopLevelInnerClasses(sinceVersion = null, kind = OTHER),
|
||||||
|
|
||||||
// Experimental features
|
// Experimental features
|
||||||
|
|
||||||
BreakContinueInInlineLambdas(null), // KT-1436
|
BreakContinueInInlineLambdas(null), // KT-1436
|
||||||
|
|||||||
Reference in New Issue
Block a user