PsiChangeTracker tests
[fedora-idea.git] / platform / lang-impl / src / com / intellij / openapi / vcs / changes / PsiChangeTracker.java
blobe8b35a78e9c805a1f34f2d2ea59e75ddfca16ac0
1 package com.intellij.openapi.vcs.changes;
3 import com.intellij.openapi.application.ApplicationManager;
4 import com.intellij.openapi.editor.Document;
5 import com.intellij.openapi.fileEditor.FileDocumentManager;
6 import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
7 import com.intellij.openapi.project.Project;
8 import com.intellij.openapi.util.Computable;
9 import com.intellij.openapi.util.text.StringUtil;
10 import com.intellij.openapi.vcs.FileStatus;
11 import com.intellij.openapi.vcs.FileStatusManager;
12 import com.intellij.openapi.vcs.VcsException;
13 import com.intellij.openapi.vfs.VirtualFile;
14 import com.intellij.psi.PsiElement;
15 import com.intellij.psi.PsiFile;
16 import com.intellij.psi.PsiFileFactory;
17 import com.intellij.psi.PsiRecursiveElementVisitor;
18 import org.jetbrains.annotations.Nullable;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
25 /**
26 * @author Konstantin Bulenkov
28 public class PsiChangeTracker {
29 private PsiChangeTracker() {
32 public static <T extends PsiElement> Map<T, FileStatus> getElementsChanged(PsiFile file, final PsiElementFilter<T> filter) {
33 final Project project = file.getProject();
34 final String oldText = getUnmodifiedDocument(file.getVirtualFile(), project);
35 //TODO: make loop for different languages
36 //TODO: for ( PsiFile f : file.getViewProvider().getAllFiles() )
37 //TODO: for some languages (eg XML) isEquivalentTo works ugly. Think about pluggable matchers for different languages/elements
38 final PsiFile oldFile = oldText == null
39 ? null : PsiFileFactory.getInstance(project).createFileFromText(oldText, file);
40 return getElementsChanged(file, oldFile, filter);
43 public static <T extends PsiElement> Map<T, FileStatus> getElementsChanged(PsiFile file, PsiFile oldFile, final PsiElementFilter<T> filter) {
44 final Project project = file.getProject();
45 final List<T> elements = new ArrayList<T>();
46 final List<T> oldElements = new ArrayList<T>();
48 file.accept(new MyVisitor<T>(filter, elements));
49 final VirtualFile vf = file.getVirtualFile();
50 final FileStatus status = vf == null ? null : FileStatusManager.getInstance(project).getStatus(vf);
51 final HashMap<T, FileStatus> result = new HashMap<T, FileStatus>();
52 if (status == FileStatus.ADDED ||
53 status == FileStatus.DELETED ||
54 status == FileStatus.DELETED_FROM_FS ||
55 status == FileStatus.UNKNOWN) {
56 for (T element : elements) {
57 result.put(element, status);
59 return result;
62 if (oldFile == null) return result;
63 oldFile.accept(new MyVisitor<T>(filter, oldElements));
64 calculateStatuses(elements, oldElements, result);
66 return result;
69 private static <T extends PsiElement> Map<T, FileStatus> calculateStatuses(List<T> elements,
70 List<T> oldElements,
71 Map<T, FileStatus> result) {
72 for (T element : elements) {
73 T e = null;
74 for (T oldElement : oldElements) {
75 if (element.isEquivalentTo(oldElement)) {
76 e = oldElement;
77 break;
80 if (e != null) {
81 oldElements.remove(e);
82 if (!element.getText().equals(e.getText())) {
83 result.put(element, FileStatus.MODIFIED);
86 else {
87 result.put(element, FileStatus.ADDED);
91 for (T oldElement : oldElements) {
92 result.put(oldElement, FileStatus.DELETED);
95 return result;
98 @Nullable
99 private static String getUnmodifiedDocument(final VirtualFile file, Project project) {
100 final Change change = ChangeListManager.getInstance(project).getChange(file);
101 if (change != null) {
102 final ContentRevision beforeRevision = change.getBeforeRevision();
103 if (beforeRevision instanceof BinaryContentRevision) {
104 return null;
106 if (beforeRevision != null) {
107 String content;
108 try {
109 content = beforeRevision.getContent();
111 catch (VcsException ex) {
112 content = null;
114 return content == null ? null : StringUtil.convertLineSeparators(content);
116 return null;
119 final Document document = FileDocumentManager.getInstance().getCachedDocument(file);
120 if (document != null && document.getModificationStamp() != file.getModificationStamp()) {
121 return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
122 public String compute() {
123 return LoadTextUtil.loadText(file).toString();
128 return null;
131 static class MyVisitor<T extends PsiElement> extends PsiRecursiveElementVisitor {
132 private final PsiElementFilter<T> filter;
133 private final List<T> elements;
135 protected MyVisitor(final PsiElementFilter<T> filter, final List<T> elements) {
136 this.filter = filter;
137 this.elements = elements;
140 @Override
141 public void visitElement(PsiElement element) {
142 if (filter.getClassFilter().isAssignableFrom(element.getClass())) {
143 final T e = (T)element;
144 if (filter.accept(e)) {
145 elements.add(e);
148 super.visitElement(element);