Detailed status for ValueArgumentsToParameterMapper
When a non-vararg parameter gets spread with a '*' in front of it, a "weak error" is returned. A candidate with a weak error in parameter matching is type-checked, but not successful.
This commit is contained in:
@@ -49,7 +49,7 @@ public enum ResolutionStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ResolutionStatus combine(ResolutionStatus other) {
|
public ResolutionStatus combine(ResolutionStatus other) {
|
||||||
if (this.isSuccess()) return other;
|
if (this == UNKNOWN_STATUS || this.isSuccess()) return other;
|
||||||
if (!other.isSuccess() && this.getSeverityIndex() < other.getSeverityIndex()) return other;
|
if (!other.isSuccess() && this.getSeverityIndex() < other.getSeverityIndex()) return other;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(@NotNull ResolutionStatus status) {
|
public void addStatus(@NotNull ResolutionStatus status) {
|
||||||
this.status = status;
|
this.status = this.status.combine(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+57
-22
@@ -33,17 +33,49 @@ import java.util.Set;
|
|||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.ValueArgumentsToParametersMapper.Status.ERROR;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.ValueArgumentsToParametersMapper.Status.OK;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.calls.ValueArgumentsToParametersMapper.Status.WEAK_ERROR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
/*package*/ class ValueArgumentsToParametersMapper {
|
/*package*/ class ValueArgumentsToParametersMapper {
|
||||||
public static <D extends CallableDescriptor> boolean mapValueArgumentsToParameters(
|
|
||||||
|
public enum Status {
|
||||||
|
ERROR(false),
|
||||||
|
WEAK_ERROR(false),
|
||||||
|
OK(true);
|
||||||
|
|
||||||
|
private final boolean success;
|
||||||
|
|
||||||
|
private Status(boolean success) {
|
||||||
|
this.success = success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status compose(Status other) {
|
||||||
|
switch (other) {
|
||||||
|
case ERROR:
|
||||||
|
return ERROR;
|
||||||
|
case WEAK_ERROR:
|
||||||
|
if (this != ERROR) {
|
||||||
|
return WEAK_ERROR;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <D extends CallableDescriptor> Status mapValueArgumentsToParameters(
|
||||||
@NotNull Call call,
|
@NotNull Call call,
|
||||||
@NotNull TracingStrategy tracing,
|
@NotNull TracingStrategy tracing,
|
||||||
@NotNull ResolvedCallImpl<D> candidateCall
|
@NotNull ResolvedCallImpl<D> candidateCall
|
||||||
) {
|
) {
|
||||||
|
|
||||||
TemporaryBindingTrace temporaryTrace = candidateCall.getTrace();
|
TemporaryBindingTrace temporaryTrace = candidateCall.getTrace();
|
||||||
Map<ValueParameterDescriptor, VarargValueArgument> varargs = Maps.newHashMap();
|
Map<ValueParameterDescriptor, VarargValueArgument> varargs = Maps.newHashMap();
|
||||||
Set<ValueParameterDescriptor> usedParameters = Sets.newHashSet();
|
Set<ValueParameterDescriptor> usedParameters = Sets.newHashSet();
|
||||||
@@ -61,7 +93,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
|
|
||||||
List<? extends ValueArgument> valueArguments = call.getValueArguments();
|
List<? extends ValueArgument> valueArguments = call.getValueArguments();
|
||||||
|
|
||||||
boolean error = false;
|
Status status = OK;
|
||||||
boolean someNamed = false;
|
boolean someNamed = false;
|
||||||
boolean somePositioned = false;
|
boolean somePositioned = false;
|
||||||
for (int i = 0; i < valueArguments.size(); i++) {
|
for (int i = 0; i < valueArguments.size(); i++) {
|
||||||
@@ -72,47 +104,47 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedName());
|
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedName());
|
||||||
if (valueParameterDescriptor == null) {
|
if (valueParameterDescriptor == null) {
|
||||||
temporaryTrace.report(NAMED_PARAMETER_NOT_FOUND.on(nameReference));
|
temporaryTrace.report(NAMED_PARAMETER_NOT_FOUND.on(nameReference));
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!usedParameters.add(valueParameterDescriptor)) {
|
if (!usedParameters.add(valueParameterDescriptor)) {
|
||||||
temporaryTrace.report(ARGUMENT_PASSED_TWICE.on(nameReference));
|
temporaryTrace.report(ARGUMENT_PASSED_TWICE.on(nameReference));
|
||||||
}
|
}
|
||||||
temporaryTrace.record(REFERENCE_TARGET, nameReference, valueParameterDescriptor);
|
temporaryTrace.record(REFERENCE_TARGET, nameReference, valueParameterDescriptor);
|
||||||
put(candidateCall, valueParameterDescriptor, valueArgument, varargs);
|
status = status.compose(put(candidateCall, valueParameterDescriptor, valueArgument, varargs));
|
||||||
}
|
}
|
||||||
if (somePositioned) {
|
if (somePositioned) {
|
||||||
temporaryTrace.report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(nameReference));
|
temporaryTrace.report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(nameReference));
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
somePositioned = true;
|
somePositioned = true;
|
||||||
if (someNamed) {
|
if (someNamed) {
|
||||||
temporaryTrace.report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(valueArgument.asElement()));
|
temporaryTrace.report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(valueArgument.asElement()));
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int parameterCount = valueParameters.size();
|
int parameterCount = valueParameters.size();
|
||||||
if (i < parameterCount) {
|
if (i < parameterCount) {
|
||||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(i);
|
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(i);
|
||||||
usedParameters.add(valueParameterDescriptor);
|
usedParameters.add(valueParameterDescriptor);
|
||||||
put(candidateCall, valueParameterDescriptor, valueArgument, varargs);
|
status = status.compose(put(candidateCall, valueParameterDescriptor, valueArgument, varargs));
|
||||||
}
|
}
|
||||||
else if (!valueParameters.isEmpty()) {
|
else if (!valueParameters.isEmpty()) {
|
||||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
||||||
if (valueParameterDescriptor.getVarargElementType() != null) {
|
if (valueParameterDescriptor.getVarargElementType() != null) {
|
||||||
put(candidateCall, valueParameterDescriptor, valueArgument, varargs);
|
status = status.compose(put(candidateCall, valueParameterDescriptor, valueArgument, varargs));
|
||||||
usedParameters.add(valueParameterDescriptor);
|
usedParameters.add(valueParameterDescriptor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(valueArgument.asElement(), candidate));
|
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(valueArgument.asElement(), candidate));
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(valueArgument.asElement(), candidate));
|
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(valueArgument.asElement(), candidate));
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,7 +156,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
|
|
||||||
if (valueParameters.isEmpty()) {
|
if (valueParameters.isEmpty()) {
|
||||||
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
|
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JetFunctionLiteralExpression functionLiteral;
|
JetFunctionLiteralExpression functionLiteral;
|
||||||
@@ -139,15 +171,15 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
||||||
if (valueParameterDescriptor.getVarargElementType() != null) {
|
if (valueParameterDescriptor.getVarargElementType() != null) {
|
||||||
temporaryTrace.report(VARARG_OUTSIDE_PARENTHESES.on(possiblyLabeledFunctionLiteral));
|
temporaryTrace.report(VARARG_OUTSIDE_PARENTHESES.on(possiblyLabeledFunctionLiteral));
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!usedParameters.add(valueParameterDescriptor)) {
|
if (!usedParameters.add(valueParameterDescriptor)) {
|
||||||
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
|
temporaryTrace.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
put(candidateCall, valueParameterDescriptor, CallMaker.makeValueArgument(functionLiteral), varargs);
|
status = status.compose(put(candidateCall, valueParameterDescriptor, CallMaker.makeValueArgument(functionLiteral), varargs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +187,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
for (int i = 1; i < functionLiteralArguments.size(); i++) {
|
for (int i = 1; i < functionLiteralArguments.size(); i++) {
|
||||||
JetExpression argument = functionLiteralArguments.get(i);
|
JetExpression argument = functionLiteralArguments.get(i);
|
||||||
temporaryTrace.report(MANY_FUNCTION_LITERAL_ARGUMENTS.on(argument));
|
temporaryTrace.report(MANY_FUNCTION_LITERAL_ARGUMENTS.on(argument));
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +203,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
else {
|
else {
|
||||||
// tracing.reportWrongValueArguments(temporaryTrace, "No value passed for parameter " + valueParameter.getName());
|
// tracing.reportWrongValueArguments(temporaryTrace, "No value passed for parameter " + valueParameter.getName());
|
||||||
tracing.noValueForParameter(temporaryTrace, valueParameter);
|
tracing.noValueForParameter(temporaryTrace, valueParameter);
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,21 +212,22 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
|
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
|
||||||
if (receiverParameter.exists() &&!receiverArgument.exists()) {
|
if (receiverParameter.exists() &&!receiverArgument.exists()) {
|
||||||
tracing.missingReceiver(temporaryTrace, receiverParameter);
|
tracing.missingReceiver(temporaryTrace, receiverParameter);
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
if (!receiverParameter.exists() && receiverArgument.exists()) {
|
if (!receiverParameter.exists() && receiverArgument.exists()) {
|
||||||
tracing.noReceiverAllowed(temporaryTrace);
|
tracing.noReceiverAllowed(temporaryTrace);
|
||||||
error = true;
|
status = ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (candidateCall.getThisObject().exists() != candidateCall.getResultingDescriptor().getExpectedThisObject().exists()) {
|
if (candidateCall.getThisObject().exists() != candidateCall.getResultingDescriptor().getExpectedThisObject().exists()) {
|
||||||
assert false : "Shouldn't happen because of TaskPrioritizer: " + candidateCall.getCandidateDescriptor();
|
assert false : "Shouldn't happen because of TaskPrioritizer: " + candidateCall.getCandidateDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> void put(ResolvedCallImpl<D> candidateCall, ValueParameterDescriptor valueParameterDescriptor, ValueArgument valueArgument, Map<ValueParameterDescriptor, VarargValueArgument> varargs) {
|
private static <D extends CallableDescriptor> Status put(ResolvedCallImpl<D> candidateCall, ValueParameterDescriptor valueParameterDescriptor, ValueArgument valueArgument, Map<ValueParameterDescriptor, VarargValueArgument> varargs) {
|
||||||
|
Status error = OK;
|
||||||
if (valueParameterDescriptor.getVarargElementType() != null) {
|
if (valueParameterDescriptor.getVarargElementType() != null) {
|
||||||
VarargValueArgument vararg = varargs.get(valueParameterDescriptor);
|
VarargValueArgument vararg = varargs.get(valueParameterDescriptor);
|
||||||
if (vararg == null) {
|
if (vararg == null) {
|
||||||
@@ -207,11 +240,13 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
else {
|
else {
|
||||||
LeafPsiElement spread = valueArgument.getSpreadElement();
|
LeafPsiElement spread = valueArgument.getSpreadElement();
|
||||||
if (spread != null) {
|
if (spread != null) {
|
||||||
candidateCall.getTrace().report(NON_VARARG_SPREAD.on(spread));
|
candidateCall.getTrace().report(NON_VARARG_SPREAD.on(spread));
|
||||||
|
error = WEAK_ERROR;
|
||||||
}
|
}
|
||||||
ResolvedValueArgument argument = new ExpressionValueArgument(valueArgument);
|
ResolvedValueArgument argument = new ExpressionValueArgument(valueArgument);
|
||||||
candidateCall.recordValueArgument(valueParameterDescriptor, argument);
|
candidateCall.recordValueArgument(valueParameterDescriptor, argument);
|
||||||
}
|
}
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user