package jetbrains.mps.vcs.annotate; /*Generated by MPS */ import java.util.Set; import jetbrains.mps.nodeEditor.EditorComponent; import jetbrains.mps.internal.collections.runtime.SetSequence; import java.util.HashSet; import jetbrains.mps.project.MPSProject; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import jetbrains.mps.nodeEditor.leftHighlighter.AbstractLeftColumn; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.nodeEditor.leftHighlighter.LeftEditorHighlighter; import org.jetbrains.mps.openapi.model.SNode; import org.jetbrains.mps.openapi.persistence.DataSource; import jetbrains.mps.vfs.IFile; import jetbrains.mps.extapi.persistence.FileDataSource; import jetbrains.mps.persistence.FilePerRootDataSource; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import jetbrains.mps.ide.vfs.VirtualFileUtils; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import jetbrains.mps.baseLanguage.closures.runtime._FunctionTypes; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vcs.annotate.AnnotationProvider; import com.intellij.openapi.progress.Task; import com.intellij.openapi.vcs.changes.BackgroundFromStartOption; import com.intellij.openapi.vcs.annotate.FileAnnotation; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.vcs.AbstractVcsHelper; import java.util.Arrays; import com.intellij.util.Consumer; import com.intellij.openapi.progress.ProgressManager; import org.jetbrains.mps.openapi.model.SModel; public class AnnotationHelper { /** * XXX if this is reloadable code (is jetbrains.mps.vcs plugin reloadable?), then what happens with values cached here on reload? */ private static Set<EditorComponent> ourProgress = SetSequence.fromSet(new HashSet<EditorComponent>()); private final MPSProject myProject; public AnnotationHelper(@NotNull MPSProject project) { myProject = project; } @Nullable private static AnnotationColumn findAnnotationColumn(@NotNull EditorComponent editorComponent) { for (AbstractLeftColumn column : ListSequence.fromList(editorComponent.getLeftEditorHighlighter().getLeftColumns())) { if (column instanceof AnnotationColumn) { return ((AnnotationColumn) column); } } return null; } private boolean annotate(@NotNull final EditorComponent editorComponent, boolean dryRun) { // check if annotation is in progress (always called from ui thread) if (SetSequence.fromSet(ourProgress).contains(editorComponent)) { return false; } final LeftEditorHighlighter leftEditorHighlighter = editorComponent.getLeftEditorHighlighter(); AnnotationColumn annotationColumn = findAnnotationColumn(editorComponent); if (annotationColumn != null) { if (!(dryRun)) { annotationColumn.close(); } return true; } final SNode root = editorComponent.getEditedNode(); DataSource source = check_19hp0u_a0i0i(check_19hp0u_a0a8a8(root)); IFile iFile; if (source instanceof FileDataSource) { iFile = ((FileDataSource) source).getFile(); } else if (source instanceof FilePerRootDataSource) { iFile = ((FilePerRootDataSource) source).getFile(root.getName() + "." + FilePerRootDataSource.ROOT_EXTENSION); } else { return false; } final Project ideaProject = myProject.getProject(); final VirtualFile file = VirtualFileUtils.getVirtualFile(iFile); if (file == null) { return false; } final AbstractVcs vcs = ProjectLevelVcsManager.getInstance(ideaProject).getVcsFor(file); if (vcs == null) { return false; } _FunctionTypes._return_P1_E0<? extends Boolean, ? super FileStatus> checkFileStatus = new _FunctionTypes._return_P1_E0<Boolean, FileStatus>() { public Boolean invoke(FileStatus fs) { return fs == FileStatus.UNKNOWN || fs == FileStatus.ADDED || fs == FileStatus.IGNORED; } }; if (checkFileStatus.invoke(FileStatusManager.getInstance(ideaProject).getStatus(file))) { return false; } final AnnotationProvider annotationProvider = vcs.getAnnotationProvider(); if (annotationProvider == null) { return false; } if (dryRun) { return true; } Task.Backgroundable annotateTask = new Task.Backgroundable(ideaProject, "Retrieving annotations", true, BackgroundFromStartOption.getInstance()) { private FileAnnotation myFileAnnotation; private VcsException myException; @Override public void run(@NotNull ProgressIndicator indicator) { try { myFileAnnotation = annotationProvider.annotate(file); } catch (VcsException e) { myException = e; } } @Override public void onCancel() { onSuccess(); } @Override public void onSuccess() { // (in UI thread) SetSequence.fromSet(ourProgress).removeElement(editorComponent); if (myException != null) { AbstractVcsHelper.getInstance(ideaProject).showErrors(Arrays.asList(myException), "Exception on retrieving annotation"); } if (myFileAnnotation != null) { // Now annotation is build asynchroniously, and is reloaded after build finished (can be done several times) myFileAnnotation.setReloader(new Consumer<FileAnnotation>() { public void consume(FileAnnotation newFA) { annotate(editorComponent); } }); // if annotation is not ready yet - just wait for reload if (myFileAnnotation.getRevisions() == null) { return; } editorComponent.getEditorContext().getRepository().getModelAccess().runReadAction(new Runnable() { public void run() { AnnotationColumn annotationColumn = new AnnotationColumn(leftEditorHighlighter, root, myFileAnnotation, vcs, file); leftEditorHighlighter.addLeftColumn(annotationColumn); } }); } } }; SetSequence.fromSet(ourProgress).addElement(editorComponent); try { ProgressManager.getInstance().run(annotateTask); } catch (Throwable t) { SetSequence.fromSet(ourProgress).removeElement(editorComponent); } return true; } public void annotate(EditorComponent editorComponent) { annotate(editorComponent, false); } public boolean isAnnotateable(EditorComponent editorComponent) { return annotate(editorComponent, true); } private static DataSource check_19hp0u_a0i0i(SModel checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getSource(); } return null; } private static SModel check_19hp0u_a0a8a8(SNode checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getModel(); } return null; } }