Expect/actual: introduce DEPRECATED_MODIFIER instead of ..._FOR_TARGET
This commit is contained in:
committed by
Mikhail Glukhikh
parent
721889600f
commit
9b0f15137f
@@ -199,6 +199,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, KtModifierKeywordToken> REDUNDANT_MODIFIER = DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, KtModifierKeywordToken> REDUNDANT_MODIFIER = DiagnosticFactory2.create(WARNING);
|
||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> WRONG_MODIFIER_TARGET = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> WRONG_MODIFIER_TARGET = DiagnosticFactory2.create(ERROR);
|
||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_FOR_TARGET = DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_FOR_TARGET = DiagnosticFactory2.create(WARNING);
|
||||||
|
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, KtModifierKeywordToken> DEPRECATED_MODIFIER = DiagnosticFactory2.create(WARNING);
|
||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> REDUNDANT_MODIFIER_FOR_TARGET = DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> REDUNDANT_MODIFIER_FOR_TARGET = DiagnosticFactory2.create(WARNING);
|
||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> WRONG_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(ERROR);
|
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> WRONG_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(ERROR);
|
||||||
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
|
||||||
|
|||||||
+1
@@ -142,6 +142,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(REPEATED_MODIFIER, "Repeated ''{0}''", TO_STRING);
|
MAP.put(REPEATED_MODIFIER, "Repeated ''{0}''", TO_STRING);
|
||||||
MAP.put(WRONG_MODIFIER_TARGET, "Modifier ''{0}'' is not applicable to ''{1}''", TO_STRING, TO_STRING);
|
MAP.put(WRONG_MODIFIER_TARGET, "Modifier ''{0}'' is not applicable to ''{1}''", TO_STRING, TO_STRING);
|
||||||
MAP.put(DEPRECATED_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is deprecated for ''{1}''", TO_STRING, TO_STRING);
|
MAP.put(DEPRECATED_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is deprecated for ''{1}''", TO_STRING, TO_STRING);
|
||||||
|
MAP.put(DEPRECATED_MODIFIER, "Modifier ''{0}'' is deprecated, use ''{1}'' instead", TO_STRING, TO_STRING);
|
||||||
MAP.put(REDUNDANT_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is redundant for ''{1}''", TO_STRING, TO_STRING);
|
MAP.put(REDUNDANT_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is redundant for ''{1}''", TO_STRING, TO_STRING);
|
||||||
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, TO_STRING);
|
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, TO_STRING);
|
||||||
MAP.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''", TO_STRING, TO_STRING);
|
MAP.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''", TO_STRING, TO_STRING);
|
||||||
|
|||||||
@@ -109,9 +109,11 @@ object ModifierCheckerCore {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NOTE: deprecated targets must be possible!
|
// NOTE: deprecated targets must be possible!
|
||||||
private val deprecatedTargetMap = mapOf<KtModifierKeywordToken, Set<KotlinTarget>>(
|
private val deprecatedTargetMap = mapOf<KtModifierKeywordToken, Set<KotlinTarget>>()
|
||||||
HEADER_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, TOP_LEVEL_PROPERTY_WITHOUT_FIELD_OR_DELEGATE, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS),
|
|
||||||
IMPL_KEYWORD to EnumSet.of(TOP_LEVEL_FUNCTION, MEMBER_FUNCTION, TOP_LEVEL_PROPERTY, MEMBER_PROPERTY, CONSTRUCTOR, CLASS_ONLY, OBJECT, INTERFACE, ENUM_CLASS, ANNOTATION_CLASS, TYPEALIAS)
|
private val deprecatedModifierMap = mapOf(
|
||||||
|
HEADER_KEYWORD to EXPECT_KEYWORD,
|
||||||
|
IMPL_KEYWORD to ACTUAL_KEYWORD
|
||||||
)
|
)
|
||||||
|
|
||||||
// NOTE: redundant targets must be possible!
|
// NOTE: redundant targets must be possible!
|
||||||
@@ -279,13 +281,16 @@ object ModifierCheckerCore {
|
|||||||
trace.report(Errors.WRONG_MODIFIER_TARGET.on(node.psi, modifier, actualTargets.firstOrNull()?.description ?: "this"))
|
trace.report(Errors.WRONG_MODIFIER_TARGET.on(node.psi, modifier, actualTargets.firstOrNull()?.description ?: "this"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
val deprecatedModifierReplacement = deprecatedModifierMap[modifier]
|
||||||
val deprecatedTargets = deprecatedTargetMap[modifier] ?: emptySet()
|
val deprecatedTargets = deprecatedTargetMap[modifier] ?: emptySet()
|
||||||
val redundantTargets = redundantTargetMap[modifier] ?: emptySet()
|
val redundantTargets = redundantTargetMap[modifier] ?: emptySet()
|
||||||
if (actualTargets.any { it in deprecatedTargets }) {
|
when {
|
||||||
trace.report(Errors.DEPRECATED_MODIFIER_FOR_TARGET.on(node.psi, modifier, actualTargets.firstOrNull()?.description ?: "this"))
|
deprecatedModifierReplacement != null ->
|
||||||
}
|
trace.report(Errors.DEPRECATED_MODIFIER.on(node.psi, modifier, deprecatedModifierReplacement))
|
||||||
else if (actualTargets.any { it in redundantTargets }) {
|
actualTargets.any { it in deprecatedTargets } ->
|
||||||
trace.report(Errors.REDUNDANT_MODIFIER_FOR_TARGET.on(node.psi, modifier, actualTargets.firstOrNull()?.description ?: "this"))
|
trace.report(Errors.DEPRECATED_MODIFIER_FOR_TARGET.on(node.psi, modifier, actualTargets.firstOrNull()?.description ?: "this"))
|
||||||
|
actualTargets.any { it in redundantTargets } ->
|
||||||
|
trace.report(Errors.REDUNDANT_MODIFIER_FOR_TARGET.on(node.psi, modifier, actualTargets.firstOrNull()?.description ?: "this"))
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,29 +2,29 @@
|
|||||||
// MODULE: m1-common
|
// MODULE: m1-common
|
||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, JVM:DEPRECATED_MODIFIER_FOR_TARGET!>header<!> class My
|
<!DEPRECATED_MODIFIER, JVM:DEPRECATED_MODIFIER!>header<!> class My
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, JVM:DEPRECATED_MODIFIER_FOR_TARGET!>header<!> fun foo(): Int
|
<!DEPRECATED_MODIFIER, JVM:DEPRECATED_MODIFIER!>header<!> fun foo(): Int
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, JVM:DEPRECATED_MODIFIER_FOR_TARGET!>header<!> val x: String
|
<!DEPRECATED_MODIFIER, JVM:DEPRECATED_MODIFIER!>header<!> val x: String
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, JVM:DEPRECATED_MODIFIER_FOR_TARGET!>header<!> object O
|
<!DEPRECATED_MODIFIER, JVM:DEPRECATED_MODIFIER!>header<!> object O
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, JVM:DEPRECATED_MODIFIER_FOR_TARGET!>header<!> enum class E {
|
<!DEPRECATED_MODIFIER, JVM:DEPRECATED_MODIFIER!>header<!> enum class E {
|
||||||
FIRST
|
FIRST
|
||||||
}
|
}
|
||||||
|
|
||||||
// MODULE: m2-jvm(m1-common)
|
// MODULE: m2-jvm(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET!>impl<!> class My
|
<!DEPRECATED_MODIFIER!>impl<!> class My
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET!>impl<!> fun foo() = 42
|
<!DEPRECATED_MODIFIER!>impl<!> fun foo() = 42
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET!>impl<!> val x get() = "Hello"
|
<!DEPRECATED_MODIFIER!>impl<!> val x get() = "Hello"
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET!>impl<!> object O
|
<!DEPRECATED_MODIFIER!>impl<!> object O
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET!>impl<!> enum class E {
|
<!DEPRECATED_MODIFIER!>impl<!> enum class E {
|
||||||
FIRST
|
FIRST
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
// !LANGUAGE: +MultiPlatformProjects
|
// !LANGUAGE: +MultiPlatformProjects
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, INCOMPATIBLE_MODIFIERS!>header<!> <!INCOMPATIBLE_MODIFIERS!>impl<!> class <!NO_ACTUAL_FOR_EXPECT!>First<!>
|
<!DEPRECATED_MODIFIER, INCOMPATIBLE_MODIFIERS!>header<!> <!INCOMPATIBLE_MODIFIERS!>impl<!> class <!NO_ACTUAL_FOR_EXPECT!>First<!>
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, INCOMPATIBLE_MODIFIERS!>header<!> <!INCOMPATIBLE_MODIFIERS!>expect<!> class <!NO_ACTUAL_FOR_EXPECT!>Second<!>
|
<!DEPRECATED_MODIFIER, INCOMPATIBLE_MODIFIERS!>header<!> <!INCOMPATIBLE_MODIFIERS!>expect<!> class <!NO_ACTUAL_FOR_EXPECT!>Second<!>
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, INCOMPATIBLE_MODIFIERS!>header<!> <!INCOMPATIBLE_MODIFIERS!>actual<!> class <!NO_ACTUAL_FOR_EXPECT!>Third<!>
|
<!DEPRECATED_MODIFIER, INCOMPATIBLE_MODIFIERS!>header<!> <!INCOMPATIBLE_MODIFIERS!>actual<!> class <!NO_ACTUAL_FOR_EXPECT!>Third<!>
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, INCOMPATIBLE_MODIFIERS!>impl<!> <!INCOMPATIBLE_MODIFIERS!>expect<!> class <!NO_ACTUAL_FOR_EXPECT!>Fourth<!>
|
<!DEPRECATED_MODIFIER, INCOMPATIBLE_MODIFIERS!>impl<!> <!INCOMPATIBLE_MODIFIERS!>expect<!> class <!NO_ACTUAL_FOR_EXPECT!>Fourth<!>
|
||||||
|
|
||||||
<!DEPRECATED_MODIFIER_FOR_TARGET, INCOMPATIBLE_MODIFIERS!>impl<!> <!INCOMPATIBLE_MODIFIERS!>actual<!> class <!ACTUAL_WITHOUT_EXPECT!>Fifth<!>
|
<!DEPRECATED_MODIFIER, INCOMPATIBLE_MODIFIERS!>impl<!> <!INCOMPATIBLE_MODIFIERS!>actual<!> class <!ACTUAL_WITHOUT_EXPECT!>Fifth<!>
|
||||||
|
|
||||||
<!INCOMPATIBLE_MODIFIERS!>expect<!> <!INCOMPATIBLE_MODIFIERS!>actual<!> class <!NO_ACTUAL_FOR_EXPECT!>Sixth<!>
|
<!INCOMPATIBLE_MODIFIERS!>expect<!> <!INCOMPATIBLE_MODIFIERS!>actual<!> class <!NO_ACTUAL_FOR_EXPECT!>Sixth<!>
|
||||||
@@ -130,7 +130,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
|||||||
removeModifierFactory)
|
removeModifierFactory)
|
||||||
REDUNDANT_MODIFIER_IN_GETTER.registerFactory(removeRedundantModifierFactory)
|
REDUNDANT_MODIFIER_IN_GETTER.registerFactory(removeRedundantModifierFactory)
|
||||||
WRONG_MODIFIER_TARGET.registerFactory(removeModifierFactory)
|
WRONG_MODIFIER_TARGET.registerFactory(removeModifierFactory)
|
||||||
DEPRECATED_MODIFIER_FOR_TARGET.registerFactory(ReplaceModifierFix)
|
DEPRECATED_MODIFIER.registerFactory(ReplaceModifierFix)
|
||||||
REDUNDANT_MODIFIER_FOR_TARGET.registerFactory(removeModifierFactory)
|
REDUNDANT_MODIFIER_FOR_TARGET.registerFactory(removeModifierFactory)
|
||||||
WRONG_MODIFIER_CONTAINING_DECLARATION.registerFactory(removeModifierFactory)
|
WRONG_MODIFIER_CONTAINING_DECLARATION.registerFactory(removeModifierFactory)
|
||||||
REPEATED_MODIFIER.registerFactory(removeModifierFactory)
|
REPEATED_MODIFIER.registerFactory(removeModifierFactory)
|
||||||
|
|||||||
@@ -29,38 +29,27 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
|||||||
|
|
||||||
class ReplaceModifierFix(
|
class ReplaceModifierFix(
|
||||||
element: KtModifierListOwner,
|
element: KtModifierListOwner,
|
||||||
private val modifier: KtModifierKeywordToken
|
private val replacement: KtModifierKeywordToken
|
||||||
) : KotlinQuickFixAction<KtModifierListOwner>(element), CleanupFix {
|
) : KotlinQuickFixAction<KtModifierListOwner>(element), CleanupFix {
|
||||||
|
|
||||||
private val text = when (modifier) {
|
private val text = "Replace with '${replacement.value}'"
|
||||||
KtTokens.HEADER_KEYWORD -> "Replace with 'expect'"
|
|
||||||
KtTokens.IMPL_KEYWORD -> "Replace with 'actual'"
|
|
||||||
else -> "Replace modifier (?)"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getText() = text
|
override fun getText() = text
|
||||||
|
|
||||||
override fun getFamilyName() = "Replace modifier"
|
override fun getFamilyName() = "Replace modifier"
|
||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
|
||||||
val element = element ?: return
|
element?.addModifier(replacement)
|
||||||
when (modifier) {
|
|
||||||
KtTokens.HEADER_KEYWORD -> {
|
|
||||||
element.addModifier(KtTokens.EXPECT_KEYWORD)
|
|
||||||
}
|
|
||||||
KtTokens.IMPL_KEYWORD -> {
|
|
||||||
element.addModifier(KtTokens.ACTUAL_KEYWORD)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object : KotlinSingleIntentionActionFactory() {
|
companion object : KotlinSingleIntentionActionFactory() {
|
||||||
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
|
||||||
val deprecatedModifier = Errors.DEPRECATED_MODIFIER_FOR_TARGET.cast(diagnostic)
|
val deprecatedModifier = Errors.DEPRECATED_MODIFIER.cast(diagnostic)
|
||||||
val modifier = deprecatedModifier.a
|
val modifier = deprecatedModifier.a
|
||||||
|
val replacement = deprecatedModifier.b
|
||||||
val modifierListOwner = deprecatedModifier.psiElement.getParentOfType<KtModifierListOwner>(strict = true) ?: return null
|
val modifierListOwner = deprecatedModifier.psiElement.getParentOfType<KtModifierListOwner>(strict = true) ?: return null
|
||||||
return when (modifier) {
|
return when (modifier) {
|
||||||
KtTokens.HEADER_KEYWORD, KtTokens.IMPL_KEYWORD -> ReplaceModifierFix(modifierListOwner, modifier)
|
KtTokens.HEADER_KEYWORD, KtTokens.IMPL_KEYWORD -> ReplaceModifierFix(modifierListOwner, replacement)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user