diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 9ea1e53a948..5cf4b728080 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -122,7 +122,8 @@ public class ClassDescriptorResolver { AttributeResolver.INSTANCE.resolveAttributes(valueParameter.getModifierList()), valueParameter.getName(), TypeResolver.INSTANCE.resolveType(parameterScope, typeReference), - valueParameter.getDefaultValue() != null + valueParameter.getDefaultValue() != null, + false // TODO : varargs ); // TODO : Default values??? diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java index dd80b884f5d..71b8a6d9003 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScope.java @@ -29,5 +29,5 @@ public interface JetScope { Type getThisType(); @NotNull - OverloadDomain getOverloadDomain(Type receiverType, String referencedName); + OverloadDomain getOverloadDomain(@Nullable Type receiverType, @NotNull String referencedName); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java index f59087e3770..a9144680a59 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java @@ -46,7 +46,7 @@ public class JetScopeAdapter implements JetScope { @NotNull @Override - public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { + public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) { return scope.getOverloadDomain(receiverType, referencedName); } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java index 38240e783ca..3746ad1e585 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java @@ -40,7 +40,7 @@ public abstract class JetScopeImpl implements JetScope { @NotNull @Override - public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { - return OverloadDomain.EMPTY; + public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) { + return receiverType.getMemberScope().getOverloadDomain(null, referencedName); } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java index 35624b3c5e0..e3f848a945d 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java @@ -55,7 +55,9 @@ public class SubstitutingScope implements JetScope { @NotNull @Override - public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { - throw new UnsupportedOperationException(); // TODO + public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) { + final OverloadDomain workerDomain = workerScope.getOverloadDomain(receiverType, referencedName); + // TODO: !!! + return workerDomain; } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java b/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java index ebd6c2af005..85ef019a4ed 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java @@ -65,7 +65,7 @@ public class WritableFunctionGroup implements FunctionGroup { private FunctionDescriptor substituteFunctionDescriptor(List typeArguments, FunctionDescriptor functionDescriptor) { return new FunctionDescriptor( - // TODO : substitute + // TODO : substitute functionDescriptor.getAttributes(), functionDescriptor.getName(), Collections.emptyList(), // TODO : questionable diff --git a/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java b/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java index 018feb706e0..c35d480cc92 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java @@ -4,10 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.types.*; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * @author abreslav @@ -71,7 +68,7 @@ public class WritableScope implements JetScope { @NotNull @Override - public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { + public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) { final FunctionGroup functionGroup = getFunctionGroups().get(referencedName); if (functionGroup == null) { return OverloadDomain.EMPTY; @@ -85,7 +82,55 @@ public class WritableScope implements JetScope { return null; } - throw new UnsupportedOperationException(); + List applicable = new ArrayList(); + + descLoop: + for (FunctionDescriptor descriptor : possiblyApplicableFunctions) { + // ASSERT: type arguments are figured out and substituted by this time!!! + assert descriptor.getTypeParameters().isEmpty(); + + List parameters = descriptor.getUnsubstitutedValueParameters(); + if (parameters.size() >= positionedValueArgumentTypes.size()) { + // possibly, some default values + // possibly, nothing passed to a vararg + // possibly, a single value passed to a vararg + // possibly an array/list/etc passed as a whole vararg + for (int i = 0, positionedValueArgumentTypesSize = positionedValueArgumentTypes.size(); i < positionedValueArgumentTypesSize; i++) { + Type argumentType = positionedValueArgumentTypes.get(i); + Type parameterType = parameters.get(i).getType(); + // TODO : handle vararg cases here + if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) { + continue descLoop; + } + } + } else { + // vararg + int nonVarargs = parameters.size() - 1; + for (int i = 0; i < nonVarargs; i++) { + Type argumentType = positionedValueArgumentTypes.get(i); + Type parameterType = parameters.get(i).getType(); + if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) { + continue descLoop; + } + } + Type varArgType = parameters.get(nonVarargs).getType(); + for (int i = nonVarargs, args = positionedValueArgumentTypes.size(); i < args; i++) { + Type argumentType = positionedValueArgumentTypes.get(i); + if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, varArgType)) { + continue descLoop; + } + } + } + applicable.add(descriptor); + } + + if (applicable.size() == 0) { + return null; + } else if (applicable.size() == 1) { + return applicable.get(0).getUnsubstitutedReturnType(); + } else { + throw new UnsupportedOperationException(); + } } @Override diff --git a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java index ad5b42c53a9..b28ab789396 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ErrorType.java +++ b/idea/src/org/jetbrains/jet/lang/types/ErrorType.java @@ -45,7 +45,7 @@ public class ErrorType { @NotNull @Override - public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { + public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) { throw new UnsupportedOperationException(); // TODO } }; diff --git a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java index 50942f6f6f7..72fd3828596 100644 --- a/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/types/FunctionDescriptor.java @@ -1,7 +1,6 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.resolve.TypeResolver; import java.util.ArrayList; import java.util.HashMap; @@ -84,7 +83,8 @@ public class FunctionDescriptor extends MemberDescriptorImpl { unsubstitutedValueParameter.getAttributes(), unsubstitutedValueParameter.getName(), TypeSubstitutor.INSTANCE.substitute(context, unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE), - unsubstitutedValueParameter.hasDefaultValue() + unsubstitutedValueParameter.hasDefaultValue(), + unsubstitutedValueParameter.isVararg() )); } return result; diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index f9bbf6471d9..a8469a30597 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -303,13 +303,24 @@ public class JetTypeChecker { // result[0] = overloadDomain.getReturnTypeForNamedArguments(typeArguments, valueArguments, functionLiteralArgument); } else { - throw new UnsupportedOperationException(); // TODO -// List positionedValueArguments = new ArrayList(); -// for (JetArgument argument : valueArguments) { -// positionedValueArguments.add(argument.getArgumentExpression()); -// } -// positionedValueArguments.addAll(functionLiteralArguments); -// result[0] = overloadDomain.getReturnTypeForPositionedArguments(typeArguments, positionedValueArguments); + List positionedValueArguments = new ArrayList(); + for (JetArgument argument : valueArguments) { + positionedValueArguments.add(argument.getArgumentExpression()); + } + positionedValueArguments.addAll(functionLiteralArguments); + + List types = new ArrayList(); + for (JetTypeProjection projection : typeArguments) { + // TODO : check that there's no projection + types.add(TypeResolver.INSTANCE.resolveType(scope, projection.getTypeReference())); + } + + List valueArgumentTypes = new ArrayList(); + for (JetExpression valueArgument : positionedValueArguments) { + valueArgumentTypes.add(getType(scope, valueArgument, false)); + } + + result[0] = overloadDomain.getReturnTypeForPositionedArguments(types, valueArgumentTypes); } } @@ -622,6 +633,11 @@ public class JetTypeChecker { throw new UnsupportedOperationException(); // TODO } + public boolean isConvertibleTo(Type actual, Type expected) { + // TODO + return isSubtypeOf(actual, expected); + } + public boolean isSubtypeOf(Type subtype, Type supertype) { if (!supertype.isNullable() && subtype.isNullable()) { return false; diff --git a/idea/src/org/jetbrains/jet/lang/types/ValueParameterDescriptorImpl.java b/idea/src/org/jetbrains/jet/lang/types/ValueParameterDescriptorImpl.java index db385d8aa85..caa5cb1d7a0 100644 --- a/idea/src/org/jetbrains/jet/lang/types/ValueParameterDescriptorImpl.java +++ b/idea/src/org/jetbrains/jet/lang/types/ValueParameterDescriptorImpl.java @@ -7,10 +7,12 @@ import java.util.List; */ public class ValueParameterDescriptorImpl extends PropertyDescriptorImpl implements ValueParameterDescriptor { private final boolean hasDefaultValue; + private final boolean isVararg; - public ValueParameterDescriptorImpl(List attributes, String name, Type type, boolean hasDefaultValue) { + public ValueParameterDescriptorImpl(List attributes, String name, Type type, boolean hasDefaultValue, boolean isVararg) { super(attributes, name, type); this.hasDefaultValue = hasDefaultValue; + this.isVararg = isVararg; } @Override @@ -25,6 +27,6 @@ public class ValueParameterDescriptorImpl extends PropertyDescriptorImpl impleme @Override public boolean isVararg() { - throw new UnsupportedOperationException(); // TODO + return isVararg; } } diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 8c7e873472f..96616c5a205 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -320,7 +320,9 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { public void testOverloads() throws Exception { assertType("new Functions().f()", "Unit"); assertType("new Functions().f(1)", "Int"); - assertType("new Functions().f(1d)", "Any"); + assertType("new Functions().f(1d)", (String) null); + assertType("new Functions().f(())", "Double"); + assertType("new Functions().f(1d)", "Any"); } // public void testImplicitConversions() throws Exception { @@ -402,8 +404,8 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { Project project = getProject(); JetExpression jetExpression = JetChangeUtil.createExpression(project, expression); Type type = JetTypeChecker.INSTANCE.getType(scope, jetExpression, false); - Type expectedType = makeType(expectedTypeStr); - assertTrue(type + " != " + expectedType, TypeImpl.equalTypes(type, expectedType)); + Type expectedType = expectedTypeStr == null ? null : makeType(expectedTypeStr); + assertEquals(expectedType, type); } private static Type makeType(String typeStr) { @@ -431,6 +433,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { "fun f() : Unit {} " + "fun f(a : Int) : Int {} " + "fun f(a : T) : Any {} " + + "fun f(a : Unit) : T {} " + "}" };