Search in sources :

Example 1 with Diagnostic

use of org.jetbrains.kotlin.diagnostics.Diagnostic in project kotlin by JetBrains.

the class ExpectedResolveData method checkResult.

public final void checkResult(BindingContext bindingContext) {
    Set<PsiElement> unresolvedReferences = Sets.newHashSet();
    for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
        if (Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS.contains(diagnostic.getFactory())) {
            unresolvedReferences.add(diagnostic.getPsiElement());
        }
    }
    Map<String, PsiElement> nameToDeclaration = Maps.newHashMap();
    Map<PsiElement, String> declarationToName = Maps.newHashMap();
    for (Map.Entry<String, Position> entry : declarationToPosition.entrySet()) {
        String name = entry.getKey();
        Position position = entry.getValue();
        PsiElement element = position.getElement();
        PsiElement ancestorOfType;
        if (name.equals("file")) {
            ancestorOfType = element.getContainingFile();
        } else {
            ancestorOfType = getAncestorOfType(KtDeclaration.class, element);
            if (ancestorOfType == null) {
                KtPackageDirective directive = getAncestorOfType(KtPackageDirective.class, element);
                assert directive != null : "Not a declaration: " + name;
                ancestorOfType = element;
            }
        }
        nameToDeclaration.put(name, ancestorOfType);
        declarationToName.put(ancestorOfType, name);
    }
    for (Map.Entry<Position, String> entry : positionToReference.entrySet()) {
        Position position = entry.getKey();
        String name = entry.getValue();
        PsiElement element = position.getElement();
        KtReferenceExpression referenceExpression = PsiTreeUtil.getParentOfType(element, KtReferenceExpression.class);
        DeclarationDescriptor referenceTarget = bindingContext.get(REFERENCE_TARGET, referenceExpression);
        if ("!".equals(name)) {
            assertTrue("Must have been unresolved: " + renderReferenceInContext(referenceExpression) + " but was resolved to " + renderNullableDescriptor(referenceTarget), unresolvedReferences.contains(referenceExpression));
            assertTrue(String.format("Reference =%s= has a reference target =%s= but expected to be unresolved", renderReferenceInContext(referenceExpression), renderNullableDescriptor(referenceTarget)), referenceTarget == null);
            continue;
        }
        if ("!!".equals(name)) {
            assertTrue("Must have been resolved to multiple descriptors: " + renderReferenceInContext(referenceExpression) + " but was resolved to " + renderNullableDescriptor(referenceTarget), bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, referenceExpression) != null);
            continue;
        } else if ("!null".equals(name)) {
            assertTrue("Must have been resolved to null: " + renderReferenceInContext(referenceExpression) + " but was resolved to " + renderNullableDescriptor(referenceTarget), referenceTarget == null);
            continue;
        } else if ("!error".equals(name)) {
            assertTrue("Must have been resolved to error: " + renderReferenceInContext(referenceExpression) + " but was resolved to " + renderNullableDescriptor(referenceTarget), ErrorUtils.isError(referenceTarget));
            continue;
        }
        PsiElement expected = nameToDeclaration.get(name);
        if (expected == null) {
            expected = nameToPsiElement.get(name);
        }
        KtReferenceExpression reference = getAncestorOfType(KtReferenceExpression.class, element);
        if (expected == null && name.startsWith(STANDARD_PREFIX)) {
            DeclarationDescriptor expectedDescriptor = nameToDescriptor.get(name);
            KtTypeReference typeReference = getAncestorOfType(KtTypeReference.class, element);
            if (expectedDescriptor != null) {
                DeclarationDescriptor actual = bindingContext.get(REFERENCE_TARGET, reference);
                assertDescriptorsEqual("Expected: " + name, expectedDescriptor.getOriginal(), actual == null ? null : actual.getOriginal());
                continue;
            }
            KotlinType actualType = bindingContext.get(BindingContext.TYPE, typeReference);
            assertNotNull("Type " + name + " not resolved for reference " + name, actualType);
            ClassifierDescriptor expectedClass = getBuiltinClass(name.substring(STANDARD_PREFIX.length()));
            assertTypeConstructorEquals("Type resolution mismatch: ", expectedClass.getTypeConstructor(), actualType.getConstructor());
            continue;
        }
        assert expected != null : "No declaration for " + name;
        if (referenceTarget instanceof PackageViewDescriptor) {
            KtPackageDirective expectedDirective = PsiTreeUtil.getParentOfType(expected, KtPackageDirective.class);
            FqName expectedFqName;
            if (expectedDirective != null) {
                expectedFqName = expectedDirective.getFqName();
            } else if (expected instanceof PsiQualifiedNamedElement) {
                String qualifiedName = ((PsiQualifiedNamedElement) expected).getQualifiedName();
                assert qualifiedName != null : "No qualified name for " + name;
                expectedFqName = new FqName(qualifiedName);
            } else {
                throw new IllegalStateException(expected.getClass().getName() + " name=" + name);
            }
            assertEquals(expectedFqName, ((PackageViewDescriptor) referenceTarget).getFqName());
            continue;
        }
        PsiElement actual = referenceTarget == null ? bindingContext.get(BindingContext.LABEL_TARGET, referenceExpression) : DescriptorToSourceUtils.descriptorToDeclaration(referenceTarget);
        if (actual instanceof KtSimpleNameExpression) {
            actual = ((KtSimpleNameExpression) actual).getIdentifier();
        }
        String actualName = null;
        if (actual != null) {
            actualName = declarationToName.get(actual);
            if (actualName == null) {
                actualName = actual.toString();
            }
        }
        assertNotNull(element.getText(), reference);
        assertEquals("Reference `" + name + "`" + renderReferenceInContext(reference) + " is resolved into " + actualName + ".", expected, actual);
    }
    for (Map.Entry<Position, String> entry : positionToType.entrySet()) {
        Position position = entry.getKey();
        String typeName = entry.getValue();
        PsiElement element = position.getElement();
        KtExpression expression = getAncestorOfType(KtExpression.class, element);
        KotlinType expressionType = bindingContext.getType(expression);
        TypeConstructor expectedTypeConstructor;
        if (typeName.startsWith(STANDARD_PREFIX)) {
            String name = typeName.substring(STANDARD_PREFIX.length());
            ClassifierDescriptor expectedClass = getBuiltinClass(name);
            expectedTypeConstructor = expectedClass.getTypeConstructor();
        } else {
            Position declarationPosition = declarationToPosition.get(typeName);
            assertNotNull("Undeclared: " + typeName, declarationPosition);
            PsiElement declElement = declarationPosition.getElement();
            assertNotNull(declarationPosition);
            KtDeclaration declaration = getAncestorOfType(KtDeclaration.class, declElement);
            assertNotNull(declaration);
            if (declaration instanceof KtClass) {
                ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, declaration);
                expectedTypeConstructor = classDescriptor.getTypeConstructor();
            } else if (declaration instanceof KtTypeParameter) {
                TypeParameterDescriptor typeParameterDescriptor = bindingContext.get(BindingContext.TYPE_PARAMETER, (KtTypeParameter) declaration);
                expectedTypeConstructor = typeParameterDescriptor.getTypeConstructor();
            } else {
                fail("Unsupported declaration: " + declaration);
                return;
            }
        }
        assertNotNull(expression.getText() + " type is null", expressionType);
        assertTypeConstructorEquals("At " + position + ": ", expectedTypeConstructor, expressionType.getConstructor());
    }
}
Also used : FqName(org.jetbrains.kotlin.name.FqName) KotlinType(org.jetbrains.kotlin.types.KotlinType) Diagnostic(org.jetbrains.kotlin.diagnostics.Diagnostic) PsiQualifiedNamedElement(com.intellij.psi.PsiQualifiedNamedElement) PsiElement(com.intellij.psi.PsiElement) TypeConstructor(org.jetbrains.kotlin.types.TypeConstructor) Map(java.util.Map)

