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;
}
}