diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/problems/pass/ProjectProblemFileSelectionListener.java b/java/java-impl/src/com/intellij/codeInsight/daemon/problems/pass/ProjectProblemFileSelectionListener.java index c7c69c12d957..536cf1a400d2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/problems/pass/ProjectProblemFileSelectionListener.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/problems/pass/ProjectProblemFileSelectionListener.java @@ -12,6 +12,7 @@ import com.intellij.openapi.startup.StartupActivity; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent; import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.psi.PsiFile; @@ -38,10 +39,15 @@ final class ProjectProblemFileSelectionListener implements FileEditorManagerList VirtualFile oldFile = event.getOldFile(); VirtualFile newFile = event.getNewFile(); TextEditor oldEditor = tryCast(event.getOldEditor(), TextEditor.class); - if (oldFile == null || oldEditor == null || oldFile instanceof VirtualFileWindow || !oldFile.isValid() || oldFile.equals(newFile)) return; - PsiJavaFile psiJavaFile = tryCast(PsiManager.getInstance(myProject).findFile(oldFile), PsiJavaFile.class); + if (oldFile == null || oldEditor == null || oldFile.equals(newFile)) return; + setPreviousState(oldFile, oldEditor); + } + + private void setPreviousState(@NotNull VirtualFile file, @NotNull TextEditor textEditor) { + if (file instanceof VirtualFileWindow || !file.isValid()) return; + PsiJavaFile psiJavaFile = tryCast(PsiManager.getInstance(myProject).findFile(file), PsiJavaFile.class); if (psiJavaFile == null) return; - ProjectProblemPassUtils.removeInfos(oldEditor.getEditor()); + ProjectProblemPassUtils.removeInfos(textEditor.getEditor()); FileStateUpdater.setPreviousState(psiJavaFile); } @@ -50,12 +56,21 @@ final class ProjectProblemFileSelectionListener implements FileEditorManagerList PsiManager psiManager = PsiManager.getInstance(myProject); ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); for (VFileEvent e : events) { - if (!(e instanceof VFileDeleteEvent)) continue; - VirtualFile virtualFile = ((VFileDeleteEvent)e).getFile(); - if (!fileIndex.isInContent(virtualFile)) continue; - PsiFile psiFile = psiManager.findFile(virtualFile); - if (psiFile == null) continue; - FileStateUpdater.removeState(psiFile); + VirtualFile changedFile = e.getFile(); + if (changedFile == null) continue; + if (e instanceof VFileDeleteEvent) { + if (!fileIndex.isInContent(changedFile)) continue; + PsiFile psiFile = psiManager.findFile(changedFile); + if (psiFile == null) continue; + FileStateUpdater.removeState(psiFile); + } + if (e instanceof VFileContentChangeEvent || e instanceof VFileDeleteEvent) { + TextEditor editor = tryCast(FileEditorManager.getInstance(myProject).getSelectedEditor(), TextEditor.class); + if (editor == null) continue; + VirtualFile selectedFile = editor.getFile(); + if (selectedFile == null || changedFile.equals(selectedFile)) continue; + setPreviousState(selectedFile, editor); + } } } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/problems/ClassProblemsTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/problems/ClassProblemsTest.kt index 28f9f6ccb51a..bb5071e74acf 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/problems/ClassProblemsTest.kt +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/problems/ClassProblemsTest.kt @@ -1,9 +1,15 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.java.codeInsight.daemon.problems +import com.intellij.codeInsight.daemon.problems.pass.ProjectProblemPassUtils import com.intellij.openapi.command.WriteCommandAction +import com.intellij.openapi.command.undo.UndoManager +import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.psi.* import com.intellij.psi.util.PsiTreeUtil +import com.intellij.refactoring.BaseRefactoringProcessor +import com.intellij.refactoring.move.moveInner.MoveInnerImpl +import com.intellij.refactoring.openapi.impl.MoveInnerRefactoringImpl internal class ClassProblemsTest : ProjectProblemsViewTest() { @@ -123,6 +129,48 @@ internal class ClassProblemsTest : ProjectProblemsViewTest() { } } + fun testMoveInnerClassAndUndo() { + val refClass = myFixture.addClass(""" + public class A { + private String s = "foo"; + public class Inner { + void test() { + System.out.println(s); + } + } + } + """.trimIndent()) + + myFixture.openFileInEditor(refClass.containingFile.virtualFile) + + doTest(refClass) { + changeClass(refClass) { psiClass, _ -> + val innerClass = psiClass.innerClasses[0] + val targetContainer = MoveInnerImpl.getTargetContainer(innerClass, false)!! + val moveRefactoring = MoveInnerRefactoringImpl(myFixture.project, innerClass, innerClass.name, true, "a", targetContainer) + BaseRefactoringProcessor.ConflictsInTestsException.withIgnoredConflicts { moveRefactoring.run() } + } + changeClass(refClass) { psiClass, _ -> + psiClass.fields[0].modifierList?.setModifierProperty(PsiModifier.PRIVATE, false) + } + changeClass(refClass) { psiClass, _ -> + psiClass.fields[0].modifierList?.setModifierProperty(PsiModifier.PRIVATE, true) + } + + assertNotEmpty(ProjectProblemPassUtils.getInlays(myFixture.editor).entries) + + val selectedEditor = FileEditorManager.getInstance(project).selectedEditor + WriteCommandAction.runWriteCommandAction(project) { + UndoManager.getInstance(project).undo(selectedEditor) + UndoManager.getInstance(project).undo(selectedEditor) + UndoManager.getInstance(project).undo(selectedEditor) + } + PsiDocumentManager.getInstance(project).commitAllDocuments() + + assertEmpty(ProjectProblemPassUtils.getInlays(myFixture.editor).entries) + } + } + private fun doNestedClassTest(isStatic: Boolean) { val staticModifier = if (isStatic) "static" else "" val targetClass = myFixture.addClass("""