Example 2 with Diagnostic

use of org.jetbrains.kotlin.diagnostics.Diagnostic in project kotlin by JetBrains.

the class CheckerTestUtil method getDiagnosticsIncludingSyntaxErrors.

@NotNull
public static List<ActualDiagnostic> getDiagnosticsIncludingSyntaxErrors(@NotNull BindingContext bindingContext, @NotNull PsiElement root, boolean markDynamicCalls, @Nullable List<DeclarationDescriptor> dynamicCallDescriptors, @Nullable String platform) {
    List<ActualDiagnostic> diagnostics = new ArrayList<ActualDiagnostic>();
    for (Diagnostic diagnostic : bindingContext.getDiagnostics().all()) {
        if (PsiTreeUtil.isAncestor(root, diagnostic.getPsiElement(), false)) {
            diagnostics.add(new ActualDiagnostic(diagnostic, platform));
        }
    }
    for (PsiErrorElement errorElement : AnalyzingUtils.getSyntaxErrorRanges(root)) {
        diagnostics.add(new ActualDiagnostic(new SyntaxErrorDiagnostic(errorElement), platform));
    }
    diagnostics.addAll(getDebugInfoDiagnostics(root, bindingContext, markDynamicCalls, dynamicCallDescriptors, platform));
    return diagnostics;
}
Also used : PsiErrorElement(com.intellij.psi.PsiErrorElement) Diagnostic(org.jetbrains.kotlin.diagnostics.Diagnostic) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with Diagnostic

