Preliminary support for extension functions: they participate in overload resolution only if no such name is found in the receiver type itself.

This commit is contained in:
Andrey Breslav
2011-05-19 00:06:01 +04:00
parent 25799cf2f0
commit 00e2c9dde3
15 changed files with 192 additions and 20 deletions
@@ -1,6 +1,7 @@
package org.jetbrains.jet.lang.descriptors; package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections; import java.util.Collections;
@@ -26,12 +27,13 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements
@Override @Override
@Deprecated @Deprecated
public FunctionDescriptor initialize(@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull JetType unsubstitutedReturnType) { public FunctionDescriptor initialize(@Nullable JetType receiverType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull JetType unsubstitutedReturnType) {
return super.initialize(typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType); assert receiverType == null;
return super.initialize(null, typeParameters, unsubstitutedValueParameters, unsubstitutedReturnType);
} }
public ConstructorDescriptor initialize(@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters) { public ConstructorDescriptor initialize(@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters) {
super.initialize(Collections.<TypeParameterDescriptor>emptyList(), unsubstitutedValueParameters, getContainingDeclaration().getDefaultType()); super.initialize(null, Collections.<TypeParameterDescriptor>emptyList(), unsubstitutedValueParameters, getContainingDeclaration().getDefaultType());
return this; return this;
} }
@@ -16,8 +16,8 @@ public interface FunctionDescriptor extends DeclarationDescriptor {
@NotNull @NotNull
DeclarationDescriptor getContainingDeclaration(); DeclarationDescriptor getContainingDeclaration();
// @Nullable @Nullable
// JetType getReceiverType(); JetType getReceiverType();
@NotNull @NotNull
List<TypeParameterDescriptor> getTypeParameters(); List<TypeParameterDescriptor> getTypeParameters();
@@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor; import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.Variance;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -18,9 +19,9 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
private List<TypeParameterDescriptor> typeParameters; private List<TypeParameterDescriptor> typeParameters;
private List<ValueParameterDescriptor> unsubstitutedValueParameters; private List<ValueParameterDescriptor> unsubstitutedValueParameters;
private JetType unsubstitutedReturnType; private JetType unsubstitutedReturnType;
private JetType receiverType;
private final Set<FunctionDescriptor> overriddenFunctions = Sets.newHashSet(); private final Set<FunctionDescriptor> overriddenFunctions = Sets.newHashSet();
private final FunctionDescriptor original; private final FunctionDescriptor original;
public FunctionDescriptorImpl( public FunctionDescriptorImpl(
@@ -40,15 +41,22 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
} }
public FunctionDescriptor initialize( public FunctionDescriptor initialize(
@Nullable JetType receiverType,
@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType) { @Nullable JetType unsubstitutedReturnType) {
this.receiverType = receiverType;
this.typeParameters = typeParameters; this.typeParameters = typeParameters;
this.unsubstitutedValueParameters = unsubstitutedValueParameters; this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType; this.unsubstitutedReturnType = unsubstitutedReturnType;
return this; return this;
} }
@Override
public JetType getReceiverType() {
return receiverType;
}
@NotNull @NotNull
@Override @Override
public Set<? extends FunctionDescriptor> getOverriddenFunctions() { public Set<? extends FunctionDescriptor> getOverriddenFunctions() {
@@ -91,6 +99,15 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
FunctionDescriptorImpl substitutedDescriptor; FunctionDescriptorImpl substitutedDescriptor;
substitutedDescriptor = createSubstitutedCopy(); substitutedDescriptor = createSubstitutedCopy();
JetType receiverType = getReceiverType();
JetType substitutedReceiverType = null;
if (receiverType != null) {
substitutedReceiverType = substitutor.substitute(receiverType, Variance.IN_VARIANCE);
if (substitutedReceiverType == null) {
return null;
}
}
List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorUtil.getSubstitutedValueParameters(substitutedDescriptor, this, substitutor); List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorUtil.getSubstitutedValueParameters(substitutedDescriptor, this, substitutor);
if (substitutedValueParameters == null) { if (substitutedValueParameters == null) {
return null; return null;
@@ -102,6 +119,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
} }
substitutedDescriptor.initialize( substitutedDescriptor.initialize(
substitutedReceiverType,
Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable
substitutedValueParameters, substitutedValueParameters,
substitutedReturnType substitutedReturnType
@@ -1,14 +1,13 @@
package org.jetbrains.jet.lang.descriptors; package org.jetbrains.jet.lang.descriptors;
import com.google.common.base.Function;
import com.google.common.collect.BiMap; import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap; import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.WritableScope;
import org.jetbrains.jet.lang.resolve.WritableScopeImpl;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import java.util.*; import java.util.*;
@@ -99,6 +98,10 @@ public class FunctionDescriptorUtil {
@NotNull @NotNull
public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) { public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, trace.getErrorHandler()); WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, trace.getErrorHandler());
JetType receiverType = descriptor.getReceiverType();
if (receiverType != null) {
parameterScope.setThisType(receiverType);
}
for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
parameterScope.addTypeParameterDescriptor(typeParameter); parameterScope.addTypeParameterDescriptor(typeParameter);
} }
@@ -229,4 +232,54 @@ public class FunctionDescriptorUtil {
return OverrideCompatibilityInfo.success(); return OverrideCompatibilityInfo.success();
} }
@NotNull
public static FunctionGroup filteredFunctionGroup(@NotNull final FunctionGroup functionGroup, @NotNull final Function<FunctionDescriptor, Boolean> criterion) {
return new FunctionGroup() {
@NotNull
@Override
public String getName() {
return functionGroup.getName();
}
@NotNull
@Override
public OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
OverloadResolutionResult possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
List<FunctionDescriptor> functionDescriptors = Lists.newArrayList(possiblyApplicableFunctions.getFunctionDescriptors());
for (Iterator<FunctionDescriptor> iterator = functionDescriptors.iterator(); iterator.hasNext(); ) {
FunctionDescriptor functionDescriptor = iterator.next();
if (!criterion.apply(functionDescriptor)) {
iterator.remove();
}
}
if (functionDescriptors.isEmpty()) {
return OverloadResolutionResult.nameNotFound();
}
if (possiblyApplicableFunctions.isSuccess() || possiblyApplicableFunctions.isAmbiguity()) {
if (functionDescriptors.size() == 1) {
return OverloadResolutionResult.success(functionDescriptors.get(0));
}
return OverloadResolutionResult.ambiguity(functionDescriptors);
}
if (functionDescriptors.size() == 1) {
return OverloadResolutionResult.singleFunctionArgumentMismatch(functionDescriptors.get(0));
}
return OverloadResolutionResult.ambiguity(functionDescriptors);
}
@Override
public boolean isEmpty() {
// TODO: not implemented
return false;
}
@NotNull
@Override
public Set<FunctionDescriptor> getFunctionDescriptors() {
// TODO: not implemented
return null;
}
};
}
} }
@@ -31,6 +31,11 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
overriddenGetters.add(overriddenGetter); overriddenGetters.add(overriddenGetter);
} }
@Override
public JetType getReceiverType() {
return null; // TODO
}
@NotNull @NotNull
@Override @Override
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() { public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
@@ -40,6 +40,11 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
overriddenSetters.add(overriddenSetter); overriddenSetters.add(overriddenSetter);
} }
@Override
public JetType getReceiverType() {
return null; // TODO
}
@NotNull @NotNull
@Override @Override
public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() { public List<ValueParameterDescriptor> getUnsubstitutedValueParameters() {
@@ -24,6 +24,18 @@ public class JetFunction extends JetTypeParameterListOwner implements JetDeclara
visitor.visitFunction(this); visitor.visitFunction(this);
} }
public boolean hasTypeParameterListBeforeFunctionName() {
JetTypeParameterList typeParameterList = getTypeParameterList();
if (typeParameterList == null) {
return false;
}
PsiElement nameIdentifier = getNameIdentifier();
if (nameIdentifier == null) {
return false;
}
return nameIdentifier.getTextOffset() > typeParameterList.getTextOffset();
}
@Nullable @IfNotParsed @Nullable @IfNotParsed
public JetParameterList getValueParameterList() { public JetParameterList getValueParameterList() {
return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST); return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST);
@@ -174,8 +174,19 @@ public class ClassDescriptorResolver {
WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler()); WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, trace.getErrorHandler());
innerScope.addLabeledDeclaration(functionDescriptor); innerScope.addLabeledDeclaration(functionDescriptor);
// The two calls below have side-effects on parameterScope
List<TypeParameterDescriptor> typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters()); List<TypeParameterDescriptor> typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters());
JetType receiverType = null;
JetTypeReference receiverTypeRef = function.getReceiverTypeRef();
if (receiverTypeRef != null) {
JetScope scopeForReceiver =
function.hasTypeParameterListBeforeFunctionName()
? innerScope
: scope;
receiverType = typeResolver.resolveType(scopeForReceiver, receiverTypeRef);
}
List<ValueParameterDescriptor> valueParameterDescriptors = resolveValueParameters(functionDescriptor, innerScope, function.getValueParameters()); List<ValueParameterDescriptor> valueParameterDescriptors = resolveValueParameters(functionDescriptor, innerScope, function.getValueParameters());
JetTypeReference returnTypeRef = function.getReturnTypeRef(); JetTypeReference returnTypeRef = function.getReturnTypeRef();
@@ -201,6 +212,7 @@ public class ClassDescriptorResolver {
} }
functionDescriptor.initialize( functionDescriptor.initialize(
receiverType,
typeParameterDescriptors, typeParameterDescriptors,
valueParameterDescriptors, valueParameterDescriptors,
returnType); returnType);
@@ -23,7 +23,7 @@ public class OverloadResolver {
@NotNull @NotNull
public OverloadDomain getOverloadDomain(JetType receiverType, @NotNull JetScope outerScope, @NotNull String name) { public OverloadDomain getOverloadDomain(JetType receiverType, @NotNull JetScope outerScope, @NotNull String name) {
// TODO : extension lookup // TODO : extension lookup
JetScope scope = receiverType == null ? outerScope : receiverType.getMemberScope(); JetScope scope = receiverType == null ? outerScope : new ScopeWithReceiver(outerScope, receiverType, typeChecker);
final FunctionGroup functionGroup = scope.getFunctionGroup(name); final FunctionGroup functionGroup = scope.getFunctionGroup(name);
@@ -1,8 +1,11 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.base.Function;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeChecker;
/** /**
* @author abreslav * @author abreslav
@@ -11,16 +14,33 @@ public class ScopeWithReceiver extends JetScopeImpl {
private final JetScope receiverTypeScope; private final JetScope receiverTypeScope;
private final JetScope outerScope; private final JetScope outerScope;
private final JetTypeChecker typeChecker;
public ScopeWithReceiver(JetScope outerScope, JetType receiverType) { public ScopeWithReceiver(JetScope outerScope, JetType receiverType, JetTypeChecker typeChecker) {
this.outerScope = outerScope; this.outerScope = outerScope;
this.receiverTypeScope = receiverType.getMemberScope(); this.receiverTypeScope = receiverType.getMemberScope();
this.typeChecker = typeChecker;
} }
@NotNull @NotNull
@Override @Override
public FunctionGroup getFunctionGroup(@NotNull String name) { public FunctionGroup getFunctionGroup(@NotNull String name) {
return receiverTypeScope.getFunctionGroup(name); // TODO FunctionGroup functionGroup = receiverTypeScope.getFunctionGroup(name);
if (functionGroup.isEmpty()) {
return FunctionDescriptorUtil.filteredFunctionGroup(outerScope.getFunctionGroup(name),
new Function<FunctionDescriptor, Boolean>() {
@Override
public Boolean apply(@Nullable FunctionDescriptor functionDescriptor) {
if (functionDescriptor == null) return false;
JetType functionReceiverType = functionDescriptor.getReceiverType();
if (functionReceiverType == null) {
return false;
}
return typeChecker.isSubtypeOf(receiverTypeScope.getThisType(), functionReceiverType);
}
});
}
return functionGroup; // TODO
} }
@Override @Override
@@ -249,6 +249,7 @@ public class JavaDescriptorResolver {
methodName methodName
); );
functionDescriptor.initialize( functionDescriptor.initialize(
null,
resolveTypeParameters(method.getTypeParameters()), resolveTypeParameters(method.getTypeParameters()),
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptor, parameters), semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptor, parameters),
semanticServices.getTypeTransformer().transformToType(method.getReturnType()) semanticServices.getTypeTransformer().transformToType(method.getReturnType())
@@ -105,6 +105,7 @@ public class ErrorUtils {
private static FunctionDescriptor createErrorFunction(List<TypeParameterDescriptor> typeParameters, List<JetType> positionedValueArgumentTypes) { private static FunctionDescriptor createErrorFunction(List<TypeParameterDescriptor> typeParameters, List<JetType> positionedValueArgumentTypes) {
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>"); FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>");
return functionDescriptor.initialize( return functionDescriptor.initialize(
null,
typeParameters, typeParameters,
getValueParameters(functionDescriptor, positionedValueArgumentTypes), getValueParameters(functionDescriptor, positionedValueArgumentTypes),
createErrorType("<ERROR FUNCTION RETURN>") createErrorType("<ERROR FUNCTION RETURN>")
@@ -117,6 +118,7 @@ public class ErrorUtils {
private static FunctionDescriptor createErrorFunction(int typeParameterCount, List<JetType> positionedValueParameterTypes) { private static FunctionDescriptor createErrorFunction(int typeParameterCount, List<JetType> positionedValueParameterTypes) {
return new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>").initialize( return new FunctionDescriptorImpl(ERROR_CLASS, Collections.<Annotation>emptyList(), "<ERROR FUNCTION>").initialize(
null,
Collections.<TypeParameterDescriptor>emptyList(), // TODO Collections.<TypeParameterDescriptor>emptyList(), // TODO
Collections.<ValueParameterDescriptor>emptyList(), // TODO Collections.<ValueParameterDescriptor>emptyList(), // TODO
createErrorType("<ERROR FUNCTION RETURN TYPE>") createErrorType("<ERROR FUNCTION RETURN TYPE>")
@@ -1002,7 +1002,7 @@ public class JetTypeInferrer {
public void visitWhenConditionCall(JetWhenConditionCall condition) { public void visitWhenConditionCall(JetWhenConditionCall condition) {
checkNullSafety(finalSubjectType, condition.getOperationTokenNode()); checkNullSafety(finalSubjectType, condition.getOperationTokenNode());
JetExpression callSuffixExpression = condition.getCallSuffixExpression(); JetExpression callSuffixExpression = condition.getCallSuffixExpression();
JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType); JetScope compositeScope = new ScopeWithReceiver(scope, finalSubjectType, semanticServices.getTypeChecker());
if (callSuffixExpression != null) { if (callSuffixExpression != null) {
JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false); JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false);
ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression"); ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression");
@@ -1290,11 +1290,12 @@ public class JetTypeInferrer {
@Override @Override
public void visitQualifiedExpression(JetQualifiedExpression expression) { public void visitQualifiedExpression(JetQualifiedExpression expression) {
// TODO : functions // TODO : functions as values
JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression selectorExpression = expression.getSelectorExpression();
JetExpression receiverExpression = expression.getReceiverExpression(); JetExpression receiverExpression = expression.getReceiverExpression();
JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression); JetType receiverType = new TypeInferrerVisitorWithNamespaces(scope, false).getType(receiverExpression);
if (receiverType != null) { if (receiverType != null) {
// TODO : extensions to 'Any?'
checkNullSafety(receiverType, expression.getOperationTokenNode()); checkNullSafety(receiverType, expression.getOperationTokenNode());
JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression); JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
if (expression.getOperationSign() == JetTokens.QUEST) { if (expression.getOperationSign() == JetTokens.QUEST) {
@@ -1314,7 +1315,7 @@ public class JetTypeInferrer {
} }
private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) { private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) {
JetScope compositeScope = new ScopeWithReceiver(scope, receiverType); JetScope compositeScope = new ScopeWithReceiver(scope, receiverType, semanticServices.getTypeChecker());
if (selectorExpression instanceof JetCallExpression) { if (selectorExpression instanceof JetCallExpression) {
JetCallExpression callExpression = (JetCallExpression) selectorExpression; JetCallExpression callExpression = (JetCallExpression) selectorExpression;
OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList()); OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
@@ -46,6 +46,17 @@ public class DescriptorRenderer {
protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) { protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) {
stringBuilder.append(descriptor.getName()); stringBuilder.append(descriptor.getName());
} }
@Override
public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) {
renderTypeParameter(descriptor, builder);
return null;
}
@Override
public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) {
return super.visitVariableDescriptor(descriptor, builder);
}
}; };
private DescriptorRenderer() {} private DescriptorRenderer() {}
@@ -106,9 +117,18 @@ public class DescriptorRenderer {
@Override @Override
public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) { public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) {
builder.append(renderKeyword("fun")).append(" "); builder.append(renderKeyword("fun")).append(" ");
renderName(descriptor, builder);
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters(); List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters();
renderTypeParameters(typeParameters, builder); renderTypeParameters(typeParameters, builder);
if (!typeParameters.isEmpty()) {
builder.append(" ");
}
JetType receiverType = descriptor.getReceiverType();
if (receiverType != null) {
builder.append(escape(receiverType.toString())).append(".");
}
renderName(descriptor, builder);
builder.append("("); builder.append("(");
for (Iterator<ValueParameterDescriptor> iterator = descriptor.getUnsubstitutedValueParameters().iterator(); iterator.hasNext(); ) { for (Iterator<ValueParameterDescriptor> iterator = descriptor.getUnsubstitutedValueParameters().iterator(); iterator.hasNext(); ) {
ValueParameterDescriptor parameterDescriptor = iterator.next(); ValueParameterDescriptor parameterDescriptor = iterator.next();
@@ -178,7 +198,7 @@ public class DescriptorRenderer {
stringBuilder.append(escape(descriptor.getName())); stringBuilder.append(escape(descriptor.getName()));
} }
private void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) { protected void renderTypeParameter(TypeParameterDescriptor descriptor, StringBuilder builder) {
renderName(descriptor, builder); renderName(descriptor, builder);
if (!descriptor.getUpperBounds().isEmpty()) { if (!descriptor.getUpperBounds().isEmpty()) {
JetType bound = descriptor.getUpperBounds().iterator().next(); JetType bound = descriptor.getUpperBounds().iterator().next();
@@ -0,0 +1,21 @@
fun <~T~T, ~E~E> `T`T.foo(x : `E`E, y : `A`A) : `T`T {
y.`+`plus(1)
y `+`plus 1
y `+1`+ 1.0
this?.`-`minus<T>(this)
this
}
~A~class A
~+1~fun `A`A.plus(a : Any) {
1
}
~+~fun `A`A.plus(a : Int) {
1
}
~-~fun <T> T.minus(t : T) : Int = 1