Automatically put 'operator' modifier on appropriate Java methods

This commit is contained in:
Yan Zhulanow
2015-10-05 15:42:39 +03:00
parent 2c848b8bb0
commit 937d1913b8
67 changed files with 285 additions and 215 deletions
@@ -109,9 +109,7 @@ public class JavaConstructorDescriptor extends ConstructorDescriptorImpl impleme
DescriptorsPackage.createEnhancedValueParameters(enhancedValueParametersTypes, getValueParameters(), enhanced),
enhancedReturnType,
getModality(),
getVisibility(),
false,
false
getVisibility()
);
return enhanced;
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.types.JetType;
import org.jetbrains.kotlin.types.TypeSubstitutor;
import org.jetbrains.kotlin.util.OperatorNameConventions;
import java.util.List;
@@ -73,6 +74,24 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement
return new JavaMethodDescriptor(containingDeclaration, null, annotations, name, Kind.DECLARATION, source);
}
@NotNull
@Override
public SimpleFunctionDescriptorImpl initialize(
@Nullable JetType receiverParameterType,
@Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType,
@Nullable Modality modality,
@NotNull Visibility visibility
) {
SimpleFunctionDescriptorImpl descriptor = super.initialize(
receiverParameterType, dispatchReceiverParameter, typeParameters, unsubstitutedValueParameters,
unsubstitutedReturnType, modality, visibility);
setOperator(OperatorNameConventions.INSTANCE$.canBeOperator(descriptor));
return descriptor;
}
@Override
public boolean hasStableParameterNames() {
assert parameterNamesStatus != null : "Parameter names status was not set: " + this;
@@ -122,7 +141,7 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement
// 1. creates full copy of descriptor
// 2. copies method's type parameters (with new containing declaration) and properly substitute to them in value parameters, return type and etc.
JavaMethodDescriptor enhancedMethod = (JavaMethodDescriptor) doSubstitute(
TypeSubstitutor.EMPTY, getContainingDeclaration(), getModality(), getVisibility(), false, false, getOriginal(),
TypeSubstitutor.EMPTY, getContainingDeclaration(), getModality(), getVisibility(), isOperator(), isInfix(), getOriginal(),
/* copyOverrides = */ true, getKind(),
enhancedValueParameters, enhancedReceiverType, enhancedReturnType
);
@@ -131,9 +131,7 @@ public abstract class LazyJavaScope(
effectiveSignature.getValueParameters(),
effectiveSignature.getReturnType(),
Modality.convertFromFlags(method.isAbstract(), !method.isFinal()),
method.getVisibility(),
false,
false
method.getVisibility()
)
functionDescriptorImpl.setParameterNamesStatus(effectiveSignature.hasStableParameterNames(), valueParameters.hasSynthesizedNames)
@@ -60,10 +60,9 @@ public class FunctionInvokeDescriptor private constructor(
.map { createValueParameter(result, it.index, it.value) },
typeParameters.last().getDefaultType(),
Modality.ABSTRACT,
Visibilities.PUBLIC,
true,
false
Visibilities.PUBLIC
)
result.isOperator = true
return result
}
@@ -60,7 +60,7 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
@NotNull Visibility visibility
) {
super.initialize(null, calculateDispatchReceiverParameter(), typeParameters, unsubstitutedValueParameters, null,
Modality.FINAL, visibility, false, false);
Modality.FINAL, visibility);
return this;
}
@@ -42,8 +42,8 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
private ReceiverParameterDescriptor dispatchReceiverParameter;
private Modality modality;
private Visibility visibility = Visibilities.UNKNOWN;
private boolean isOperator;
private boolean isInfix;
private boolean isOperator = false;
private boolean isInfix = false;
private final Set<FunctionDescriptor> overriddenFunctions = SmartSet.create();
private final FunctionDescriptor original;
private final Kind kind;
@@ -69,17 +69,13 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType,
@Nullable Modality modality,
@NotNull Visibility visibility,
boolean isOperator,
boolean isInfix
@NotNull Visibility visibility
) {
this.typeParameters = UtilsPackage.toReadOnlyList(typeParameters);
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType;
this.modality = modality;
this.visibility = visibility;
this.isOperator = isOperator;
this.isInfix = isInfix;
this.extensionReceiverParameter = DescriptorFactory.createExtensionReceiverParameterForCallable(this, receiverParameterType);
this.dispatchReceiverParameter = dispatchReceiverParameter;
@@ -106,6 +102,14 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
this.visibility = visibility;
}
public void setOperator(boolean isOperator) {
this.isOperator = isOperator;
}
public void setInfix(boolean isInfix) {
this.isInfix = isInfix;
}
public void setReturnType(@NotNull JetType unsubstitutedReturnType) {
if (this.unsubstitutedReturnType != null) {
// TODO: uncomment and fix tests
@@ -309,10 +313,10 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo
substitutedValueParameters,
substitutedReturnType,
newModality,
newVisibility,
isOperator,
isInfix
newVisibility
);
substitutedDescriptor.setOperator(isOperator);
substitutedDescriptor.setInfix(isInfix);
if (copyOverrides) {
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
@@ -37,7 +37,7 @@ public class ScriptCodeDescriptor extends FunctionDescriptorImpl {
@NotNull List<ValueParameterDescriptor> valueParameters,
@NotNull JetType returnType) {
super.initialize(null, dispatchReceiverParameter, Collections.<TypeParameterDescriptor>emptyList(), valueParameters, returnType,
Modality.FINAL, Visibilities.INTERNAL, false, false);
Modality.FINAL, Visibilities.INTERNAL);
}
@NotNull
@@ -58,12 +58,10 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType,
@Nullable Modality modality,
@NotNull Visibility visibility,
boolean isOperator,
boolean isInfix
@NotNull Visibility visibility
) {
super.initialize(receiverParameterType, dispatchReceiverParameter, typeParameters, unsubstitutedValueParameters,
unsubstitutedReturnType, modality, visibility, isOperator, isInfix);
unsubstitutedReturnType, modality, visibility);
return this;
}
@@ -103,7 +103,7 @@ public class DescriptorFactory {
return values.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(),
getBuiltIns(enumClass).getArrayType(Variance.INVARIANT, enumClass.getDefaultType()),
Modality.FINAL, Visibilities.PUBLIC, false, false);
Modality.FINAL, Visibilities.PUBLIC);
}
@NotNull
@@ -117,7 +117,7 @@ public class DescriptorFactory {
);
return valueOf.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
Collections.singletonList(parameterDescriptor), enumClass.getDefaultType(),
Modality.FINAL, Visibilities.PUBLIC, false, false);
Modality.FINAL, Visibilities.PUBLIC);
}
@Nullable
@@ -499,9 +499,7 @@ public class ErrorUtils {
Collections.<ValueParameterDescriptor>emptyList(), // TODO
createErrorType("<ERROR FUNCTION RETURN TYPE>"),
Modality.OPEN,
Visibilities.INTERNAL,
false,
false
Visibilities.INTERNAL
);
return function;
}
@@ -0,0 +1,86 @@
/*
* 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.
*/
package org.jetbrains.kotlin.util
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.name.Name
import kotlin.text.Regex
object OperatorNameConventions {
val EQUALS = Name.identifier("equals")
val IDENTITY_EQUALS = Name.identifier("identityEquals");
val COMPARE_TO = Name.identifier("compareTo")
val CONTAINS = Name.identifier("contains")
val INVOKE = Name.identifier("invoke")
val ITERATOR = Name.identifier("iterator")
val GET = Name.identifier("get")
val SET = Name.identifier("set")
val NEXT = Name.identifier("next")
val HAS_NEXT = Name.identifier("hasNext")
val COMPONENT_REGEX = Regex("component\\d+")
val AND = Name.identifier("and")
val OR = Name.identifier("or")
val INC = Name.identifier("inc")
val DEC = Name.identifier("dec")
val PLUS = Name.identifier("plus")
val MINUS = Name.identifier("minus")
val NOT = Name.identifier("not")
val TIMES = Name.identifier("times")
val DIV = Name.identifier("div")
val MOD = Name.identifier("mod")
val RANGE_TO = Name.identifier("rangeTo")
val TIMES_ASSIGN = Name.identifier("timesAssign")
val DIV_ASSIGN = Name.identifier("divAssign")
val MOD_ASSIGN = Name.identifier("modAssign")
val PLUS_ASSIGN = Name.identifier("plusAssign")
val MINUS_ASSIGN = Name.identifier("minusAssign")
// If you add new unary, binary or assignment operators, add it to OperatorConventions as well
private val UNARY_OPERATION_NAMES = setOf(INC, DEC, PLUS, MINUS, NOT)
private val BINARY_OPERATION_NAMES = setOf(TIMES, PLUS, MINUS, DIV, MOD, RANGE_TO)
private val ASSIGNMENT_OPERATIONS = setOf(TIMES_ASSIGN, DIV_ASSIGN, MOD_ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN)
fun canBeOperator(functionDescriptor: FunctionDescriptor): Boolean {
val name = functionDescriptor.name
return when {
GET == name -> true
SET == name -> true
INVOKE == name -> true
CONTAINS == name -> true
ITERATOR == name -> true
NEXT == name -> true
HAS_NEXT == name -> true
EQUALS == name -> true
COMPARE_TO == name -> true
UNARY_OPERATION_NAMES.any { it == name } && functionDescriptor.valueParameters.isEmpty() -> true
BINARY_OPERATION_NAMES.any { it == name } && functionDescriptor.valueParameters.size() == 1 -> true
ASSIGNMENT_OPERATIONS.any { it == name } -> true
name.asString().matches(COMPONENT_REGEX) -> true
else -> false
}
}
}
@@ -151,10 +151,10 @@ public class MemberDeserializer(private val c: DeserializationContext) {
local.memberDeserializer.valueParameters(proto, AnnotatedCallableKind.FUNCTION),
local.typeDeserializer.type(proto.returnType),
Deserialization.modality(Flags.MODALITY.get(proto.flags)),
Deserialization.visibility(Flags.VISIBILITY.get(proto.flags)),
Flags.OLD_IS_OPERATOR.get(proto.flags),
Flags.OLD_IS_INFIX.get(proto.flags)
Deserialization.visibility(Flags.VISIBILITY.get(proto.flags))
)
function.isOperator = Flags.OLD_IS_OPERATOR.get(proto.flags)
function.isInfix = Flags.OLD_IS_INFIX.get(proto.flags)
return function
}