use of org.jetbrains.kotlin.diagnostics.Diagnostic in project kotlin by JetBrains.

the class DebugInfoUtil method markDebugAnnotations.

public static void markDebugAnnotations(@NotNull PsiElement root, @NotNull final BindingContext bindingContext, @NotNull final DebugInfoReporter debugInfoReporter) {
    final Map<KtReferenceExpression, DiagnosticFactory<?>> markedWithErrorElements = Maps.newHashMap();
    for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
        DiagnosticFactory<?> factory = diagnostic.getFactory();
        if (Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS.contains(diagnostic.getFactory())) {
            markedWithErrorElements.put((KtReferenceExpression) diagnostic.getPsiElement(), factory);
        } else if (factory == Errors.SUPER_IS_NOT_AN_EXPRESSION || factory == Errors.SUPER_NOT_AVAILABLE) {
            KtSuperExpression superExpression = (KtSuperExpression) diagnostic.getPsiElement();
            markedWithErrorElements.put(superExpression.getInstanceReference(), factory);
        } else if (factory == Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND) {
            markedWithErrorElements.put((KtSimpleNameExpression) diagnostic.getPsiElement(), factory);
        } else if (factory == Errors.UNSUPPORTED) {
            for (KtReferenceExpression reference : PsiTreeUtil.findChildrenOfType(diagnostic.getPsiElement(), KtReferenceExpression.class)) {
                markedWithErrorElements.put(reference, factory);
            }
        }
    }
    root.acceptChildren(new KtTreeVisitorVoid() {

        @Override
        public void visitForExpression(@NotNull KtForExpression expression) {
            KtExpression range = expression.getLoopRange();
            reportIfDynamicCall(range, range, LOOP_RANGE_ITERATOR_RESOLVED_CALL);
            reportIfDynamicCall(range, range, LOOP_RANGE_HAS_NEXT_RESOLVED_CALL);
            reportIfDynamicCall(range, range, LOOP_RANGE_NEXT_RESOLVED_CALL);
            super.visitForExpression(expression);
        }

        @Override
        public void visitDestructuringDeclaration(@NotNull KtDestructuringDeclaration destructuringDeclaration) {
            for (KtDestructuringDeclarationEntry entry : destructuringDeclaration.getEntries()) {
                reportIfDynamicCall(entry, entry, COMPONENT_RESOLVED_CALL);
            }
            super.visitDestructuringDeclaration(destructuringDeclaration);
        }

        @Override
        public void visitProperty(@NotNull KtProperty property) {
            VariableDescriptor descriptor = bindingContext.get(VARIABLE, property);
            if (descriptor instanceof PropertyDescriptor && property.getDelegate() != null) {
                PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
                reportIfDynamicCall(property.getDelegate(), propertyDescriptor, PROVIDE_DELEGATE_RESOLVED_CALL);
                reportIfDynamicCall(property.getDelegate(), propertyDescriptor.getGetter(), DELEGATED_PROPERTY_RESOLVED_CALL);
                reportIfDynamicCall(property.getDelegate(), propertyDescriptor.getSetter(), DELEGATED_PROPERTY_RESOLVED_CALL);
            }
            super.visitProperty(property);
        }

        @Override
        public void visitThisExpression(@NotNull KtThisExpression expression) {
            ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext);
            if (resolvedCall != null) {
                reportIfDynamic(expression, resolvedCall.getResultingDescriptor(), debugInfoReporter);
            }
            super.visitThisExpression(expression);
        }

        @Override
        public void visitReferenceExpression(@NotNull KtReferenceExpression expression) {
            super.visitReferenceExpression(expression);
            if (!BindingContextUtils.isExpressionWithValidReference(expression, bindingContext)) {
                return;
            }
            IElementType referencedNameElementType = null;
            if (expression instanceof KtSimpleNameExpression) {
                KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) expression;
                IElementType elementType = expression.getNode().getElementType();
                if (elementType == KtNodeTypes.OPERATION_REFERENCE) {
                    referencedNameElementType = nameExpression.getReferencedNameElementType();
                    if (EXCLUDED.contains(referencedNameElementType)) {
                        return;
                    }
                }
                if (elementType == KtNodeTypes.LABEL || nameExpression.getReferencedNameElementType() == KtTokens.THIS_KEYWORD) {
                    return;
                }
            }
            debugInfoReporter.preProcessReference(expression);
            String target = null;
            DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, expression);
            if (declarationDescriptor != null) {
                target = declarationDescriptor.toString();
                reportIfDynamic(expression, declarationDescriptor, debugInfoReporter);
            }
            if (target == null) {
                PsiElement labelTarget = bindingContext.get(LABEL_TARGET, expression);
                if (labelTarget != null) {
                    target = labelTarget.getText();
                }
            }
            if (target == null) {
                Collection<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression);
                if (declarationDescriptors != null) {
                    target = "[" + declarationDescriptors.size() + " descriptors]";
                }
            }
            if (target == null) {
                Collection<? extends PsiElement> labelTargets = bindingContext.get(AMBIGUOUS_LABEL_TARGET, expression);
                if (labelTargets != null) {
                    target = "[" + labelTargets.size() + " elements]";
                }
            }
            if (MAY_BE_UNRESOLVED.contains(referencedNameElementType)) {
                return;
            }
            boolean resolved = target != null;
            boolean markedWithError = markedWithErrorElements.containsKey(expression);
            if (expression instanceof KtArrayAccessExpression && markedWithErrorElements.containsKey(((KtArrayAccessExpression) expression).getArrayExpression())) {
                // if 'foo' in 'foo[i]' is unresolved it means 'foo[i]' is unresolved (otherwise 'foo[i]' is marked as 'missing unresolved')
                markedWithError = true;
            }
            KotlinType expressionType = bindingContext.getType(expression);
            DiagnosticFactory<?> factory = markedWithErrorElements.get(expression);
            if (declarationDescriptor != null && (ErrorUtils.isError(declarationDescriptor) || ErrorUtils.containsErrorType(expressionType))) {
                if (factory != Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND) {
                    debugInfoReporter.reportElementWithErrorType(expression);
                }
            }
            if (resolved && markedWithError) {
                if (Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS.contains(factory)) {
                    debugInfoReporter.reportUnresolvedWithTarget(expression, target);
                }
            } else if (!resolved && !markedWithError) {
                debugInfoReporter.reportMissingUnresolved(expression);
            }
        }

        private <E extends KtElement, K, D extends CallableDescriptor> boolean reportIfDynamicCall(E element, K key, WritableSlice<K, ResolvedCall<D>> slice) {
            ResolvedCall<D> resolvedCall = bindingContext.get(slice, key);
            if (resolvedCall != null) {
                return reportIfDynamic(element, resolvedCall.getResultingDescriptor(), debugInfoReporter);
            }
            return false;
        }
    });
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) Diagnostic(org.jetbrains.kotlin.diagnostics.Diagnostic) VariableDescriptor(org.jetbrains.kotlin.descriptors.VariableDescriptor) CallableDescriptor(org.jetbrains.kotlin.descriptors.CallableDescriptor) PsiElement(com.intellij.psi.PsiElement) PropertyDescriptor(org.jetbrains.kotlin.descriptors.PropertyDescriptor) DiagnosticFactory(org.jetbrains.kotlin.diagnostics.DiagnosticFactory) IElementType(com.intellij.psi.tree.IElementType) ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) DeclarationDescriptor(org.jetbrains.kotlin.descriptors.DeclarationDescriptor) Collection(java.util.Collection)

