diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/AstBufferUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/AstBufferUtil.java index 0ce4f8939d27..b8ae62e88c84 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/AstBufferUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/AstBufferUtil.java @@ -30,7 +30,11 @@ public class AstBufferUtil { } public static int toBuffer(ASTNode element, char[] buffer, int offset, TokenSet skipTypes) { - if (element instanceof ForeignLeafPsiElement || skipTypes != null && skipTypes.contains(element.getElementType())) return offset; + if (element instanceof ForeignLeafPsiElement || + skipTypes != null && skipTypes.contains(element.getElementType())) { + return offset; + } + if (element instanceof LeafElement) { return ((LeafElement)element).copyTo(buffer, offset); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java index 527b438002e8..5d3a7f9af145 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java @@ -196,7 +196,7 @@ public class CompositeElement extends TreeElement { @NotNull public char[] textToCharArray() { char[] buffer = new char[getTextLength()]; - AstBufferUtil.toBuffer(this, buffer, 0); + walkCopyingText(buffer); return buffer; } @@ -404,10 +404,10 @@ public class CompositeElement extends TreeElement { if (myCachedLength != NOT_CACHED) { throw new AssertionError("Before walking: cached="+myCachedLength); } - TreeElement cur = this; + TreeElement cur = this; while (cur != null) { - cur = next(cur, cur.getCachedLength() == NOT_CACHED); + cur = next(cur, cur.getCachedLength() == NOT_CACHED, true); } if (myCachedLength < 0) { @@ -415,8 +415,23 @@ public class CompositeElement extends TreeElement { } } + private void walkCopyingText(char[] buffer) { + if (TreeUtil.isCollapsedChameleon(this)) { + AstBufferUtil.toBuffer(this, buffer, 0); + return; + } + + int offset = 0; + TreeElement cur = this; + while ((cur = next(cur, cur instanceof CompositeElement && !TreeUtil.isCollapsedChameleon(cur), false)) != null) { + if (cur instanceof LeafElement || TreeUtil.isCollapsedChameleon(cur)) { + offset = AstBufferUtil.toBuffer(cur, buffer, offset); + } + } + } + @Nullable - private TreeElement next(TreeElement cur, boolean down) { + private TreeElement next(TreeElement cur, boolean down, boolean update) { if (down) { CompositeElement composite = (CompositeElement)cur; // It's a composite or we won't be going down TreeElement child = composite.firstChild; @@ -425,15 +440,19 @@ public class CompositeElement extends TreeElement { return child; } - composite.myCachedLength = 0; + if (update) { + composite.myCachedLength = 0; + } } // up while (cur != this) { CompositeElement parent = cur.getTreeParent(); int curLength = cur.getCachedLength(); - LOG.assertTrue(curLength != NOT_CACHED, cur); - parent.myCachedLength -= curLength; + if (update) { + LOG.assertTrue(curLength != NOT_CACHED, cur); + parent.myCachedLength -= curLength; + } TreeElement next = cur.getTreeNext(); if (next != null) { @@ -442,7 +461,9 @@ public class CompositeElement extends TreeElement { } LOG.assertTrue(parent.lastChild == cur, parent); - parent.myCachedLength = -parent.myCachedLength + NOT_CACHED; + if (update) { + parent.myCachedLength = -parent.myCachedLength + NOT_CACHED; + } cur = parent; } @@ -450,7 +471,6 @@ public class CompositeElement extends TreeElement { return null; } - public TreeElement getFirstChildNode() { return firstChild; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java index 0182f9bb65f1..61ff91733922 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java @@ -186,15 +186,13 @@ public class LazyParseableElement extends CompositeElement { if (parsedNode != null) { rawAddChildren((TreeElement)parsedNode); - /* - if (getTextLength() != text.length()) { - if (ApplicationManagerEx.getApplicationEx().isInternal() && !ApplicationManager.getApplication().isUnitTestMode()) { - LOG.error("Inconsistent reparse: type=" + getElementType() + "; text=" + text + "; treeText=" + getText()); - } else { - LOG.error("Inconsistent reparse: type=" + getElementType()); - } - } - */ + //if (getNotCachedLength() != text.length()) { + // if (ApplicationManagerEx.getApplicationEx().isInternal()) { + // LOG.error("Inconsistent reparse: type=" + getElementType() + "; text=" + text + "; treeText=" + getText()); + // } else { + // LOG.error("Inconsistent reparse: type=" + getElementType()); + // } + //} //ensure PSI is created all at once, to reduce contention of PsiLock in CompositeElement.getPsi() ((TreeElement)parsedNode).acceptTree(CREATE_PSI);