Extracted VariablesHighlightingVisitor from JetPsiChecker.

This commit is contained in:
Evgeny Gerashchenko
2012-03-29 14:30:33 +04:00
parent 3328dda81a
commit e92d8fcda7
2 changed files with 103 additions and 79 deletions
@@ -19,7 +19,6 @@ package org.jetbrains.jet.plugin.highlighter;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
@@ -31,13 +30,9 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.diagnostics.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.quickfix.JetIntentionActionFactory;
import org.jetbrains.jet.plugin.quickfix.QuickFixes;
@@ -46,13 +41,10 @@ import java.util.Collection;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
/**
* @author abreslav
*/
public class JetPsiChecker implements Annotator {
private static volatile boolean errorReportingEnabled = true;
public static void setErrorReportingEnabled(boolean value) {
@@ -66,16 +58,15 @@ public class JetPsiChecker implements Annotator {
@Override
public void annotate(@NotNull PsiElement element, @NotNull final AnnotationHolder holder) {
if (element instanceof JetFile) {
JetFile file = (JetFile) element;
JetFile file = (JetFile)element;
try {
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file);
if (errorReportingEnabled) {
Collection<Diagnostic> diagnostics = Sets.newLinkedHashSet(bindingContext.getDiagnostics());
Set<PsiElement> redeclarations = Sets.newHashSet();
for (Diagnostic diagnostic : diagnostics) {
// This is needed because we have the same context for all files
if (diagnostic.getPsiFile() != file) continue;
@@ -84,58 +75,7 @@ public class JetPsiChecker implements Annotator {
}
file.acceptChildren(new BackingFieldHighlightingVisitor(holder, bindingContext));
file.acceptChildren(new JetVisitorVoid() {
@Override
public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) {
DeclarationDescriptor target = bindingContext.get(REFERENCE_TARGET, expression);
if (target instanceof ValueParameterDescriptor) {
ValueParameterDescriptor parameterDescriptor = (ValueParameterDescriptor) target;
if (bindingContext.get(AUTO_CREATED_IT, parameterDescriptor)) {
holder.createInfoAnnotation(expression, "Automatically declared based on the expected type").setTextAttributes(JetHighlightingColors.FUNCTION_LITERAL_DEFAULT_PARAMETER);
}
}
markVariableAsWrappedIfNeeded(expression.getNode(), target);
super.visitSimpleNameExpression(expression);
}
private void markVariableAsWrappedIfNeeded(@NotNull ASTNode node, DeclarationDescriptor target) {
if (target instanceof VariableDescriptor) {
VariableDescriptor variableDescriptor = (VariableDescriptor) target;
if (bindingContext.get(MUST_BE_WRAPPED_IN_A_REF, variableDescriptor)) {
holder.createInfoAnnotation(node, "Wrapped into a ref-object to be modifier when captured in a closure").setTextAttributes(
JetHighlightingColors.WRAPPED_INTO_REF);
}
}
}
@Override
public void visitProperty(@NotNull JetProperty property) {
DeclarationDescriptor declarationDescriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property);
PsiElement nameIdentifier = property.getNameIdentifier();
if (nameIdentifier != null) {
markVariableAsWrappedIfNeeded(nameIdentifier.getNode(), declarationDescriptor);
}
super.visitProperty(property);
}
@Override
public void visitExpression(@NotNull JetExpression expression) {
JetType autoCast = bindingContext.get(AUTOCAST, expression);
if (autoCast != null) {
holder.createInfoAnnotation(expression, "Automatically cast to " + autoCast).setTextAttributes(
JetHighlightingColors.AUTO_CASTED_VALUE);
}
expression.acceptChildren(this);
}
@Override
public void visitJetElement(@NotNull JetElement element) {
element.acceptChildren(this);
}
});
file.acceptChildren(new VariablesHighlightingVisitor(holder, bindingContext));
}
catch (ProcessCanceledException e) {
throw e;
@@ -153,26 +93,24 @@ public class JetPsiChecker implements Annotator {
}
}
private void registerDiagnosticAnnotations(
@NotNull Diagnostic diagnostic,
@NotNull Set<PsiElement> redeclarations,
@NotNull final AnnotationHolder holder
) {
private static void registerDiagnosticAnnotations(@NotNull Diagnostic diagnostic,
@NotNull Set<PsiElement> redeclarations,
@NotNull final AnnotationHolder holder) {
List<TextRange> textRanges = diagnostic.getTextRanges();
if (diagnostic.getSeverity() == Severity.ERROR) {
if (diagnostic.getFactory() == Errors.UNRESOLVED_IDE_TEMPLATE) {
return;
}
if (diagnostic instanceof UnresolvedReferenceDiagnostic) {
UnresolvedReferenceDiagnostic unresolvedReferenceDiagnostic = (UnresolvedReferenceDiagnostic) diagnostic;
UnresolvedReferenceDiagnostic unresolvedReferenceDiagnostic = (UnresolvedReferenceDiagnostic)diagnostic;
JetReferenceExpression referenceExpression = unresolvedReferenceDiagnostic.getPsiElement();
PsiReference reference = referenceExpression.getReference();
if (reference instanceof MultiRangeReference) {
MultiRangeReference mrr = (MultiRangeReference) reference;
MultiRangeReference mrr = (MultiRangeReference)reference;
for (TextRange range : mrr.getRanges()) {
Annotation annotation = holder.createErrorAnnotation(
range.shiftRight(referenceExpression.getTextOffset()),
diagnostic.getMessage());
range.shiftRight(referenceExpression.getTextOffset()),
diagnostic.getMessage());
registerQuickFix(annotation, diagnostic);
@@ -191,7 +129,7 @@ public class JetPsiChecker implements Annotator {
}
if (diagnostic instanceof RedeclarationDiagnostic) {
RedeclarationDiagnostic redeclarationDiagnostic = (RedeclarationDiagnostic) diagnostic;
RedeclarationDiagnostic redeclarationDiagnostic = (RedeclarationDiagnostic)diagnostic;
registerQuickFix(markRedeclaration(redeclarations, redeclarationDiagnostic, holder), diagnostic);
return;
}
@@ -218,10 +156,7 @@ public class JetPsiChecker implements Annotator {
* Add a quick fix if and return modified annotation.
*/
@Nullable
private Annotation registerQuickFix(
@Nullable Annotation annotation,
@NotNull Diagnostic diagnostic) {
private static Annotation registerQuickFix(@Nullable Annotation annotation, @NotNull Diagnostic diagnostic) {
if (annotation == null) {
return null;
}
@@ -246,7 +181,7 @@ public class JetPsiChecker implements Annotator {
}
@NotNull
private String getMessage(@NotNull Diagnostic diagnostic) {
private static String getMessage(@NotNull Diagnostic diagnostic) {
if (ApplicationManager.getApplication().isInternal() || ApplicationManager.getApplication().isUnitTestMode()) {
return "[" + diagnostic.getFactory().getName() + "] " + diagnostic.getMessage();
}
@@ -254,7 +189,9 @@ public class JetPsiChecker implements Annotator {
}
@Nullable
private Annotation markRedeclaration(@NotNull Set<PsiElement> redeclarations, @NotNull RedeclarationDiagnostic diagnostic, @NotNull AnnotationHolder holder) {
private static Annotation markRedeclaration(@NotNull Set<PsiElement> redeclarations,
@NotNull RedeclarationDiagnostic diagnostic,
@NotNull AnnotationHolder holder) {
if (!redeclarations.add(diagnostic.getPsiElement())) return null;
List<TextRange> textRanges = diagnostic.getTextRanges();
if (textRanges.isEmpty()) return null;
@@ -0,0 +1,87 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.highlighter;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetType;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
class VariablesHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
VariablesHighlightingVisitor(AnnotationHolder holder, BindingContext bindingContext) {
super(holder, bindingContext);
}
@Override
public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) {
DeclarationDescriptor target = bindingContext.get(REFERENCE_TARGET, expression);
if (target instanceof ValueParameterDescriptor) {
ValueParameterDescriptor parameterDescriptor = (ValueParameterDescriptor) target;
if (Boolean.TRUE.equals(bindingContext.get(AUTO_CREATED_IT, parameterDescriptor))) {
holder.createInfoAnnotation(expression, "Automatically declared based on the expected type").setTextAttributes(
JetHighlightingColors.FUNCTION_LITERAL_DEFAULT_PARAMETER);
}
}
markVariableAsWrappedIfNeeded(expression.getNode(), target);
super.visitSimpleNameExpression(expression);
}
private void markVariableAsWrappedIfNeeded(@NotNull ASTNode node, DeclarationDescriptor target) {
if (target instanceof VariableDescriptor) {
VariableDescriptor variableDescriptor = (VariableDescriptor) target;
if (Boolean.TRUE.equals(bindingContext.get(MUST_BE_WRAPPED_IN_A_REF, variableDescriptor))) {
holder.createInfoAnnotation(node, "Wrapped into a ref-object to be modifier when captured in a closure").setTextAttributes(
JetHighlightingColors.WRAPPED_INTO_REF);
}
}
}
@Override
public void visitProperty(@NotNull JetProperty property) {
DeclarationDescriptor declarationDescriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, property);
PsiElement nameIdentifier = property.getNameIdentifier();
if (nameIdentifier != null) {
markVariableAsWrappedIfNeeded(nameIdentifier.getNode(), declarationDescriptor);
}
super.visitProperty(property);
}
@Override
public void visitExpression(@NotNull JetExpression expression) {
JetType autoCast = bindingContext.get(AUTOCAST, expression);
if (autoCast != null) {
holder.createInfoAnnotation(expression, "Automatically cast to " + autoCast).setTextAttributes(
JetHighlightingColors.AUTO_CASTED_VALUE);
}
expression.acceptChildren(this);
}
@Override
public void visitJetElement(@NotNull JetElement element) {
element.acceptChildren(this);
}
}