Logic refactored to a finite automaton
This commit is contained in:
+233
-183
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
|||||||
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.model.*;
|
import org.jetbrains.jet.lang.resolve.calls.model.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
|
import org.jetbrains.jet.lang.resolve.calls.tasks.TracingStrategy;
|
||||||
@@ -66,246 +67,295 @@ import static org.jetbrains.jet.lang.resolve.calls.ValueArgumentsToParametersMap
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <D extends CallableDescriptor> Status mapValueArgumentsToParameters(
|
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,
|
||||||
@NotNull Set<ValueArgument> unmappedArguments
|
@NotNull Set<ValueArgument> unmappedArguments
|
||||||
) {
|
) {
|
||||||
Map<ValueParameterDescriptor, VarargValueArgument> varargs = Maps.newHashMap();
|
//return new ValueArgumentsToParametersMapper().process(call, tracing, candidateCall, unmappedArguments);
|
||||||
Set<ValueParameterDescriptor> usedParameters = Sets.newHashSet();
|
Processor<D> processor = new Processor<D>(call, candidateCall, tracing);
|
||||||
|
processor.process();
|
||||||
Status status = processArgumentsInParens(call, candidateCall, unmappedArguments, varargs, usedParameters);
|
unmappedArguments.addAll(processor.unmappedArguments);
|
||||||
|
return processor.status;
|
||||||
status = processFunctionLiteralArguments(call, candidateCall, varargs, usedParameters, status);
|
|
||||||
|
|
||||||
status = reportUnusedParameters(tracing, candidateCall, usedParameters, status);
|
|
||||||
|
|
||||||
status = checkReceiverArgument(call, tracing, candidateCall, status);
|
|
||||||
|
|
||||||
assert (candidateCall.getThisObject().exists() == (candidateCall.getResultingDescriptor().getExpectedThisObject() != null))
|
|
||||||
: "Shouldn't happen because of TaskPrioritizer: " + candidateCall.getCandidateDescriptor();
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> Status processArgumentsInParens(
|
private static class Processor<D extends CallableDescriptor> {
|
||||||
Call call,
|
private final Call call;
|
||||||
ResolvedCallImpl<D> candidateCall,
|
private final TracingStrategy tracing;
|
||||||
Set<ValueArgument> unmappedArguments,
|
private final ResolvedCallImpl<D> candidateCall;
|
||||||
Map<ValueParameterDescriptor, VarargValueArgument> varargs,
|
|
||||||
Set<ValueParameterDescriptor> usedParameters
|
|
||||||
) {
|
|
||||||
DelegatingBindingTrace traceForCall = candidateCall.getTrace();
|
|
||||||
D candidate = candidateCall.getCandidateDescriptor();
|
|
||||||
List<ValueParameterDescriptor> valueParameters = candidate.getValueParameters();
|
|
||||||
|
|
||||||
Map<Name, ValueParameterDescriptor> parameterByName = Maps.newHashMap();
|
private final Map<Name,ValueParameterDescriptor> parameterByName;
|
||||||
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
|
||||||
parameterByName.put(valueParameter.getName(), valueParameter);
|
private final Set<ValueArgument> unmappedArguments = Sets.newHashSet();
|
||||||
|
private final Map<ValueParameterDescriptor, VarargValueArgument> varargs = Maps.newHashMap();
|
||||||
|
private final Set<ValueParameterDescriptor> usedParameters = Sets.newHashSet();
|
||||||
|
private Status status = OK;
|
||||||
|
|
||||||
|
private Processor(@NotNull Call call, @NotNull ResolvedCallImpl<D> candidateCall, @NotNull TracingStrategy tracing) {
|
||||||
|
this.call = call;
|
||||||
|
this.tracing = tracing;
|
||||||
|
this.candidateCall = candidateCall;
|
||||||
|
|
||||||
|
this.parameterByName = Maps.newHashMap();
|
||||||
|
for (ValueParameterDescriptor valueParameter : candidateCall.getCandidateDescriptor().getValueParameters()) {
|
||||||
|
parameterByName.put(valueParameter.getName(), valueParameter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<? extends ValueArgument> valueArguments = call.getValueArguments();
|
private final ProcessorState initial = new ProcessorState() {
|
||||||
|
|
||||||
Status status = OK;
|
@Override
|
||||||
boolean someNamed = false;
|
public ProcessorState processNamedArgument(@NotNull ValueArgument argument) {
|
||||||
boolean somePositioned = false;
|
return namedOnly.processNamedArgument(argument);
|
||||||
for (int i = 0; i < valueArguments.size(); i++) {
|
}
|
||||||
ValueArgument valueArgument = valueArguments.get(i);
|
|
||||||
if (valueArgument.isNamed()) {
|
@Override
|
||||||
someNamed = true;
|
public ProcessorState processPositionedArgument(
|
||||||
JetSimpleNameExpression nameReference = valueArgument.getArgumentName().getReferenceExpression();
|
@NotNull ValueArgument argument, int index
|
||||||
|
) {
|
||||||
|
return positionedOnly.processPositionedArgument(argument, index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final ProcessorState positionedOnly = new ProcessorState() {
|
||||||
|
@Override
|
||||||
|
public ProcessorState processNamedArgument(@NotNull ValueArgument argument) {
|
||||||
|
return error.processNamedArgument(argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorState processPositionedArgument(@NotNull ValueArgument argument, int index) {
|
||||||
|
BindingTrace traceForCall = candidateCall.getTrace();
|
||||||
|
D candidate = candidateCall.getCandidateDescriptor();
|
||||||
|
|
||||||
|
List<ValueParameterDescriptor> valueParameters = candidate.getValueParameters();
|
||||||
|
|
||||||
|
int parameterCount = valueParameters.size();
|
||||||
|
if (index < parameterCount) {
|
||||||
|
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(index);
|
||||||
|
usedParameters.add(valueParameterDescriptor);
|
||||||
|
putVararg(valueParameterDescriptor, argument);
|
||||||
|
}
|
||||||
|
else if (!valueParameters.isEmpty()) {
|
||||||
|
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
||||||
|
if (valueParameterDescriptor.getVarargElementType() != null) {
|
||||||
|
putVararg(valueParameterDescriptor, argument);
|
||||||
|
usedParameters.add(valueParameterDescriptor);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
traceForCall.report(TOO_MANY_ARGUMENTS.on(argument.asElement(), candidate));
|
||||||
|
unmappedArguments.add(argument);
|
||||||
|
setStatus(WEAK_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
traceForCall.report(TOO_MANY_ARGUMENTS.on(argument.asElement(), candidate));
|
||||||
|
unmappedArguments.add(argument);
|
||||||
|
setStatus(ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return positionedOnly;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final ProcessorState namedOnly = new ProcessorState() {
|
||||||
|
@Override
|
||||||
|
public ProcessorState processNamedArgument(@NotNull ValueArgument argument) {
|
||||||
|
assert argument.isNamed();
|
||||||
|
DelegatingBindingTrace traceForCall = candidateCall.getTrace();
|
||||||
|
|
||||||
|
JetSimpleNameExpression nameReference = argument.getArgumentName().getReferenceExpression();
|
||||||
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedNameAsName());
|
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedNameAsName());
|
||||||
if (valueParameterDescriptor == null) {
|
if (valueParameterDescriptor == null) {
|
||||||
traceForCall.report(NAMED_PARAMETER_NOT_FOUND.on(nameReference));
|
traceForCall.report(NAMED_PARAMETER_NOT_FOUND.on(nameReference));
|
||||||
unmappedArguments.add(valueArgument);
|
unmappedArguments.add(argument);
|
||||||
status = WEAK_ERROR;
|
setStatus(WEAK_ERROR);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
traceForCall.record(REFERENCE_TARGET, nameReference, valueParameterDescriptor);
|
traceForCall.record(REFERENCE_TARGET, nameReference, valueParameterDescriptor);
|
||||||
if (!usedParameters.add(valueParameterDescriptor)) {
|
if (!usedParameters.add(valueParameterDescriptor)) {
|
||||||
traceForCall.report(ARGUMENT_PASSED_TWICE.on(nameReference));
|
traceForCall.report(ARGUMENT_PASSED_TWICE.on(nameReference));
|
||||||
unmappedArguments.add(valueArgument);
|
unmappedArguments.add(argument);
|
||||||
status = WEAK_ERROR;
|
setStatus(WEAK_ERROR);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
status = status.compose(put(candidateCall, valueParameterDescriptor, valueArgument, varargs));
|
putVararg(valueParameterDescriptor, argument);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (somePositioned) {
|
|
||||||
traceForCall.report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(nameReference));
|
return namedOnly;
|
||||||
status = WEAK_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
somePositioned = true;
|
@Override
|
||||||
if (someNamed) {
|
public ProcessorState processPositionedArgument(
|
||||||
traceForCall.report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(valueArgument.asElement()));
|
@NotNull ValueArgument argument, int index
|
||||||
status = WEAK_ERROR;
|
) {
|
||||||
|
return error.processPositionedArgument(argument, index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final ProcessorState error = new ProcessorState() {
|
||||||
|
@Override
|
||||||
|
public ProcessorState processNamedArgument(@NotNull ValueArgument argument) {
|
||||||
|
namedOnly.processNamedArgument(argument);
|
||||||
|
|
||||||
|
candidateCall.getTrace().report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(argument.getArgumentName()));
|
||||||
|
setStatus(WEAK_ERROR);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProcessorState processPositionedArgument(
|
||||||
|
@NotNull ValueArgument argument, int index
|
||||||
|
) {
|
||||||
|
candidateCall.getTrace().report(MIXING_NAMED_AND_POSITIONED_ARGUMENTS.on(argument.asElement()));
|
||||||
|
setStatus(WEAK_ERROR);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void process() {
|
||||||
|
ProcessorState state = initial;
|
||||||
|
List<? extends ValueArgument> arguments = call.getValueArguments();
|
||||||
|
for (int i = 0; i < arguments.size(); i++) {
|
||||||
|
ValueArgument valueArgument = arguments.get(i);
|
||||||
|
if (valueArgument.isNamed()) {
|
||||||
|
state = state.processNamedArgument(valueArgument);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int parameterCount = valueParameters.size();
|
state = state.processPositionedArgument(valueArgument, i);
|
||||||
if (i < parameterCount) {
|
}
|
||||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(i);
|
}
|
||||||
usedParameters.add(valueParameterDescriptor);
|
|
||||||
status = status.compose(put(candidateCall, valueParameterDescriptor, valueArgument, varargs));
|
processFunctionLiteralArguments();
|
||||||
|
reportUnmappedParameters();
|
||||||
|
checkReceiverArgument();
|
||||||
|
|
||||||
|
assert (candidateCall.getThisObject().exists() == (candidateCall.getResultingDescriptor().getExpectedThisObject() != null))
|
||||||
|
: "Shouldn't happen because of TaskPrioritizer: " + candidateCall.getCandidateDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processFunctionLiteralArguments() {
|
||||||
|
D candidate = candidateCall.getCandidateDescriptor();
|
||||||
|
DelegatingBindingTrace traceForCall = candidateCall.getTrace();
|
||||||
|
List<ValueParameterDescriptor> valueParameters = candidate.getValueParameters();
|
||||||
|
|
||||||
|
List<JetExpression> functionLiteralArguments = call.getFunctionLiteralArguments();
|
||||||
|
if (!functionLiteralArguments.isEmpty()) {
|
||||||
|
JetExpression possiblyLabeledFunctionLiteral = functionLiteralArguments.get(0);
|
||||||
|
|
||||||
|
if (valueParameters.isEmpty()) {
|
||||||
|
traceForCall.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
|
||||||
|
setStatus(ERROR);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JetFunctionLiteralExpression functionLiteral;
|
||||||
|
if (possiblyLabeledFunctionLiteral instanceof JetLabelQualifiedExpression) {
|
||||||
|
JetLabelQualifiedExpression labeledFunctionLiteral = (JetLabelQualifiedExpression) possiblyLabeledFunctionLiteral;
|
||||||
|
functionLiteral = (JetFunctionLiteralExpression) labeledFunctionLiteral.getLabeledExpression();
|
||||||
}
|
}
|
||||||
else if (!valueParameters.isEmpty()) {
|
else {
|
||||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
functionLiteral = (JetFunctionLiteralExpression) possiblyLabeledFunctionLiteral;
|
||||||
if (valueParameterDescriptor.getVarargElementType() != null) {
|
}
|
||||||
status = status.compose(put(candidateCall, valueParameterDescriptor, valueArgument, varargs));
|
|
||||||
usedParameters.add(valueParameterDescriptor);
|
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
||||||
|
if (valueParameterDescriptor.getVarargElementType() != null) {
|
||||||
|
traceForCall.report(VARARG_OUTSIDE_PARENTHESES.on(possiblyLabeledFunctionLiteral));
|
||||||
|
setStatus(ERROR);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!usedParameters.add(valueParameterDescriptor)) {
|
||||||
|
traceForCall.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
|
||||||
|
setStatus(WEAK_ERROR);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
traceForCall.report(TOO_MANY_ARGUMENTS.on(valueArgument.asElement(), candidate));
|
putVararg(valueParameterDescriptor, CallMaker.makeValueArgument(functionLiteral));
|
||||||
unmappedArguments.add(valueArgument);
|
|
||||||
status = WEAK_ERROR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
traceForCall.report(TOO_MANY_ARGUMENTS.on(valueArgument.asElement(), candidate));
|
|
||||||
unmappedArguments.add(valueArgument);
|
for (int i = 1; i < functionLiteralArguments.size(); i++) {
|
||||||
status = ERROR;
|
JetExpression argument = functionLiteralArguments.get(i);
|
||||||
}
|
traceForCall.report(MANY_FUNCTION_LITERAL_ARGUMENTS.on(argument));
|
||||||
|
setStatus(WEAK_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> Status processFunctionLiteralArguments(
|
private void reportUnmappedParameters() {
|
||||||
Call call,
|
DelegatingBindingTrace traceForCall = candidateCall.getTrace();
|
||||||
ResolvedCallImpl<D> candidateCall,
|
|
||||||
Map<ValueParameterDescriptor, VarargValueArgument> varargs,
|
|
||||||
Set<ValueParameterDescriptor> usedParameters,
|
|
||||||
Status status
|
|
||||||
) {
|
|
||||||
D candidate = candidateCall.getCandidateDescriptor();
|
|
||||||
DelegatingBindingTrace traceForCall = candidateCall.getTrace();
|
|
||||||
List<ValueParameterDescriptor> valueParameters = candidate.getValueParameters();
|
|
||||||
|
|
||||||
List<JetExpression> functionLiteralArguments = call.getFunctionLiteralArguments();
|
List<ValueParameterDescriptor> valueParameters = candidateCall.getCandidateDescriptor().getValueParameters();
|
||||||
if (!functionLiteralArguments.isEmpty()) {
|
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
||||||
JetExpression possiblyLabeledFunctionLiteral = functionLiteralArguments.get(0);
|
if (!usedParameters.contains(valueParameter)) {
|
||||||
|
if (valueParameter.hasDefaultValue()) {
|
||||||
if (valueParameters.isEmpty()) {
|
candidateCall.recordValueArgument(valueParameter, DefaultValueArgument.DEFAULT);
|
||||||
traceForCall.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
|
}
|
||||||
status = ERROR;
|
else if (valueParameter.getVarargElementType() != null) {
|
||||||
}
|
candidateCall.recordValueArgument(valueParameter, new VarargValueArgument());
|
||||||
else {
|
|
||||||
JetFunctionLiteralExpression functionLiteral;
|
|
||||||
if (possiblyLabeledFunctionLiteral instanceof JetLabelQualifiedExpression) {
|
|
||||||
JetLabelQualifiedExpression labeledFunctionLiteral = (JetLabelQualifiedExpression) possiblyLabeledFunctionLiteral;
|
|
||||||
functionLiteral = (JetFunctionLiteralExpression) labeledFunctionLiteral.getLabeledExpression();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
functionLiteral = (JetFunctionLiteralExpression) possiblyLabeledFunctionLiteral;
|
|
||||||
}
|
|
||||||
|
|
||||||
ValueParameterDescriptor valueParameterDescriptor = valueParameters.get(valueParameters.size() - 1);
|
|
||||||
if (valueParameterDescriptor.getVarargElementType() != null) {
|
|
||||||
traceForCall.report(VARARG_OUTSIDE_PARENTHESES.on(possiblyLabeledFunctionLiteral));
|
|
||||||
status = ERROR;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!usedParameters.add(valueParameterDescriptor)) {
|
|
||||||
traceForCall.report(TOO_MANY_ARGUMENTS.on(possiblyLabeledFunctionLiteral, candidate));
|
|
||||||
status = WEAK_ERROR;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
status = status.compose(put(candidateCall, valueParameterDescriptor, CallMaker.makeValueArgument(functionLiteral), varargs));
|
tracing.noValueForParameter(traceForCall, valueParameter);
|
||||||
|
setStatus(ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i < functionLiteralArguments.size(); i++) {
|
|
||||||
JetExpression argument = functionLiteralArguments.get(i);
|
|
||||||
traceForCall.report(MANY_FUNCTION_LITERAL_ARGUMENTS.on(argument));
|
|
||||||
status = WEAK_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> Status reportUnusedParameters(
|
private void checkReceiverArgument() {
|
||||||
TracingStrategy tracing,
|
DelegatingBindingTrace traceForCall = candidateCall.getTrace();
|
||||||
ResolvedCallImpl<D> candidateCall,
|
D candidate = candidateCall.getCandidateDescriptor();
|
||||||
Set<ValueParameterDescriptor> usedParameters,
|
|
||||||
Status status
|
|
||||||
) {
|
|
||||||
DelegatingBindingTrace traceForCall = candidateCall.getTrace();
|
|
||||||
|
|
||||||
List<ValueParameterDescriptor> valueParameters = candidateCall.getCandidateDescriptor().getValueParameters();
|
ReceiverParameterDescriptor receiverParameter = candidate.getReceiverParameter();
|
||||||
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
ReceiverValue receiverArgument = candidateCall.getReceiverArgument();
|
||||||
if (!usedParameters.contains(valueParameter)) {
|
if (receiverParameter != null &&!receiverArgument.exists()) {
|
||||||
if (valueParameter.hasDefaultValue()) {
|
tracing.missingReceiver(traceForCall, receiverParameter);
|
||||||
candidateCall.recordValueArgument(valueParameter, DefaultValueArgument.DEFAULT);
|
setStatus(ERROR);
|
||||||
}
|
}
|
||||||
else if (valueParameter.getVarargElementType() != null) {
|
if (receiverParameter == null && receiverArgument.exists()) {
|
||||||
candidateCall.recordValueArgument(valueParameter, new VarargValueArgument());
|
tracing.noReceiverAllowed(traceForCall);
|
||||||
|
if (call.getCalleeExpression() instanceof JetSimpleNameExpression) {
|
||||||
|
setStatus(STRONG_ERROR);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tracing.noValueForParameter(traceForCall, valueParameter);
|
setStatus(ERROR);
|
||||||
status = ERROR;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> Status checkReceiverArgument(
|
private void putVararg(
|
||||||
Call call,
|
ValueParameterDescriptor valueParameterDescriptor,
|
||||||
TracingStrategy tracing,
|
ValueArgument valueArgument
|
||||||
ResolvedCallImpl<D> candidateCall,
|
) {
|
||||||
Status status
|
if (valueParameterDescriptor.getVarargElementType() != null) {
|
||||||
) {
|
VarargValueArgument vararg = varargs.get(valueParameterDescriptor);
|
||||||
DelegatingBindingTrace traceForCall = candidateCall.getTrace();
|
if (vararg == null) {
|
||||||
D candidate = candidateCall.getCandidateDescriptor();
|
vararg = new VarargValueArgument();
|
||||||
|
varargs.put(valueParameterDescriptor, vararg);
|
||||||
ReceiverParameterDescriptor receiverParameter = candidate.getReceiverParameter();
|
candidateCall.recordValueArgument(valueParameterDescriptor, vararg);
|
||||||
ReceiverValue receiverArgument = candidateCall.getReceiverArgument();
|
}
|
||||||
if (receiverParameter != null &&!receiverArgument.exists()) {
|
vararg.addArgument(valueArgument);
|
||||||
tracing.missingReceiver(traceForCall, receiverParameter);
|
|
||||||
status = ERROR;
|
|
||||||
}
|
|
||||||
if (receiverParameter == null && receiverArgument.exists()) {
|
|
||||||
tracing.noReceiverAllowed(traceForCall);
|
|
||||||
if (call.getCalleeExpression() instanceof JetSimpleNameExpression) {
|
|
||||||
status = STRONG_ERROR;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
status = ERROR;
|
LeafPsiElement spread = valueArgument.getSpreadElement();
|
||||||
|
if (spread != null) {
|
||||||
|
candidateCall.getTrace().report(NON_VARARG_SPREAD.on(spread));
|
||||||
|
setStatus(WEAK_ERROR);
|
||||||
|
}
|
||||||
|
ResolvedValueArgument argument = new ExpressionValueArgument(valueArgument);
|
||||||
|
candidateCall.recordValueArgument(valueParameterDescriptor, argument);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <D extends CallableDescriptor> Status put(
|
private void setStatus(@NotNull Status newStatus) {
|
||||||
ResolvedCallImpl<D> candidateCall,
|
status = status.compose(newStatus);
|
||||||
ValueParameterDescriptor valueParameterDescriptor,
|
|
||||||
ValueArgument valueArgument,
|
|
||||||
Map<ValueParameterDescriptor, VarargValueArgument> varargs
|
|
||||||
) {
|
|
||||||
Status error = OK;
|
|
||||||
if (valueParameterDescriptor.getVarargElementType() != null) {
|
|
||||||
VarargValueArgument vararg = varargs.get(valueParameterDescriptor);
|
|
||||||
if (vararg == null) {
|
|
||||||
vararg = new VarargValueArgument();
|
|
||||||
varargs.put(valueParameterDescriptor, vararg);
|
|
||||||
candidateCall.recordValueArgument(valueParameterDescriptor, vararg);
|
|
||||||
}
|
|
||||||
vararg.addArgument(valueArgument);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
LeafPsiElement spread = valueArgument.getSpreadElement();
|
private interface ProcessorState {
|
||||||
if (spread != null) {
|
ProcessorState processNamedArgument(@NotNull ValueArgument argument);
|
||||||
candidateCall.getTrace().report(NON_VARARG_SPREAD.on(spread));
|
ProcessorState processPositionedArgument(@NotNull ValueArgument argument, int index);
|
||||||
error = WEAK_ERROR;
|
|
||||||
}
|
|
||||||
ResolvedValueArgument argument = new ExpressionValueArgument(valueArgument);
|
|
||||||
candidateCall.recordValueArgument(valueParameterDescriptor, argument);
|
|
||||||
}
|
}
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user