Example 4 with Diagnostic

use of org.jetbrains.kotlin.diagnostics.Diagnostic in project kotlin by JetBrains.

the class KotlinBytecodeToolWindow method getBytecodeForFile.

// public for tests
@NotNull
public static String getBytecodeForFile(@NotNull KtFile ktFile, @NotNull CompilerConfiguration configuration) {
    GenerationState state;
    try {
        state = compileSingleFile(ktFile, configuration);
    } catch (ProcessCanceledException e) {
        throw e;
    } catch (Exception e) {
        return printStackTraceToString(e);
    }
    StringBuilder answer = new StringBuilder();
    Collection<Diagnostic> diagnostics = state.getCollectedExtraJvmDiagnostics().all();
    if (!diagnostics.isEmpty()) {
        answer.append("// Backend Errors: \n");
        answer.append("// ================\n");
        for (Diagnostic diagnostic : diagnostics) {
            answer.append("// Error at ").append(diagnostic.getPsiFile().getName()).append(StringsKt.join(diagnostic.getTextRanges(), ",")).append(": ").append(DefaultErrorMessages.render(diagnostic)).append("\n");
        }
        answer.append("// ================\n\n");
    }
    OutputFileCollection outputFiles = state.getFactory();
    for (OutputFile outputFile : outputFiles.asList()) {
        answer.append("// ================");
        answer.append(outputFile.getRelativePath());
        answer.append(" =================\n");
        answer.append(outputFile.asText()).append("\n\n");
    }
    return answer.toString();
}
Also used : OutputFile(org.jetbrains.kotlin.backend.common.output.OutputFile) OutputFileCollection(org.jetbrains.kotlin.backend.common.output.OutputFileCollection) Diagnostic(org.jetbrains.kotlin.diagnostics.Diagnostic) GenerationState(org.jetbrains.kotlin.codegen.state.GenerationState) ProcessCanceledException(com.intellij.openapi.progress.ProcessCanceledException) ProcessCanceledException(com.intellij.openapi.progress.ProcessCanceledException) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with Diagnostic

