Prohibit operator mod as declaration and calls that resolved via it
#KT-24197 Fixed
This commit is contained in:
@@ -747,7 +747,9 @@ public interface Errors {
|
||||
DiagnosticFactory2<KtBinaryExpression, KotlinType, KotlinType> FORBIDDEN_IDENTITY_EQUALS = DiagnosticFactory2.create(ERROR);
|
||||
|
||||
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> DEPRECATED_BINARY_MOD = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> FORBIDDEN_BINARY_MOD = DiagnosticFactory2.create(ERROR);
|
||||
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> DEPRECATED_BINARY_MOD_AS_REM = DiagnosticFactory2.create(WARNING);
|
||||
DiagnosticFactory2<PsiElement, FunctionDescriptor, String> FORBIDDEN_BINARY_MOD_AS_REM = DiagnosticFactory2.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtArrayAccessExpression> NO_GET_METHOD = DiagnosticFactory0.create(ERROR, ARRAY_ACCESS);
|
||||
DiagnosticFactory0<KtArrayAccessExpression> NO_SET_METHOD = DiagnosticFactory0.create(ERROR, ARRAY_ACCESS);
|
||||
|
||||
+2
@@ -396,7 +396,9 @@ public class DefaultErrorMessages {
|
||||
MAP.put(FORBIDDEN_IDENTITY_EQUALS, "Identity equality for arguments of types {0} and {1} is forbidden", RENDER_TYPE, RENDER_TYPE);
|
||||
|
||||
MAP.put(DEPRECATED_BINARY_MOD, "Deprecated convention for ''{0}''. Use ''{1}''", NAME, STRING);
|
||||
MAP.put(FORBIDDEN_BINARY_MOD, "Convention for ''{0}'' is forbidden. Use ''{1}''", NAME, STRING);
|
||||
MAP.put(DEPRECATED_BINARY_MOD_AS_REM, "''%'' is resolved to deprecated ''{0}'' operator. Replace with ''.{0}'' or add operator ''{1}''", NAME, STRING);
|
||||
MAP.put(FORBIDDEN_BINARY_MOD_AS_REM, "''%'' is resolved to forbidden ''{0}'' operator. Replace with ''.{0}'' or add operator ''{1}''", NAME, STRING);
|
||||
|
||||
MAP.put(NO_GET_METHOD, "No get method providing array access");
|
||||
MAP.put(NO_SET_METHOD, "No set method providing array access");
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
@@ -50,10 +51,18 @@ object OperatorModifierChecker {
|
||||
checkSupportsFeature(LanguageFeature.OperatorProvideDelegate, languageVersionSettings, diagnosticHolder, modifier)
|
||||
}
|
||||
|
||||
if (functionDescriptor.name in REM_TO_MOD_OPERATION_NAMES.values
|
||||
&& languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)) {
|
||||
if (functionDescriptor.name in REM_TO_MOD_OPERATION_NAMES.values &&
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)
|
||||
) {
|
||||
val diagnosticFactory = if (!KotlinBuiltIns.isUnderKotlinPackage(descriptor) &&
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.ProhibitOperatorMod)
|
||||
)
|
||||
Errors.FORBIDDEN_BINARY_MOD
|
||||
else
|
||||
Errors.DEPRECATED_BINARY_MOD
|
||||
|
||||
val newNameConvention = REM_TO_MOD_OPERATION_NAMES.inverse()[functionDescriptor.name]
|
||||
diagnosticHolder.report(Errors.DEPRECATED_BINARY_MOD.on(modifier, functionDescriptor, newNameConvention!!.asString()))
|
||||
diagnosticHolder.report(diagnosticFactory.on(modifier, functionDescriptor, newNameConvention!!.asString()))
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
+14
-4
@@ -117,16 +117,26 @@ private fun checkModConvention(
|
||||
|
||||
if (KotlinBuiltIns.isUnderKotlinPackage(descriptor)) {
|
||||
if (shouldWarnAboutDeprecatedModFromBuiltIns(languageVersionSettings)) {
|
||||
addWarningAboutDeprecatedMod(descriptor, diagnosticHolder, modifier)
|
||||
warnAboutDeprecatedOrForbiddenMod(descriptor, diagnosticHolder, modifier, languageVersionSettings)
|
||||
}
|
||||
} else {
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)) {
|
||||
addWarningAboutDeprecatedMod(descriptor, diagnosticHolder, modifier)
|
||||
warnAboutDeprecatedOrForbiddenMod(descriptor, diagnosticHolder, modifier, languageVersionSettings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addWarningAboutDeprecatedMod(descriptor: FunctionDescriptor, diagnosticHolder: DiagnosticSink, reportOn: PsiElement) {
|
||||
private fun warnAboutDeprecatedOrForbiddenMod(
|
||||
descriptor: FunctionDescriptor,
|
||||
diagnosticHolder: DiagnosticSink,
|
||||
reportOn: PsiElement,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
val diagnosticFactory = if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitOperatorMod))
|
||||
Errors.FORBIDDEN_BINARY_MOD_AS_REM
|
||||
else
|
||||
Errors.DEPRECATED_BINARY_MOD_AS_REM
|
||||
|
||||
val newNameConvention = OperatorConventions.REM_TO_MOD_OPERATION_NAMES.inverse()[descriptor.name]
|
||||
diagnosticHolder.report(Errors.DEPRECATED_BINARY_MOD_AS_REM.on(reportOn, descriptor, newNameConvention!!.asString()))
|
||||
diagnosticHolder.report(diagnosticFactory.on(reportOn, descriptor, newNameConvention!!.asString()))
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
// !LANGUAGE: +ProhibitOperatorMod
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
object ModAndRem {
|
||||
<!FORBIDDEN_BINARY_MOD!>operator<!> fun mod(x: Int) {}
|
||||
operator fun rem(x: Int) {}
|
||||
|
||||
<!FORBIDDEN_BINARY_MOD!>operator<!> fun modAssign(x: Int) {}
|
||||
operator fun remAssign(x: Int) {}
|
||||
}
|
||||
|
||||
object JustMod {
|
||||
<!FORBIDDEN_BINARY_MOD!>operator<!> fun mod(x: Int) {}
|
||||
<!FORBIDDEN_BINARY_MOD!>operator<!> fun modAssign(x: Int) {}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
ModAndRem % 1
|
||||
ModAndRem.mod(1)
|
||||
ModAndRem.rem(1)
|
||||
|
||||
JustMod <!FORBIDDEN_BINARY_MOD_AS_REM!>%<!> 1
|
||||
JustMod.mod(1)
|
||||
|
||||
val r = ModAndRem
|
||||
r %= 1
|
||||
r.remAssign(1)
|
||||
|
||||
val m = JustMod
|
||||
m <!FORBIDDEN_BINARY_MOD_AS_REM!>%=<!> 1
|
||||
m.modAssign(1)
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
|
||||
public object JustMod {
|
||||
private constructor JustMod()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final operator fun mod(/*0*/ x: kotlin.Int): kotlin.Unit
|
||||
public final operator fun modAssign(/*0*/ x: kotlin.Int): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public object ModAndRem {
|
||||
private constructor ModAndRem()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final operator fun mod(/*0*/ x: kotlin.Int): kotlin.Unit
|
||||
public final operator fun modAssign(/*0*/ x: kotlin.Int): kotlin.Unit
|
||||
public final operator fun rem(/*0*/ x: kotlin.Int): kotlin.Unit
|
||||
public final operator fun remAssign(/*0*/ x: kotlin.Int): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -13813,6 +13813,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/operatorRem/doNotResolveToInapplicableRem.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forbiddenModOperatorConvention.kt")
|
||||
public void testForbiddenModOperatorConvention() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("modWithRemAssign.kt")
|
||||
public void testModWithRemAssign() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/operatorRem/modWithRemAssign.kt");
|
||||
|
||||
Generated
+5
@@ -13813,6 +13813,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/operatorRem/doNotResolveToInapplicableRem.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("forbiddenModOperatorConvention.kt")
|
||||
public void testForbiddenModOperatorConvention() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/operatorRem/forbiddenModOperatorConvention.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("modWithRemAssign.kt")
|
||||
public void testModWithRemAssign() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/operatorRem/modWithRemAssign.kt");
|
||||
|
||||
@@ -77,6 +77,7 @@ enum class LanguageFeature(
|
||||
AllowContractsForCustomFunctions(KOTLIN_1_3, kind = UNSTABLE_FEATURE),
|
||||
ProhibitLocalAnnotations(KOTLIN_1_3, kind = BUG_FIX),
|
||||
ProhibitSmartcastsOnLocalDelegatedProperty(KOTLIN_1_3, kind = BUG_FIX),
|
||||
ProhibitOperatorMod(KOTLIN_1_3, kind = BUG_FIX),
|
||||
|
||||
StrictJavaNullabilityAssertions(sinceVersion = null, defaultState = State.DISABLED),
|
||||
ProperIeee754Comparisons(sinceVersion = null, defaultState = State.DISABLED),
|
||||
|
||||
Reference in New Issue
Block a user