Invalidate cached external annotations info when annotations file is edited in Idea IDEA-196967

This commit is contained in:
Nikita Skvortsov
2018-08-14 18:43:10 +03:00
parent 2b6f1b53b9
commit d7b44732e6
4 changed files with 50 additions and 8 deletions
@@ -16,12 +16,11 @@ import com.intellij.openapi.command.undo.BasicUndoableAction;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileChooser.FileChooser;
@@ -50,10 +49,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.ui.OptionsMessageDialog;
@@ -77,8 +73,10 @@ import java.util.Set;
*/
public class ExternalAnnotationsManagerImpl extends ReadableExternalAnnotationsManager {
private static final Logger LOG = Logger.getInstance(ExternalAnnotationsManagerImpl.class);
public static final long ANNOTATION_EDITED_TIMEOUT_MILLIS = 100;
private final MessageBus myBus;
private final Alarm myAnnotationDocumentEdited;
public ExternalAnnotationsManagerImpl(@NotNull final Project project, final PsiManager psiManager) {
super(psiManager);
@@ -91,6 +89,8 @@ public class ExternalAnnotationsManagerImpl extends ReadableExternalAnnotationsM
});
VirtualFileManager.getInstance().addVirtualFileListener(new MyVirtualFileListener(), project);
myAnnotationDocumentEdited = new Alarm(Alarm.ThreadToUse.SWING_THREAD, project);
EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new MyDocumentListener(), project);
}
private void notifyAfterAnnotationChanging(@NotNull PsiModifierListOwner owner, @NotNull String annotationFQName, boolean successful) {
@@ -847,4 +847,18 @@ public class ExternalAnnotationsManagerImpl extends ReadableExternalAnnotationsM
processEvent(event);
}
}
private class MyDocumentListener implements DocumentListener {
final FileDocumentManager myFileDocumentManager = FileDocumentManager.getInstance();
@Override
public void documentChanged(DocumentEvent event) {
final VirtualFile file = myFileDocumentManager.getFile(event.getDocument());
if (file != null && ANNOTATIONS_XML.equals(file.getName()) && isUnderAnnotationRoot(file)) {
myAnnotationDocumentEdited.cancelAllRequests();
myAnnotationDocumentEdited.addRequest(() -> dropCache(), ANNOTATION_EDITED_TIMEOUT_MILLIS);
}
}
}
}
@@ -0,0 +1,3 @@
<root>
<item name='edit.Foo'><annotation name='java.lang.Deprecated'/></item><caret>
</root>
@@ -0,0 +1,2 @@
package edit;
public class Foo {}
@@ -5,6 +5,7 @@ import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.ExternalAnnotationsListener;
import com.intellij.codeInsight.ExternalAnnotationsManager;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.generation.actions.CommentByLineCommentAction;
import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
import com.intellij.codeInsight.intention.impl.AnnotateIntentionAction;
import com.intellij.codeInsight.intention.impl.DeannotateIntentionAction;
@@ -36,6 +37,7 @@ import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.*;
import com.intellij.util.ObjectUtils;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -44,6 +46,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.intellij.psi.impl.DebugUtil.sleep;
/**
* @author anna
* @since 27-Jun-2007
@@ -368,6 +372,25 @@ public class AddAnnotationFixTest extends UsefulTestCase {
stopListeningAndCheckEvents();
}
public void testAnnotationsUpdatedWhenFileEdited() {
addDefaultLibrary();
final PsiFile[] files = myFixture.configureByFiles("/content/anno/edit/annotations.xml", "lib/edit/Foo.java");
final PsiClass fooJava = ((PsiClassOwner)files[1]).getClasses()[0];
ExternalAnnotationsManager.getInstance(myProject);
PsiAnnotation annotation = AnnotationUtil.findAnnotation(fooJava, "java.lang.Deprecated");
assertNotNull(annotation);
assertEquals("java.lang.Deprecated", annotation.getQualifiedName());
startListeningForExternalChanges();
myFixture.testAction(new CommentByLineCommentAction()); // comment out a line in annotations file
sleep(150);
UIUtil.dispatchAllInvocationEvents();
annotation = AnnotationUtil.findAnnotation(fooJava, "java.lang.Deprecated");
assertNull(annotation);
}
private class DefaultAnnotationsListener extends ExternalAnnotationsListener.Adapter {
@Override
public void afterExternalAnnotationChanging(@NotNull PsiModifierListOwner owner, @NotNull String annotationFQName,