Extracted VariablesHighlightingVisitor from JetPsiChecker.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user