Package org.intellij.sonar

Source Code of org.intellij.sonar.DocumentChangeListener

package org.intellij.sonar;

import com.google.common.base.Optional;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import org.intellij.sonar.analysis.SonarExternalAnnotator;
import org.intellij.sonar.index.SonarIssue;
import org.intellij.sonar.persistence.IssuesByFileIndexProjectComponent;
import org.intellij.sonar.util.Finders;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

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

public class DocumentChangeListener extends AbstractProjectComponent {

  public static final Set<VirtualFile> CHANGED_FILES = new CopyOnWriteArraySet<VirtualFile>();

  protected DocumentChangeListener(final Project project) {
    super(project);

    EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {

      @Override
      public void documentChanged(final DocumentEvent e) {
        rememberChangedFile(e);

        updateIssuesPositions(e, project);
      }
    });


  }

  @Override
  public void projectOpened() {
    super.projectOpened();
    CHANGED_FILES.clear();
  }

  @Override
  public void projectClosed() {
    super.projectClosed();
    CHANGED_FILES.clear();
  }

  private void updateIssuesPositions(final DocumentEvent e, final Project project) {
    final Optional<Document> document = fromNullable(e.getDocument());
    final List<Editor> editors = Finders.findEditorsFrom(document.get());
    for (final Editor editor : editors) {

      ApplicationManager.getApplication().invokeLater(new Runnable() {
        @Override
        public void run() {
          // update issue line
          Set<RangeHighlighter> allHighlighters = Finders.findAllRangeHighlightersFrom(document.get());
          for (RangeHighlighter highlighter : allHighlighters) {
            Optional<Set<SonarIssue>> issues = fromNullable(highlighter.getUserData(SonarExternalAnnotator.KEY));
            if (!issues.isPresent()) continue;
            int ijLine = Finders.findLineOfRangeHighlighter(highlighter, editor);
            int rhLine = ijLine + 1;
            for (SonarIssue issue : issues.get()) {
              if (issue.getLine() == null) continue;
              if (issue.getLine() != rhLine) {
                issue.setLine(rhLine);
              }
            }
          }

          // remove issues without highlighter (highlighter was removed in editor)
          final Optional<VirtualFile> file = Optional.fromNullable(FileDocumentManager.getInstance().getFile(e.getDocument()));
          if (file.isPresent()) {
            Set<SonarIssue> issuesFromHighlighters = Sets.newLinkedHashSet();
            Set<RangeHighlighter> highlighters = Finders.findAllRangeHighlightersFrom(e.getDocument());
            for (RangeHighlighter highlighter : highlighters) {
              Optional<Set<SonarIssue>> issuesFromHighlighter = fromNullable(highlighter.getUserData(SonarExternalAnnotator.KEY));
              if (issuesFromHighlighter.isPresent()) {
                issuesFromHighlighters.addAll(issuesFromHighlighter.get());
              }
            }
            final Optional<IssuesByFileIndexProjectComponent> indexComponent = IssuesByFileIndexProjectComponent.getInstance(project);
            if (indexComponent.isPresent()) {
              final Map<String, Set<SonarIssue>> index = indexComponent.get().getIndex();
              index.put(file.get().getPath(), issuesFromHighlighters);
            }
          }

          if (file.isPresent() && !project.isDisposed() && project.isInitialized()) {
            Optional<PsiFile> psiFile = fromNullable(PsiManager.getInstance(project).findFile(file.get()));
            if (psiFile.isPresent()) {
              DaemonCodeAnalyzer.getInstance(project).restart(psiFile.get());
            }
          }

        }
      });
    }
  }

  private void rememberChangedFile(final DocumentEvent e) {
    ApplicationManager.getApplication().invokeLater(new Runnable() {
      @Override
      public void run() {
        ApplicationManager.getApplication().runReadAction(new Runnable() {
          @Override
          public void run() {

            final Optional<VirtualFile> file = fromNullable(FileDocumentManager.getInstance().getFile(e.getDocument()));
            if (file.isPresent()) {
              CHANGED_FILES.add(file.get());
            }
          }
        });
      }
    });
  }
}
TOP

Related Classes of org.intellij.sonar.DocumentChangeListener

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.