package jetbrains.mps.vcs.changesmanager; /*Generated by MPS */ import com.intellij.openapi.components.AbstractProjectComponent; import java.util.Map; import org.jetbrains.mps.openapi.model.SNodeReference; import com.intellij.openapi.vcs.FileStatus; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import jetbrains.mps.project.MPSProject; import jetbrains.mps.nodefs.NodeVirtualFileSystem; import org.jetbrains.annotations.NotNull; import com.intellij.openapi.vcs.FileStatusManager; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.util.ComputeRunnable; import jetbrains.mps.util.Computable; import org.jetbrains.mps.openapi.model.SModel; import org.jetbrains.mps.openapi.model.EditableSModel; import jetbrains.mps.extapi.persistence.FileDataSource; import jetbrains.mps.vcs.platform.util.ConflictsUtil; import java.util.List; import jetbrains.mps.vcs.diff.changes.ModelChange; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.vcs.diff.changes.AddRootChange; import com.intellij.openapi.vfs.VirtualFile; import jetbrains.mps.ide.vfs.VirtualFileUtils; import org.jetbrains.annotations.Nullable; import jetbrains.mps.smodel.SNodePointer; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import java.util.ArrayList; import jetbrains.mps.internal.collections.runtime.IVisitor; import jetbrains.mps.vcs.diff.ChangeSet; public class NodeFileStatusMapping extends AbstractProjectComponent { private final CurrentDifferenceRegistry myRegistry; private final Map<SNodeReference, FileStatus> myFileStatusMap = MapSequence.fromMap(new HashMap<SNodeReference, FileStatus>()); private final CurrentDifferenceListener myGlobalListener = new NodeFileStatusMapping.MyGlobalListener(); protected final MPSProject myMPSProject; protected final NodeVirtualFileSystem myNodeFileSystem; public NodeFileStatusMapping(MPSProject project, CurrentDifferenceRegistry registry, NodeVirtualFileSystem nodeFileSystem) { super(project.getProject()); myRegistry = registry; myMPSProject = project; myNodeFileSystem = nodeFileSystem; } @Override public void projectOpened() { myRegistry.addGlobalDifferenceListener(myGlobalListener); } @Override public void projectClosed() { myRegistry.removeGlobalDifferenceListener(myGlobalListener); } private void statusChanged(@NotNull final SNodeReference nodePointer) { myMPSProject.getModelAccess().runReadAction(new Runnable() { public void run() { FileStatusManager fsm = FileStatusManager.getInstance(myProject); SNode currentNode = nodePointer.resolve(myMPSProject.getRepository()); if (currentNode == null) { return; } statusChanged(fsm, currentNode); } }); } protected void statusChanged(FileStatusManager fsm, @NotNull SNode node) { fsm.fileStatusChanged(myNodeFileSystem.getFileFor(myMPSProject.getRepository(), node)); } private void updateNodeStatus(@NotNull final SNodeReference nodePointer) { myRegistry.getCommandQueue().runTask(new Runnable() { public void run() { if (calcStatus(nodePointer)) { statusChanged(nodePointer); } } }); } private boolean calcStatus(@NotNull final SNodeReference root) { ComputeRunnable<FileStatus> cr = new ComputeRunnable<FileStatus>(new Computable<FileStatus>() { public FileStatus compute() { SModel m = root.getModelReference().resolve(myMPSProject.getRepository()); if (m instanceof EditableSModel && m.getSource() instanceof FileDataSource && !(m.isReadOnly())) { EditableSModel model = (EditableSModel) m; if (ConflictsUtil.isModelOrModuleConflicting(model, myProject)) { return FileStatus.MERGED_WITH_CONFLICTS; } CurrentDifference diff = myRegistry.getCurrentDifference(model); List<ModelChange> modelChanges = check_onkh7z_a0d0b0a0a0a0o(diff.getChangeSet()); List<ModelChange> rootChanges = ListSequence.fromList(modelChanges).where(new IWhereFilter<ModelChange>() { public boolean accept(ModelChange ch) { return root.getNodeId().equals(ch.getRootId()); } }).toListSequence(); if (ListSequence.fromList(rootChanges).count() != 0) { if (ListSequence.fromList(rootChanges).first() instanceof AddRootChange) { VirtualFile vf = VirtualFileUtils.getVirtualFile(((FileDataSource) m.getSource()).getFile()); if (vf != null) { FileStatus modelStatus = FileStatusManager.getInstance(myProject).getStatus(vf); if (BaseVersionUtil.isAddedFileStatus(modelStatus)) { return modelStatus; } } return FileStatus.ADDED; } return FileStatus.MODIFIED; } } return FileStatus.NOT_CHANGED; } }); myMPSProject.getModelAccess().runReadAction(cr); FileStatus status = cr.getResult(); synchronized (myFileStatusMap) { if (MapSequence.fromMap(myFileStatusMap).get(root) != status) { MapSequence.fromMap(myFileStatusMap).put(root, status); return true; } else { return false; } } } @Nullable public FileStatus getStatus(@NotNull final SNode root) { final SNodeReference nodePointer = new SNodePointer(root); myRegistry.getCommandQueue().runTask(new Runnable() { public void run() { myMPSProject.getModelAccess().runReadAction(new Runnable() { public void run() { SModel md = null; SNode node = nodePointer.resolve(myMPSProject.getRepository()); if (node != null) { md = SNodeOperations.getModel(root); } if (md instanceof EditableSModel && !(md.isReadOnly())) { myRegistry.getCurrentDifference((EditableSModel) md).setEnabled(true); } } }); } }); synchronized (myFileStatusMap) { return MapSequence.fromMap(myFileStatusMap).get(nodePointer); } } @Nullable public FileStatus getStatus(@NotNull SNodeReference nodePointer) { synchronized (myFileStatusMap) { return MapSequence.fromMap(myFileStatusMap).get(nodePointer); } } private class MyGlobalListener extends CurrentDifferenceAdapter { private List<SNodeReference> myAffectedRoots = ListSequence.fromList(new ArrayList<SNodeReference>()); private MyGlobalListener() { } @Override public void changeUpdateFinished() { ListSequence.fromList(myAffectedRoots).visitAll(new IVisitor<SNodeReference>() { public void visit(SNodeReference np) { updateNodeStatus(np); } }); ListSequence.fromList(myAffectedRoots).clear(); } private void addAffectedRoot(@NotNull ModelChange change) { if (change.getRootId() != null) { ListSequence.fromList(myAffectedRoots).addElement(new SNodePointer(change.getChangeSet().getNewModel().getReference(), change.getRootId())); } } @Override public void changeAdded(@NotNull ModelChange change) { addAffectedRoot(change); } @Override public void changeRemoved(@NotNull ModelChange change) { addAffectedRoot(change); } } private static List<ModelChange> check_onkh7z_a0d0b0a0a0a0o(ChangeSet checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getModelChanges(); } return null; } }