Package org.intellij.sonar.analysis

Source Code of org.intellij.sonar.analysis.SonarExternalAnnotator$State

package org.intellij.sonar.analysis;

import com.google.common.base.Optional;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.daemon.DaemonBundle;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.ExternalAnnotator;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.ui.UIUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.intellij.sonar.DocumentChangeListener;
import org.intellij.sonar.index.IssuesByFileIndex;
import org.intellij.sonar.index.SonarIssue;
import org.intellij.sonar.util.Finders;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.Set;

import static com.google.common.base.Optional.fromNullable;

public class SonarExternalAnnotator extends ExternalAnnotator<SonarExternalAnnotator.State, SonarExternalAnnotator.State> {

  public static final Key<Set<SonarIssue>> KEY = new Key<Set<SonarIssue>>("issues");

  public static class State {
    private VirtualFile vfile;
  }

  @Nullable
  @Override
  public State collectInformation(@NotNull PsiFile file) {
    State state = new State();
    state.vfile = file.getVirtualFile();
    return state;
  }

  @Nullable
  @Override
  public State doAnnotate(State collectedInfo) {
    return collectedInfo;
  }

  @Override
  public void apply(@NotNull final PsiFile file, final State annotationResult, @NotNull final AnnotationHolder holder) {
    ApplicationManager.getApplication().invokeLater(new Runnable() {
      @Override
      public void run() {
        createAnnotations(file, annotationResult, holder);
      }
    });
  }

  private void createAnnotations(@NotNull final PsiFile psiFile, State annotationResult, @NotNull AnnotationHolder holder) {
    final Set<SonarIssue> issues;

    if (!DocumentChangeListener.CHANGED_FILES.contains(psiFile.getVirtualFile())) {
      issues = IssuesByFileIndex.getIssuesForFile(psiFile);
      for (SonarIssue issue : issues) {
        final TextRange textRange = Finders.getLineRange(psiFile, issue.getLine());
        createInvisibleHighlighter(psiFile, issue, textRange);
      }
    } else {
      final Set<SonarIssue> issuesFromHighlighters = Sets.newLinkedHashSet();

      Optional<Document> document = Finders.findDocumentFromPsiFile(psiFile);
      if (document.isPresent()) {
        Set<RangeHighlighter> highlighters = Finders.findAllRangeHighlightersFrom(document.get());
        for (RangeHighlighter highlighter : highlighters) {
          Optional<Set<SonarIssue>> issuesFromHighlighter = fromNullable(highlighter.getUserData(KEY));
          if (issuesFromHighlighter.isPresent()) {
            issuesFromHighlighters.addAll(issuesFromHighlighter.get());
          }
        }
      }

      issues = issuesFromHighlighters;
    }
    for (SonarIssue issue : issues) {
      Optional<Annotation> annotation = createAnnotation(holder, psiFile, issue);
      if (annotation.isPresent()) {
        String tooltip = createTooltip(issue);
        annotation.get().setTooltip(tooltip);
      }
    }
  }

  private void createInvisibleHighlighter(PsiFile psiFile, final SonarIssue issue, final TextRange textRange) {
    final Optional<Document> document = Finders.findDocumentFromPsiFile(psiFile);
    final List<Editor> editors = Finders.findEditorsFrom(document.get());
    for (final Editor editor : editors) {

      final MarkupModel markupModel = editor.getMarkupModel();

      ApplicationManager.getApplication().invokeLater(new Runnable() {
        @Override
        public void run() {
          final Optional<RangeHighlighter> rangeHighlighterAtLine = Finders.findRangeHighlighterAtLine(editor, issue.getLine());
          if (rangeHighlighterAtLine.isPresent()) {
            final Set<SonarIssue> issuesOfHighlighter = rangeHighlighterAtLine.get().getUserData(KEY);
            if (null != issuesOfHighlighter) {
              issuesOfHighlighter.add(issue);
            }
          } else {
            TextAttributes attrs = new TextAttributes();
//            uncomment to make visible
//            attrs.setForegroundColor(JBColor.BLUE);
            final RangeHighlighter rangeHighlighter = markupModel.addRangeHighlighter(
                textRange.getStartOffset(),
                textRange.getEndOffset(),
                0,
                attrs,
                HighlighterTargetArea.EXACT_RANGE);
            Set<SonarIssue> issuesOfHighlighter = Sets.newLinkedHashSet();
            issuesOfHighlighter.add(issue);
            rangeHighlighter.putUserData(KEY, issuesOfHighlighter);
          }
        }
      });
    }
  }

  public static Optional<Annotation> createAnnotation(AnnotationHolder holder, PsiFile psiFile, SonarIssue issue) {
    HighlightSeverity severity = SonarToIjSeverityMapping.toHighlightSeverity(issue.getSeverity());
    Annotation annotation;
    if (issue.getLine() == null) {
      annotation = createAnnotation(holder, issue.formattedMessage(), psiFile, severity);
      annotation.setFileLevelAnnotation(true);
    } else {
      Optional<PsiElement> startElement = Finders.findFirstElementAtLine(psiFile, issue.getLine());
      if (!startElement.isPresent()) {
        // There is no AST element on this line. Maybe a tabulation issue on a blank line?
        annotation = createAnnotation(holder, issue.formattedMessage(), Finders.getLineRange(psiFile, issue.getLine()), severity);
      } else if (startElement.get().isValid()) {
        TextRange lineRange = Finders.getLineRange(startElement.get());
        annotation = createAnnotation(holder, issue.formattedMessage(), lineRange, severity);
      } else {
        annotation = null;
      }
    }
    return fromNullable(annotation);

  }

  private static String createTooltip(SonarIssue issue) {
    String myShortcutText;
    final KeymapManager keymapManager = KeymapManager.getInstance();
    if (keymapManager != null) {
      final Keymap keymap = keymapManager.getActiveKeymap();
      myShortcutText = keymap == null ? "" : "(" + KeymapUtil.getShortcutsText(keymap.getShortcuts(IdeActions.ACTION_SHOW_ERROR_DESCRIPTION)) + ")";
    }
    else {
      myShortcutText = "";
    }
    @NonNls final String link = " <a "
        +"href=\"#sonarissue/"+issue.getKey()+"\""
        + (UIUtil.isUnderDarcula() ? " color=\"7AB4C9\" " : "")
        +">" + DaemonBundle.message("inspection.extended.description")
        +"</a> " + myShortcutText;
    return XmlStringUtil.wrapInHtml(XmlStringUtil.escapeString(issue.formattedMessage()) + link);
  }

  private static Annotation createAnnotation(AnnotationHolder holder, String message, PsiElement location, HighlightSeverity severity) {
    return holder.createAnnotation(severity, location.getTextRange(), message);
  }

  private static Annotation createAnnotation(AnnotationHolder holder, String message, TextRange textRange, HighlightSeverity severity) {
    return holder.createAnnotation(severity, textRange, message);
  }

}
TOP

Related Classes of org.intellij.sonar.analysis.SonarExternalAnnotator$State

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.