diff --git a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java index 72f442e407b4..991a7e1dea9e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java @@ -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); + } + } + } } diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/edit/annotations.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/edit/annotations.xml new file mode 100644 index 000000000000..abd01e3a9064 --- /dev/null +++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/edit/annotations.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/lib/edit/Foo.java b/java/java-tests/testData/codeInsight/externalAnnotations/lib/edit/Foo.java new file mode 100644 index 000000000000..65269e0ab137 --- /dev/null +++ b/java/java-tests/testData/codeInsight/externalAnnotations/lib/edit/Foo.java @@ -0,0 +1,2 @@ +package edit; +public class Foo {} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/AddAnnotationFixTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/AddAnnotationFixTest.java index d8d58f83b9cc..75ce07b3facc 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/AddAnnotationFixTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/AddAnnotationFixTest.java @@ -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,