JET-49 Resolve extension functions with generic receivers
+ Error report fixed for 'new java.util.List<Int>'
This commit is contained in:
@@ -17,4 +17,7 @@ public interface JetCall {
|
||||
|
||||
@NotNull
|
||||
List<JetExpression> getFunctionLiteralArguments();
|
||||
|
||||
@NotNull
|
||||
JetElement asElement();
|
||||
}
|
||||
|
||||
@@ -45,6 +45,12 @@ public class JetCallExpression extends JetExpression implements JetCall {
|
||||
return findChildrenByType(JetNodeTypes.FUNCTION_LITERAL);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement asElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetArgument> getValueArguments() {
|
||||
|
||||
@@ -37,4 +37,10 @@ public class JetDelegatorToSuperCall extends JetDelegationSpecifier implements J
|
||||
public List<JetExpression> getFunctionLiteralArguments() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement asElement() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,12 @@ public class JetDelegatorToThisCall extends JetDelegationSpecifier implements Je
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement asElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public JetReferenceExpression getThisReference() {
|
||||
return findChildByClass(JetThisReferenceExpression.class);
|
||||
}
|
||||
|
||||
@@ -45,4 +45,10 @@ public class JetNewExpression extends JetExpression implements JetCall {
|
||||
return findChildrenByType(JetNodeTypes.FUNCTION_LITERAL);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement asElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,9 +5,13 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionGroup;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -21,17 +25,17 @@ public class OverloadResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadDomain getOverloadDomain(JetType receiverType, @NotNull JetScope outerScope, @NotNull String name) {
|
||||
public OverloadDomain getOverloadDomain(@Nullable JetType receiverType, @NotNull JetScope outerScope, @NotNull String name) {
|
||||
// TODO : extension lookup
|
||||
JetScope scope = receiverType == null ? outerScope : new ScopeWithReceiver(outerScope, receiverType, typeChecker);
|
||||
|
||||
final FunctionGroup functionGroup = scope.getFunctionGroup(name);
|
||||
|
||||
return getOverloadDomain(functionGroup);
|
||||
return getOverloadDomain(receiverType, functionGroup);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadDomain getOverloadDomain(@NotNull final FunctionGroup functionGroup) {
|
||||
public OverloadDomain getOverloadDomain(@Nullable final JetType receiverType, @NotNull final FunctionGroup functionGroup) {
|
||||
if (functionGroup.isEmpty()) {
|
||||
return OverloadDomain.EMPTY;
|
||||
}
|
||||
@@ -56,6 +60,21 @@ public class OverloadResolver {
|
||||
// ASSERT: type arguments are figured out and substituted by this time!!!
|
||||
assert descriptor.getTypeParameters().isEmpty();
|
||||
|
||||
if (receiverType != null) {
|
||||
// ASSERT : either the receiver in not present or we are in a scope with no top-level functions
|
||||
final JetType functionReceiverType = descriptor.getReceiverType();
|
||||
// final ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
|
||||
// assert functionReceiverType != null || containingDeclaration != null &&
|
||||
// containingDeclaration.getTypeConstructor().equals(receiverType.getConstructor());
|
||||
|
||||
if (functionReceiverType != null && !typeChecker.isSubtypeOf(receiverType, functionReceiverType)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (descriptor.getReceiverType() != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<ValueParameterDescriptor> parameters = descriptor.getUnsubstitutedValueParameters();
|
||||
if (parameters.size() >= positionedValueArgumentTypes.size()) {
|
||||
// possibly, some default values
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
@@ -27,19 +25,20 @@ public class ScopeWithReceiver extends JetScopeImpl {
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
FunctionGroup functionGroup = receiverType.getMemberScope().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;
|
||||
}
|
||||
// TODO : in case of inferred type arguments, substitute the receiver type first
|
||||
return typeChecker.isSubtypeOf(receiverType, functionReceiverType);
|
||||
}
|
||||
});
|
||||
return outerScope.getFunctionGroup(name);
|
||||
// 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;
|
||||
// }
|
||||
// // TODO : in case of inferred type arguments, substitute the receiver type first
|
||||
// return typeChecker.isSubtypeOf(receiverType, functionReceiverType);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
return functionGroup; // TODO
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
private OverloadDomain getOverloadDomain(
|
||||
@Nullable final JetType receiverType,
|
||||
@NotNull final JetScope scope,
|
||||
@NotNull JetExpression calleeExpression,
|
||||
@Nullable PsiElement argumentList
|
||||
@@ -150,6 +151,8 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public void visitQualifiedExpression(JetQualifiedExpression expression) {
|
||||
trace.getErrorHandler().genericError(expression.getNode(), "Unsupported [JetTypeInferrer]");
|
||||
|
||||
// . or ?.
|
||||
JetType receiverType = getType(scope, expression.getReceiverExpression(), false);
|
||||
checkNullSafety(receiverType, expression.getOperationTokenNode());
|
||||
@@ -173,7 +176,7 @@ public class JetTypeInferrer {
|
||||
// a -- create a hierarchical lookup domain for this.a
|
||||
String referencedName = expression.getReferencedName();
|
||||
if (referencedName != null) {
|
||||
result[0] = semanticServices.getOverloadResolver().getOverloadDomain(null, scope, referencedName);
|
||||
result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referencedName);
|
||||
reference[0] = expression;
|
||||
}
|
||||
}
|
||||
@@ -539,7 +542,7 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
FunctionGroup constructors = classDescriptor.getConstructors(projectionsStripped);
|
||||
OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors);
|
||||
OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(null, constructors);
|
||||
JetType constructorReturnedType = resolveOverloads(
|
||||
scope,
|
||||
wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false),
|
||||
@@ -555,6 +558,9 @@ public class JetTypeInferrer {
|
||||
if (argumentList != null) {
|
||||
trace.getErrorHandler().genericError(argumentList.getNode(), "Cannot find an overload for these arguments");
|
||||
}
|
||||
else {
|
||||
trace.getErrorHandler().genericError(call.asElement().getNode(), "Cannot find an overload for these arguments");
|
||||
}
|
||||
constructorReturnedType = receiverType;
|
||||
}
|
||||
// If no upcast needed:
|
||||
@@ -1391,7 +1397,7 @@ public class JetTypeInferrer {
|
||||
JetScope compositeScope = new ScopeWithReceiver(scope, receiverType, semanticServices.getTypeChecker());
|
||||
if (selectorExpression instanceof JetCallExpression) {
|
||||
JetCallExpression callExpression = (JetCallExpression) selectorExpression;
|
||||
OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
|
||||
OverloadDomain overloadDomain = getOverloadDomain(receiverType, compositeScope, callExpression.getCalleeExpression(), callExpression.getValueArgumentList());
|
||||
return resolveOverloads(scope, callExpression, overloadDomain);
|
||||
}
|
||||
else if (selectorExpression instanceof JetSimpleNameExpression) {
|
||||
@@ -1407,7 +1413,7 @@ public class JetTypeInferrer {
|
||||
@Override
|
||||
public void visitCallExpression(JetCallExpression expression) {
|
||||
JetExpression calleeExpression = expression.getCalleeExpression();
|
||||
OverloadDomain overloadDomain = getOverloadDomain(scope, calleeExpression, expression.getValueArgumentList());
|
||||
OverloadDomain overloadDomain = getOverloadDomain(null, scope, calleeExpression, expression.getValueArgumentList());
|
||||
result = resolveOverloads(scope, expression, overloadDomain);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,11 @@ public class DescriptorRenderer {
|
||||
public String renderKeyword(String keyword) {
|
||||
return "<b>" + keyword + "</b>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String renderMessage(String s) {
|
||||
return "<i>" + s + "</i>";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -45,11 +50,6 @@ public class DescriptorRenderer {
|
||||
private final DeclarationDescriptorVisitor<Void, StringBuilder> rootVisitor = new RenderDeclarationDescriptorVisitor();
|
||||
|
||||
private final DeclarationDescriptorVisitor<Void, StringBuilder> subVisitor = new RenderDeclarationDescriptorVisitor() {
|
||||
@Override
|
||||
protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) {
|
||||
stringBuilder.append(descriptor.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, StringBuilder builder) {
|
||||
renderTypeParameter(descriptor, builder);
|
||||
@@ -80,10 +80,30 @@ public class DescriptorRenderer {
|
||||
if (declarationDescriptor == null) return lt() + "null>";
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
declarationDescriptor.accept(rootVisitor, stringBuilder);
|
||||
stringBuilder.append(" " + renderMessage("defined in") + " ");
|
||||
|
||||
final DeclarationDescriptor containingDeclaration = declarationDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration != null) {
|
||||
renderFullyQualifiedName(containingDeclaration, stringBuilder);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public String renderMessage(String s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
private void renderFullyQualifiedName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) {
|
||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (containingDeclaration != null) {
|
||||
renderFullyQualifiedName(containingDeclaration, stringBuilder);
|
||||
stringBuilder.append(".");
|
||||
}
|
||||
stringBuilder.append(escape(descriptor.getName()));
|
||||
}
|
||||
|
||||
private class RenderDeclarationDescriptorVisitor extends DeclarationDescriptorVisitor<Void, StringBuilder> {
|
||||
|
||||
@Override
|
||||
public Void visitValueParameterDescriptor(ValueParameterDescriptor descriptor, StringBuilder builder) {
|
||||
builder.append(renderKeyword("value-parameter")).append(" ");
|
||||
@@ -217,11 +237,6 @@ public class DescriptorRenderer {
|
||||
}
|
||||
|
||||
protected void renderName(DeclarationDescriptor descriptor, StringBuilder stringBuilder) {
|
||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (containingDeclaration != null) {
|
||||
renderName(containingDeclaration, stringBuilder);
|
||||
stringBuilder.append("::");
|
||||
}
|
||||
stringBuilder.append(escape(descriptor.getName()));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,38 @@
|
||||
fun Int?.optint() : Unit
|
||||
val Int?.optval : Unit
|
||||
val Int?.optval : Unit
|
||||
|
||||
fun <T, E> T.foo(x : E, y : A) : T {
|
||||
y.plus(1)
|
||||
y plus 1
|
||||
y + 1.0
|
||||
|
||||
this?.minus<T>(this)
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
class A
|
||||
|
||||
fun A.plus(a : Any) {
|
||||
|
||||
1.foo()
|
||||
true.foo<error>()</error>
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
fun A.plus(a : Int) {
|
||||
1
|
||||
}
|
||||
|
||||
fun <T> T.minus(t : T) : Int = 1
|
||||
|
||||
fun test() {
|
||||
val y = 1.abs
|
||||
}
|
||||
val Int.abs : Int
|
||||
get() = if (this > 0) this else -this;
|
||||
|
||||
val <T> T.foo : T
|
||||
|
||||
fun Int.foo() = this
|
||||
@@ -20,4 +20,6 @@ fun test(l : java.util.List<Int>) {
|
||||
|
||||
Collections.singleton<Int>(1) : Set<Int>?
|
||||
Collections.singleton<Int><error>(1.0)</error>
|
||||
|
||||
<error>new List<Int></error>
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ fun <~T~T, ~E~E> `T`T.foo(x : `E`E, y : `A`A) : `T`T {
|
||||
y `+`plus 1
|
||||
y `+1`+ 1.0
|
||||
|
||||
this?.minus<T>(this)
|
||||
this?.`-`minus<T>(this)
|
||||
|
||||
this
|
||||
}
|
||||
@@ -13,7 +13,7 @@ fun <~T~T, ~E~E> `T`T.foo(x : `E`E, y : `A`A) : `T`T {
|
||||
~+1~fun `A`A.plus(a : Any) {
|
||||
|
||||
1.`foo`foo()
|
||||
true.`!`foo()
|
||||
true.`foo`foo()
|
||||
|
||||
1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user