Unbind general FirDiagnostic from PsiFile & PsiElement
This commit is contained in:
+3
-4
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
import org.jetbrains.kotlin.resolve.checkers.ExperimentalUsageChecker
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices
|
import org.jetbrains.kotlin.resolve.jvm.JvmBindingContextSlices
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
|
import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData
|
||||||
@@ -154,16 +153,16 @@ class AnalyzerWithCompilerReport(
|
|||||||
return diagnostic.severity == Severity.ERROR
|
return diagnostic.severity == Severity.ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reportDiagnostics(unsortedDiagnostics: Diagnostics, reporter: DiagnosticMessageReporter): Boolean {
|
fun reportDiagnostics(unsortedDiagnostics: GenericDiagnostics<*>, reporter: DiagnosticMessageReporter): Boolean {
|
||||||
var hasErrors = false
|
var hasErrors = false
|
||||||
val diagnostics = sortedDiagnostics(unsortedDiagnostics.all())
|
val diagnostics = sortedDiagnostics(unsortedDiagnostics.all().filterIsInstance<Diagnostic>())
|
||||||
for (diagnostic in diagnostics) {
|
for (diagnostic in diagnostics) {
|
||||||
hasErrors = hasErrors or reportDiagnostic(diagnostic, reporter)
|
hasErrors = hasErrors or reportDiagnostic(diagnostic, reporter)
|
||||||
}
|
}
|
||||||
return hasErrors
|
return hasErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reportDiagnostics(diagnostics: Diagnostics, messageCollector: MessageCollector): Boolean {
|
fun reportDiagnostics(diagnostics: GenericDiagnostics<*>, messageCollector: MessageCollector): Boolean {
|
||||||
val hasErrors = reportDiagnostics(diagnostics, DefaultDiagnosticReporter(messageCollector))
|
val hasErrors = reportDiagnostics(diagnostics, DefaultDiagnosticReporter(messageCollector))
|
||||||
|
|
||||||
if (diagnostics.any { it.factory == Errors.INCOMPATIBLE_CLASS }) {
|
if (diagnostics.any { it.factory == Errors.INCOMPATIBLE_CLASS }) {
|
||||||
|
|||||||
+2
-2
@@ -28,9 +28,9 @@ class DefaultDiagnosticReporter(override val messageCollector: MessageCollector)
|
|||||||
interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
|
interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
|
||||||
val messageCollector: MessageCollector
|
val messageCollector: MessageCollector
|
||||||
|
|
||||||
override fun report(diagnostic: Diagnostic, file: PsiFile?, render: String) = messageCollector.report(
|
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report(
|
||||||
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
|
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
|
||||||
render,
|
render,
|
||||||
MessageUtil.psiFileToMessageLocation(file!!, file.name, DiagnosticUtils.getLineAndColumnRange(diagnostic))
|
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumnRange(diagnostic))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -28,9 +28,9 @@ class DefaultDiagnosticReporter(override val messageCollector: MessageCollector)
|
|||||||
interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
|
interface MessageCollectorBasedReporter : DiagnosticMessageReporter {
|
||||||
val messageCollector: MessageCollector
|
val messageCollector: MessageCollector
|
||||||
|
|
||||||
override fun report(diagnostic: Diagnostic, file: PsiFile?, render: String) = messageCollector.report(
|
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) = messageCollector.report(
|
||||||
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
|
AnalyzerWithCompilerReport.convertSeverity(diagnostic.severity),
|
||||||
render,
|
render,
|
||||||
MessageUtil.psiFileToMessageLocation(file!!, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
|
MessageUtil.psiFileToMessageLocation(file, file.name, DiagnosticUtils.getLineAndColumn(diagnostic))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -20,5 +20,5 @@ import com.intellij.psi.PsiFile
|
|||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
|
||||||
interface DiagnosticMessageReporter {
|
interface DiagnosticMessageReporter {
|
||||||
fun report(diagnostic: Diagnostic, file: PsiFile?, render: String)
|
fun report(diagnostic: Diagnostic, file: PsiFile, render: String)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-5
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.cli.jvm.compiler
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.vfs.*
|
import com.intellij.openapi.vfs.*
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.PsiElementFinder
|
import com.intellij.psi.PsiElementFinder
|
||||||
import com.intellij.psi.PsiJavaModule
|
import com.intellij.psi.PsiJavaModule
|
||||||
import com.intellij.psi.search.DelegatingGlobalSearchScope
|
import com.intellij.psi.search.DelegatingGlobalSearchScope
|
||||||
@@ -54,9 +53,7 @@ import org.jetbrains.kotlin.config.*
|
|||||||
import org.jetbrains.kotlin.container.get
|
import org.jetbrains.kotlin.container.get
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.diagnostics.*
|
import org.jetbrains.kotlin.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
|
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
|
|
||||||
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
|
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
|
||||||
import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer
|
import org.jetbrains.kotlin.fir.backend.jvm.FirMetadataSerializer
|
||||||
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
|
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
|
||||||
@@ -72,7 +69,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
import org.jetbrains.kotlin.resolve.CompilerEnvironment
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.SimpleDiagnostics
|
import org.jetbrains.kotlin.resolve.diagnostics.SimpleGenericDiagnostics
|
||||||
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
||||||
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
|
import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize
|
||||||
@@ -343,7 +340,7 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
firAnalyzerFacade.runResolution()
|
firAnalyzerFacade.runResolution()
|
||||||
val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten()
|
val firDiagnostics = firAnalyzerFacade.runCheckers().values.flatten()
|
||||||
AnalyzerWithCompilerReport.reportDiagnostics(
|
AnalyzerWithCompilerReport.reportDiagnostics(
|
||||||
SimpleDiagnostics(firDiagnostics),
|
SimpleGenericDiagnostics(firDiagnostics),
|
||||||
environment.messageCollector
|
environment.messageCollector
|
||||||
)
|
)
|
||||||
performanceManager?.notifyAnalysisFinished()
|
performanceManager?.notifyAnalysisFinished()
|
||||||
|
|||||||
+3
-10
@@ -10,13 +10,14 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.Severity
|
import org.jetbrains.kotlin.diagnostics.Severity
|
||||||
|
import org.jetbrains.kotlin.diagnostics.UnboundDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
import org.jetbrains.kotlin.fir.FirLightSourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
import org.jetbrains.kotlin.fir.FirPsiSourceElement
|
||||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||||
|
|
||||||
// ------------------------------ diagnostics ------------------------------
|
// ------------------------------ diagnostics ------------------------------
|
||||||
|
|
||||||
sealed class FirDiagnostic<out E : FirSourceElement> : Diagnostic {
|
sealed class FirDiagnostic<out E : FirSourceElement> : UnboundDiagnostic {
|
||||||
abstract val element: E
|
abstract val element: E
|
||||||
abstract override val severity: Severity
|
abstract override val severity: Severity
|
||||||
abstract override val factory: AbstractFirDiagnosticFactory<*, *>
|
abstract override val factory: AbstractFirDiagnosticFactory<*, *>
|
||||||
@@ -94,16 +95,8 @@ data class FirPsiDiagnosticWithParameters3<P : PsiElement, A : Any, B : Any, C :
|
|||||||
|
|
||||||
// ------------------------------ light tree diagnostics ------------------------------
|
// ------------------------------ light tree diagnostics ------------------------------
|
||||||
|
|
||||||
interface FirLightDiagnostic : Diagnostic {
|
interface FirLightDiagnostic : UnboundDiagnostic {
|
||||||
val element: FirLightSourceElement
|
val element: FirLightSourceElement
|
||||||
|
|
||||||
override val psiElement: PsiElement
|
|
||||||
get() {
|
|
||||||
throw UnsupportedOperationException("Light diagnostic does not hold PSI element")
|
|
||||||
}
|
|
||||||
|
|
||||||
override val psiFile: PsiFile?
|
|
||||||
get() = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class FirLightSimpleDiagnostic(
|
data class FirLightSimpleDiagnostic(
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.diagnostics
|
||||||
|
|
||||||
|
interface GenericDiagnostics<T : UnboundDiagnostic> : Iterable<T> {
|
||||||
|
fun all(): Collection<T>
|
||||||
|
|
||||||
|
fun isEmpty(): Boolean = all().isEmpty()
|
||||||
|
|
||||||
|
override fun iterator(): Iterator<T> = all().iterator()
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ class ActualDiagnostic constructor(val diagnostic: Diagnostic, override val plat
|
|||||||
get() = diagnostic.factory.name!!
|
get() = diagnostic.factory.name!!
|
||||||
|
|
||||||
val file: PsiFile
|
val file: PsiFile
|
||||||
get() = diagnostic.psiFile!!
|
get() = diagnostic.psiFile
|
||||||
|
|
||||||
override fun compareTo(other: AbstractTestDiagnostic): Int {
|
override fun compareTo(other: AbstractTestDiagnostic): Int {
|
||||||
return if (this.diagnostic is DiagnosticWithParameters1<*, *> && other is ActualDiagnostic && other.diagnostic is DiagnosticWithParameters1<*, *>) {
|
return if (this.diagnostic is DiagnosticWithParameters1<*, *> && other is ActualDiagnostic && other.diagnostic is DiagnosticWithParameters1<*, *>) {
|
||||||
|
|||||||
@@ -2,222 +2,216 @@
|
|||||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
package org.jetbrains.kotlin.checkers.utils
|
||||||
|
|
||||||
package org.jetbrains.kotlin.checkers.utils;
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
import com.intellij.psi.tree.TokenSet
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||||
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
|
import org.jetbrains.kotlin.util.slicedMap.WritableSlice
|
||||||
|
import java.util.HashMap
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
object DebugInfoUtil {
|
||||||
import com.intellij.psi.tree.IElementType;
|
private val MAY_BE_UNRESOLVED = TokenSet.create(KtTokens.IN_KEYWORD, KtTokens.NOT_IN)
|
||||||
import com.intellij.psi.tree.TokenSet;
|
private val EXCLUDED = TokenSet.create(
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
KtTokens.COLON,
|
||||||
import org.jetbrains.annotations.NotNull;
|
KtTokens.AS_KEYWORD,
|
||||||
import org.jetbrains.kotlin.KtNodeTypes;
|
KtTokens.`AS_SAFE`,
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
KtTokens.IS_KEYWORD,
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
KtTokens.NOT_IS,
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
|
KtTokens.OROR,
|
||||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor;
|
KtTokens.ANDAND,
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
KtTokens.EQ,
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
KtTokens.EQEQEQ,
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
KtTokens.EXCLEQEQEQ,
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
KtTokens.ELVIS,
|
||||||
import org.jetbrains.kotlin.psi.*;
|
KtTokens.EXCLEXCL
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
)
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallsKt;
|
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils;
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
|
||||||
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
fun markDebugAnnotations(
|
||||||
import java.util.HashMap;
|
root: PsiElement,
|
||||||
import java.util.Map;
|
bindingContext: BindingContext,
|
||||||
|
debugInfoReporter: DebugInfoReporter
|
||||||
import static org.jetbrains.kotlin.lexer.KtTokens.*;
|
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
|
||||||
|
|
||||||
public class DebugInfoUtil {
|
|
||||||
private static final TokenSet MAY_BE_UNRESOLVED = TokenSet.create(IN_KEYWORD, NOT_IN);
|
|
||||||
private static final TokenSet EXCLUDED = TokenSet.create(
|
|
||||||
COLON, AS_KEYWORD, AS_SAFE, IS_KEYWORD, NOT_IS, OROR, ANDAND, EQ, EQEQEQ, EXCLEQEQEQ, ELVIS, EXCLEXCL);
|
|
||||||
|
|
||||||
public abstract static class DebugInfoReporter {
|
|
||||||
|
|
||||||
public void preProcessReference(@NotNull KtReferenceExpression expression) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void reportElementWithErrorType(@NotNull KtReferenceExpression expression);
|
|
||||||
|
|
||||||
public abstract void reportMissingUnresolved(@NotNull KtReferenceExpression expression);
|
|
||||||
|
|
||||||
public abstract void reportUnresolvedWithTarget(@NotNull KtReferenceExpression expression, @NotNull String target);
|
|
||||||
|
|
||||||
public void reportDynamicCall(@NotNull KtElement element, DeclarationDescriptor declarationDescriptor) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void markDebugAnnotations(
|
|
||||||
@NotNull PsiElement root,
|
|
||||||
@NotNull BindingContext bindingContext,
|
|
||||||
@NotNull DebugInfoReporter debugInfoReporter
|
|
||||||
) {
|
) {
|
||||||
Map<KtReferenceExpression, DiagnosticFactory<?>> markedWithErrorElements = new HashMap<>();
|
val markedWithErrorElements: MutableMap<KtReferenceExpression, DiagnosticFactory<*>?> = HashMap()
|
||||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
|
for (diagnostic in bindingContext.diagnostics) {
|
||||||
DiagnosticFactory<?> factory = diagnostic.getFactory();
|
val factory = diagnostic.factory
|
||||||
if (Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS.contains(diagnostic.getFactory())) {
|
if (Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS.contains(diagnostic.factory)) {
|
||||||
markedWithErrorElements.put((KtReferenceExpression) diagnostic.getPsiElement(), factory);
|
markedWithErrorElements[diagnostic.psiElement as KtReferenceExpression] = factory
|
||||||
}
|
} else if (factory === Errors.SUPER_IS_NOT_AN_EXPRESSION
|
||||||
else if (factory == Errors.SUPER_IS_NOT_AN_EXPRESSION
|
|| factory === Errors.SUPER_NOT_AVAILABLE
|
||||||
|| factory == Errors.SUPER_NOT_AVAILABLE) {
|
) {
|
||||||
KtSuperExpression superExpression = (KtSuperExpression) diagnostic.getPsiElement();
|
val superExpression = diagnostic.psiElement as KtSuperExpression
|
||||||
markedWithErrorElements.put(superExpression.getInstanceReference(), factory);
|
markedWithErrorElements[superExpression.instanceReference] = factory
|
||||||
}
|
} else if (factory === Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND) {
|
||||||
else if (factory == Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND) {
|
markedWithErrorElements[diagnostic.psiElement as KtSimpleNameExpression] = factory
|
||||||
markedWithErrorElements.put((KtSimpleNameExpression) diagnostic.getPsiElement(), factory);
|
} else if (factory === Errors.UNSUPPORTED) {
|
||||||
}
|
for (reference in PsiTreeUtil.findChildrenOfType(
|
||||||
else if (factory == Errors.UNSUPPORTED) {
|
diagnostic.psiElement,
|
||||||
for (KtReferenceExpression reference : PsiTreeUtil.findChildrenOfType(diagnostic.getPsiElement(),
|
KtReferenceExpression::class.java
|
||||||
KtReferenceExpression.class)) {
|
)) {
|
||||||
markedWithErrorElements.put(reference, factory);
|
markedWithErrorElements[reference] = factory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
root.acceptChildren(object : KtTreeVisitorVoid() {
|
||||||
root.acceptChildren(new KtTreeVisitorVoid() {
|
override fun visitForExpression(expression: KtForExpression) {
|
||||||
|
val range = expression.loopRange
|
||||||
@Override
|
if (range != null) {
|
||||||
public void visitForExpression(@NotNull KtForExpression expression) {
|
reportIfDynamicCall(range, range, BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL)
|
||||||
KtExpression range = expression.getLoopRange();
|
reportIfDynamicCall(range, range, BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL)
|
||||||
reportIfDynamicCall(range, range, LOOP_RANGE_ITERATOR_RESOLVED_CALL);
|
reportIfDynamicCall(range, range, BindingContext.LOOP_RANGE_NEXT_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);
|
super.visitForExpression(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun visitDestructuringDeclaration(destructuringDeclaration: KtDestructuringDeclaration) {
|
||||||
public void visitProperty(@NotNull KtProperty property) {
|
for (entry in destructuringDeclaration.entries) {
|
||||||
VariableDescriptor descriptor = bindingContext.get(VARIABLE, property);
|
reportIfDynamicCall(entry, entry, BindingContext.COMPONENT_RESOLVED_CALL)
|
||||||
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);
|
super.visitDestructuringDeclaration(destructuringDeclaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun visitProperty(property: KtProperty) {
|
||||||
public void visitThisExpression(@NotNull KtThisExpression expression) {
|
val descriptor = bindingContext.get(BindingContext.VARIABLE, property)
|
||||||
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilKt.getResolvedCall(expression, bindingContext);
|
val delegate = property.delegate
|
||||||
|
if (descriptor is PropertyDescriptor && delegate != null) {
|
||||||
|
reportIfDynamicCall(delegate, descriptor, BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL)
|
||||||
|
reportIfDynamicCall(delegate, descriptor.getter, BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL)
|
||||||
|
reportIfDynamicCall(delegate, descriptor.setter, BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL)
|
||||||
|
}
|
||||||
|
super.visitProperty(property)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitThisExpression(expression: KtThisExpression) {
|
||||||
|
val resolvedCall = expression.getResolvedCall(bindingContext)
|
||||||
if (resolvedCall != null) {
|
if (resolvedCall != null) {
|
||||||
reportIfDynamic(expression, resolvedCall.getResultingDescriptor(), debugInfoReporter);
|
reportIfDynamic(expression, resolvedCall.resultingDescriptor, debugInfoReporter)
|
||||||
}
|
}
|
||||||
super.visitThisExpression(expression);
|
super.visitThisExpression(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun visitReferenceExpression(expression: KtReferenceExpression) {
|
||||||
public void visitReferenceExpression(@NotNull KtReferenceExpression expression) {
|
super.visitReferenceExpression(expression)
|
||||||
super.visitReferenceExpression(expression);
|
if (!BindingContextUtils.isExpressionWithValidReference(expression, bindingContext)) {
|
||||||
if (!BindingContextUtils.isExpressionWithValidReference(expression, bindingContext)){
|
return
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
IElementType referencedNameElementType = null;
|
var referencedNameElementType: IElementType? = null
|
||||||
if (expression instanceof KtSimpleNameExpression) {
|
if (expression is KtSimpleNameExpression) {
|
||||||
KtSimpleNameExpression nameExpression = (KtSimpleNameExpression) expression;
|
val elementType = expression.getNode().elementType
|
||||||
IElementType elementType = expression.getNode().getElementType();
|
if (elementType === KtNodeTypes.OPERATION_REFERENCE) {
|
||||||
if (elementType == KtNodeTypes.OPERATION_REFERENCE) {
|
referencedNameElementType = expression.getReferencedNameElementType()
|
||||||
referencedNameElementType = nameExpression.getReferencedNameElementType();
|
|
||||||
if (EXCLUDED.contains(referencedNameElementType)) {
|
if (EXCLUDED.contains(referencedNameElementType)) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (elementType == KtNodeTypes.LABEL ||
|
if (elementType === KtNodeTypes.LABEL ||
|
||||||
nameExpression.getReferencedNameElementType() == KtTokens.THIS_KEYWORD) {
|
expression.getReferencedNameElementType() === KtTokens.THIS_KEYWORD
|
||||||
return;
|
) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
debugInfoReporter.preProcessReference(expression)
|
||||||
debugInfoReporter.preProcessReference(expression);
|
var target: String? = null
|
||||||
|
val declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression)
|
||||||
String target = null;
|
|
||||||
DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, expression);
|
|
||||||
if (declarationDescriptor != null) {
|
if (declarationDescriptor != null) {
|
||||||
target = declarationDescriptor.toString();
|
target = declarationDescriptor.toString()
|
||||||
|
reportIfDynamic(expression, declarationDescriptor, debugInfoReporter)
|
||||||
reportIfDynamic(expression, declarationDescriptor, debugInfoReporter);
|
|
||||||
}
|
}
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
PsiElement labelTarget = bindingContext.get(LABEL_TARGET, expression);
|
val labelTarget = bindingContext.get(BindingContext.LABEL_TARGET, expression)
|
||||||
if (labelTarget != null) {
|
if (labelTarget != null) {
|
||||||
target = labelTarget.getText();
|
target = labelTarget.text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
Collection<? extends DeclarationDescriptor> declarationDescriptors =
|
val declarationDescriptors = bindingContext.get(BindingContext.AMBIGUOUS_REFERENCE_TARGET, expression)
|
||||||
bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression);
|
|
||||||
if (declarationDescriptors != null) {
|
if (declarationDescriptors != null) {
|
||||||
target = "[" + declarationDescriptors.size() + " descriptors]";
|
target = "[" + declarationDescriptors.size + " descriptors]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
Collection<? extends PsiElement> labelTargets = bindingContext.get(AMBIGUOUS_LABEL_TARGET, expression);
|
val labelTargets = bindingContext.get(BindingContext.AMBIGUOUS_LABEL_TARGET, expression)
|
||||||
if (labelTargets != null) {
|
if (labelTargets != null) {
|
||||||
target = "[" + labelTargets.size() + " elements]";
|
target = "[" + labelTargets.size + " elements]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MAY_BE_UNRESOLVED.contains(referencedNameElementType)) {
|
if (MAY_BE_UNRESOLVED.contains(referencedNameElementType)) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
val resolved = target != null
|
||||||
boolean resolved = target != null;
|
var markedWithError = markedWithErrorElements.containsKey(expression)
|
||||||
boolean markedWithError = markedWithErrorElements.containsKey(expression);
|
if (expression is KtArrayAccessExpression &&
|
||||||
if (expression instanceof KtArrayAccessExpression &&
|
markedWithErrorElements.containsKey(expression.arrayExpression)
|
||||||
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')
|
// if 'foo' in 'foo[i]' is unresolved it means 'foo[i]' is unresolved (otherwise 'foo[i]' is marked as 'missing unresolved')
|
||||||
markedWithError = true;
|
markedWithError = true
|
||||||
}
|
}
|
||||||
KotlinType expressionType = bindingContext.getType(expression);
|
val expressionType = bindingContext.getType(expression)
|
||||||
DiagnosticFactory<?> factory = markedWithErrorElements.get(expression);
|
val factory = markedWithErrorElements[expression]
|
||||||
if (declarationDescriptor != null &&
|
if (declarationDescriptor != null &&
|
||||||
(ErrorUtils.isError(declarationDescriptor) || ErrorUtils.containsErrorType(expressionType))) {
|
(ErrorUtils.isError(declarationDescriptor) || ErrorUtils.containsErrorType(expressionType))
|
||||||
if (factory != Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND) {
|
) {
|
||||||
debugInfoReporter.reportElementWithErrorType(expression);
|
if (factory !== Errors.EXPRESSION_EXPECTED_PACKAGE_FOUND) {
|
||||||
|
debugInfoReporter.reportElementWithErrorType(expression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (resolved && markedWithError) {
|
if (resolved && markedWithError) {
|
||||||
if (Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS.contains(factory)) {
|
if (Errors.UNRESOLVED_REFERENCE_DIAGNOSTICS.contains(factory)) {
|
||||||
debugInfoReporter.reportUnresolvedWithTarget(expression, target);
|
debugInfoReporter.reportUnresolvedWithTarget(expression, target!!)
|
||||||
}
|
}
|
||||||
}
|
} else if (!resolved && !markedWithError) {
|
||||||
else if (!resolved && !markedWithError) {
|
debugInfoReporter.reportMissingUnresolved(expression)
|
||||||
debugInfoReporter.reportMissingUnresolved(expression);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <E extends KtElement, K, D extends CallableDescriptor> boolean reportIfDynamicCall(E element, K key, WritableSlice<K, ResolvedCall<D>> slice) {
|
private fun <E : KtElement, K, D : CallableDescriptor?> reportIfDynamicCall(
|
||||||
ResolvedCall<D> resolvedCall = bindingContext.get(slice, key);
|
element: E,
|
||||||
if (resolvedCall != null) {
|
key: K,
|
||||||
return reportIfDynamic(element, resolvedCall.getResultingDescriptor(), debugInfoReporter);
|
slice: WritableSlice<K, ResolvedCall<D>>
|
||||||
}
|
): Boolean {
|
||||||
return false;
|
val resolvedCall = bindingContext[slice, key]
|
||||||
|
return if (resolvedCall != null) {
|
||||||
|
reportIfDynamic(element, resolvedCall.resultingDescriptor, debugInfoReporter)
|
||||||
|
} else false
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean reportIfDynamic(KtElement element, DeclarationDescriptor declarationDescriptor, DebugInfoReporter debugInfoReporter) {
|
private fun reportIfDynamic(
|
||||||
if (declarationDescriptor != null && DynamicCallsKt.isDynamic(declarationDescriptor)) {
|
element: KtElement,
|
||||||
debugInfoReporter.reportDynamicCall(element, declarationDescriptor);
|
declarationDescriptor: DeclarationDescriptor?,
|
||||||
return true;
|
debugInfoReporter: DebugInfoReporter
|
||||||
|
): Boolean {
|
||||||
|
if (declarationDescriptor != null && declarationDescriptor.isDynamic()) {
|
||||||
|
debugInfoReporter.reportDynamicCall(element, declarationDescriptor)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
abstract class DebugInfoReporter {
|
||||||
|
fun preProcessReference(expression: KtReferenceExpression) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun reportElementWithErrorType(expression: KtReferenceExpression)
|
||||||
|
abstract fun reportMissingUnresolved(expression: KtReferenceExpression)
|
||||||
|
abstract fun reportUnresolvedWithTarget(expression: KtReferenceExpression, target: String)
|
||||||
|
open fun reportDynamicCall(element: KtElement, declarationDescriptor: DeclarationDescriptor) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,5 +20,5 @@ import com.intellij.psi.PsiFile
|
|||||||
|
|
||||||
interface Diagnostic : UnboundDiagnostic {
|
interface Diagnostic : UnboundDiagnostic {
|
||||||
val psiElement: PsiElement
|
val psiElement: PsiElement
|
||||||
val psiFile: PsiFile?
|
val psiFile: PsiFile
|
||||||
}
|
}
|
||||||
@@ -74,9 +74,6 @@ public class DiagnosticUtils {
|
|||||||
List<TextRange> textRanges = diagnostic.getTextRanges();
|
List<TextRange> textRanges = diagnostic.getTextRanges();
|
||||||
if (textRanges.isEmpty()) return PsiDiagnosticUtils.LineAndColumn.NONE;
|
if (textRanges.isEmpty()) return PsiDiagnosticUtils.LineAndColumn.NONE;
|
||||||
TextRange firstRange = firstRange(textRanges);
|
TextRange firstRange = firstRange(textRanges);
|
||||||
if (file == null) {
|
|
||||||
return PsiDiagnosticUtils.LineAndColumn.NONE;
|
|
||||||
}
|
|
||||||
return getLineAndColumnInPsiFile(file, firstRange);
|
return getLineAndColumnInPsiFile(file, firstRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,9 +89,6 @@ public class DiagnosticUtils {
|
|||||||
List<TextRange> textRanges = diagnostic.getTextRanges();
|
List<TextRange> textRanges = diagnostic.getTextRanges();
|
||||||
if (textRanges.isEmpty()) return PsiDiagnosticUtils.LineAndColumnRange.NONE;
|
if (textRanges.isEmpty()) return PsiDiagnosticUtils.LineAndColumnRange.NONE;
|
||||||
TextRange firstRange = firstRange(textRanges);
|
TextRange firstRange = firstRange(textRanges);
|
||||||
if (file == null) {
|
|
||||||
return PsiDiagnosticUtils.LineAndColumnRange.NONE;
|
|
||||||
}
|
|
||||||
return getLineAndColumnRangeInPsiFile(file, firstRange);
|
return getLineAndColumnRangeInPsiFile(file, firstRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,11 +125,9 @@ public class DiagnosticUtils {
|
|||||||
result.sort((d1, d2) -> {
|
result.sort((d1, d2) -> {
|
||||||
PsiFile file1 = d1.getPsiFile();
|
PsiFile file1 = d1.getPsiFile();
|
||||||
PsiFile file2 = d2.getPsiFile();
|
PsiFile file2 = d2.getPsiFile();
|
||||||
if (file1 != null && file2 != null) {
|
String path1 = file1.getViewProvider().getVirtualFile().getPath();
|
||||||
String path1 = file1.getViewProvider().getVirtualFile().getPath();
|
String path2 = file2.getViewProvider().getVirtualFile().getPath();
|
||||||
String path2 = file2.getViewProvider().getVirtualFile().getPath();
|
if (!path1.equals(path2)) return path1.compareTo(path2);
|
||||||
if (!path1.equals(path2)) return path1.compareTo(path2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TextRange range1 = firstRange(d1.getTextRanges());
|
TextRange range1 = firstRange(d1.getTextRanges());
|
||||||
TextRange range2 = firstRange(d2.getTextRanges());
|
TextRange range2 = firstRange(d2.getTextRanges());
|
||||||
|
|||||||
+3
-2
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.config.LanguageVersion;
|
|||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.UnboundDiagnostic;
|
||||||
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement;
|
import org.jetbrains.kotlin.metadata.deserialization.VersionRequirement;
|
||||||
import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
|
import org.jetbrains.kotlin.resolve.VarianceConflictDiagnosticData;
|
||||||
import org.jetbrains.kotlin.types.KotlinTypeKt;
|
import org.jetbrains.kotlin.types.KotlinTypeKt;
|
||||||
@@ -46,7 +47,7 @@ public class DefaultErrorMessages {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static String render(@NotNull Diagnostic diagnostic) {
|
public static String render(@NotNull UnboundDiagnostic diagnostic) {
|
||||||
DiagnosticRenderer renderer = getRendererForDiagnostic(diagnostic);
|
DiagnosticRenderer renderer = getRendererForDiagnostic(diagnostic);
|
||||||
if (renderer != null) {
|
if (renderer != null) {
|
||||||
return renderer.render(diagnostic);
|
return renderer.render(diagnostic);
|
||||||
@@ -55,7 +56,7 @@ public class DefaultErrorMessages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static DiagnosticRenderer getRendererForDiagnostic(@NotNull Diagnostic diagnostic) {
|
public static DiagnosticRenderer getRendererForDiagnostic(@NotNull UnboundDiagnostic diagnostic) {
|
||||||
DiagnosticRenderer<?> renderer = AddToStdlibKt.firstNotNullResult(RENDERER_MAPS, map -> map.get(diagnostic.getFactory()));
|
DiagnosticRenderer<?> renderer = AddToStdlibKt.firstNotNullResult(RENDERER_MAPS, map -> map.get(diagnostic.getFactory()));
|
||||||
if (renderer != null)
|
if (renderer != null)
|
||||||
return renderer;
|
return renderer;
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.diagnostics.*
|
|||||||
import java.text.MessageFormat
|
import java.text.MessageFormat
|
||||||
|
|
||||||
|
|
||||||
abstract class AbstractDiagnosticWithParametersRenderer<in D : Diagnostic> protected constructor(message: String) : DiagnosticRenderer<D> {
|
abstract class AbstractDiagnosticWithParametersRenderer<in D : UnboundDiagnostic> protected constructor(message: String) : DiagnosticRenderer<D> {
|
||||||
private val messageFormat = MessageFormat(message)
|
private val messageFormat = MessageFormat(message)
|
||||||
|
|
||||||
override fun render(diagnostic: D): String {
|
override fun render(diagnostic: D): String {
|
||||||
|
|||||||
@@ -13,81 +13,77 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
package org.jetbrains.kotlin.resolve;
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiErrorElement
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||||
|
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
|
||||||
|
import org.jetbrains.kotlin.psi.debugText.getDebugText
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
|
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid
|
||||||
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||||
|
import java.lang.IllegalArgumentException
|
||||||
|
import java.lang.StringBuilder
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
object AnalyzingUtils {
|
||||||
import com.intellij.psi.PsiErrorElement;
|
private const val WRITE_DEBUG_TRACE_NAMES = false
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink;
|
|
||||||
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils;
|
|
||||||
import org.jetbrains.kotlin.psi.KtElement;
|
|
||||||
import org.jetbrains.kotlin.psi.KtTreeVisitorVoid;
|
|
||||||
import org.jetbrains.kotlin.psi.debugText.DebugTextUtilKt;
|
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
@JvmStatic
|
||||||
import java.util.List;
|
fun checkForSyntacticErrors(root: PsiElement) {
|
||||||
|
root.acceptChildren(object : PsiErrorElementVisitor() {
|
||||||
public class AnalyzingUtils {
|
override fun visitErrorElement(element: PsiErrorElement) {
|
||||||
private static final boolean WRITE_DEBUG_TRACE_NAMES = false;
|
throw IllegalArgumentException(
|
||||||
|
element.errorDescription + "; looking at " +
|
||||||
public abstract static class PsiErrorElementVisitor extends KtTreeVisitorVoid {
|
element.node.elementType + " '" +
|
||||||
@Override
|
element.text + PsiDiagnosticUtils.atLocation(element)
|
||||||
public abstract void visitErrorElement(@NotNull PsiErrorElement element);
|
)
|
||||||
}
|
|
||||||
|
|
||||||
public static void checkForSyntacticErrors(@NotNull PsiElement root) {
|
|
||||||
root.acceptChildren(new PsiErrorElementVisitor() {
|
|
||||||
@Override
|
|
||||||
public void visitErrorElement(@NotNull PsiErrorElement element) {
|
|
||||||
throw new IllegalArgumentException(element.getErrorDescription() + "; looking at " +
|
|
||||||
element.getNode().getElementType() + " '" +
|
|
||||||
element.getText() + PsiDiagnosticUtils.atLocation(element));
|
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<PsiErrorElement> getSyntaxErrorRanges(@NotNull PsiElement root) {
|
@JvmStatic
|
||||||
List<PsiErrorElement> r = new ArrayList<>();
|
fun getSyntaxErrorRanges(root: PsiElement): List<PsiErrorElement> {
|
||||||
root.acceptChildren(new PsiErrorElementVisitor() {
|
val r: MutableList<PsiErrorElement> = ArrayList()
|
||||||
@Override
|
root.acceptChildren(object : PsiErrorElementVisitor() {
|
||||||
public void visitErrorElement(@NotNull PsiErrorElement element) {
|
override fun visitErrorElement(element: PsiErrorElement) {
|
||||||
r.add(element);
|
r.add(element)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
return r;
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void throwExceptionOnErrors(BindingContext bindingContext) {
|
fun throwExceptionOnErrors(bindingContext: BindingContext) {
|
||||||
throwExceptionOnErrors(bindingContext.getDiagnostics());
|
throwExceptionOnErrors(bindingContext.diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void throwExceptionOnErrors(Diagnostics diagnostics) {
|
fun throwExceptionOnErrors(diagnostics: Diagnostics) {
|
||||||
for (Diagnostic diagnostic : diagnostics) {
|
for (diagnostic in diagnostics) {
|
||||||
DiagnosticSink.THROW_EXCEPTION.report(diagnostic);
|
DiagnosticSink.THROW_EXCEPTION.report(diagnostic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------------------------------
|
||||||
public static String formDebugNameForBindingTrace(@NotNull String debugName, @Nullable Object resolutionSubjectForMessage) {
|
@JvmStatic
|
||||||
|
fun formDebugNameForBindingTrace(debugName: String, resolutionSubjectForMessage: Any?): String {
|
||||||
if (WRITE_DEBUG_TRACE_NAMES) {
|
if (WRITE_DEBUG_TRACE_NAMES) {
|
||||||
StringBuilder debugInfo = new StringBuilder(debugName);
|
val debugInfo = StringBuilder(debugName)
|
||||||
if (resolutionSubjectForMessage instanceof KtElement) {
|
if (resolutionSubjectForMessage is KtElement) {
|
||||||
KtElement element = (KtElement) resolutionSubjectForMessage;
|
debugInfo.append(" ").append(resolutionSubjectForMessage.getDebugText())
|
||||||
debugInfo.append(" ").append(DebugTextUtilKt.getDebugText(element));
|
|
||||||
//debugInfo.append(" in ").append(element.getContainingFile().getName());
|
//debugInfo.append(" in ").append(element.getContainingFile().getName());
|
||||||
debugInfo.append(" in ").append(element.getContainingKtFile().getName()).append(" ").append(element.getTextOffset());
|
debugInfo.append(" in ").append(resolutionSubjectForMessage.containingKtFile.name).append(" ").append(
|
||||||
|
resolutionSubjectForMessage.textOffset
|
||||||
|
)
|
||||||
|
} else if (resolutionSubjectForMessage != null) {
|
||||||
|
debugInfo.append(" ").append(resolutionSubjectForMessage)
|
||||||
}
|
}
|
||||||
else if (resolutionSubjectForMessage != null) {
|
return debugInfo.toString()
|
||||||
debugInfo.append(" ").append(resolutionSubjectForMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return debugInfo.toString();
|
|
||||||
}
|
}
|
||||||
|
return ""
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
abstract class PsiErrorElementVisitor : KtTreeVisitorVoid() {
|
||||||
|
abstract override fun visitErrorElement(element: PsiErrorElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,25 +17,26 @@
|
|||||||
package org.jetbrains.kotlin.resolve.diagnostics
|
package org.jetbrains.kotlin.resolve.diagnostics
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
|
||||||
import com.intellij.openapi.util.ModificationTracker
|
import com.intellij.openapi.util.ModificationTracker
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
|
import org.jetbrains.kotlin.diagnostics.GenericDiagnostics
|
||||||
|
|
||||||
interface Diagnostics : Iterable<Diagnostic> {
|
interface Diagnostics : GenericDiagnostics<Diagnostic> {
|
||||||
//should not be called on readonly views
|
//should not be called on readonly views
|
||||||
//any Diagnostics object returned by BindingContext#getDiagnostics() should implement this property
|
//any Diagnostics object returned by BindingContext#getDiagnostics() should implement this property
|
||||||
val modificationTracker: ModificationTracker
|
val modificationTracker: ModificationTracker
|
||||||
get() = throw IllegalStateException("Trying to obtain modification tracker for Diagnostics object of class ${this::class.java}")
|
get() = throw IllegalStateException("Trying to obtain modification tracker for Diagnostics object of class ${this::class.java}")
|
||||||
|
|
||||||
fun all(): Collection<Diagnostic>
|
override fun all(): Collection<Diagnostic>
|
||||||
|
|
||||||
|
override fun isEmpty(): Boolean = all().isEmpty()
|
||||||
|
|
||||||
|
override fun iterator(): Iterator<Diagnostic> = all().iterator()
|
||||||
|
|
||||||
fun forElement(psiElement: PsiElement): Collection<Diagnostic>
|
fun forElement(psiElement: PsiElement): Collection<Diagnostic>
|
||||||
|
|
||||||
fun isEmpty(): Boolean = all().isEmpty()
|
|
||||||
|
|
||||||
fun noSuppression(): Diagnostics
|
fun noSuppression(): Diagnostics
|
||||||
|
|
||||||
override fun iterator() = all().iterator()
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY: Diagnostics = object : Diagnostics {
|
val EMPTY: Diagnostics = object : Diagnostics {
|
||||||
override fun noSuppression(): Diagnostics = this
|
override fun noSuppression(): Diagnostics = this
|
||||||
|
|||||||
@@ -16,21 +16,20 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.diagnostics
|
package org.jetbrains.kotlin.resolve.diagnostics
|
||||||
|
|
||||||
import com.intellij.openapi.util.Condition
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
class SimpleDiagnostics(diagnostics: Collection<Diagnostic>) : Diagnostics {
|
class SimpleDiagnostics(diagnostics: Collection<Diagnostic>) : SimpleGenericDiagnostics<Diagnostic>(diagnostics), Diagnostics {
|
||||||
//copy to prevent external change
|
//copy to prevent external change
|
||||||
private val diagnostics = ArrayList(diagnostics)
|
private val diagnostics = ArrayList(diagnostics)
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private val elementsCache = DiagnosticsElementsCache(this, { true })
|
private val elementsCache = DiagnosticsElementsCache(this) { true }
|
||||||
|
|
||||||
override fun all() = diagnostics
|
override fun all() = diagnostics
|
||||||
|
|
||||||
override fun forElement(psiElement: PsiElement) = elementsCache.getDiagnostics(psiElement)
|
override fun forElement(psiElement: PsiElement): MutableCollection<Diagnostic> = elementsCache.getDiagnostics(psiElement)
|
||||||
|
|
||||||
override fun noSuppression() = this
|
override fun noSuppression() = this
|
||||||
}
|
}
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.resolve.diagnostics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.diagnostics.UnboundDiagnostic
|
||||||
|
import org.jetbrains.kotlin.diagnostics.GenericDiagnostics
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
open class SimpleGenericDiagnostics<T : UnboundDiagnostic>(diagnostics: Collection<T>) : GenericDiagnostics<T> {
|
||||||
|
//copy to prevent external change
|
||||||
|
private val diagnostics = ArrayList(diagnostics)
|
||||||
|
|
||||||
|
override fun all() = diagnostics
|
||||||
|
}
|
||||||
+2
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.checkers.diagnostics.TextDiagnostic
|
|||||||
import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil
|
import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||||
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
|
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||||
@@ -324,7 +325,7 @@ abstract class AbstractFirBaseDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
|
|
||||||
private fun Iterable<FirDiagnostic<*>>.toActualDiagnostic(root: PsiElement): List<ActualDiagnostic> {
|
private fun Iterable<FirDiagnostic<*>>.toActualDiagnostic(root: PsiElement): List<ActualDiagnostic> {
|
||||||
val result = mutableListOf<ActualDiagnostic>()
|
val result = mutableListOf<ActualDiagnostic>()
|
||||||
mapTo(result) {
|
filterIsInstance<Diagnostic>().mapTo(result) {
|
||||||
ActualDiagnostic(it, null, true)
|
ActualDiagnostic(it, null, true)
|
||||||
}
|
}
|
||||||
for (errorElement in AnalyzingUtils.getSyntaxErrorRanges(root)) {
|
for (errorElement in AnalyzingUtils.getSyntaxErrorRanges(root)) {
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ class DiagnosticTestTypeValidator(
|
|||||||
|
|
||||||
private fun findTestCases(diagnostic: Diagnostic): TestCasesByNumbers {
|
private fun findTestCases(diagnostic: Diagnostic): TestCasesByNumbers {
|
||||||
val ranges = diagnostic.textRanges
|
val ranges = diagnostic.textRanges
|
||||||
val filename = diagnostic.psiFile!!.name
|
val filename = diagnostic.psiFile.name
|
||||||
val foundTestCases = testInfo.cases.byRanges[filename]!!.floorEntry(ranges[0].startOffset)
|
val foundTestCases = testInfo.cases.byRanges[filename]!!.floorEntry(ranges[0].startOffset)
|
||||||
|
|
||||||
if (foundTestCases != null)
|
if (foundTestCases != null)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.intellij.icons.AllIcons;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.TestOnly;
|
import org.jetbrains.annotations.TestOnly;
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||||
|
import org.jetbrains.kotlin.diagnostics.UnboundDiagnostic;
|
||||||
import org.jetbrains.kotlin.diagnostics.rendering.*;
|
import org.jetbrains.kotlin.diagnostics.rendering.*;
|
||||||
import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundle;
|
import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundle;
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs;
|
import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs;
|
||||||
@@ -42,7 +43,7 @@ public class IdeErrorMessages {
|
|||||||
private static final DiagnosticFactoryToRendererMap MAP = new DiagnosticFactoryToRendererMap("IDE");
|
private static final DiagnosticFactoryToRendererMap MAP = new DiagnosticFactoryToRendererMap("IDE");
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String render(@NotNull Diagnostic diagnostic) {
|
public static String render(@NotNull UnboundDiagnostic diagnostic) {
|
||||||
DiagnosticRenderer renderer = MAP.get(diagnostic.getFactory());
|
DiagnosticRenderer renderer = MAP.get(diagnostic.getFactory());
|
||||||
|
|
||||||
if (renderer != null) {
|
if (renderer != null) {
|
||||||
@@ -54,7 +55,7 @@ public class IdeErrorMessages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
public static boolean hasIdeSpecificMessage(@NotNull Diagnostic diagnostic) {
|
public static boolean hasIdeSpecificMessage(@NotNull UnboundDiagnostic diagnostic) {
|
||||||
return MAP.get(diagnostic.getFactory()) != null;
|
return MAP.get(diagnostic.getFactory()) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
|
|||||||
answer.append("// ================\n")
|
answer.append("// ================\n")
|
||||||
for (diagnostic in diagnostics) {
|
for (diagnostic in diagnostics) {
|
||||||
answer.append("// Error at ")
|
answer.append("// Error at ")
|
||||||
.append(diagnostic.psiFile?.name)
|
.append(diagnostic.psiFile.name)
|
||||||
.append(join(diagnostic.textRanges, ","))
|
.append(join(diagnostic.textRanges, ","))
|
||||||
.append(": ")
|
.append(": ")
|
||||||
.append(DefaultErrorMessages.render(diagnostic))
|
.append(DefaultErrorMessages.render(diagnostic))
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ class AddFunctionToSupertypeFix private constructor(
|
|||||||
val descriptors = generateFunctionsToAdd(function)
|
val descriptors = generateFunctionsToAdd(function)
|
||||||
if (descriptors.isEmpty()) return null
|
if (descriptors.isEmpty()) return null
|
||||||
|
|
||||||
val project = diagnostic.psiFile!!.project
|
val project = diagnostic.psiFile.project
|
||||||
val functionData = descriptors.mapNotNull { createFunctionData(it, project) }
|
val functionData = descriptors.mapNotNull { createFunctionData(it, project) }
|
||||||
if (functionData.isEmpty()) return null
|
if (functionData.isEmpty()) return null
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class AddPropertyToSupertypeFix private constructor(
|
|||||||
val descriptors = generatePropertiesToAdd(property)
|
val descriptors = generatePropertiesToAdd(property)
|
||||||
if (descriptors.isEmpty()) return null
|
if (descriptors.isEmpty()) return null
|
||||||
|
|
||||||
val project = diagnostic.psiFile!!.project
|
val project = diagnostic.psiFile.project
|
||||||
val propertyData = descriptors.mapNotNull { createPropertyData(it, property.initializer, project) }
|
val propertyData = descriptors.mapNotNull { createPropertyData(it, property.initializer, project) }
|
||||||
if (propertyData.isEmpty()) return null
|
if (propertyData.isEmpty()) return null
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ import javax.xml.parsers.DocumentBuilderFactory
|
|||||||
class IdeDiagnosticMessageHolder : DiagnosticMessageHolder {
|
class IdeDiagnosticMessageHolder : DiagnosticMessageHolder {
|
||||||
private val diagnostics = arrayListOf<Pair<Diagnostic, String>>()
|
private val diagnostics = arrayListOf<Pair<Diagnostic, String>>()
|
||||||
|
|
||||||
override fun report(diagnostic: Diagnostic, file: PsiFile?, render: String) {
|
override fun report(diagnostic: Diagnostic, file: PsiFile, render: String) {
|
||||||
diagnostics.add(Pair(diagnostic, render))
|
diagnostics.add(Pair(diagnostic, render))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user