Search in sources :

Example 1 with BindingTrace

use of org.jetbrains.kotlin.resolve.BindingTrace 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));
        }
    };
}
Also used : ResolutionContext(org.jetbrains.kotlin.resolve.calls.context.ResolutionContext) ConstraintSystem(org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem) ConstraintSystemStatus(org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemStatus) NotNull(org.jetbrains.annotations.NotNull) InferenceErrorData(org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData) ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) BindingTrace(org.jetbrains.kotlin.resolve.BindingTrace) ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) Nullable(org.jetbrains.annotations.Nullable) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with BindingTrace

use of org.jetbrains.kotlin.resolve.BindingTrace in project kotlin by JetBrains.

the class AbstractTracingStrategy method typeInferenceFailed.

@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()) {
        // (it's useful, when the arguments, e.g. lambdas or calls are incomplete)
        return;
    }
    BindingTrace trace = context.trace;
    if (status.hasOnlyErrorsDerivedFrom(EXPECTED_TYPE_POSITION)) {
        KotlinType declaredReturnType = data.descriptor.getReturnType();
        if (declaredReturnType == null)
            return;
        ConstraintSystem systemWithoutExpectedTypeConstraint = filterConstraintsOut(constraintSystem, EXPECTED_TYPE_POSITION);
        KotlinType substitutedReturnType = systemWithoutExpectedTypeConstraint.getResultingSubstitutor().substitute(declaredReturnType, Variance.OUT_VARIANCE);
        //todo
        assert substitutedReturnType != null;
        assert !noExpectedType(data.expectedType) : "Expected type doesn't exist, but there is an expected type mismatch error";
        if (!DiagnosticUtilsKt.reportTypeMismatchDueToTypeProjection(context, call.getCallElement(), data.expectedType, substitutedReturnType)) {
            trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(call.getCallElement(), data.expectedType, substitutedReturnType));
        }
    } else if (status.hasCannotCaptureTypesError()) {
        trace.report(TYPE_INFERENCE_CANNOT_CAPTURE_TYPES.on(reference, data));
    } else if (status.hasViolatedUpperBound()) {
        trace.report(TYPE_INFERENCE_UPPER_BOUND_VIOLATED.on(reference, data));
    } else if (status.hasParameterConstraintError()) {
        trace.report(TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR.on(reference, data));
    } else if (status.hasConflictingConstraints()) {
        trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(reference, data));
    } else if (status.hasTypeInferenceIncorporationError()) {
        trace.report(TYPE_INFERENCE_INCORPORATION_ERROR.on(reference));
    } else if (status.hasTypeParameterWithUnsatisfiedOnlyInputTypesError()) {
        //todo
        trace.report(TYPE_INFERENCE_ONLY_INPUT_TYPES.on(reference, data.descriptor.getTypeParameters().get(0)));
    } else {
        assert status.hasUnknownParameters();
        trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, data));
    }
}
Also used : BindingTrace(org.jetbrains.kotlin.resolve.BindingTrace) ConstraintSystem(org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem) KotlinType(org.jetbrains.kotlin.types.KotlinType) ConstraintSystemStatus(org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemStatus)

Example 3 with BindingTrace

use of org.jetbrains.kotlin.resolve.BindingTrace in project kotlin by JetBrains.

the class K2JSTranslator method translate.

@NotNull
public TranslationResult translate(@NotNull List<KtFile> files, @NotNull MainCallParameters mainCallParameters, @Nullable JsAnalysisResult analysisResult) throws TranslationException {
    if (analysisResult == null) {
        analysisResult = TopDownAnalyzerFacadeForJS.analyzeFiles(files, config);
        ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
    }
    BindingTrace bindingTrace = analysisResult.getBindingTrace();
    TopDownAnalyzerFacadeForJS.checkForErrors(files, bindingTrace.getBindingContext());
    ModuleDescriptor moduleDescriptor = analysisResult.getModuleDescriptor();
    Diagnostics diagnostics = bindingTrace.getBindingContext().getDiagnostics();
    TranslationContext context = Translation.generateAst(bindingTrace, files, mainCallParameters, moduleDescriptor, config);
    ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
    if (hasError(diagnostics))
        return new TranslationResult.Fail(diagnostics);
    JsProgram program = JsInliner.process(context);
    ResolveTemporaryNamesKt.resolveTemporaryNames(program);
    ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
    if (hasError(diagnostics))
        return new TranslationResult.Fail(diagnostics);
    CoroutineTransformer coroutineTransformer = new CoroutineTransformer(program);
    coroutineTransformer.accept(program);
    RemoveUnusedImportsKt.removeUnusedImports(program);
    ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
    if (hasError(diagnostics))
        return new TranslationResult.Fail(diagnostics);
    expandIsCalls(program, context);
    ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
    List<String> importedModules = new ArrayList<String>();
    for (StaticContext.ImportedModule module : context.getImportedModules()) {
        importedModules.add(module.getExternalName());
    }
    return new TranslationResult.Success(config, files, program, diagnostics, importedModules, moduleDescriptor, bindingTrace.getBindingContext());
}
Also used : BindingTrace(org.jetbrains.kotlin.resolve.BindingTrace) Diagnostics(org.jetbrains.kotlin.resolve.diagnostics.Diagnostics) CoroutineTransformer(org.jetbrains.kotlin.js.coroutine.CoroutineTransformer) ArrayList(java.util.ArrayList) JsProgram(org.jetbrains.kotlin.js.backend.ast.JsProgram) ModuleDescriptor(org.jetbrains.kotlin.descriptors.ModuleDescriptor) TranslationContext(org.jetbrains.kotlin.js.translate.context.TranslationContext) StaticContext(org.jetbrains.kotlin.js.translate.context.StaticContext) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

BindingTrace (org.jetbrains.kotlin.resolve.BindingTrace)3 NotNull (org.jetbrains.annotations.NotNull)2 ConstraintSystem (org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystem)2 ConstraintSystemStatus (org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemStatus)2 ArrayList (java.util.ArrayList)1 Nullable (org.jetbrains.annotations.Nullable)1 ModuleDescriptor (org.jetbrains.kotlin.descriptors.ModuleDescriptor)1 JsProgram (org.jetbrains.kotlin.js.backend.ast.JsProgram)1 CoroutineTransformer (org.jetbrains.kotlin.js.coroutine.CoroutineTransformer)1 StaticContext (org.jetbrains.kotlin.js.translate.context.StaticContext)1 TranslationContext (org.jetbrains.kotlin.js.translate.context.TranslationContext)1 ResolutionContext (org.jetbrains.kotlin.resolve.calls.context.ResolutionContext)1 InferenceErrorData (org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData)1 ResolvedCall (org.jetbrains.kotlin.resolve.calls.model.ResolvedCall)1 Diagnostics (org.jetbrains.kotlin.resolve.diagnostics.Diagnostics)1 KotlinType (org.jetbrains.kotlin.types.KotlinType)1