mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
advance java structure mod count on complex events collapsed into CHILDREN_CHANGED
This commit is contained in:
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType;
|
||||
import com.intellij.psi.impl.source.jsp.jspXml.JspDirective;
|
||||
import com.intellij.psi.impl.source.tree.TreeUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -60,7 +61,7 @@ public class JavaCodeBlockModificationListener extends PsiTreeChangePreprocessor
|
||||
|
||||
@Override
|
||||
protected boolean containsStructuralElements(@NotNull PsiElement element) {
|
||||
return hasClassesInside(element);
|
||||
return mayHaveJavaStructureInside(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,7 +69,7 @@ public class JavaCodeBlockModificationListener extends PsiTreeChangePreprocessor
|
||||
Set<PsiElement> changedChildren = getChangedChildren(event);
|
||||
|
||||
PsiModificationTrackerImpl tracker = (PsiModificationTrackerImpl)myPsiManager.getModificationTracker();
|
||||
if (!changedChildren.isEmpty() && changedChildren.stream().anyMatch(JavaCodeBlockModificationListener::hasClassesInside)) {
|
||||
if (!changedChildren.isEmpty() && changedChildren.stream().anyMatch(JavaCodeBlockModificationListener::mayHaveJavaStructureInside)) {
|
||||
tracker.incCounter();
|
||||
}
|
||||
|
||||
@@ -91,12 +92,24 @@ public class JavaCodeBlockModificationListener extends PsiTreeChangePreprocessor
|
||||
if (code == PsiEventType.CHILD_ADDED || code == PsiEventType.CHILD_REMOVED || code == PsiEventType.CHILD_REPLACED) {
|
||||
return StreamEx.of(event.getOldChild(), event.getChild(), event.getNewChild()).nonNull().toSet();
|
||||
}
|
||||
if (code == PsiEventType.BEFORE_CHILD_REMOVAL || code == PsiEventType.BEFORE_CHILD_REPLACEMENT) {
|
||||
return StreamEx.of(event.getOldChild(), event.getChild()).nonNull().toSet();
|
||||
}
|
||||
if (code == PsiEventType.BEFORE_CHILDREN_CHANGE && !event.isGenericChange()) {
|
||||
PsiElement parent = event.getParent();
|
||||
if (!(parent instanceof PsiFileSystemItem) && !TreeUtil.isCollapsedChameleon(parent.getNode())) {
|
||||
return ContainerUtil.newHashSet(parent.getChildren());
|
||||
}
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
private static boolean hasClassesInside(@NotNull PsiElement element) {
|
||||
return !SyntaxTraverser.psiTraverser(element).traverse()
|
||||
.filter(Conditions.instanceOf(PsiClass.class, PsiLambdaExpression.class)).isEmpty();
|
||||
private static boolean mayHaveJavaStructureInside(@NotNull PsiElement root) {
|
||||
return !SyntaxTraverser.psiTraverser(root)
|
||||
.expand(e -> !TreeUtil.isCollapsedChameleon(e.getNode()))
|
||||
.traverse()
|
||||
.filter(e -> e instanceof PsiClass || e instanceof PsiLambdaExpression || TreeUtil.isCollapsedChameleon(e.getNode()))
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -143,7 +144,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
|
||||
private void doTest(@NonNls String text, Processor<PsiFile> run) {
|
||||
PsiFile file = configureByText(JavaFileType.INSTANCE, text);
|
||||
PsiModificationTracker modificationTracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker modificationTracker = getTracker();
|
||||
long count = modificationTracker.getModificationCount();
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), ()->{run.process(file);});
|
||||
|
||||
@@ -162,7 +163,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
setFileText(virtualFile, "text");
|
||||
configureByFile(virtualFile);
|
||||
PsiFile file = getFile();
|
||||
PsiModificationTracker modificationTracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker modificationTracker = getTracker();
|
||||
long count = modificationTracker.getJavaStructureModificationCount();
|
||||
|
||||
ApplicationManager.getApplication().runWriteAction(() -> file.getContainingDirectory().delete());
|
||||
@@ -228,7 +229,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testClassShouldNotDisappearWithoutEvents() throws Exception {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
long count0 = tracker.getJavaStructureModificationCount();
|
||||
|
||||
final VirtualFile file = addFileToProject("Foo.java", "class Foo {}").getVirtualFile();
|
||||
@@ -253,7 +254,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
|
||||
|
||||
public void testClassShouldNotDisappearWithoutEvents_NoDocument() throws IOException {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
final PsiManagerEx psiManager = PsiManagerEx.getInstanceEx(getProject());
|
||||
|
||||
final VirtualFile file = addFileToProject("Foo.java", "class Foo {}").getVirtualFile();
|
||||
@@ -273,7 +274,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testClassShouldNotAppearWithoutEvents_NoPsiDirectory() throws IOException {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
long count0 = tracker.getJavaStructureModificationCount();
|
||||
|
||||
final PsiManagerEx psiManager = PsiManagerEx.getInstanceEx(getProject());
|
||||
@@ -290,7 +291,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testClassShouldNotAppearWithoutEvents_NoPsiGrandParentDirectory() throws IOException {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
long count0 = tracker.getJavaStructureModificationCount();
|
||||
|
||||
final PsiManagerEx psiManager = PsiManagerEx.getInstanceEx(getProject());
|
||||
@@ -306,7 +307,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testClassShouldNotDisappearWithoutEvents_VirtualFileDeleted() throws IOException {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
final PsiManagerEx psiManager = PsiManagerEx.getInstanceEx(getProject());
|
||||
|
||||
final VirtualFile file = addFileToProject("Foo.java", "class Foo {}").getVirtualFile();
|
||||
@@ -324,7 +325,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testClassShouldNotDisappearWithoutEvents_ParentVirtualDirectoryDeleted() throws Exception {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
final PsiManagerEx psiManager = PsiManagerEx.getInstanceEx(getProject());
|
||||
|
||||
final VirtualFile file = addFileToProject("foo/Foo.java", "package foo; class Foo {}").getVirtualFile();
|
||||
@@ -343,7 +344,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testClassShouldNotDisappearWithoutEvents_InCodeBlock() throws Exception {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
|
||||
String barStr = "class Bar {}";
|
||||
PsiFile file = addFileToProject("Foo.java", "class Foo {{" + barStr + "}}");
|
||||
@@ -361,7 +362,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testClassShouldNotAppearWithoutEvents_InCodeBlock() throws Exception {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
|
||||
String barStr = "class Bar {}";
|
||||
PsiFile file = addFileToProject("Foo.java", "class Foo {{" + "}}");
|
||||
@@ -378,7 +379,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testVirtualFileRename_WithPsi() throws IOException {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
final PsiManagerEx psiManager = PsiManagerEx.getInstanceEx(getProject());
|
||||
GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
|
||||
|
||||
@@ -406,11 +407,11 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
PsiClass psiClass = JavaPsiFacade.getInstance(getProject()).findClass("Foo", scope);
|
||||
assertNotNull(psiClass);
|
||||
|
||||
long count = PsiManager.getInstance(getProject()).getModificationTracker().getJavaStructureModificationCount();
|
||||
long count = getTracker().getJavaStructureModificationCount();
|
||||
|
||||
IdeaTestUtil.setModuleLanguageLevel(getModule(), LanguageLevel.JDK_1_3);
|
||||
|
||||
assertTrue(count != PsiManager.getInstance(getProject()).getModificationTracker().getJavaStructureModificationCount());
|
||||
assertTrue(count != getTracker().getJavaStructureModificationCount());
|
||||
|
||||
psiClass = JavaPsiFacade.getInstance(getProject()).findClass("Foo", scope);
|
||||
assertNotNull(psiClass);
|
||||
@@ -426,7 +427,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testRootsChangeIncreasesCounts() {
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
long mc = tracker.getModificationCount();
|
||||
long js = tracker.getJavaStructureModificationCount();
|
||||
long ocb = tracker.getOutOfCodeBlockModificationCount();
|
||||
@@ -442,7 +443,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
FixtureRuleKt.runInLoadComponentStateMode(myProject, () -> {
|
||||
ProjectKt.getStateStore(myProject).save(new SmartList<>());
|
||||
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
long mc = tracker.getModificationCount();
|
||||
|
||||
VirtualFile ws = myProject.getWorkspaceFile();
|
||||
@@ -462,7 +463,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
public void testNoIncrementOnReadOnlyStatusChange() throws IOException {
|
||||
VirtualFile file = addFileToProject("Foo.java", "class Foo {}").getVirtualFile();
|
||||
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
long mc = tracker.getModificationCount();
|
||||
|
||||
WriteAction.run(() -> file.setWritable(false));
|
||||
@@ -478,7 +479,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
public void testJavaStructureModCountMustNotBeAdvancedOnJavadocChange() {
|
||||
configureByText(JavaFileType.INSTANCE, "/* <selection>abc</selection> */ class A{}");
|
||||
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
long javaCount = tracker.getJavaStructureModificationCount();
|
||||
long codeBlockCount = tracker.getOutOfCodeBlockModificationCount();
|
||||
|
||||
@@ -491,7 +492,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
public void testJavaStructureModCountMustNotBeAdvancedOnAddingSpace() {
|
||||
configureByText(JavaFileType.INSTANCE, "class A{ <selection></selection> }");
|
||||
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
long javaCount = tracker.getJavaStructureModificationCount();
|
||||
long codeBlockCount = tracker.getOutOfCodeBlockModificationCount();
|
||||
|
||||
@@ -512,7 +513,7 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
PsiAnonymousClass anon = SyntaxTraverser.psiTraverser(file).filter(PsiAnonymousClass.class).first();
|
||||
Arrays.stream(anon.getAllMethods()).forEach(PsiUtilCore::ensureValid);
|
||||
|
||||
PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
PsiModificationTracker tracker = getTracker();
|
||||
long javaCount = tracker.getJavaStructureModificationCount();
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||
@@ -529,4 +530,41 @@ public class PsiModificationTrackerTest extends CodeInsightTestCase {
|
||||
assertFalse(javaCount == tracker.getJavaStructureModificationCount());
|
||||
}
|
||||
|
||||
public void testDeleteLocalClass() {
|
||||
PsiFile file = configureByText(JavaFileType.INSTANCE, "class A{ void bar() {\n" +
|
||||
"abstract class Local { abstract void foo(); }\n" +
|
||||
"int a = 1;" +
|
||||
"while (true) {\n" +
|
||||
"Local r = new Local() {\n" +
|
||||
" public void foo() {}\n" +
|
||||
"}" +
|
||||
"};\n" +
|
||||
"}}");
|
||||
|
||||
PsiAnonymousClass anon = SyntaxTraverser.psiTraverser(file).filter(PsiAnonymousClass.class).first();
|
||||
PsiMethod method = anon.getMethods()[0];
|
||||
|
||||
PsiUtilCore.ensureValid(method);
|
||||
Arrays.stream(method.findSuperMethods()).forEach(PsiUtilCore::ensureValid);
|
||||
|
||||
long javaCount = getTracker().getJavaStructureModificationCount();
|
||||
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||
TextRange localRange = anon.getSuperClass().getTextRange();
|
||||
getEditor().getDocument().deleteString(localRange.getStartOffset(), localRange.getEndOffset());
|
||||
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(getEditor().getDocument());
|
||||
});
|
||||
|
||||
PsiUtilCore.ensureValid(method);
|
||||
Arrays.stream(method.findSuperMethods()).forEach(PsiUtilCore::ensureValid);
|
||||
|
||||
assertFalse(javaCount == getTracker().getJavaStructureModificationCount());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiModificationTracker getTracker() {
|
||||
return PsiManager.getInstance(getProject()).getModificationTracker();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -87,11 +87,13 @@ public abstract class PsiTreeChangePreprocessorBase implements PsiTreeChangePrep
|
||||
protected final boolean isOutOfCodeBlockChangeEvent(@NotNull PsiTreeChangeEventImpl event) {
|
||||
switch (event.getCode()) {
|
||||
case BEFORE_PROPERTY_CHANGE:
|
||||
case BEFORE_CHILD_MOVEMENT:
|
||||
case BEFORE_CHILD_ADDITION:
|
||||
case BEFORE_CHILD_MOVEMENT:
|
||||
return false;
|
||||
|
||||
case BEFORE_CHILD_REMOVAL:
|
||||
case BEFORE_CHILD_REPLACEMENT:
|
||||
return false;
|
||||
return _containsStructuralElements(event.getChild()) || _containsStructuralElements(event.getOldChild());
|
||||
|
||||
case BEFORE_CHILDREN_CHANGE:
|
||||
case CHILDREN_CHANGED:
|
||||
|
||||
Reference in New Issue
Block a user