use of org.jetbrains.kotlin.diagnostics.Diagnostic in project kotlin by JetBrains.

the class AbstractDiagnosticMessageTest method doTest.

public void doTest(String filePath) throws Exception {
    File file = new File(filePath);
    String fileName = file.getName();
    String fileData = KotlinTestUtils.doLoadFile(file);
    Map<String, String> directives = KotlinTestUtils.parseDirectives(fileData);
    int diagnosticNumber = getDiagnosticNumber(directives);
    final Set<DiagnosticFactory<?>> diagnosticFactories = getDiagnosticFactories(directives);
    MessageType messageType = getMessageTypeDirective(directives);
    String explicitLanguageVersion = InTextDirectivesUtils.findStringWithPrefixes(fileData, "// LANGUAGE_VERSION:");
    LanguageVersion version = explicitLanguageVersion == null ? null : LanguageVersion.fromVersionString(explicitLanguageVersion);
    KtFile psiFile = KotlinTestUtils.createFile(fileName, KotlinTestUtils.doLoadFile(getTestDataPath(), fileName), getProject());
    AnalysisResult analysisResult = analyze(psiFile, version);
    BindingContext bindingContext = analysisResult.getBindingContext();
    List<Diagnostic> diagnostics = ContainerUtil.filter(bindingContext.getDiagnostics().all(), new Condition<Diagnostic>() {

        @Override
        public boolean value(Diagnostic diagnostic) {
            return diagnosticFactories.contains(diagnostic.getFactory());
        }
    });
    assertEquals("Expected diagnostics number mismatch:", diagnosticNumber, diagnostics.size());
    int index = 1;
    String name = FileUtil.getNameWithoutExtension(fileName);
    for (Diagnostic diagnostic : diagnostics) {
        String readableDiagnosticText;
        String extension;
        if (messageType != MessageType.TEXT && IdeErrorMessages.hasIdeSpecificMessage(diagnostic)) {
            readableDiagnosticText = FormatHtmlUtilKt.formatHtml(IdeErrorMessages.render(diagnostic));
            extension = MessageType.HTML.extension;
        } else {
            readableDiagnosticText = DefaultErrorMessages.render(diagnostic);
            extension = MessageType.TEXT.extension;
        }
        String errorMessageFileName = name + index;
        String path = getTestDataPath() + "/" + errorMessageFileName + "." + extension;
        String actualText = "<!-- " + errorMessageFileName + " -->\n" + readableDiagnosticText;
        assertSameLinesWithFile(path, actualText);
        index++;
    }
}
Also used : Diagnostic(org.jetbrains.kotlin.diagnostics.Diagnostic) BindingContext(org.jetbrains.kotlin.resolve.BindingContext) AnalysisResult(org.jetbrains.kotlin.analyzer.AnalysisResult) DiagnosticFactory(org.jetbrains.kotlin.diagnostics.DiagnosticFactory) LanguageVersion(org.jetbrains.kotlin.config.LanguageVersion) KtFile(org.jetbrains.kotlin.psi.KtFile) KtFile(org.jetbrains.kotlin.psi.KtFile) File(java.io.File)

