mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
correct event firing when AST has no PSI (EA-111703 - IAE: PsiChangeHandler.$$$reportNull$$$)
This commit is contained in:
@@ -22,6 +22,7 @@ import com.intellij.psi.impl.PsiManagerImpl;
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
|
||||
import com.intellij.psi.impl.source.tree.CompositeElement;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ChangeInfoImpl implements ChangeInfo {
|
||||
@@ -64,12 +65,10 @@ public class ChangeInfoImpl implements ChangeInfo {
|
||||
}
|
||||
|
||||
void fireEvent(int parentStart, PsiFile file, CompositeElement parent) {
|
||||
PsiTreeChangeEventImpl e = new PsiTreeChangeEventImpl(file.getManager());
|
||||
e.setFile(file);
|
||||
e.setOffset(myOffset + parentStart);
|
||||
PsiTreeChangeEventImpl e = createEvent(file, myOffset + parentStart);
|
||||
|
||||
if (myOldChild == myNewChild && myNewChild != null) {
|
||||
childrenChanged(e, myNewChild);
|
||||
childrenChanged(e, myNewChild, myOldLength);
|
||||
}
|
||||
else if (myOldChild != null && myNewChild != null) {
|
||||
childReplaced(e, myOldChild, myNewChild, parent);
|
||||
@@ -82,6 +81,19 @@ public class ChangeInfoImpl implements ChangeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static PsiTreeChangeEventImpl createEvent(PsiFile file, int offset) {
|
||||
PsiTreeChangeEventImpl e = new PsiTreeChangeEventImpl(file.getManager());
|
||||
e.setFile(file);
|
||||
e.setOffset(offset);
|
||||
return e;
|
||||
}
|
||||
|
||||
boolean hasNoPsi() {
|
||||
return myOldChild != null && myOldChild.getPsi() == null ||
|
||||
myNewChild != null && myNewChild.getPsi() == null;
|
||||
}
|
||||
|
||||
private static void childAdded(PsiTreeChangeEventImpl e, TreeElement child, CompositeElement parent) {
|
||||
e.setParent(parent.getPsi());
|
||||
e.setChild(child.getPsi());
|
||||
@@ -104,9 +116,9 @@ public class ChangeInfoImpl implements ChangeInfo {
|
||||
getPsiManagerImpl(e).childReplaced(e);
|
||||
}
|
||||
|
||||
private void childrenChanged(PsiTreeChangeEventImpl e, TreeElement parent) {
|
||||
static void childrenChanged(PsiTreeChangeEventImpl e, TreeElement parent, int oldLength) {
|
||||
e.setParent(parent.getPsi());
|
||||
e.setOldLength(myOldLength);
|
||||
e.setOldLength(oldLength);
|
||||
getPsiManagerImpl(e).childrenChanged(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ public class TreeChangeImpl implements TreeChange, Comparable<TreeChangeImpl> {
|
||||
|
||||
public TreeChangeImpl(@NotNull CompositeElement parent) {
|
||||
myParent = parent;
|
||||
assert myParent.getPsi() != null;
|
||||
mySuperParents = JBIterable.generate(parent.getTreeParent(), TreeElement::getTreeParent).toList();
|
||||
for (TreeElement child : getCurrentChildren()) {
|
||||
myInitialChildren.add(child);
|
||||
@@ -152,7 +153,13 @@ public class TreeChangeImpl implements TreeChange, Comparable<TreeChangeImpl> {
|
||||
|
||||
void fireEvents(PsiFile file) {
|
||||
int start = myParent.getStartOffset();
|
||||
for (ChangeInfoImpl change : getAllChanges().values()) {
|
||||
Collection<ChangeInfoImpl> changes = getAllChanges().values();
|
||||
if (ContainerUtil.exists(changes, c -> c.hasNoPsi())) {
|
||||
ChangeInfoImpl.childrenChanged(ChangeInfoImpl.createEvent(file, start), myParent, myParent.getTextLength() - getLengthDelta());
|
||||
return;
|
||||
}
|
||||
|
||||
for (ChangeInfoImpl change : changes) {
|
||||
change.fireEvent(start, file, myParent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,17 @@ class PsiEventConsistencyTest : LightPlatformCodeInsightFixtureTestCase() {
|
||||
assertEquals(root.text, file.viewProvider.document!!.text)
|
||||
}
|
||||
}
|
||||
|
||||
fun `test changes on AST without PSI`() {
|
||||
val file = createEmptyFile()
|
||||
WriteCommandAction.runWriteCommandAction(project) {
|
||||
val root = file.node as FileElement
|
||||
root.replaceChild(root.firstChildNode, leaf(leafTypes[0], "A"))
|
||||
|
||||
assertEquals("A", root.text)
|
||||
assertEquals(root.text, file.viewProvider.document!!.text)
|
||||
}
|
||||
}
|
||||
|
||||
fun testPsiDocSynchronization() {
|
||||
ImperativeCommand.checkScenarios { RandomAstChanges() }
|
||||
@@ -198,6 +209,13 @@ class PsiEventConsistencyTest : LightPlatformCodeInsightFixtureTestCase() {
|
||||
}
|
||||
|
||||
private fun leaf(type: IElementType, text: String): TreeElement {
|
||||
if (text[0].isUpperCase()) {
|
||||
// no PSI
|
||||
return withDummyHolder(object : LeafElement(type, text) {
|
||||
override fun toString() = text
|
||||
})
|
||||
}
|
||||
|
||||
return withDummyHolder(object : LeafPsiElement(type, text) {
|
||||
override fun toString() = text
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user