Prohibit operator mod as declaration and calls that resolved via it

#KT-24197 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2018-06-28 03:04:13 +03:00
parent c887b88ed9
commit 2e88f5c47d
16 changed files with 149 additions and 8 deletions
@@ -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);
@@ -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
@@ -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()))
}