TopDown resolve for functions
This commit is contained in:
@@ -131,6 +131,7 @@ public class ClassDescriptorResolver {
|
||||
|
||||
return new FunctionDescriptorImpl(
|
||||
function,
|
||||
null,
|
||||
AttributeResolver.INSTANCE.resolveAttributes(function.getModifierList()),
|
||||
function.getName(),
|
||||
typeParameterDescriptors,
|
||||
|
||||
@@ -29,4 +29,9 @@ public class MutableFunctionDescriptor extends MutableDeclarationDescriptor impl
|
||||
public Type getUnsubstitutedReturnType() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionDescriptor getOriginal() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.types.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.types.Type;
|
||||
|
||||
import java.util.List;
|
||||
@@ -14,25 +15,36 @@ public interface OverloadDomain {
|
||||
OverloadDomain EMPTY = new OverloadDomain() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Type getReturnTypeForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
|
||||
public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Type getReturnTypeForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
|
||||
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param typeArguments
|
||||
* @param valueArgumentTypes
|
||||
* @param functionLiteralArgumentType
|
||||
* @return A function descriptor with NO type parameters (they are already substituted), or null
|
||||
*/
|
||||
@Nullable
|
||||
Type getReturnTypeForNamedArguments(
|
||||
FunctionDescriptor getFunctionDescriptorForNamedArguments(
|
||||
@NotNull List<Type> typeArguments,
|
||||
@NotNull Map<String, Type> valueArgumentTypes,
|
||||
@Nullable Type functionLiteralArgumentType);
|
||||
|
||||
/**
|
||||
* @param typeArguments
|
||||
* @param positionedValueArgumentTypes
|
||||
* @return A function descriptor with NO type parameters (they are already substituted), or null
|
||||
*/
|
||||
@Nullable
|
||||
Type getReturnTypeForPositionedArguments(
|
||||
FunctionDescriptor getFunctionDescriptorForPositionedArguments(
|
||||
@NotNull List<Type> typeArguments,
|
||||
@NotNull List<Type> positionedValueArgumentTypes);
|
||||
}
|
||||
|
||||
@@ -19,11 +19,6 @@ public class OverloadResolver {
|
||||
|
||||
@NotNull
|
||||
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
|
||||
return getOverloadDomain(TypeCheckerTrace.DUMMY, receiverType, outerScope, name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadDomain getOverloadDomain(@NotNull TypeCheckerTrace trace, @Nullable Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
|
||||
// TODO : extension lookup
|
||||
JetScope scope = receiverType == null ? outerScope : receiverType.getMemberScope();
|
||||
|
||||
@@ -35,7 +30,7 @@ public class OverloadResolver {
|
||||
|
||||
return new OverloadDomain() {
|
||||
@Override
|
||||
public Type getReturnTypeForPositionedArguments(@NotNull final List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
|
||||
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull final List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
|
||||
Collection<FunctionDescriptor> possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
|
||||
if (possiblyApplicableFunctions.isEmpty()) {
|
||||
return null;
|
||||
@@ -86,14 +81,14 @@ public class OverloadResolver {
|
||||
if (applicable.size() == 0) {
|
||||
return null;
|
||||
} else if (applicable.size() == 1) {
|
||||
return applicable.get(0).getUnsubstitutedReturnType();
|
||||
return applicable.get(0);
|
||||
} else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getReturnTypeForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
|
||||
public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface FunctionDescriptor extends Annotated, Named {
|
||||
public interface FunctionDescriptor extends DeclarationDescriptor {
|
||||
@NotNull
|
||||
List<TypeParameterDescriptor> getTypeParameters();
|
||||
|
||||
@@ -16,4 +17,13 @@ public interface FunctionDescriptor extends Annotated, Named {
|
||||
|
||||
@NotNull
|
||||
Type getUnsubstitutedReturnType();
|
||||
|
||||
/**
|
||||
* @return The descriptor that corresponds to the original declaration of this function.
|
||||
* A descriptor can be obtained from its original by substituting type arguments (of the declaring class
|
||||
* or of the function itself).
|
||||
* null if the current descriptor is original itself
|
||||
*/
|
||||
@Nullable
|
||||
FunctionDescriptor getOriginal();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetFunction;
|
||||
|
||||
import java.util.*;
|
||||
@@ -15,15 +16,19 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl<JetFunctio
|
||||
private final List<ValueParameterDescriptor> unsubstitutedValueParameters;
|
||||
@NotNull
|
||||
private final Type unsubstitutedReturnType;
|
||||
@Nullable
|
||||
private final FunctionDescriptor original;
|
||||
|
||||
public FunctionDescriptorImpl(
|
||||
JetFunction psiElement,
|
||||
@Nullable FunctionDescriptor original,
|
||||
@NotNull List<Attribute> attributes,
|
||||
String name,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
|
||||
@NotNull Type unsubstitutedReturnType) {
|
||||
super(psiElement, attributes, name);
|
||||
this.original = original;
|
||||
this.typeParameters = typeParameters;
|
||||
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
|
||||
this.unsubstitutedReturnType = unsubstitutedReturnType;
|
||||
@@ -47,4 +52,9 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl<JetFunctio
|
||||
return unsubstitutedReturnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionDescriptor getOriginal() {
|
||||
return original;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ public class FunctionDescriptorUtil {
|
||||
public static FunctionDescriptor substituteFunctionDescriptor(@NotNull List<Type> typeArguments, @NotNull FunctionDescriptor functionDescriptor) {
|
||||
return new FunctionDescriptorImpl(
|
||||
ResolveUtil.getJetFunction(functionDescriptor),
|
||||
functionDescriptor,
|
||||
// TODO : substitute
|
||||
functionDescriptor.getAttributes(),
|
||||
functionDescriptor.getName(),
|
||||
|
||||
@@ -299,7 +299,7 @@ public class JetTypeChecker {
|
||||
// TODO : check that all are named
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
|
||||
// result[0] = overloadDomain.getReturnTypeForNamedArguments(typeArguments, valueArguments, functionLiteralArgument);
|
||||
// result[0] = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArguments, functionLiteralArgument);
|
||||
} else {
|
||||
List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
|
||||
for (JetArgument argument : valueArguments) {
|
||||
@@ -319,7 +319,10 @@ public class JetTypeChecker {
|
||||
valueArgumentTypes.add(getType(scope, valueArgument, false));
|
||||
}
|
||||
|
||||
result[0] = overloadDomain.getReturnTypeForPositionedArguments(types, valueArgumentTypes);
|
||||
FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
|
||||
if (functionDescriptor != null) {
|
||||
result[0] = functionDescriptor.getUnsubstitutedReturnType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,6 +337,7 @@ public class JetTypeChecker {
|
||||
|
||||
private OverloadDomain getOverloadDomain(final JetScope scope, JetExpression calleeExpression) {
|
||||
final OverloadDomain[] result = new OverloadDomain[1];
|
||||
final JetReferenceExpression[] reference = new JetReferenceExpression[1];
|
||||
calleeExpression.accept(new JetVisitor() {
|
||||
|
||||
@Override
|
||||
@@ -357,6 +361,7 @@ public class JetTypeChecker {
|
||||
|
||||
Type receiverType = getType(scope, expression.getReceiverExpression(), false);
|
||||
result[0] = OverloadResolver.INSTANCE.getOverloadDomain(receiverType, scope, referenceExpression.getReferencedName());
|
||||
reference[0] = referenceExpression;
|
||||
} else {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
@@ -366,6 +371,7 @@ public class JetTypeChecker {
|
||||
public void visitReferenceExpression(JetReferenceExpression expression) {
|
||||
// a -- create a hierarchical lookup domain for this.a
|
||||
result[0] = OverloadResolver.INSTANCE.getOverloadDomain(null, scope, expression.getReferencedName());
|
||||
reference[0] = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -379,7 +385,21 @@ public class JetTypeChecker {
|
||||
throw new IllegalArgumentException("Unsupported element: " + elem);
|
||||
}
|
||||
});
|
||||
return result[0];
|
||||
return new OverloadDomain() {
|
||||
@Override
|
||||
public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List<Type> typeArguments, @NotNull Map<String, Type> valueArgumentTypes, @Nullable Type functionLiteralArgumentType) {
|
||||
FunctionDescriptor descriptor = result[0].getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType);
|
||||
trace.recordResolutionResult(reference[0], descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
|
||||
FunctionDescriptor descriptor = result[0].getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes);
|
||||
trace.recordResolutionResult(reference[0], descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Type getBlockReturnedType(@NotNull JetScope outerScope, List<JetElement> block) {
|
||||
|
||||
@@ -58,6 +58,11 @@ public class LazySubstitutingFunctionDescriptor implements FunctionDescriptor {
|
||||
return TypeSubstitutor.INSTANCE.substitute(substitutionContext, functionDescriptor.getUnsubstitutedReturnType(), Variance.OUT_VARIANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionDescriptor getOriginal() {
|
||||
return functionDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Attribute> getAttributes() {
|
||||
// TODO : Substitute?
|
||||
|
||||
@@ -4,6 +4,7 @@ class A {
|
||||
}
|
||||
|
||||
fun foo(a : Int) = a
|
||||
fun fooB() = foo(1)
|
||||
fun foo() : Int = 1
|
||||
fun foo1() : B = new B()
|
||||
}
|
||||
|
||||
@@ -40,16 +40,12 @@ public class JetResolveTest extends LightDaemonAnalyzerTestCase {
|
||||
ClassDescriptor classB = membersOfA.getClass("B");
|
||||
assertNotNull(classB);
|
||||
|
||||
FunctionGroup foo = membersOfA.getFunctionGroup("foo");
|
||||
assertFalse(foo.isEmpty());
|
||||
FunctionGroup fooFG = membersOfA.getFunctionGroup("foo");
|
||||
assertFalse(fooFG.isEmpty());
|
||||
|
||||
OverloadDomain overloadsForFoo = OverloadResolver.INSTANCE.getOverloadDomain(null, membersOfA, "foo");
|
||||
Type fooType = overloadsForFoo.getReturnTypeForPositionedArguments(Collections.<Type>emptyList(), Collections.<Type>emptyList());
|
||||
assertEquals(JetStandardClasses.getIntType(), fooType);
|
||||
|
||||
OverloadDomain overloadsForFoo1 = OverloadResolver.INSTANCE.getOverloadDomain(null, membersOfA, "foo1");
|
||||
Type foo1Type = overloadsForFoo1.getReturnTypeForPositionedArguments(Collections.<Type>emptyList(), Collections.<Type>emptyList());
|
||||
assertEquals(new TypeImpl(classB), foo1Type);
|
||||
assertReturnType(membersOfA, "foo", JetStandardClasses.getIntType());
|
||||
assertReturnType(membersOfA, "foo1", new TypeImpl(classB));
|
||||
assertReturnType(membersOfA, "fooB", JetStandardClasses.getIntType());
|
||||
|
||||
JetFunction fooDecl = (JetFunction) classADecl.getDeclarations().get(1);
|
||||
Type expressionType = bindingContext.getExpressionType(fooDecl.getBodyExpression());
|
||||
@@ -58,6 +54,12 @@ public class JetResolveTest extends LightDaemonAnalyzerTestCase {
|
||||
DeclarationDescriptor resolve = bindingContext.resolve((JetReferenceExpression) fooDecl.getBodyExpression());
|
||||
assertSame(bindingContext.getFunctionDescriptor(fooDecl).getUnsubstitutedValueParameters().get(0), resolve);
|
||||
|
||||
JetFunction fooBDecl = (JetFunction) classADecl.getDeclarations().get(2);
|
||||
JetCallExpression fooBBody = (JetCallExpression) fooBDecl.getBodyExpression();
|
||||
JetReferenceExpression refToFoo = (JetReferenceExpression) fooBBody.getCalleeExpression();
|
||||
FunctionDescriptor mustBeFoo = (FunctionDescriptor) bindingContext.resolve(refToFoo);
|
||||
assertSame(bindingContext.getFunctionDescriptor(fooDecl), mustBeFoo.getOriginal());
|
||||
|
||||
JetClass classCDecl = (JetClass) declarations.get(1);
|
||||
ClassDescriptor classC = bindingContext.getClassDescriptor(classCDecl);
|
||||
assertNotNull(classC);
|
||||
@@ -69,7 +71,13 @@ public class JetResolveTest extends LightDaemonAnalyzerTestCase {
|
||||
assertNotNull(classC_B);
|
||||
assertNotSame(classC_B, classB);
|
||||
assertEquals(classC.getTypeConstructor(), classC_B.getTypeConstructor().getSupertypes().iterator().next().getConstructor());
|
||||
}
|
||||
|
||||
|
||||
private void assertReturnType(JetScope membersOfA, String foo, Type returnType) {
|
||||
OverloadDomain overloadsForFoo = OverloadResolver.INSTANCE.getOverloadDomain(null, membersOfA, foo);
|
||||
FunctionDescriptor descriptorForFoo = overloadsForFoo.getFunctionDescriptorForPositionedArguments(Collections.<Type>emptyList(), Collections.<Type>emptyList());
|
||||
assertNotNull(descriptorForFoo);
|
||||
Type fooType = descriptorForFoo.getUnsubstitutedReturnType();
|
||||
assertEquals(returnType, fooType);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user