Report exceptions from analyzer in the editor

They are rendered as errors and positioned on those expressions that cause them
This commit is contained in:
Andrey Breslav
2015-04-09 17:08:39 +03:00
parent 5b3ff187da
commit b810ebbb0e
6 changed files with 56 additions and 9 deletions
@@ -53,6 +53,7 @@ public interface Errors {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DiagnosticFactory1<PsiElement, String> UNSUPPORTED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, Throwable> EXCEPTION_FROM_ANALYZER = DiagnosticFactory1.create(ERROR);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -422,6 +422,7 @@ public class DefaultErrorMessages {
MAP.put(UNSAFE_CALL, "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type {0}", RENDER_TYPE);
MAP.put(AMBIGUOUS_LABEL, "Ambiguous label");
MAP.put(UNSUPPORTED, "Unsupported [{0}]", STRING);
MAP.put(EXCEPTION_FROM_ANALYZER, "Internal Error occurred while analyzing this expression:\n{0}", THROWABLE);
MAP.put(UNNECESSARY_SAFE_CALL, "Unnecessary safe call on a non-null receiver of type {0}", RENDER_TYPE);
MAP.put(UNNECESSARY_NOT_NULL_ASSERTION, "Unnecessary non-null assertion (!!) on a non-null receiver of type {0}", RENDER_TYPE);
MAP.put(NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER, "{0} does not refer to a type parameter of {1}", new Renderer<JetTypeConstraint>() {
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.diagnostics.rendering
import com.google.common.base.Predicate
import com.google.common.collect.Lists
import com.google.common.collect.Sets
import com.intellij.openapi.diagnostic.Logger
@@ -24,6 +23,8 @@ import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.newTable
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.newText
import org.jetbrains.kotlin.psi.JetClass
import org.jetbrains.kotlin.psi.JetClassOrObject
import org.jetbrains.kotlin.psi.JetNamedDeclaration
@@ -31,18 +32,20 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.Renderer
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.inference.*
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.JetTypeChecker
import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.*
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.checker.JetTypeChecker
import java.io.PrintWriter
import java.io.StringWriter
import kotlin.platform.platformStatic
import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound
public object Renderers {
@@ -60,6 +63,12 @@ public object Renderers {
public val STRING: Renderer<String> = Renderer { it }
public val THROWABLE: Renderer<Throwable> = Renderer {
val writer = StringWriter()
it.printStackTrace(PrintWriter(writer))
StringUtil.first(writer.toString(), 2048, true)
}
public val NAME: Renderer<Named> = Renderer { it.getName().asString() }
public val ELEMENT_TEXT: Renderer<PsiElement> = Renderer { it.getText() }
@@ -16,10 +16,12 @@
package org.jetbrains.kotlin.types.expressions;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils;
import org.jetbrains.kotlin.diagnostics.Errors;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingContextUtils;
@@ -35,6 +37,8 @@ import static org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtil
public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, ExpressionTypingContext> implements ExpressionTypingInternals {
private static final Logger LOG = Logger.getInstance(ExpressionTypingVisitor.class);
@NotNull
public static ExpressionTypingFacade create(@NotNull ExpressionTypingComponents components) {
return new ExpressionTypingVisitorDispatcher(components, null);
@@ -164,10 +168,15 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
throw e;
}
catch (Throwable e) {
throw new KotlinFrontEndException(
context.trace.report(Errors.EXCEPTION_FROM_ANALYZER.on(expression, e));
LOG.error(
"Exception while analyzing expression at " + DiagnosticUtils.atLocation(expression) + ":\n" + expression.getText() + "\n",
e
);
return JetTypeInfo.create(
ErrorUtils.createErrorType(e.getClass().getSimpleName() + " from analyzer"),
context.dataFlowInfo
);
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.highlighter;
import com.intellij.icons.AllIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
@@ -26,6 +27,8 @@ import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs;
import org.jetbrains.kotlin.js.resolve.diagnostics.JsCallDataHtmlRenderer;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import java.net.URL;
import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.diagnostics.rendering.Renderers.RENDER_CLASS_OR_OBJECT;
import static org.jetbrains.kotlin.diagnostics.rendering.Renderers.STRING;
@@ -127,6 +130,21 @@ public class IdeErrorMessages {
MAP.put(CONFLICTING_JVM_DECLARATIONS, "<html>Platform declaration clash: {0}</html>", HTML_CONFLICTING_JVM_DECLARATIONS_DATA);
MAP.put(ACCIDENTAL_OVERRIDE, "<html>Accidental override: {0}</html>", HTML_CONFLICTING_JVM_DECLARATIONS_DATA);
URL errorIconUrl = AllIcons.class.getResource("/general/error.png");
MAP.put(EXCEPTION_FROM_ANALYZER, "<html>Internal Error occurred while analyzing this expression <br/>" +
"<table cellspacing=\"0\" cellpadding=\"0\">" +
"<tr>" +
"<td>(<strong>Please use the \"</strong></td>" +
"<td><img src=\"" + errorIconUrl + "\"/></td>" +
"<td><strong>\" icon in the bottom-right corner to report this error</strong>):</td>" +
"</tr>" +
"</table>" +
"<br/>" +
"<pre>{0}</pre>" +
"</html>",
HTML_THROWABLE);
MAP.put(ErrorsJs.JSCODE_ERROR, "<html>JavaScript: {0}</html>", JsCallDataHtmlRenderer.INSTANCE$);
MAP.put(ErrorsJs.JSCODE_WARNING, "<html>JavaScript: {0}</html>", JsCallDataHtmlRenderer.INSTANCE$);
MAP.setImmutable();
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.highlighter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.diagnostics.rendering.Renderers;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.renderer.Renderer;
import org.jetbrains.kotlin.resolve.calls.inference.InferenceErrorData;
@@ -151,4 +152,12 @@ public class IdeRenderers {
return ("The following declarations have the same JVM signature (<code>" + data.getSignature().getName() + data.getSignature().getDesc() + "</code>):<br/>\n" + sb).trim();
}
};
public static final Renderer<Throwable> HTML_THROWABLE = new Renderer<Throwable>() {
@NotNull
@Override
public String render(@NotNull Throwable e) {
return Renderers.THROWABLE.render(e).replace("\n", "<br/>");
}
};
}