reparse file after a PSI deletion/replacement which results in whitespaces as outermost children

because reparse from scratch is likely to place those whitespaces somewhere else (e.g. in the parent)
This commit is contained in:
peter
2019-01-04 18:32:08 +01:00
parent 41beeed926
commit 1ddb413043
3 changed files with 33 additions and 7 deletions
@@ -347,6 +347,15 @@ class A {
PsiTestUtil.checkStubsMatchText(file)
}
void "test remove type argument list after space"() {
def file = myFixture.addFileToProject('a.java', 'class A { A <B>a; }')
WriteCommandAction.runWriteCommandAction(project) {
myFixture.findClass("A").fields[0].typeElement.innermostComponentReferenceElement.parameterList.delete()
}
PsiTestUtil.checkStubsMatchText(file)
PsiTestUtil.checkFileStructure(file)
}
void "test add reference into broken extends list"() {
def file = myFixture.addFileToProject('a.java', 'class A extends.ends Foo { int a; }')
WriteCommandAction.runWriteCommandAction(project) {
@@ -40,10 +40,16 @@ public class ChangeInfoImpl implements ChangeInfo {
myNewLength = newChild != null ? newChild.getNotCachedLength() : 0;
}
@Nullable
public TreeElement getOldChild() {
return myOldChild;
}
@Nullable
public TreeElement getNewChild() {
return myNewChild;
}
@Override
public int getChangeType(){
if (myOldChild == myNewChild) return CONTENTS_CHANGED;
@@ -24,6 +24,7 @@ import com.intellij.pom.tree.TreeAspect;
import com.intellij.pom.tree.events.ChangeInfo;
import com.intellij.pom.tree.events.TreeChange;
import com.intellij.pom.tree.events.TreeChangeEvent;
import com.intellij.pom.tree.events.impl.ChangeInfoImpl;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
@@ -164,7 +165,9 @@ public class PostprocessReformattingAspect implements PomModelAspect {
for (final ASTNode node : changeSet.getChangedElements()) {
final TreeChange treeChange = changeSet.getChangesByElement(node);
for (final ASTNode affectedChild : treeChange.getAffectedChildren()) {
scheduleReparseIfNeeded(containingFile, affectedChild);
if (changeMightBreakPsiTextConsistency(treeChange, affectedChild)) {
containingFile.putUserData(REPARSE_PENDING, true);
}
final ChangeInfo childChange = treeChange.getChangeByChild(affectedChild);
switch (childChange.getChangeType()) {
@@ -191,14 +194,22 @@ public class PostprocessReformattingAspect implements PomModelAspect {
}
}
private void scheduleReparseIfNeeded(PsiFile containingFile, ASTNode affectedChild) {
if (changeMightBreakPsiTextConsistency(affectedChild)) {
containingFile.putUserData(REPARSE_PENDING, true);
}
private boolean changeMightBreakPsiTextConsistency(TreeChange treeChange, ASTNode child) {
return TreeUtil.containsOuterLanguageElements(child) ||
isRightAfterErrorElement(child) ||
isBetweenWhitespaceAndEdge(child) && leavesEmptyRange(treeChange, child);
}
private boolean changeMightBreakPsiTextConsistency(ASTNode node) {
return TreeUtil.containsOuterLanguageElements(node) || isRightAfterErrorElement(node);
private boolean leavesEmptyRange(TreeChange treeChange, ASTNode child) {
TreeElement newChild = ((ChangeInfoImpl)treeChange.getChangeByChild(child)).getNewChild();
return newChild == null || newChild.getTextLength() == 0;
}
private boolean isBetweenWhitespaceAndEdge(ASTNode deleted) {
ASTNode prev = deleted.getTreePrev();
ASTNode next = deleted.getTreeNext();
return next == null && prev instanceof PsiWhiteSpace ||
prev == null && next instanceof PsiWhiteSpace;
}
private boolean isRightAfterErrorElement(ASTNode _node) {