diff --git a/grammar/src/types.grm b/grammar/src/types.grm index 1532efb9859..290125415ac 100644 --- a/grammar/src/types.grm +++ b/grammar/src/types.grm @@ -12,6 +12,7 @@ Foo, T, Object> // user type type : attributes typeDescriptor +// IF YOU CHANGE THIS, please, update TYPE_FIRST in JetParsing typeDescriptor : selfType : functionType diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 040aafea8f9..926a279046c 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -31,7 +31,7 @@ public class JetExpressionParsing extends AbstractJetParsing { COLON ); - private static final TokenSet EXPRESSION_FIRST = TokenSet.orSet(TokenSet.create( + /*package*/ static final TokenSet EXPRESSION_FIRST = TokenSet.orSet(TokenSet.create( // Prefix MINUS, PLUS, MINUSMINUS, PLUSPLUS, EXCL, LBRACKET, LABEL_IDENTIFIER, AT, ATAT, // Atomic @@ -82,7 +82,7 @@ public class JetExpressionParsing extends AbstractJetParsing { NAMESPACE_KEYWORD // for absolute qualified names ), MODIFIER_KEYWORDS); - private static final TokenSet EXPRESSION_FOLLOW = TokenSet.create( + /*package*/ static final TokenSet EXPRESSION_FOLLOW = TokenSet.create( SEMICOLON, DOUBLE_ARROW, COMMA, RBRACE, RPAR, RBRACKET ); @@ -533,7 +533,7 @@ public class JetExpressionParsing extends AbstractJetParsing { } else if (!parseLiteralConstant()) { // TODO: better recovery if FIRST(expression) did not match - errorAndAdvance("Expecting an expression"); + errorWithRecovery("Expecting an expression", EXPRESSION_FOLLOW); } } @@ -1494,7 +1494,7 @@ public class JetExpressionParsing extends AbstractJetParsing { PsiBuilder.Marker list = mark(); myBuilder.disableNewlines(); - expect(LPAR, "Expecting an argument list", TokenSet.create(RPAR)); + expect(LPAR, "Expecting an argument list", EXPRESSION_FOLLOW); if (!at(RPAR)) { while (true) { @@ -1509,7 +1509,7 @@ public class JetExpressionParsing extends AbstractJetParsing { } } - expect(RPAR, "Expecting ')'"); + expect(RPAR, "Expecting ')'", EXPRESSION_FOLLOW); myBuilder.restoreNewlinesState(); list.done(VALUE_ARGUMENT_LIST); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index 92f175396bb..e7059f3cf0d 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -37,7 +37,7 @@ public class JetParsing extends AbstractJetParsing { private static final TokenSet TYPE_PARAMETER_GT_RECOVERY_SET = TokenSet.create(WHERE_KEYWORD, WRAPS_KEYWORD, LPAR, COLON, LBRACE, GT); private static final TokenSet PARAMETER_NAME_RECOVERY_SET = TokenSet.create(COLON, EQ, COMMA, RPAR); private static final TokenSet NAMESPACE_NAME_RECOVERY_SET = TokenSet.create(DOT, EOL_OR_SEMICOLON); - /*package*/ static final TokenSet TYPE_REF_FIRST = TokenSet.create(LBRACKET, IDENTIFIER, LBRACE, LPAR); + /*package*/ static final TokenSet TYPE_REF_FIRST = TokenSet.create(LBRACKET, IDENTIFIER, LBRACE, LPAR, CAPITALIZED_THIS_KEYWORD); public static JetParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) { builder.setDebugMode(true); @@ -835,10 +835,17 @@ public class JetParsing extends AbstractJetParsing { advance(); // FUN_KEYWORD + // Recovery for the case of class A { fun| } + if (at(RBRACE)) { + error("Function body expected"); + return FUN; + } + if (at(LT)) { parseTypeParameterList(TokenSet.create(LBRACKET, LBRACE, LPAR)); } + int lastDot = findLastBefore(TokenSet.create(DOT), TokenSet.create(LPAR), true); if (lastDot == -1) { // There's no explicit receiver type specified @@ -1246,7 +1253,7 @@ public class JetParsing extends AbstractJetParsing { PsiBuilder.Marker reference = mark(); while (true) { - expect(IDENTIFIER, "Type name expected", TokenSet.create(LT)); + expect(IDENTIFIER, "Type name expected", TokenSet.orSet(JetExpressionParsing.EXPRESSION_FIRST, JetExpressionParsing.EXPRESSION_FOLLOW)); reference.done(REFERENCE_EXPRESSION); parseTypeArgumentList(); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetArgument.java b/idea/src/org/jetbrains/jet/lang/psi/JetArgument.java index a66ae80d56f..5a637440998 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetArgument.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetArgument.java @@ -13,7 +13,7 @@ public class JetArgument extends JetElement { super(node); } - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitArgument(this); } @@ -25,6 +25,9 @@ public class JetArgument extends JetElement { @Nullable public String getArgumentName() { ASTNode firstChildNode = getNode().getFirstChildNode(); + if (firstChildNode == null) { + return null; + } return firstChildNode.getElementType() == JetTokens.IDENTIFIER ? firstChildNode.getText() : null; } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypeReference.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypeReference.java index 241a7ed70e8..abc84e3e270 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypeReference.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypeReference.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; import java.util.ArrayList; @@ -25,6 +26,7 @@ public class JetTypeReference extends JetElement { return findChildrenByType(JetNodeTypes.ATTRIBUTE_ANNOTATION); } + @Nullable public JetTypeElement getTypeElement() { return findChildByClass(JetTypeElement.class); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 942cefff9d0..e4cc15230c9 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -329,7 +329,7 @@ public class ClassDescriptorResolver { } @Nullable - private ConstructorDescriptor resolvePrimaryConstructor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass classElement) { + public ConstructorDescriptor resolvePrimaryConstructor(@NotNull JetScope scope, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass classElement) { JetParameterList primaryConstructorParameterList = classElement.getPrimaryConstructorParameterList(); if (primaryConstructorParameterList != null) { return createConstructorDescriptor( diff --git a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java index 73e2d0aeb3e..8d67fa50916 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java @@ -13,14 +13,12 @@ import java.util.Map; public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor { private final WritableScope unsubstitutedMemberScope; private final WritableFunctionGroup constructors = new WritableFunctionGroup(""); - private final JetSemanticServices semanticServices; private TypeConstructor typeConstructor; public MutableClassDescriptor(@NotNull JetSemanticServices semanticServices, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) { super(containingDeclaration); this.unsubstitutedMemberScope = semanticServices.createWritableScope(outerScope, this); - this.semanticServices = semanticServices; } @NotNull diff --git a/idea/src/org/jetbrains/jet/lang/resolve/OverloadDomain.java b/idea/src/org/jetbrains/jet/lang/resolve/OverloadDomain.java index 2ca0b2176b3..5602e47c799 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/OverloadDomain.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/OverloadDomain.java @@ -2,7 +2,6 @@ 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.JetType; import java.util.List; @@ -12,17 +11,18 @@ import java.util.Map; * @author abreslav */ public interface OverloadDomain { + OverloadDomain EMPTY = new OverloadDomain() { - @Nullable + @NotNull @Override - public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { - return null; + public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { + return OverloadResolutionResult.nameNotFound(); } - @Nullable + @NotNull @Override - public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes) { - return null; + public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes) { + return OverloadResolutionResult.nameNotFound(); } @Override @@ -32,24 +32,19 @@ public interface OverloadDomain { }; /** - * @param typeArguments - * @param valueArgumentTypes - * @param functionLiteralArgumentType - * @return A function descriptor with NO type parameters (they are already substituted), or null + * @return A function descriptor with NO type parameters (they are already substituted) wrapped together with a result code */ - @Nullable - FunctionDescriptor getFunctionDescriptorForNamedArguments( + @NotNull + OverloadResolutionResult getFunctionDescriptorForNamedArguments( @NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType); /** - * @param typeArguments - * @param positionedValueArgumentTypes - * @return A function descriptor with NO type parameters (they are already substituted), or null + * @return A function descriptor with NO type parameters (they are already substituted) wrapped together with a result code */ - @Nullable - FunctionDescriptor getFunctionDescriptorForPositionedArguments( + @NotNull + OverloadResolutionResult getFunctionDescriptorForPositionedArguments( @NotNull List typeArguments, @NotNull List positionedValueArgumentTypes); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolutionResult.java b/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolutionResult.java new file mode 100644 index 00000000000..c8afc4591b4 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolutionResult.java @@ -0,0 +1,75 @@ +package org.jetbrains.jet.lang.resolve; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.types.FunctionDescriptor; + +import java.util.Collection; + +/** +* @author abreslav +*/ +public class OverloadResolutionResult { + public enum Code { + SUCCESS(true), + NAME_NOT_FOUND(false), + SINGLE_FUNCTION_ARGUMENT_MISMATCH(false), + AMBIGUITY(false); + + private final boolean success; + + Code(boolean success) { + this.success = success; + } + + boolean isSuccess() { + return success; + } + } + + public static OverloadResolutionResult success(@NotNull FunctionDescriptor functionDescriptor) { + return new OverloadResolutionResult(Code.SUCCESS, functionDescriptor); + } + + public static OverloadResolutionResult nameNotFound() { + return new OverloadResolutionResult(Code.NAME_NOT_FOUND, null); + } + + public static OverloadResolutionResult singleFunctionArgumentMismatch(FunctionDescriptor functionDescriptor) { + return new OverloadResolutionResult(Code.SINGLE_FUNCTION_ARGUMENT_MISMATCH, functionDescriptor); + } + + public static OverloadResolutionResult ambiguity(Collection functionDescriptors) { + return new OverloadResolutionResult(Code.AMBIGUITY, null); // TODO + } + + private final FunctionDescriptor functionDescriptor; + private final Code resultCode; + + public OverloadResolutionResult(@NotNull Code resultCode, FunctionDescriptor functionDescriptor) { + this.functionDescriptor = functionDescriptor; + this.resultCode = resultCode; + + } + + @NotNull // This is done on purpose, despite the fact that errors may not carry a descriptor: + // one should not call this method at all in that case + public FunctionDescriptor getFunctionDescriptor() { + assert functionDescriptor != null; + return functionDescriptor; + } + + @NotNull + public Code getResultCode() { + return resultCode; + } + + public boolean isSuccess() { + return resultCode.isSuccess(); + } + + public boolean singleFunction() { + return isSuccess() || resultCode == Code.SINGLE_FUNCTION_ARGUMENT_MISMATCH; + } + + +} diff --git a/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java index dd3389d4fb4..d0175e79f38 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java @@ -34,11 +34,12 @@ public class OverloadResolver { } return new OverloadDomain() { + @NotNull @Override - public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull final List typeArguments, @NotNull List positionedValueArgumentTypes) { + public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull final List typeArguments, @NotNull List positionedValueArgumentTypes) { Collection possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes); if (possiblyApplicableFunctions.isEmpty()) { - return null; + return OverloadResolutionResult.nameNotFound(); // TODO : it may be found, only the number of params did not match } List applicable = new ArrayList(); @@ -84,9 +85,9 @@ public class OverloadResolver { } if (applicable.size() == 0) { - return null; + return OverloadResolutionResult.nameNotFound(); } else if (applicable.size() == 1) { - return applicable.get(0); + return OverloadResolutionResult.success(applicable.get(0)); } else { // TODO : varargs @@ -100,10 +101,10 @@ public class OverloadResolver { maximallySpecific.add(me); } if (maximallySpecific.isEmpty()) { - return null; + return OverloadResolutionResult.ambiguity(applicable); } if (maximallySpecific.size() == 1) { - return maximallySpecific.get(0); + return OverloadResolutionResult.success(maximallySpecific.get(0)); } throw new UnsupportedOperationException(); } @@ -114,8 +115,9 @@ public class OverloadResolver { return functionGroup.isEmpty(); } + @NotNull @Override - public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { + public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { throw new UnsupportedOperationException(); // TODO } }; diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index bb53f782259..8b5c6fb3b3b 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -36,7 +36,7 @@ public class TopDownAnalyzer { trace.setToplevelScope(toplevelScope); // TODO : this is a hack collectTypeDeclarators(toplevelScope, declarations); resolveTypeDeclarations(); - collectBehaviorDeclarators(toplevelScope, declarations); + processBehaviorDeclarators(toplevelScope, declarations); resolveBehaviorDeclarationBodies(); } @@ -136,24 +136,26 @@ public class TopDownAnalyzer { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - private void collectBehaviorDeclarators(@NotNull final WritableScope declaringScope, List declarations) { + private void processBehaviorDeclarators(@NotNull final WritableScope declaringScope, List declarations) { for (JetDeclaration declaration : declarations) { declaration.accept(new JetVisitor() { @Override public void visitClass(JetClass klass) { - collectBehaviorDeclarators(classes.get(klass).getUnsubstitutedMemberScope(), klass.getDeclarations()); + MutableClassDescriptor mutableClassDescriptor = classes.get(klass); + processBehaviorDeclarators(mutableClassDescriptor.getUnsubstitutedMemberScope(), klass.getDeclarations()); + processPrimaryConstructor(mutableClassDescriptor, klass); } @Override public void visitClassObject(JetClassObject classObject) { processClassObject(classObject); - collectBehaviorDeclarators(declaringScope, classObject.getObject().getDeclarations()); + processBehaviorDeclarators(declaringScope, classObject.getObject().getDeclarations()); } @Override public void visitNamespace(JetNamespace namespace) { WritableScope namespaceScope = namespaceScopes.get(namespace); - collectBehaviorDeclarators(namespaceScope, namespace.getDeclarations()); + processBehaviorDeclarators(namespaceScope, namespace.getDeclarations()); } @Override @@ -179,13 +181,20 @@ public class TopDownAnalyzer { @Override public void visitDeclaration(JetDeclaration dcl) { - throw new UnsupportedOperationException(); // TODO + throw new UnsupportedOperationException(dcl.getText() + " " + dcl.getClass().getCanonicalName()); // TODO } }); } } + private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) { + ConstructorDescriptor constructorDescriptor = classDescriptorResolver.resolvePrimaryConstructor(classDescriptor.getUnsubstitutedMemberScope(), classDescriptor, klass); + if (constructorDescriptor != null) { + classDescriptor.addConstructor(constructorDescriptor); + } + } + private void processConstructor(MutableClassDescriptor classDescriptor, JetConstructor constructor) { classDescriptor.addConstructor(classDescriptorResolver.resolveConstructorDescriptor(classDescriptor.getUnsubstitutedMemberScope(), classDescriptor, constructor, false)); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index f2f7ac8ba79..bf460c1f9ee 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -41,9 +41,14 @@ public class TypeResolver { typeElement.accept(new JetVisitor() { @Override public void visitUserType(JetUserType type) { + JetSimpleNameExpression referenceExpression = type.getReferenceExpression(); + String referencedName = type.getReferencedName(); + if (referenceExpression == null || referencedName == null) { + return; + } ClassDescriptor classDescriptor = resolveClass(scope, type); if (classDescriptor != null) { - trace.recordReferenceResolution(type.getReferenceExpression(), classDescriptor); + trace.recordReferenceResolution(referenceExpression, classDescriptor); TypeConstructor typeConstructor = classDescriptor.getTypeConstructor(); List arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments()); if (arguments.size() != typeConstructor.getParameters().size()) { @@ -59,9 +64,9 @@ public class TypeResolver { } } else if (type.getTypeArguments().isEmpty()) { - TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameter(type.getReferencedName()); + TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameter(referencedName); if (typeParameterDescriptor != null) { - trace.recordReferenceResolution(type.getReferenceExpression(), typeParameterDescriptor); + trace.recordReferenceResolution(referenceExpression, typeParameterDescriptor); result[0] = new JetTypeImpl( attributes, typeParameterDescriptor.getTypeConstructor(), @@ -71,11 +76,11 @@ public class TypeResolver { JetStandardClasses.STUB ); } else { - semanticServices.getErrorHandler().unresolvedReference(type.getReferenceExpression()); + semanticServices.getErrorHandler().unresolvedReference(referenceExpression); } } else { - semanticServices.getErrorHandler().unresolvedReference(type.getReferenceExpression()); + semanticServices.getErrorHandler().unresolvedReference(referenceExpression); } } @@ -171,14 +176,21 @@ public class TypeResolver { @Nullable public ClassDescriptor resolveClass(JetScope scope, JetUserType userType) { JetSimpleNameExpression expression = userType.getReferenceExpression(); + if (expression == null) { + return null; + } + String referencedName = expression.getReferencedName(); + if (referencedName == null) { + return null; + } if (userType.isAbsoluteInRootNamespace()) { - return JetModuleUtil.getRootNamespaceScope(userType).getClass(expression.getReferencedName()); + return JetModuleUtil.getRootNamespaceScope(userType).getClass(referencedName); } JetUserType qualifier = userType.getQualifier(); if (qualifier != null) { scope = resolveClassLookupScope(scope, qualifier); } - return scope.getClass(expression.getReferencedName()); + return scope.getClass(referencedName); } private JetScope resolveClassLookupScope(JetScope scope, JetUserType userType) { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java b/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java index 6406a3caec9..74e1646b2e1 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/WritableFunctionGroup.java @@ -18,6 +18,7 @@ public class WritableFunctionGroup implements FunctionGroup { this.name = name; } + @NotNull @Override public String getName() { return name; @@ -51,7 +52,8 @@ public class WritableFunctionGroup implements FunctionGroup { for (FunctionDescriptor functionDescriptor : getFunctionDescriptors()) { // TODO : type argument inference breaks this logic if (functionDescriptor.getTypeParameters().size() == typeArgCount) { - if (FunctionDescriptorUtil.getMinimumArity(functionDescriptor) <= valueArgCount && valueArgCount <= FunctionDescriptorUtil.getMaximumArity(functionDescriptor)) { + if (FunctionDescriptorUtil.getMinimumArity(functionDescriptor) <= valueArgCount && + valueArgCount <= FunctionDescriptorUtil.getMaximumArity(functionDescriptor)) { result.add(FunctionDescriptorUtil.substituteFunctionDescriptor(typeArguments, functionDescriptor)); } } diff --git a/idea/src/org/jetbrains/jet/lang/types/FunctionGroup.java b/idea/src/org/jetbrains/jet/lang/types/FunctionGroup.java index e115c991fe2..4083e1e027b 100644 --- a/idea/src/org/jetbrains/jet/lang/types/FunctionGroup.java +++ b/idea/src/org/jetbrains/jet/lang/types/FunctionGroup.java @@ -11,6 +11,7 @@ import java.util.List; */ public interface FunctionGroup extends Named { FunctionGroup EMPTY = new FunctionGroup() { + @NotNull @Override public String getName() { return ""; @@ -19,7 +20,8 @@ public interface FunctionGroup extends Named { @NotNull @Override public Collection getPossiblyApplicableFunctions(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes) { - return Collections.emptySet(); + return Collections.emptyList(); +// return OverloadResolutionResult.nameNotFound(); } @Override @@ -35,6 +37,8 @@ public interface FunctionGroup extends Named { @NotNull Collection getPossiblyApplicableFunctions(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes); +// @NotNull +// OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes); boolean isEmpty(); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 5368faf0b46..2e8575863f1 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -122,7 +122,8 @@ public class JetTypeInferrer { boolean reportUnresolved) { OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name); overloadDomain = wrapForTracing(overloadDomain, reference, null, reportUnresolved); - return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.emptyList(), argumentTypes); + OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.emptyList(), argumentTypes); + return resolutionResult.isSuccess() ? resolutionResult.getFunctionDescriptor() : null; } @@ -209,41 +210,54 @@ public class JetTypeInferrer { @Nullable final OverloadDomain overloadDomain, @NotNull final JetReferenceExpression referenceExpression, @Nullable final PsiElement argumentList, - final boolean reportUnresolved) { + final boolean reportErrors) { if (overloadDomain == null) return OverloadDomain.EMPTY; return new OverloadDomain() { + @NotNull @Override - public FunctionDescriptor getFunctionDescriptorForNamedArguments(@NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { - FunctionDescriptor descriptor = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType); - if (descriptor != null) { - trace.recordReferenceResolution(referenceExpression, descriptor); - } - else { - reportError(); - } - return descriptor; + public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List typeArguments, @NotNull Map valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) { + OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType); + report(resolutionResult); + return resolutionResult; } + @NotNull @Override - public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes) { - FunctionDescriptor descriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes); - if (descriptor != null) { - trace.recordReferenceResolution(referenceExpression, descriptor); - } - else { - reportError(); - } - return descriptor; + public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List typeArguments, @NotNull List positionedValueArgumentTypes) { + OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes); + report(resolutionResult); + return resolutionResult; } - private void reportError() { - if (reportUnresolved) { - if (overloadDomain.isEmpty() || argumentList == null) { - semanticServices.getErrorHandler().unresolvedReference(referenceExpression); - } - else { - // TODO : More helpful message. NOTE: there's a separate handling for this for constructors - semanticServices.getErrorHandler().genericError(argumentList.getNode(), "No overload found for these arguments"); + private void report(OverloadResolutionResult resolutionResult) { + if (resolutionResult.isSuccess() || resolutionResult.singleFunction()) { + trace.recordReferenceResolution(referenceExpression, resolutionResult.getFunctionDescriptor()); + } + if (reportErrors) { + switch (resolutionResult.getResultCode()) { + case NAME_NOT_FOUND: + semanticServices.getErrorHandler().unresolvedReference(referenceExpression); + break; + case SINGLE_FUNCTION_ARGUMENT_MISMATCH: + if (argumentList != null) { + // TODO : More helpful message. NOTE: there's a separate handling for this for constructors + semanticServices.getErrorHandler().genericError(argumentList.getNode(), "Arguments do not match " + resolutionResult.getFunctionDescriptor()); + } + else { + semanticServices.getErrorHandler().unresolvedReference(referenceExpression); + } + break; + case AMBIGUITY: + if (argumentList != null) { + // TODO : More helpful message. NOTE: there's a separate handling for this for constructors + semanticServices.getErrorHandler().genericError(argumentList.getNode(), "Overload ambiguity [TODO : more helpful message]"); + } + else { + semanticServices.getErrorHandler().unresolvedReference(referenceExpression); + } + break; + default: + // Not a success } } } @@ -693,7 +707,9 @@ public class JetTypeInferrer { } } else { - semanticServices.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message + if (typeElement != null) { + semanticServices.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message + } } } } @@ -799,7 +815,10 @@ public class JetTypeInferrer { List positionedValueArguments = new ArrayList(); for (JetArgument argument : valueArguments) { - positionedValueArguments.add(argument.getArgumentExpression()); + JetExpression argumentExpression = argument.getArgumentExpression(); + if (argumentExpression != null) { + positionedValueArguments.add(argumentExpression); + } } positionedValueArguments.addAll(functionLiteralArguments); @@ -809,9 +828,9 @@ public class JetTypeInferrer { valueArgumentTypes.add(safeGetType(scope, valueArgument, false)); } - FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes); - if (functionDescriptor != null) { - return functionDescriptor.getUnsubstitutedReturnType(); + OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes); + if (resolutionResult.isSuccess()) { + return resolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType(); } } return null; diff --git a/idea/src/org/jetbrains/jet/lang/types/Named.java b/idea/src/org/jetbrains/jet/lang/types/Named.java index c8677b44757..8a8352f2bb2 100644 --- a/idea/src/org/jetbrains/jet/lang/types/Named.java +++ b/idea/src/org/jetbrains/jet/lang/types/Named.java @@ -1,8 +1,11 @@ package org.jetbrains.jet.lang.types; +import org.jetbrains.annotations.NotNull; + /** * @author abreslav */ public interface Named { + @NotNull String getName(); }