Aggregations

Diagnostic (org.jetbrains.kotlin.diagnostics.Diagnostic)9 NotNull (org.jetbrains.annotations.NotNull)5 PsiElement (com.intellij.psi.PsiElement)3 DiagnosticFactory (org.jetbrains.kotlin.diagnostics.DiagnosticFactory)2 KotlinType (org.jetbrains.kotlin.types.KotlinType)2 ProcessCanceledException (com.intellij.openapi.progress.ProcessCanceledException)1 TextRange (com.intellij.openapi.util.TextRange)1 PsiErrorElement (com.intellij.psi.PsiErrorElement)1 PsiQualifiedNamedElement (com.intellij.psi.PsiQualifiedNamedElement)1 IElementType (com.intellij.psi.tree.IElementType)1 File (java.io.File)1 Collection (java.util.Collection)1 Map (java.util.Map)1 AnalysisResult (org.jetbrains.kotlin.analyzer.AnalysisResult)1 OutputFile (org.jetbrains.kotlin.backend.common.output.OutputFile)1 OutputFileCollection (org.jetbrains.kotlin.backend.common.output.OutputFileCollection)1 GenerationState (org.jetbrains.kotlin.codegen.state.GenerationState)1 LanguageVersion (org.jetbrains.kotlin.config.LanguageVersion)1 CallableDescriptor (org.jetbrains.kotlin.descriptors.CallableDescriptor)1 DeclarationDescriptor (org.jetbrains.kotlin.descriptors.DeclarationDescriptor)1