Working on error messages for overload resolution
This commit is contained in:
@@ -12,6 +12,7 @@ Foo<Bar<X>, T, Object> // user type
|
|||||||
type
|
type
|
||||||
: attributes typeDescriptor
|
: attributes typeDescriptor
|
||||||
|
|
||||||
|
// IF YOU CHANGE THIS, please, update TYPE_FIRST in JetParsing
|
||||||
typeDescriptor
|
typeDescriptor
|
||||||
: selfType
|
: selfType
|
||||||
: functionType
|
: functionType
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
COLON
|
COLON
|
||||||
);
|
);
|
||||||
|
|
||||||
private static final TokenSet EXPRESSION_FIRST = TokenSet.orSet(TokenSet.create(
|
/*package*/ static final TokenSet EXPRESSION_FIRST = TokenSet.orSet(TokenSet.create(
|
||||||
// Prefix
|
// Prefix
|
||||||
MINUS, PLUS, MINUSMINUS, PLUSPLUS, EXCL, LBRACKET, LABEL_IDENTIFIER, AT, ATAT,
|
MINUS, PLUS, MINUSMINUS, PLUSPLUS, EXCL, LBRACKET, LABEL_IDENTIFIER, AT, ATAT,
|
||||||
// Atomic
|
// Atomic
|
||||||
@@ -82,7 +82,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
NAMESPACE_KEYWORD // for absolute qualified names
|
NAMESPACE_KEYWORD // for absolute qualified names
|
||||||
), MODIFIER_KEYWORDS);
|
), 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
|
SEMICOLON, DOUBLE_ARROW, COMMA, RBRACE, RPAR, RBRACKET
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -533,7 +533,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
}
|
}
|
||||||
else if (!parseLiteralConstant()) {
|
else if (!parseLiteralConstant()) {
|
||||||
// TODO: better recovery if FIRST(expression) did not match
|
// 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();
|
PsiBuilder.Marker list = mark();
|
||||||
|
|
||||||
myBuilder.disableNewlines();
|
myBuilder.disableNewlines();
|
||||||
expect(LPAR, "Expecting an argument list", TokenSet.create(RPAR));
|
expect(LPAR, "Expecting an argument list", EXPRESSION_FOLLOW);
|
||||||
|
|
||||||
if (!at(RPAR)) {
|
if (!at(RPAR)) {
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -1509,7 +1509,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(RPAR, "Expecting ')'");
|
expect(RPAR, "Expecting ')'", EXPRESSION_FOLLOW);
|
||||||
myBuilder.restoreNewlinesState();
|
myBuilder.restoreNewlinesState();
|
||||||
|
|
||||||
list.done(VALUE_ARGUMENT_LIST);
|
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 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 PARAMETER_NAME_RECOVERY_SET = TokenSet.create(COLON, EQ, COMMA, RPAR);
|
||||||
private static final TokenSet NAMESPACE_NAME_RECOVERY_SET = TokenSet.create(DOT, EOL_OR_SEMICOLON);
|
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) {
|
public static JetParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||||
builder.setDebugMode(true);
|
builder.setDebugMode(true);
|
||||||
@@ -835,10 +835,17 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
advance(); // FUN_KEYWORD
|
advance(); // FUN_KEYWORD
|
||||||
|
|
||||||
|
// Recovery for the case of class A { fun| }
|
||||||
|
if (at(RBRACE)) {
|
||||||
|
error("Function body expected");
|
||||||
|
return FUN;
|
||||||
|
}
|
||||||
|
|
||||||
if (at(LT)) {
|
if (at(LT)) {
|
||||||
parseTypeParameterList(TokenSet.create(LBRACKET, LBRACE, LPAR));
|
parseTypeParameterList(TokenSet.create(LBRACKET, LBRACE, LPAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int lastDot = findLastBefore(TokenSet.create(DOT), TokenSet.create(LPAR), true);
|
int lastDot = findLastBefore(TokenSet.create(DOT), TokenSet.create(LPAR), true);
|
||||||
|
|
||||||
if (lastDot == -1) { // There's no explicit receiver type specified
|
if (lastDot == -1) { // There's no explicit receiver type specified
|
||||||
@@ -1246,7 +1253,7 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
|
|
||||||
PsiBuilder.Marker reference = mark();
|
PsiBuilder.Marker reference = mark();
|
||||||
while (true) {
|
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);
|
reference.done(REFERENCE_EXPRESSION);
|
||||||
|
|
||||||
parseTypeArgumentList();
|
parseTypeArgumentList();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class JetArgument extends JetElement {
|
|||||||
super(node);
|
super(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void accept(JetVisitor visitor) {
|
public void accept(@NotNull JetVisitor visitor) {
|
||||||
visitor.visitArgument(this);
|
visitor.visitArgument(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,6 +25,9 @@ public class JetArgument extends JetElement {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public String getArgumentName() {
|
public String getArgumentName() {
|
||||||
ASTNode firstChildNode = getNode().getFirstChildNode();
|
ASTNode firstChildNode = getNode().getFirstChildNode();
|
||||||
|
if (firstChildNode == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return firstChildNode.getElementType() == JetTokens.IDENTIFIER ? firstChildNode.getText() : 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 com.intellij.lang.ASTNode;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.JetNodeTypes;
|
import org.jetbrains.jet.JetNodeTypes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -25,6 +26,7 @@ public class JetTypeReference extends JetElement {
|
|||||||
return findChildrenByType(JetNodeTypes.ATTRIBUTE_ANNOTATION);
|
return findChildrenByType(JetNodeTypes.ATTRIBUTE_ANNOTATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public JetTypeElement getTypeElement() {
|
public JetTypeElement getTypeElement() {
|
||||||
return findChildByClass(JetTypeElement.class);
|
return findChildByClass(JetTypeElement.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ public class ClassDescriptorResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@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();
|
JetParameterList primaryConstructorParameterList = classElement.getPrimaryConstructorParameterList();
|
||||||
if (primaryConstructorParameterList != null) {
|
if (primaryConstructorParameterList != null) {
|
||||||
return createConstructorDescriptor(
|
return createConstructorDescriptor(
|
||||||
|
|||||||
@@ -13,14 +13,12 @@ import java.util.Map;
|
|||||||
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor {
|
public class MutableClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor {
|
||||||
private final WritableScope unsubstitutedMemberScope;
|
private final WritableScope unsubstitutedMemberScope;
|
||||||
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
|
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
|
||||||
private final JetSemanticServices semanticServices;
|
|
||||||
|
|
||||||
private TypeConstructor typeConstructor;
|
private TypeConstructor typeConstructor;
|
||||||
|
|
||||||
public MutableClassDescriptor(@NotNull JetSemanticServices semanticServices, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
|
public MutableClassDescriptor(@NotNull JetSemanticServices semanticServices, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
|
||||||
super(containingDeclaration);
|
super(containingDeclaration);
|
||||||
this.unsubstitutedMemberScope = semanticServices.createWritableScope(outerScope, this);
|
this.unsubstitutedMemberScope = semanticServices.createWritableScope(outerScope, this);
|
||||||
this.semanticServices = semanticServices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.resolve;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.types.FunctionDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -12,17 +11,18 @@ import java.util.Map;
|
|||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public interface OverloadDomain {
|
public interface OverloadDomain {
|
||||||
|
|
||||||
OverloadDomain EMPTY = new OverloadDomain() {
|
OverloadDomain EMPTY = new OverloadDomain() {
|
||||||
@Nullable
|
@NotNull
|
||||||
@Override
|
@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) {
|
||||||
return null;
|
return OverloadResolutionResult.nameNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||||
return null;
|
return OverloadResolutionResult.nameNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -32,24 +32,19 @@ public interface OverloadDomain {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param typeArguments
|
* @return A function descriptor with NO type parameters (they are already substituted) wrapped together with a result code
|
||||||
* @param valueArgumentTypes
|
|
||||||
* @param functionLiteralArgumentType
|
|
||||||
* @return A function descriptor with NO type parameters (they are already substituted), or null
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@NotNull
|
||||||
FunctionDescriptor getFunctionDescriptorForNamedArguments(
|
OverloadResolutionResult getFunctionDescriptorForNamedArguments(
|
||||||
@NotNull List<JetType> typeArguments,
|
@NotNull List<JetType> typeArguments,
|
||||||
@NotNull Map<String, JetType> valueArgumentTypes,
|
@NotNull Map<String, JetType> valueArgumentTypes,
|
||||||
@Nullable JetType functionLiteralArgumentType);
|
@Nullable JetType functionLiteralArgumentType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param typeArguments
|
* @return A function descriptor with NO type parameters (they are already substituted) wrapped together with a result code
|
||||||
* @param positionedValueArgumentTypes
|
|
||||||
* @return A function descriptor with NO type parameters (they are already substituted), or null
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@NotNull
|
||||||
FunctionDescriptor getFunctionDescriptorForPositionedArguments(
|
OverloadResolutionResult getFunctionDescriptorForPositionedArguments(
|
||||||
@NotNull List<JetType> typeArguments,
|
@NotNull List<JetType> typeArguments,
|
||||||
@NotNull List<JetType> positionedValueArgumentTypes);
|
@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() {
|
return new OverloadDomain() {
|
||||||
|
@NotNull
|
||||||
@Override
|
@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);
|
Collection<FunctionDescriptor> possiblyApplicableFunctions = functionGroup.getPossiblyApplicableFunctions(typeArguments, positionedValueArgumentTypes);
|
||||||
if (possiblyApplicableFunctions.isEmpty()) {
|
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>();
|
List<FunctionDescriptor> applicable = new ArrayList<FunctionDescriptor>();
|
||||||
@@ -84,9 +85,9 @@ public class OverloadResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (applicable.size() == 0) {
|
if (applicable.size() == 0) {
|
||||||
return null;
|
return OverloadResolutionResult.nameNotFound();
|
||||||
} else if (applicable.size() == 1) {
|
} else if (applicable.size() == 1) {
|
||||||
return applicable.get(0);
|
return OverloadResolutionResult.success(applicable.get(0));
|
||||||
} else {
|
} else {
|
||||||
// TODO : varargs
|
// TODO : varargs
|
||||||
|
|
||||||
@@ -100,10 +101,10 @@ public class OverloadResolver {
|
|||||||
maximallySpecific.add(me);
|
maximallySpecific.add(me);
|
||||||
}
|
}
|
||||||
if (maximallySpecific.isEmpty()) {
|
if (maximallySpecific.isEmpty()) {
|
||||||
return null;
|
return OverloadResolutionResult.ambiguity(applicable);
|
||||||
}
|
}
|
||||||
if (maximallySpecific.size() == 1) {
|
if (maximallySpecific.size() == 1) {
|
||||||
return maximallySpecific.get(0);
|
return OverloadResolutionResult.success(maximallySpecific.get(0));
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
@@ -114,8 +115,9 @@ public class OverloadResolver {
|
|||||||
return functionGroup.isEmpty();
|
return functionGroup.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@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
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class TopDownAnalyzer {
|
|||||||
trace.setToplevelScope(toplevelScope); // TODO : this is a hack
|
trace.setToplevelScope(toplevelScope); // TODO : this is a hack
|
||||||
collectTypeDeclarators(toplevelScope, declarations);
|
collectTypeDeclarators(toplevelScope, declarations);
|
||||||
resolveTypeDeclarations();
|
resolveTypeDeclarations();
|
||||||
collectBehaviorDeclarators(toplevelScope, declarations);
|
processBehaviorDeclarators(toplevelScope, declarations);
|
||||||
resolveBehaviorDeclarationBodies();
|
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) {
|
for (JetDeclaration declaration : declarations) {
|
||||||
declaration.accept(new JetVisitor() {
|
declaration.accept(new JetVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visitClass(JetClass klass) {
|
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
|
@Override
|
||||||
public void visitClassObject(JetClassObject classObject) {
|
public void visitClassObject(JetClassObject classObject) {
|
||||||
processClassObject(classObject);
|
processClassObject(classObject);
|
||||||
collectBehaviorDeclarators(declaringScope, classObject.getObject().getDeclarations());
|
processBehaviorDeclarators(declaringScope, classObject.getObject().getDeclarations());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitNamespace(JetNamespace namespace) {
|
public void visitNamespace(JetNamespace namespace) {
|
||||||
WritableScope namespaceScope = namespaceScopes.get(namespace);
|
WritableScope namespaceScope = namespaceScopes.get(namespace);
|
||||||
collectBehaviorDeclarators(namespaceScope, namespace.getDeclarations());
|
processBehaviorDeclarators(namespaceScope, namespace.getDeclarations());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -179,13 +181,20 @@ public class TopDownAnalyzer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitDeclaration(JetDeclaration dcl) {
|
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) {
|
private void processConstructor(MutableClassDescriptor classDescriptor, JetConstructor constructor) {
|
||||||
classDescriptor.addConstructor(classDescriptorResolver.resolveConstructorDescriptor(classDescriptor.getUnsubstitutedMemberScope(), classDescriptor, constructor, false));
|
classDescriptor.addConstructor(classDescriptorResolver.resolveConstructorDescriptor(classDescriptor.getUnsubstitutedMemberScope(), classDescriptor, constructor, false));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,9 +41,14 @@ public class TypeResolver {
|
|||||||
typeElement.accept(new JetVisitor() {
|
typeElement.accept(new JetVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visitUserType(JetUserType type) {
|
public void visitUserType(JetUserType type) {
|
||||||
|
JetSimpleNameExpression referenceExpression = type.getReferenceExpression();
|
||||||
|
String referencedName = type.getReferencedName();
|
||||||
|
if (referenceExpression == null || referencedName == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ClassDescriptor classDescriptor = resolveClass(scope, type);
|
ClassDescriptor classDescriptor = resolveClass(scope, type);
|
||||||
if (classDescriptor != null) {
|
if (classDescriptor != null) {
|
||||||
trace.recordReferenceResolution(type.getReferenceExpression(), classDescriptor);
|
trace.recordReferenceResolution(referenceExpression, classDescriptor);
|
||||||
TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
|
TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
|
||||||
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
|
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
|
||||||
if (arguments.size() != typeConstructor.getParameters().size()) {
|
if (arguments.size() != typeConstructor.getParameters().size()) {
|
||||||
@@ -59,9 +64,9 @@ public class TypeResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type.getTypeArguments().isEmpty()) {
|
else if (type.getTypeArguments().isEmpty()) {
|
||||||
TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameter(type.getReferencedName());
|
TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameter(referencedName);
|
||||||
if (typeParameterDescriptor != null) {
|
if (typeParameterDescriptor != null) {
|
||||||
trace.recordReferenceResolution(type.getReferenceExpression(), typeParameterDescriptor);
|
trace.recordReferenceResolution(referenceExpression, typeParameterDescriptor);
|
||||||
result[0] = new JetTypeImpl(
|
result[0] = new JetTypeImpl(
|
||||||
attributes,
|
attributes,
|
||||||
typeParameterDescriptor.getTypeConstructor(),
|
typeParameterDescriptor.getTypeConstructor(),
|
||||||
@@ -71,11 +76,11 @@ public class TypeResolver {
|
|||||||
JetStandardClasses.STUB
|
JetStandardClasses.STUB
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
semanticServices.getErrorHandler().unresolvedReference(type.getReferenceExpression());
|
semanticServices.getErrorHandler().unresolvedReference(referenceExpression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
semanticServices.getErrorHandler().unresolvedReference(type.getReferenceExpression());
|
semanticServices.getErrorHandler().unresolvedReference(referenceExpression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,14 +176,21 @@ public class TypeResolver {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public ClassDescriptor resolveClass(JetScope scope, JetUserType userType) {
|
public ClassDescriptor resolveClass(JetScope scope, JetUserType userType) {
|
||||||
JetSimpleNameExpression expression = userType.getReferenceExpression();
|
JetSimpleNameExpression expression = userType.getReferenceExpression();
|
||||||
|
if (expression == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String referencedName = expression.getReferencedName();
|
||||||
|
if (referencedName == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (userType.isAbsoluteInRootNamespace()) {
|
if (userType.isAbsoluteInRootNamespace()) {
|
||||||
return JetModuleUtil.getRootNamespaceScope(userType).getClass(expression.getReferencedName());
|
return JetModuleUtil.getRootNamespaceScope(userType).getClass(referencedName);
|
||||||
}
|
}
|
||||||
JetUserType qualifier = userType.getQualifier();
|
JetUserType qualifier = userType.getQualifier();
|
||||||
if (qualifier != null) {
|
if (qualifier != null) {
|
||||||
scope = resolveClassLookupScope(scope, qualifier);
|
scope = resolveClassLookupScope(scope, qualifier);
|
||||||
}
|
}
|
||||||
return scope.getClass(expression.getReferencedName());
|
return scope.getClass(referencedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JetScope resolveClassLookupScope(JetScope scope, JetUserType userType) {
|
private JetScope resolveClassLookupScope(JetScope scope, JetUserType userType) {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ public class WritableFunctionGroup implements FunctionGroup {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
@@ -51,7 +52,8 @@ public class WritableFunctionGroup implements FunctionGroup {
|
|||||||
for (FunctionDescriptor functionDescriptor : getFunctionDescriptors()) {
|
for (FunctionDescriptor functionDescriptor : getFunctionDescriptors()) {
|
||||||
// TODO : type argument inference breaks this logic
|
// TODO : type argument inference breaks this logic
|
||||||
if (functionDescriptor.getTypeParameters().size() == typeArgCount) {
|
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));
|
result.add(FunctionDescriptorUtil.substituteFunctionDescriptor(typeArguments, functionDescriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface FunctionGroup extends Named {
|
public interface FunctionGroup extends Named {
|
||||||
FunctionGroup EMPTY = new FunctionGroup() {
|
FunctionGroup EMPTY = new FunctionGroup() {
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "<empty>";
|
return "<empty>";
|
||||||
@@ -19,7 +20,8 @@ public interface FunctionGroup extends Named {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<FunctionDescriptor> getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
public Collection<FunctionDescriptor> getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||||
return Collections.emptySet();
|
return Collections.emptyList();
|
||||||
|
// return OverloadResolutionResult.nameNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -35,6 +37,8 @@ public interface FunctionGroup extends Named {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
Collection<FunctionDescriptor> getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes);
|
Collection<FunctionDescriptor> getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes);
|
||||||
|
// @NotNull
|
||||||
|
// OverloadResolutionResult getPossiblyApplicableFunctions(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes);
|
||||||
|
|
||||||
boolean isEmpty();
|
boolean isEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,8 @@ public class JetTypeInferrer {
|
|||||||
boolean reportUnresolved) {
|
boolean reportUnresolved) {
|
||||||
OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name);
|
OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name);
|
||||||
overloadDomain = wrapForTracing(overloadDomain, reference, null, reportUnresolved);
|
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,
|
@Nullable final OverloadDomain overloadDomain,
|
||||||
@NotNull final JetReferenceExpression referenceExpression,
|
@NotNull final JetReferenceExpression referenceExpression,
|
||||||
@Nullable final PsiElement argumentList,
|
@Nullable final PsiElement argumentList,
|
||||||
final boolean reportUnresolved) {
|
final boolean reportErrors) {
|
||||||
if (overloadDomain == null) return OverloadDomain.EMPTY;
|
if (overloadDomain == null) return OverloadDomain.EMPTY;
|
||||||
return new OverloadDomain() {
|
return new OverloadDomain() {
|
||||||
|
@NotNull
|
||||||
@Override
|
@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) {
|
||||||
FunctionDescriptor descriptor = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType);
|
OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArgumentTypes, functionLiteralArgumentType);
|
||||||
if (descriptor != null) {
|
report(resolutionResult);
|
||||||
trace.recordReferenceResolution(referenceExpression, descriptor);
|
return resolutionResult;
|
||||||
}
|
|
||||||
else {
|
|
||||||
reportError();
|
|
||||||
}
|
|
||||||
return descriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
public OverloadResolutionResult getFunctionDescriptorForPositionedArguments(@NotNull List<JetType> typeArguments, @NotNull List<JetType> positionedValueArgumentTypes) {
|
||||||
FunctionDescriptor descriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes);
|
OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes);
|
||||||
if (descriptor != null) {
|
report(resolutionResult);
|
||||||
trace.recordReferenceResolution(referenceExpression, descriptor);
|
return resolutionResult;
|
||||||
}
|
|
||||||
else {
|
|
||||||
reportError();
|
|
||||||
}
|
|
||||||
return descriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reportError() {
|
private void report(OverloadResolutionResult resolutionResult) {
|
||||||
if (reportUnresolved) {
|
if (resolutionResult.isSuccess() || resolutionResult.singleFunction()) {
|
||||||
if (overloadDomain.isEmpty() || argumentList == null) {
|
trace.recordReferenceResolution(referenceExpression, resolutionResult.getFunctionDescriptor());
|
||||||
semanticServices.getErrorHandler().unresolvedReference(referenceExpression);
|
}
|
||||||
}
|
if (reportErrors) {
|
||||||
else {
|
switch (resolutionResult.getResultCode()) {
|
||||||
// TODO : More helpful message. NOTE: there's a separate handling for this for constructors
|
case NAME_NOT_FOUND:
|
||||||
semanticServices.getErrorHandler().genericError(argumentList.getNode(), "No overload found for these arguments");
|
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 {
|
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>();
|
List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
|
||||||
for (JetArgument argument : valueArguments) {
|
for (JetArgument argument : valueArguments) {
|
||||||
positionedValueArguments.add(argument.getArgumentExpression());
|
JetExpression argumentExpression = argument.getArgumentExpression();
|
||||||
|
if (argumentExpression != null) {
|
||||||
|
positionedValueArguments.add(argumentExpression);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
positionedValueArguments.addAll(functionLiteralArguments);
|
positionedValueArguments.addAll(functionLiteralArguments);
|
||||||
@@ -809,9 +828,9 @@ public class JetTypeInferrer {
|
|||||||
valueArgumentTypes.add(safeGetType(scope, valueArgument, false));
|
valueArgumentTypes.add(safeGetType(scope, valueArgument, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
|
OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
|
||||||
if (functionDescriptor != null) {
|
if (resolutionResult.isSuccess()) {
|
||||||
return functionDescriptor.getUnsubstitutedReturnType();
|
return resolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package org.jetbrains.jet.lang.types;
|
package org.jetbrains.jet.lang.types;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public interface Named {
|
public interface Named {
|
||||||
|
@NotNull
|
||||||
String getName();
|
String getName();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user