Working on error messages for overload resolution
This commit is contained in:
@@ -12,6 +12,7 @@ Foo<Bar<X>, T, Object> // user type
|
||||
type
|
||||
: attributes typeDescriptor
|
||||
|
||||
// IF YOU CHANGE THIS, please, update TYPE_FIRST in JetParsing
|
||||
typeDescriptor
|
||||
: selfType
|
||||
: functionType
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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("<init>");
|
||||
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
|
||||
|
||||
@@ -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<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
return null;
|
||||
public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
return OverloadResolutionResult.nameNotFound();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
return null;
|
||||
public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> 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<JetType> typeArguments,
|
||||
@NotNull Map<String, JetType> 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<JetType> typeArguments,
|
||||
@NotNull List<JetType> positionedValueArgumentTypes);
|
||||
|
||||
|
||||
@@ -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<FunctionDescriptor> 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -34,11 +34,12 @@ public class OverloadResolver {
|
||||
}
|
||||
|
||||
return new OverloadDomain() {
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull final List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull final List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
Collection<FunctionDescriptor> 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<FunctionDescriptor> applicable = new ArrayList<FunctionDescriptor>();
|
||||
@@ -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<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
public OverloadResolutionResult getFunctionDescriptorForNamedArguments(@NotNull List<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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<JetDeclaration> declarations) {
|
||||
private void processBehaviorDeclarators(@NotNull final WritableScope declaringScope, List<JetDeclaration> 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));
|
||||
}
|
||||
|
||||
@@ -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<TypeProjection> 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) {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.List;
|
||||
*/
|
||||
public interface FunctionGroup extends Named {
|
||||
FunctionGroup EMPTY = new FunctionGroup() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return "<empty>";
|
||||
@@ -19,7 +20,8 @@ public interface FunctionGroup extends Named {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<FunctionDescriptor> getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
return Collections.emptySet();
|
||||
return Collections.emptyList();
|
||||
// return OverloadResolutionResult.nameNotFound();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -35,6 +37,8 @@ public interface FunctionGroup extends Named {
|
||||
|
||||
@NotNull
|
||||
Collection<FunctionDescriptor> getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes);
|
||||
// @NotNull
|
||||
// OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes);
|
||||
|
||||
boolean isEmpty();
|
||||
}
|
||||
|
||||
@@ -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.<JetType>emptyList(), argumentTypes);
|
||||
OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<JetType>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<JetType> typeArguments, @NotNull Map<String, JetType> 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<JetType> typeArguments, @NotNull Map<String, JetType> valueArgumentTypes, @Nullable JetType functionLiteralArgumentType) {
|
||||
OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType);
|
||||
report(resolutionResult);
|
||||
return resolutionResult;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||
FunctionDescriptor descriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes);
|
||||
if (descriptor != null) {
|
||||
trace.recordReferenceResolution(referenceExpression, descriptor);
|
||||
}
|
||||
else {
|
||||
reportError();
|
||||
}
|
||||
return descriptor;
|
||||
public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> 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<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
|
||||
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;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface Named {
|
||||
@NotNull
|
||||
String getName();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user