use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.
the class BasicExpressionTypingVisitor method recordThisOrSuperCallInTraceAndCallExtension.
private void recordThisOrSuperCallInTraceAndCallExtension(ExpressionTypingContext context, ReceiverParameterDescriptor descriptor, KtExpression expression) {
BindingTrace trace = context.trace;
Call call = CallMaker.makeCall(expression, null, null, expression, Collections.<ValueArgument>emptyList());
ResolutionCandidate<ReceiverParameterDescriptor> resolutionCandidate = ResolutionCandidate.create(call, descriptor, null, ExplicitReceiverKind.NO_EXPLICIT_RECEIVER, null);
ResolvedCallImpl<ReceiverParameterDescriptor> resolvedCall = ResolvedCallImpl.create(resolutionCandidate, TemporaryBindingTrace.create(trace, "Fake trace for fake 'this' or 'super' resolved call"), TracingStrategy.EMPTY, new DataFlowInfoForArgumentsImpl(context.dataFlowInfo, call));
resolvedCall.markCallAsCompleted();
trace.record(RESOLVED_CALL, call, resolvedCall);
trace.record(CALL, expression, call);
if (context.trace.wantsDiagnostics()) {
CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageVersionSettings);
for (CallChecker checker : components.callCheckers) {
checker.check(resolvedCall, expression, callCheckerContext);
}
}
}
use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.
the class ControlStructureTypingUtils method createTracingForSpecialConstruction.
@NotNull
private TracingStrategy createTracingForSpecialConstruction(@NotNull final Call call, @NotNull String constructionName, @NotNull final ExpressionTypingContext context) {
class CheckTypeContext {
public BindingTrace trace;
public KotlinType expectedType;
CheckTypeContext(@NotNull BindingTrace trace, @NotNull KotlinType expectedType) {
this.trace = trace;
this.expectedType = expectedType;
}
CheckTypeContext makeTypeNullable() {
if (TypeUtils.noExpectedType(expectedType))
return this;
return new CheckTypeContext(trace, TypeUtils.makeNullable(expectedType));
}
}
final KtVisitor<Boolean, CheckTypeContext> checkTypeVisitor = new KtVisitor<Boolean, CheckTypeContext>() {
private boolean checkExpressionType(@NotNull KtExpression expression, CheckTypeContext c) {
KotlinTypeInfo typeInfo = BindingContextUtils.getRecordedTypeInfo(expression, c.trace.getBindingContext());
if (typeInfo == null)
return false;
Ref<Boolean> hasError = Ref.create();
dataFlowAnalyzer.checkType(typeInfo.getType(), expression, context.replaceExpectedType(c.expectedType).replaceDataFlowInfo(typeInfo.getDataFlowInfo()).replaceBindingTrace(c.trace), hasError);
return hasError.get();
}
private boolean checkExpressionTypeRecursively(@Nullable KtExpression expression, CheckTypeContext c) {
if (expression == null)
return false;
return expression.accept(this, c);
}
private boolean checkSubExpressions(KtExpression firstSub, KtExpression secondSub, KtExpression expression, CheckTypeContext firstContext, CheckTypeContext secondContext, CheckTypeContext context) {
boolean errorWasReported = checkExpressionTypeRecursively(firstSub, firstContext);
errorWasReported |= checkExpressionTypeRecursively(secondSub, secondContext);
return errorWasReported || checkExpressionType(expression, context);
}
@Override
public Boolean visitWhenExpression(@NotNull KtWhenExpression whenExpression, CheckTypeContext c) {
boolean errorWasReported = false;
for (KtWhenEntry whenEntry : whenExpression.getEntries()) {
KtExpression entryExpression = whenEntry.getExpression();
if (entryExpression != null) {
errorWasReported |= checkExpressionTypeRecursively(entryExpression, c);
}
}
errorWasReported |= checkExpressionType(whenExpression, c);
return errorWasReported;
}
@Override
public Boolean visitIfExpression(@NotNull KtIfExpression ifExpression, CheckTypeContext c) {
KtExpression thenBranch = ifExpression.getThen();
KtExpression elseBranch = ifExpression.getElse();
if (thenBranch == null || elseBranch == null) {
return checkExpressionType(ifExpression, c);
}
return checkSubExpressions(thenBranch, elseBranch, ifExpression, c, c, c);
}
@Override
public Boolean visitBlockExpression(@NotNull KtBlockExpression expression, CheckTypeContext c) {
if (expression.getStatements().isEmpty()) {
return checkExpressionType(expression, c);
}
KtExpression lastStatement = KtPsiUtil.getLastStatementInABlock(expression);
if (lastStatement != null) {
return checkExpressionTypeRecursively(lastStatement, c);
}
return false;
}
@Override
public Boolean visitPostfixExpression(@NotNull KtPostfixExpression expression, CheckTypeContext c) {
if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL) {
return checkExpressionTypeRecursively(expression.getBaseExpression(), c.makeTypeNullable());
}
return super.visitPostfixExpression(expression, c);
}
@Override
public Boolean visitBinaryExpression(@NotNull KtBinaryExpression expression, CheckTypeContext c) {
if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.ELVIS) {
return checkSubExpressions(expression.getLeft(), expression.getRight(), expression, c.makeTypeNullable(), c, c);
}
return super.visitBinaryExpression(expression, c);
}
@Override
public Boolean visitExpression(@NotNull KtExpression expression, CheckTypeContext c) {
return checkExpressionType(expression, c);
}
};
return new ThrowingOnErrorTracingStrategy("resolve " + constructionName + " as a call") {
@Override
public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall) {
//do nothing
}
@Override
public void bindCall(@NotNull BindingTrace trace, @NotNull Call call) {
trace.record(CALL, call.getCalleeExpression(), call);
}
@Override
public <D extends CallableDescriptor> void bindResolvedCall(@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall) {
trace.record(RESOLVED_CALL, call, resolvedCall);
}
@Override
public void typeInferenceFailed(@NotNull ResolutionContext<?> context, @NotNull InferenceErrorData data) {
ConstraintSystem constraintSystem = data.constraintSystem;
ConstraintSystemStatus status = constraintSystem.getStatus();
assert !status.isSuccessful() : "Report error only for not successful constraint system";
if (status.hasErrorInConstrainingTypes() || status.hasUnknownParameters()) {
return;
}
KtExpression expression = (KtExpression) call.getCallElement();
if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION) || status.hasConflictingConstraints() || status.hasTypeInferenceIncorporationError()) {
// todo after KT-... remove this line
if (noTypeCheckingErrorsInExpression(expression, context.trace, data.expectedType)) {
KtExpression calleeExpression = call.getCalleeExpression();
if (calleeExpression instanceof KtWhenExpression || calleeExpression instanceof KtIfExpression) {
if (status.hasConflictingConstraints() || status.hasTypeInferenceIncorporationError()) {
// TODO provide comprehensible error report for hasConflictingConstraints() case (if possible)
context.trace.report(TYPE_INFERENCE_FAILED_ON_SPECIAL_CONSTRUCT.on(expression));
}
}
}
return;
}
KtDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, KtNamedDeclaration.class);
logError("Expression: " + (parentDeclaration != null ? parentDeclaration.getText() : expression.getText()) + "\nConstraint system status: \n" + ConstraintsUtil.getDebugMessageForStatus(status));
}
private boolean noTypeCheckingErrorsInExpression(KtExpression expression, @NotNull BindingTrace trace, @NotNull KotlinType expectedType) {
return Boolean.TRUE != expression.accept(checkTypeVisitor, new CheckTypeContext(trace, expectedType));
}
};
}
use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.
the class BasicExpressionTypingVisitor method checkLValue.
/**
* @return {@code true} iff expression can be assigned to
*/
public boolean checkLValue(@NotNull BindingTrace trace, @NotNull ExpressionTypingContext context, @NotNull KtExpression expressionWithParenthesis, @Nullable KtExpression rightHandSide, @NotNull KtOperationExpression operationExpression) {
KtExpression expression = KtPsiUtil.deparenthesize(expressionWithParenthesis);
if (expression instanceof KtArrayAccessExpression) {
KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) expression;
KtExpression arrayExpression = arrayAccessExpression.getArrayExpression();
if (arrayExpression == null || rightHandSide == null)
return false;
TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(trace, "Trace for checking set function");
ExpressionTypingContext findSetterContext = context.replaceBindingTrace(ignoreReportsTrace);
KotlinTypeInfo info = resolveArrayAccessSetMethod(arrayAccessExpression, rightHandSide, findSetterContext, ignoreReportsTrace);
IElementType operationType = operationExpression.getOperationReference().getReferencedNameElementType();
if (KtTokens.AUGMENTED_ASSIGNMENTS.contains(operationType) || operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) {
ResolvedCall<?> resolvedCall = ignoreReportsTrace.get(INDEXED_LVALUE_SET, expression);
if (resolvedCall != null && trace.wantsDiagnostics()) {
// Call must be validated with the actual, not temporary trace in order to report operator diagnostic
// Only unary assignment expressions (++, --) and +=/... must be checked, normal assignments have the proper trace
CallCheckerContext callCheckerContext = new CallCheckerContext(context, trace, components.languageVersionSettings);
for (CallChecker checker : components.callCheckers) {
checker.check(resolvedCall, expression, callCheckerContext);
}
}
}
return info.getType() != null;
}
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorFromReference(trace.getBindingContext(), expression);
boolean result = true;
KtExpression reportOn = expression != null ? expression : expressionWithParenthesis;
if (reportOn instanceof KtQualifiedExpression) {
KtExpression selector = ((KtQualifiedExpression) reportOn).getSelectorExpression();
if (selector != null)
reportOn = selector;
}
if (variable instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
if (propertyDescriptor.isSetterProjectedOut()) {
trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
result = false;
} else if (setter != null) {
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expressionWithParenthesis, context.trace.getBindingContext());
assert resolvedCall != null : "Call is not resolved for property setter: " + PsiUtilsKt.getElementTextWithContext(expressionWithParenthesis);
checkPropertySetterCall(context.replaceBindingTrace(trace), setter, resolvedCall, reportOn);
}
}
if (variable == null) {
trace.report(VARIABLE_EXPECTED.on(reportOn));
result = false;
} else if (!variable.isVar()) {
result = false;
}
return result;
}
use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.
the class BasicExpressionTypingVisitor method checkPropertySetterCall.
private void checkPropertySetterCall(@NotNull ExpressionTypingContext context, @NotNull PropertySetterDescriptor descriptor, @NotNull ResolvedCall<?> propertyResolvedCall, @NotNull KtExpression expression) {
Call call = propertyResolvedCall.getCall();
ResolutionCandidate<PropertySetterDescriptor> resolutionCandidate = ResolutionCandidate.create(call, descriptor, propertyResolvedCall.getDispatchReceiver(), propertyResolvedCall.getExplicitReceiverKind(), null);
ResolvedCallImpl<PropertySetterDescriptor> resolvedCall = ResolvedCallImpl.create(resolutionCandidate, TemporaryBindingTrace.create(context.trace, "Trace for fake property setter resolved call"), TracingStrategy.EMPTY, new DataFlowInfoForArgumentsImpl(propertyResolvedCall.getDataFlowInfoForArguments().getResultInfo(), call));
resolvedCall.markCallAsCompleted();
if (context.trace.wantsDiagnostics()) {
CallCheckerContext callCheckerContext = new CallCheckerContext(context, components.languageVersionSettings);
for (CallChecker checker : components.callCheckers) {
checker.check(resolvedCall, expression, callCheckerContext);
}
}
}
use of org.jetbrains.kotlin.resolve.calls.model.ResolvedCall in project kotlin by JetBrains.
the class FunctionReferenceGenerationStrategy method doGenerateBody.
@Override
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
/*
Here we need to put the arguments from our locals to the stack and invoke the referenced method. Since invocation
of methods is highly dependent on expressions, we create a fake call expression. Then we create a new instance of
ExpressionCodegen and, in order for it to generate code correctly, we save to its 'tempVariables' field every
argument of our fake expression, pointing it to the corresponding index in our locals. This way generation of
every argument boils down to calling LOAD with the corresponding index
*/
KtCallExpression fakeExpression = CodegenUtil.constructFakeFunctionCall(state.getProject(), referencedFunction);
final List<? extends ValueArgument> fakeArguments = fakeExpression.getValueArguments();
final ReceiverValue dispatchReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getDispatchReceiverParameter());
final ReceiverValue extensionReceiver = computeAndSaveReceiver(signature, codegen, referencedFunction.getExtensionReceiverParameter());
computeAndSaveArguments(fakeArguments, codegen);
ResolvedCall<CallableDescriptor> fakeResolvedCall = new DelegatingResolvedCall<CallableDescriptor>(resolvedCall) {
private final Map<ValueParameterDescriptor, ResolvedValueArgument> argumentMap;
{
argumentMap = new LinkedHashMap<ValueParameterDescriptor, ResolvedValueArgument>(fakeArguments.size());
int index = 0;
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
for (ValueArgument argument : fakeArguments) {
argumentMap.put(parameters.get(index), new ExpressionValueArgument(argument));
index++;
}
}
@Nullable
@Override
public ReceiverValue getExtensionReceiver() {
return extensionReceiver;
}
@Nullable
@Override
public ReceiverValue getDispatchReceiver() {
return dispatchReceiver;
}
@NotNull
@Override
public List<ResolvedValueArgument> getValueArgumentsByIndex() {
return new ArrayList<ResolvedValueArgument>(argumentMap.values());
}
@NotNull
@Override
public Map<ValueParameterDescriptor, ResolvedValueArgument> getValueArguments() {
return argumentMap;
}
};
StackValue result;
Type returnType = codegen.getReturnType();
if (referencedFunction instanceof ConstructorDescriptor) {
if (returnType.getSort() == Type.ARRAY) {
//noinspection ConstantConditions
result = codegen.generateNewArray(fakeExpression, referencedFunction.getReturnType(), fakeResolvedCall);
} else {
result = codegen.generateConstructorCall(fakeResolvedCall, returnType);
}
} else {
Call call = CallMaker.makeCall(fakeExpression, null, null, fakeExpression, fakeArguments);
result = codegen.invokeFunction(call, fakeResolvedCall, StackValue.none());
}
InstructionAdapter v = codegen.v;
result.put(returnType, v);
v.areturn(returnType);
}
Aggregations