From fcaf60e139ed8ecebdd8a9044b84324565ab0637 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Tue, 4 Jun 2013 15:50:22 +0400 Subject: [PATCH] Sorting annotations on saving instead of loading. --- .../ExternalAnnotationsManagerImpl.java | 79 +++++++++++++++---- .../BaseExternalAnnotationsManager.java | 55 +------------ .../p/annotationsAnnotateLibrary_after.xml | 12 +-- .../anno/p/annotationsDeannotation1_after.xml | 6 +- .../anno/p/annotationsDeannotation_after.xml | 4 +- .../annotationsExistingExternalName_after.xml | 18 ++--- .../annotationsNewSuppress_after.xml | 16 ++-- .../annotationsSecondSuppression_after.xml | 16 ++-- .../root1/multiRoot/annotations_after.xml | 10 +-- .../root2/multiRoot/annotations_after.xml | 10 +-- 10 files changed, 109 insertions(+), 117 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java index c4c156c6d963..c3f9778677cc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java @@ -80,9 +80,8 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.io.IOException; -import java.util.ArrayList; +import java.util.*; import java.util.List; -import java.util.Set; /** * @author anna @@ -397,30 +396,40 @@ public class ExternalAnnotationsManagerImpl extends ReadableExternalAnnotationsM } final String externalName = getExternalName(listOwner, false); final String oldExternalName = getNormalizedExternalName(listOwner); - for (final XmlTag tag : rootTag.getSubTags()) { - final String className = StringUtil.unescapeXml(tag.getAttributeValue("name")); + + final List tagsToProcess = new ArrayList(); + for (XmlTag tag : rootTag.getSubTags()) { + String className = StringUtil.unescapeXml(tag.getAttributeValue("name")); if (!Comparing.strEqual(className, externalName) && !Comparing.strEqual(className, oldExternalName)) { continue; } - for (final XmlTag annotationTag : tag.getSubTags()) { + for (XmlTag annotationTag : tag.getSubTags()) { if (!Comparing.strEqual(annotationTag.getAttributeValue("name"), annotationFQN)) { continue; } - CommandProcessor.getInstance().executeCommand(myPsiManager.getProject(), new Runnable() { - @Override - public void run() { - try { - annotationTagProcessor.process(annotationTag); - commitChanges(file); - } - catch (IncorrectOperationException e) { - LOG.error(e); - } - } - }, ExternalAnnotationsManagerImpl.class.getName(), null); + tagsToProcess.add(annotationTag); processedAnything = true; } } + if (tagsToProcess.isEmpty()) { + continue; + } + + CommandProcessor.getInstance().executeCommand(myPsiManager.getProject(), new Runnable() { + @Override + public void run() { + PsiDocumentManager.getInstance(myPsiManager.getProject()).commitAllDocuments(); + try { + for (XmlTag annotationTag : tagsToProcess) { + annotationTagProcessor.process(annotationTag); + } + commitChanges(file); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + }, ExternalAnnotationsManagerImpl.class.getName(), null); } notifyAfterAnnotationChanging(listOwner, annotationFQN, processedAnything); return processedAnything; @@ -576,7 +585,43 @@ public class ExternalAnnotationsManagerImpl extends ReadableExternalAnnotationsM }, ExternalAnnotationsManagerImpl.class.getName(), null); } + private static void sortItems(@NotNull XmlFile xmlFile) { + XmlDocument document = xmlFile.getDocument(); + if (document == null) { + return; + } + XmlTag rootTag = document.getRootTag(); + if (rootTag == null) { + return; + } + + List itemTags = new ArrayList(); + for (XmlTag item : rootTag.getSubTags()) { + if (item.getAttributeValue("name") != null) { + itemTags.add(item); + } + else { + item.delete(); + } + } + + Collections.sort(itemTags, new Comparator() { + @Override + public int compare(XmlTag item1, XmlTag item2) { + String externalName1 = item1.getAttributeValue("name"); + String externalName2 = item2.getAttributeValue("name"); + assert externalName1 != null && externalName2 != null; // null names were not added + return externalName1.compareTo(externalName2); + } + }); + for (XmlTag item : itemTags) { + rootTag.addAfter(item, null); + item.delete(); + } + } + private void commitChanges(XmlFile xmlFile) { + sortItems(xmlFile); Document doc = PsiDocumentManager.getInstance(myPsiManager.getProject()).getDocument(xmlFile); assert doc != null; FileDocumentManager.getInstance().saveDocument(doc); diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java index 1045dcd3f7cd..283211ccd699 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java @@ -197,22 +197,10 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations try { Document document = JDOMUtil.loadDocument(escapeAttributes(file.getText())); Element rootElement = document.getRootElement(); - //noinspection unchecked + //noinspection unchecked List itemElements = rootElement == null ? Collections.emptyList() : (List)rootElement.getChildren("item"); - boolean sorted = true; - boolean modified = false; - String prevItemName = null; for (Element element : itemElements) { String externalName = element.getAttributeValue("name"); - if (externalName == null) { - element.detach(); - modified = true; - continue; - } - if (prevItemName != null && prevItemName.compareTo(externalName) > 0) { - sorted = false; - } - prevItemName = externalName; //noinspection unchecked for (Element annotationElement : (List) element.getChildren("annotation")) { @@ -244,47 +232,6 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations data.add(externalName, annData); } } - if (!sorted) { - modified = true; - List items = new ArrayList(rootElement.getChildren("item")); - rootElement.removeChildren("item"); - Collections.sort(items, new Comparator() { - @Override - public int compare(Element item1, Element item2) { - String externalName1 = item1.getAttributeValue("name"); - String externalName2 = item2.getAttributeValue("name"); - return externalName1.compareTo(externalName2); - } - }); - for (Element item : items) { - rootElement.addContent(item); - } - } - final VirtualFile virtualFile = file.getVirtualFile(); - if (modified && virtualFile.isInLocalFileSystem() && virtualFile.isWritable()) { - final Project project = file.getProject(); - final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); - final StringWriter string = new StringWriter(file.getTextLength()); - JDOMUtil.writeDocument(document, string, "\n"); - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - if (file.getModificationStamp() == fileModificationStamp && !fileDocumentManager.isFileModified(virtualFile)) { - // modify .xml in write action to avoid conflicts and torn reads - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - com.intellij.openapi.editor.Document editorDoc = PsiDocumentManager.getInstance(project).getDocument(file); - if (editorDoc != null) { - editorDoc.setText(string.toString()); - fileDocumentManager.saveDocument(editorDoc); - } - } - }); - } - } - }, project.getDisposed()); - } } catch (IOException e) { LOG.error(e); diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsAnnotateLibrary_after.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsAnnotateLibrary_after.xml index 97d0dd5efeba..8b6ad7dfa54f 100644 --- a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsAnnotateLibrary_after.xml +++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsAnnotateLibrary_after.xml @@ -1,11 +1,11 @@ - - - - - - + + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsDeannotation1_after.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsDeannotation1_after.xml index 62fa98b42b99..ae478685803c 100644 --- a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsDeannotation1_after.xml +++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsDeannotation1_after.xml @@ -1,5 +1,5 @@ - - - + + + \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsDeannotation_after.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsDeannotation_after.xml index 7b5c7f721a8c..5ef438488a57 100644 --- a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsDeannotation_after.xml +++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotationsDeannotation_after.xml @@ -1,5 +1,5 @@ - - + + \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsExistingExternalName_after.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsExistingExternalName_after.xml index 3ea793646df7..1e77ab91421d 100644 --- a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsExistingExternalName_after.xml +++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsExistingExternalName_after.xml @@ -1,13 +1,13 @@ - - + + + + + + + - + - - - - - - + \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsNewSuppress_after.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsNewSuppress_after.xml index 03f8c40dc079..cc3e7078cc0e 100644 --- a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsNewSuppress_after.xml +++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsNewSuppress_after.xml @@ -1,15 +1,15 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsSecondSuppression_after.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsSecondSuppression_after.xml index afdf1536b9d0..70cbe4ca03c2 100644 --- a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsSecondSuppression_after.xml +++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotationsSecondSuppression_after.xml @@ -1,10 +1,10 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root1/multiRoot/annotations_after.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root1/multiRoot/annotations_after.xml index f635a33b9c73..51d624c76d31 100644 --- a/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root1/multiRoot/annotations_after.xml +++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root1/multiRoot/annotations_after.xml @@ -1,7 +1,7 @@ - - - - - + + + + + \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root2/multiRoot/annotations_after.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root2/multiRoot/annotations_after.xml index 60e041c8bd99..2cc3ed107ab5 100644 --- a/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root2/multiRoot/annotations_after.xml +++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root2/multiRoot/annotations_after.xml @@ -1,7 +1,7 @@ - - - - - + + + + + \ No newline at end of file