Gradual migration of operator 'mod' to 'rem'
- Introduce new 'rem' operator convention - Prefer 'rem()' to 'mod()' when both are available, even if mod() is a member, and rem() -- an extension - Place operator 'rem' under the language feature
This commit is contained in:
@@ -1,21 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,6 +24,7 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions.REM_TO_MOD_OPERATION_NAMES
|
||||
import org.jetbrains.kotlin.util.CheckResult
|
||||
import org.jetbrains.kotlin.util.OperatorChecks
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
@@ -57,10 +42,20 @@ object OperatorModifierChecker {
|
||||
|
||||
val checkResult = OperatorChecks.check(functionDescriptor)
|
||||
if (checkResult.isSuccess) {
|
||||
if (functionDescriptor.name in COROUTINE_OPERATOR_NAMES
|
||||
&& !languageVersionSettings.supportsFeature(LanguageFeature.Coroutines)) {
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, LanguageFeature.Coroutines))
|
||||
when (functionDescriptor.name) {
|
||||
in COROUTINE_OPERATOR_NAMES -> {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.Coroutines)) {
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, LanguageFeature.Coroutines))
|
||||
}
|
||||
}
|
||||
|
||||
in REM_TO_MOD_OPERATION_NAMES.keys -> {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.OperatorRem)) {
|
||||
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, LanguageFeature.OperatorRem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.coroutines.getExpectedTypeForCoroutineControllerHandleResult
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtToken
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.getImplicitReceiversHierarchy
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.TypeUtils.DONT_CARE
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
@@ -127,6 +128,14 @@ fun isOrOverridesSynthesized(descriptor: CallableMemberDescriptor): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
fun isBinaryRemOperator(call: Call): Boolean {
|
||||
val callElement = call.callElement as? KtBinaryExpression ?: return false
|
||||
val operator = callElement.operationToken
|
||||
if (operator !is KtToken) return false
|
||||
|
||||
val name = OperatorConventions.getNameForOperationSymbol(operator, true, true)
|
||||
return name in OperatorConventions.REM_TO_MOD_OPERATION_NAMES.keys
|
||||
}
|
||||
|
||||
fun isConventionCall(call: Call): Boolean {
|
||||
if (call is CallTransformer.CallForImplicitInvoke) return true
|
||||
|
||||
+14
-1
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.CandidateResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isBinaryRemOperator
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isInfixCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.createLookupLocation
|
||||
@@ -49,6 +50,7 @@ import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*
|
||||
import org.jetbrains.kotlin.types.DeferredType
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
@@ -159,7 +161,18 @@ class NewResolutionOldInference(
|
||||
return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor))
|
||||
}
|
||||
|
||||
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference)
|
||||
var candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference)
|
||||
|
||||
// Temporary hack to resolve 'rem' as 'mod' if the first is do not present
|
||||
val emptyOrInapplicableCandidates = candidates.isEmpty() ||
|
||||
candidates.all {
|
||||
it.candidateStatus.resultingApplicability == ResolutionCandidateApplicability.INAPPLICABLE
|
||||
}
|
||||
if (emptyOrInapplicableCandidates && isBinaryRemOperator(context.call)) {
|
||||
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name]
|
||||
val processorForDeprecatedName = kind.createTowerProcessor(this, deprecatedName!!, tracing, scopeTower, detailedReceiver, context)
|
||||
candidates = towerResolver.runResolve(scopeTower, processorForDeprecatedName, useOrder = kind != ResolutionKind.CallableReference)
|
||||
}
|
||||
|
||||
if (candidates.isEmpty()) {
|
||||
if (reportAdditionalDiagnosticIfNoCandidates(context, name, kind, scopeTower, detailedReceiver)) {
|
||||
|
||||
+8
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -60,10 +60,15 @@ public class OperatorConventions {
|
||||
.put(KtTokens.PLUS, PLUS)
|
||||
.put(KtTokens.MINUS, MINUS)
|
||||
.put(KtTokens.DIV, DIV)
|
||||
.put(KtTokens.PERC, MOD)
|
||||
.put(KtTokens.PERC, REM)
|
||||
.put(KtTokens.RANGE, RANGE_TO)
|
||||
.build();
|
||||
|
||||
public static final ImmutableBiMap<Name, Name> REM_TO_MOD_OPERATION_NAMES = ImmutableBiMap.<Name, Name>builder()
|
||||
.put(REM, MOD)
|
||||
.put(REM_ASSIGN, MOD_ASSIGN)
|
||||
.build();
|
||||
|
||||
public static final ImmutableSet<KtSingleValueToken> NOT_OVERLOADABLE =
|
||||
ImmutableSet.of(KtTokens.ANDAND, KtTokens.OROR, KtTokens.ELVIS, KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ);
|
||||
|
||||
@@ -85,7 +90,7 @@ public class OperatorConventions {
|
||||
public static final ImmutableBiMap<KtSingleValueToken, Name> ASSIGNMENT_OPERATIONS = ImmutableBiMap.<KtSingleValueToken, Name>builder()
|
||||
.put(KtTokens.MULTEQ, TIMES_ASSIGN)
|
||||
.put(KtTokens.DIVEQ, DIV_ASSIGN)
|
||||
.put(KtTokens.PERCEQ, MOD_ASSIGN)
|
||||
.put(KtTokens.PERCEQ, REM_ASSIGN)
|
||||
.put(KtTokens.PLUSEQ, PLUS_ASSIGN)
|
||||
.put(KtTokens.MINUSEQ, MINUS_ASSIGN)
|
||||
.build();
|
||||
|
||||
Reference in New Issue
Block a user