diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 3e7739c9d4e..6fbcc23d4b6 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -38,6 +38,7 @@ + diff --git a/idea/src/org/jetbrains/jet/lang/JetDiagnostic.java b/idea/src/org/jetbrains/jet/lang/JetDiagnostic.java index f05a8465266..068d101b13f 100644 --- a/idea/src/org/jetbrains/jet/lang/JetDiagnostic.java +++ b/idea/src/org/jetbrains/jet/lang/JetDiagnostic.java @@ -1,7 +1,7 @@ package org.jetbrains.jet.lang; import com.intellij.lang.ASTNode; -import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression; @@ -16,14 +16,19 @@ public abstract class JetDiagnostic { private final JetReferenceExpression referenceExpression; - public UnresolvedReferenceError(@NonNls JetReferenceExpression referenceExpression) { + public UnresolvedReferenceError(@NotNull JetReferenceExpression referenceExpression) { this.referenceExpression = referenceExpression; } @Override - public void acceptHandler(@NonNls ErrorHandler handler) { + public void acceptHandler(@NotNull ErrorHandler handler) { handler.unresolvedReference(referenceExpression); } + + @NotNull + public JetReferenceExpression getReferenceExpression() { + return referenceExpression; + } } public static class GenericError extends JetDiagnostic { @@ -31,13 +36,13 @@ public abstract class JetDiagnostic { private final ASTNode node; private final String message; - public GenericError(@NonNls ASTNode node, @NonNls String message) { + public GenericError(@NotNull ASTNode node, @NotNull String message) { this.node = node; this.message = message; } @Override - public void acceptHandler(@NonNls ErrorHandler handler) { + public void acceptHandler(@NotNull ErrorHandler handler) { handler.genericError(node, message); } } @@ -48,14 +53,14 @@ public abstract class JetDiagnostic { private final JetType expectedType; private final JetType actualType; - public TypeMismatchError(@NonNls JetExpression expression, @NonNls JetType expectedType, @NonNls JetType actualType) { + public TypeMismatchError(@NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull JetType actualType) { this.expression = expression; this.expectedType = expectedType; this.actualType = actualType; } @Override - public void acceptHandler(@NonNls ErrorHandler handler) { + public void acceptHandler(@NotNull ErrorHandler handler) { handler.typeMismatch(expression, expectedType, actualType); } } @@ -65,13 +70,13 @@ public abstract class JetDiagnostic { private final DeclarationDescriptor existingDescriptor; private final DeclarationDescriptor redeclaredDescriptor; - public RedeclarationError(@NonNls DeclarationDescriptor existingDescriptor, @NonNls DeclarationDescriptor redeclaredDescriptor) { + public RedeclarationError(@NotNull DeclarationDescriptor existingDescriptor, @NotNull DeclarationDescriptor redeclaredDescriptor) { this.existingDescriptor = existingDescriptor; this.redeclaredDescriptor = redeclaredDescriptor; } @Override - public void acceptHandler(@NonNls ErrorHandler handler) { + public void acceptHandler(@NotNull ErrorHandler handler) { handler.redeclaration(existingDescriptor, redeclaredDescriptor); } } @@ -81,13 +86,13 @@ public abstract class JetDiagnostic { private final ASTNode node; private final String message; - public GenericWarning(@NonNls ASTNode node, @NonNls String message) { + public GenericWarning(@NotNull ASTNode node, @NotNull String message) { this.message = message; this.node = node; } @Override - public void acceptHandler(@NonNls ErrorHandler handler) { + public void acceptHandler(@NotNull ErrorHandler handler) { handler.genericWarning(node, message); } } @@ -102,5 +107,5 @@ public abstract class JetDiagnostic { // return stackTrace; // } - public abstract void acceptHandler(@NonNls ErrorHandler handler); + public abstract void acceptHandler(@NotNull ErrorHandler handler); } diff --git a/idea/src/org/jetbrains/jet/plugin/JetHighlighter.java b/idea/src/org/jetbrains/jet/plugin/JetHighlighter.java index dd5ab7174bc..5e971f21cab 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetHighlighter.java +++ b/idea/src/org/jetbrains/jet/plugin/JetHighlighter.java @@ -7,6 +7,7 @@ import com.intellij.lexer.Lexer; import com.intellij.openapi.editor.HighlighterColors; import com.intellij.openapi.editor.SyntaxHighlighterColors; import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.fileTypes.SyntaxHighlighterBase; import com.intellij.psi.TokenType; @@ -96,6 +97,15 @@ public class JetHighlighter extends SyntaxHighlighterBase { JET_AUTO_CAST_EXPRESSION = TextAttributesKey.createTextAttributesKey("JET.AUTO.CAST.EXPRESSION", clone); } + public static final TextAttributesKey JET_DEBUG_INFO; + + static { + TextAttributes textAttributes = new TextAttributes(); + textAttributes.setEffectType(EffectType.ROUNDED_BOX); + textAttributes.setEffectColor(Color.BLACK); + JET_DEBUG_INFO = TextAttributesKey.createTextAttributesKey("JET.DEBUG.INFO", textAttributes); + } + @NotNull public Lexer getHighlightingLexer() { return new JetLexer(); diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java b/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java new file mode 100644 index 00000000000..0ce7336449d --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java @@ -0,0 +1,90 @@ +package org.jetbrains.jet.plugin.annotations; + +import com.google.common.collect.Sets; +import com.intellij.lang.annotation.AnnotationHolder; +import com.intellij.lang.annotation.Annotator; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.JetDiagnostic; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetReferenceExpression; +import org.jetbrains.jet.lang.psi.JetVisitorVoid; +import org.jetbrains.jet.lang.resolve.AnalyzingUtils; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.plugin.JetHighlighter; + +import java.util.Set; + +import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; + +/** + * @author abreslav + */ +public class DebugInfoAnnotator implements Annotator { + + private static volatile boolean debugInfoEnabled = !ApplicationManager.getApplication().isUnitTestMode(); + + public static void setDebugInfoEnabled(boolean value) { + debugInfoEnabled = value; + } + + public static boolean isDebugInfoEnabled() { + return debugInfoEnabled; + } + + @Override + public void annotate(@NotNull PsiElement element, @NotNull final AnnotationHolder holder) { + if (!debugInfoEnabled) { + return; + } + + if (element instanceof JetFile) { + JetFile file = (JetFile) element; + try { + final BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file); + + final Set unresolvedReferences = Sets.newHashSet(); + for (JetDiagnostic diagnostic : bindingContext.getDiagnostics()) { + if (diagnostic instanceof JetDiagnostic.UnresolvedReferenceError) { + JetDiagnostic.UnresolvedReferenceError error = (JetDiagnostic.UnresolvedReferenceError) diagnostic; + unresolvedReferences.add(error.getReferenceExpression()); + } + } + + file.acceptChildren(new JetVisitorVoid() { + + @Override + public void visitReferenceExpression(JetReferenceExpression expression) { + DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, expression); + boolean resolved = declarationDescriptor != null; + boolean unresolved = unresolvedReferences.contains(expression); + if (resolved && unresolved) { + holder.createErrorAnnotation(expression, "Reference marked as unresolved is actually resolved to " + declarationDescriptor).setTextAttributes(JetHighlighter.JET_DEBUG_INFO); + } + else if (!resolved && !unresolved) { + holder.createErrorAnnotation(expression, "Reference is not resolved to anything, but is not marked unresolved").setTextAttributes(JetHighlighter.JET_DEBUG_INFO); + } + } + + @Override + public void visitJetElement(JetElement element) { + element.acceptChildren(this); + } + }); + } + catch (ProcessCanceledException e) { + throw e; + } + catch (Throwable e) { + // TODO + holder.createErrorAnnotation(element, e.getClass().getCanonicalName() + ": " + e.getMessage()); + e.printStackTrace(); + } + } + } + +}