diff --git a/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy b/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy index 484ae3831e1d..4512efb41b41 100644 --- a/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy +++ b/java/java-tests/testSrc/com/intellij/index/IndexTest.groovy @@ -33,6 +33,7 @@ import com.intellij.psi.* import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.impl.PsiManagerEx import com.intellij.psi.impl.file.impl.FileManagerImpl +import com.intellij.psi.impl.source.PsiFileWithStubSupport import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.PsiSearchHelper import com.intellij.testFramework.IdeaTestUtil @@ -359,4 +360,20 @@ public class IndexTest extends JavaCodeInsightFixtureTestCase { assert JavaPsiFacade.getInstance(project).findClass("Foo3", scope) } + public void "test do not collect stub tree while holding stub elements"() throws IOException { + final VirtualFile vFile = myFixture.addClass("class Foo {}").getContainingFile().getVirtualFile(); + + PsiFileWithStubSupport psiFile = getPsiManager().findFile(vFile) as PsiFileWithStubSupport; + assertNotNull(psiFile); + + def clazz = findClass("Foo") + assertNotNull(clazz) + def stubTreeHash = psiFile.getStubTree().hashCode() + + PlatformTestUtil.tryGcSoftlyReachableObjects(); + def stubTree = psiFile.getStubTree() + assertNotNull(stubTree) + assertEquals(stubTreeHash, stubTree.hashCode()) + } + } diff --git a/platform/core-api/src/com/intellij/psi/stubs/PsiFileStub.java b/platform/core-api/src/com/intellij/psi/stubs/PsiFileStub.java index 069c3b38585d..074954604c78 100644 --- a/platform/core-api/src/com/intellij/psi/stubs/PsiFileStub.java +++ b/platform/core-api/src/com/intellij/psi/stubs/PsiFileStub.java @@ -22,7 +22,11 @@ package com.intellij.psi.stubs; import com.intellij.openapi.util.UserDataHolder; import com.intellij.psi.PsiFile; import com.intellij.psi.tree.IStubFileElementType; +import org.jetbrains.annotations.NotNull; public interface PsiFileStub extends StubElement, UserDataHolder { IStubFileElementType getType(); + + @NotNull + PsiFileStub[] getStubRoots(); } diff --git a/platform/core-api/src/com/intellij/psi/stubs/PsiFileStubImpl.java b/platform/core-api/src/com/intellij/psi/stubs/PsiFileStubImpl.java index 2ea7294c59ed..207e7649a3d6 100644 --- a/platform/core-api/src/com/intellij/psi/stubs/PsiFileStubImpl.java +++ b/platform/core-api/src/com/intellij/psi/stubs/PsiFileStubImpl.java @@ -29,6 +29,7 @@ public class PsiFileStubImpl extends StubBase implements P public static final IStubFileElementType TYPE = new IStubFileElementType(Language.ANY); private volatile T myFile; private volatile String myInvalidationReason; + private volatile PsiFileStub[] myStubRoots; public PsiFileStubImpl(final T file) { super(null, null); @@ -64,4 +65,14 @@ public class PsiFileStubImpl extends StubBase implements P public IStubFileElementType getType() { return TYPE; } + + @NotNull + @Override + public PsiFileStub[] getStubRoots() { + return myStubRoots != null ? myStubRoots : new PsiFileStub[]{this}; + } + + public void setStubRoots(@NotNull PsiFileStub[] roots) { + myStubRoots = roots; + } } \ No newline at end of file diff --git a/platform/core-api/src/com/intellij/psi/stubs/StubSerializationHelper.java b/platform/core-api/src/com/intellij/psi/stubs/StubSerializationHelper.java index 4ced12477ba4..bcf65ad79fc2 100644 --- a/platform/core-api/src/com/intellij/psi/stubs/StubSerializationHelper.java +++ b/platform/core-api/src/com/intellij/psi/stubs/StubSerializationHelper.java @@ -78,7 +78,17 @@ public class StubSerializationHelper { FileLocalStringEnumerator storage = new FileLocalStringEnumerator(true); StubOutputStream stubOutputStream = new StubOutputStream(out, storage); - doSerialize(rootStub, stubOutputStream); + if (rootStub instanceof PsiFileStub) { + final PsiFileStub[] roots = ((PsiFileStub)rootStub).getStubRoots(); + DataInputOutputUtil.writeINT(stubOutputStream, roots.length); + for (PsiFileStub root : roots) { + doSerialize(root, stubOutputStream); + } + } + else { + DataInputOutputUtil.writeINT(stubOutputStream, 1); + doSerialize(rootStub, stubOutputStream); + } DataOutputStream resultStream = new DataOutputStream(stream); DataInputOutputUtil.writeINT(resultStream, storage.myStrings.size()); byte[] buffer = IOUtil.allocReadWriteUTFBuffer(); @@ -111,7 +121,24 @@ public class StubSerializationHelper { ++i; } - return deserialize(inputStream, null); + int stubFilesCount = DataInputOutputUtil.readINT(inputStream); + if (stubFilesCount > 1) { + final List stubs = new ArrayList(stubFilesCount); + while (stubFilesCount-- > 0) { + final PsiFileStub fileStub = (PsiFileStub)deserialize(inputStream, null); + stubs.add(fileStub); + } + final PsiFileStub[] stubsArray = stubs.toArray(new PsiFileStub[stubs.size()]); + for (PsiFileStub stub : stubsArray) { + if (stub instanceof PsiFileStubImpl) { + ((PsiFileStubImpl)stub).setStubRoots(stubsArray); + } + } + return stubsArray[0]; + } + else { + return deserialize(inputStream, null); + } } String intern(String str) { diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java index d82c91ae3928..00747fd4460e 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java @@ -678,15 +678,10 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF final VirtualFile vFile = getVirtualFile(); if (!(vFile instanceof VirtualFileWithId)) return null; - final PsiFile stubBindingRoot = getViewProvider().getStubBindingRoot(); - if (stubBindingRoot != this) { - LOG.error("Attempted to create stubs for non-root file: " + this + ", stub binding root: " + stubBindingRoot); - return null; - } - ObjectStubTree tree = StubTreeLoader.getInstance().readOrBuild(getProject(), vFile, this); if (!(tree instanceof StubTree)) return null; StubTree stubHolder = (StubTree)tree; + final List> roots = StubTreeBuilder.getStubbedRoots(getViewProvider()); synchronized (PsiLock.LOCK) { if (getTreeElement() != null) return null; @@ -694,9 +689,17 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF final StubTree derefdOnLock = derefStub(); if (derefdOnLock != null) return derefdOnLock; - //noinspection unchecked - ((StubBase)stubHolder.getRoot()).setPsi(this); - myStub = new SoftReference(stubHolder); + final PsiFileStub[] stubRoots = stubHolder.getRoot().getStubRoots(); + int matchingRoot = 0; + for (Pair root : roots) { + final PsiFileStub matchingStub = stubRoots[matchingRoot++]; + //noinspection unchecked + ((StubBase)matchingStub).setPsi(root.second); + final StubTree stubTree = new StubTree(matchingStub); + stubTree.setDebugInfo("created in getStubTree()"); + if (root.second == this) stubHolder = stubTree; + ((PsiFileImpl)root.second).myStub = new SoftReference(stubTree); + } return stubHolder; } } @@ -780,6 +783,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF public int getStartOffsetInParent() { return calcTreeElement().getStartOffsetInParent(); } + @Override public int getTextOffset() { return calcTreeElement().getTextOffset(); diff --git a/platform/core-impl/src/com/intellij/psi/stubs/CumulativeStubVersion.java b/platform/core-impl/src/com/intellij/psi/stubs/CumulativeStubVersion.java index 0d22e819579f..74e1f63e9900 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/CumulativeStubVersion.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/CumulativeStubVersion.java @@ -25,7 +25,7 @@ import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.IStubFileElementType; public class CumulativeStubVersion { - private static final int VERSION = 27; + private static final int VERSION = 28; public static int getCumulativeVersion() { int version = VERSION; diff --git a/platform/core-impl/src/com/intellij/psi/stubs/ObjectStubTree.java b/platform/core-impl/src/com/intellij/psi/stubs/ObjectStubTree.java index 2d84c928db22..4c47f6791195 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/ObjectStubTree.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/ObjectStubTree.java @@ -30,7 +30,7 @@ import java.util.Map; * Date: 8/3/12 */ public class ObjectStubTree { - private static final Key STUB_TO_TREE_REFERENCE = Key.create("stub to tree reference"); + protected static final Key STUB_TO_TREE_REFERENCE = Key.create("stub to tree reference"); protected final ObjectStubBase myRoot; private String myDebugInfo; protected final List myPlainList = new ArrayList(); @@ -53,12 +53,17 @@ public class ObjectStubTree { return myPlainList; } + @NotNull + public List getPlainListFromAllRoots() { + return getPlainList(); + } + @NotNull public Map> indexStubTree() { StubIndexSink sink = new StubIndexSink(); - - for (int i = 0, plainListSize = myPlainList.size(); i < plainListSize; i++) { - final Stub stub = myPlainList.get(i); + final List plainList = getPlainListFromAllRoots(); + for (int i = 0, plainListSize = plainList.size(); i < plainListSize; i++) { + final Stub stub = plainList.get(i); sink.myStubIdx = i; StubSerializationUtil.getSerializer(stub).indexStub(stub, sink); } @@ -66,11 +71,15 @@ public class ObjectStubTree { return sink.getResult(); } - protected static void enumerateStubs(@NotNull Stub root, @NotNull List result) { - ((ObjectStubBase)root).id = result.size(); + protected void enumerateStubs(@NotNull Stub root, @NotNull List result) { + enumerateStubs(root, result, 0); + } + + protected static void enumerateStubs(@NotNull Stub root, @NotNull List result, int idOffset) { + ((ObjectStubBase)root).id = idOffset + result.size(); result.add(root); for (Stub child : root.getChildrenStubs()) { - enumerateStubs(child, result); + enumerateStubs(child, result, idOffset); } } diff --git a/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java b/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java index 36a855d6458c..16488845acff 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java @@ -19,8 +19,14 @@ */ package com.intellij.psi.stubs; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + public class StubTree extends ObjectStubTree> { public StubTree(@NotNull final PsiFileStub root) { @@ -31,6 +37,41 @@ public class StubTree extends ObjectStubTree> { super((ObjectStubBase)root, withBackReference); } + @Override + protected void enumerateStubs(@NotNull Stub root, @NotNull List result) { + final PsiFileStub[] files = ((PsiFileStub)root).getStubRoots(); + int idOffset = 0; + final List dummyList = new ArrayList(); + for (PsiFileStub file : files) { + if (file == root) break; + final int fileStubsCount; + final ObjectStubTree existingTree = file.getUserData(STUB_TO_TREE_REFERENCE); + if (existingTree != null) { + fileStubsCount = existingTree.getPlainList().size(); + } + else { + dummyList.clear(); + enumerateStubs(file, dummyList, idOffset); + fileStubsCount = dummyList.size(); + } + idOffset += fileStubsCount; + } + enumerateStubs(root, result, idOffset); + } + + @NotNull + @Override + public List> getPlainListFromAllRoots() { + return ContainerUtil.concat(getRoot().getStubRoots(), new Function>>() { + @Override + public Collection> fun(PsiFileStub stub) { + final ObjectStubTree existingTree = stub.getUserData(STUB_TO_TREE_REFERENCE); + //noinspection unchecked + return existingTree != null ? existingTree.getPlainList() : new StubTree(stub, false).getPlainList(); + } + }); + } + @NotNull @Override public PsiFileStub getRoot() { diff --git a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java index 830915968efd..f48bc38de414 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java @@ -20,16 +20,30 @@ import com.intellij.lang.LanguageParserDefinitions; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Trinity; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiFile; import com.intellij.psi.StubBuilder; +import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.IStubFileElementType; +import com.intellij.util.Function; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.FileContent; import com.intellij.util.indexing.FileContentImpl; import com.intellij.util.indexing.IndexingDataKeys; import com.intellij.util.indexing.SubstitutedFileType; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + public class StubTreeBuilder { private static final Key stubElementKey = Key.create("stub.tree.for.file.content"); @@ -59,7 +73,8 @@ public class StubTreeBuilder { CharSequence contentAsText = inputData.getContentAsText(); FileContentImpl fileContent = (FileContentImpl)inputData; PsiFile psi = fileContent.getPsiFileForPsiDependentIndex(); - psi = psi.getViewProvider().getStubBindingRoot(); + final FileViewProvider viewProvider = psi.getViewProvider(); + psi = viewProvider.getStubBindingRoot(); psi.putUserData(IndexingDataKeys.FILE_TEXT_CONTENT_KEY, contentAsText); // if we load AST, it should be easily gc-able. See PsiFileImpl.createTreeElementPointer() @@ -80,11 +95,31 @@ public class StubTreeBuilder { stubFileElementType = null; } if (stubFileElementType != null) { - StubBuilder stubBuilder = stubFileElementType.getBuilder(); + final StubBuilder stubBuilder = stubFileElementType.getBuilder(); if (stubBuilder instanceof LightStubBuilder) { LightStubBuilder.FORCED_AST.set(fileContent.getLighterASTForPsiDependentIndex()); } data = stubBuilder.buildStubTree(psi); + + final List> stubbedRoots = getStubbedRoots(viewProvider); + if (stubbedRoots.size() > 1) { + final List stubs = new ArrayList(stubbedRoots.size()); + stubs.add((PsiFileStub)data); + + for (Pair stubbedRoot : stubbedRoots) { + if (psi == stubbedRoot.second) continue; + final StubElement element = stubbedRoot.first.getBuilder().buildStubTree(stubbedRoot.second); + if (element instanceof PsiFileStub) { + stubs.add((PsiFileStub)element); + } + } + final PsiFileStub[] stubsArray = stubs.toArray(new PsiFileStub[stubs.size()]); + for (PsiFileStub stub : stubsArray) { + if (stub instanceof PsiFileStubImpl) { + ((PsiFileStubImpl)stub).setStubRoots(stubsArray); + } + } + } } } finally { @@ -97,4 +132,37 @@ public class StubTreeBuilder { return data; } } + + /** Order is deterministic. First element matches {@link FileViewProvider#getStubBindingRoot()} */ + @NotNull + public static List> getStubbedRoots(@NotNull FileViewProvider viewProvider) { + final List> roots = + new SmartList>(); + final PsiFile stubBindingRoot = viewProvider.getStubBindingRoot(); + for (Language language : viewProvider.getLanguages()) { + final PsiFile file = viewProvider.getPsi(language); + if (file instanceof PsiFileImpl) { + final IElementType contentType = ((PsiFileImpl)file).getContentElementType(); + if (contentType instanceof IStubFileElementType) { + roots.add(Trinity.create(language, (IStubFileElementType)contentType, file)); + } + } + } + + ContainerUtil.sort(roots, new Comparator>() { + @Override + public int compare(Trinity o1, Trinity o2) { + if (o1.third == stubBindingRoot) return o2.third == stubBindingRoot ? 0 : -1; + else if (o2.third == stubBindingRoot) return 1; + else return StringUtil.compare(o1.first.getID(), o2.first.getID(), false); + } + }); + + return ContainerUtil.map(roots, new Function, Pair>() { + @Override + public Pair fun(Trinity trinity) { + return Pair.create(trinity.second, trinity.third); + } + }); + } } diff --git a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java index 83bd87271fc4..b45be7a17c22 100644 --- a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java +++ b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java @@ -3,17 +3,16 @@ package com.intellij.psi.stubs; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiPlainTextFile; +import com.intellij.psi.*; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.PsiFileWithStubSupport; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IStubFileElementType; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.Processor; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -52,11 +51,12 @@ public abstract class StubProcessingHelperBase { boolean customStubs = false; if (candidatePsiFile != null && !(candidatePsiFile instanceof PsiPlainTextFile)) { - candidatePsiFile = candidatePsiFile.getViewProvider().getStubBindingRoot(); - if (candidatePsiFile instanceof PsiFileWithStubSupport) { - psiFile = (PsiFileWithStubSupport)candidatePsiFile; + final FileViewProvider viewProvider = candidatePsiFile.getViewProvider(); + final PsiFile stubBindingRoot = viewProvider.getStubBindingRoot(); + if (stubBindingRoot instanceof PsiFileWithStubSupport) { + psiFile = (PsiFileWithStubSupport)stubBindingRoot; stubTree = psiFile.getStubTree(); - if (stubTree == null && psiFile instanceof PsiFileImpl) { + if (stubTree == null && psiFile instanceof PsiFileImpl) { IElementType contentElementType = ((PsiFileImpl)psiFile).getContentElementType(); if (contentElementType instanceof IStubFileElementType) { stubTree = ((PsiFileImpl)psiFile).calcStubTree(); @@ -67,6 +67,26 @@ public abstract class StubProcessingHelperBase { } } } + if (!customStubs && stubTree != null) { + final List roots = new SmartList(stubTree.getRoot()); + final List> stubbedRoots = StubTreeBuilder.getStubbedRoots(viewProvider); + for (Pair stubbedRoot : stubbedRoots) { + if (stubbedRoot.second == stubBindingRoot) continue; + if (stubbedRoot.second instanceof PsiFileImpl) { + final StubTree secondaryStubTree = ((PsiFileImpl)stubbedRoot.second).calcStubTree(); + if (secondaryStubTree != null) { + final PsiFileStub root = secondaryStubTree.getRoot(); + roots.add(root); + } + } + } + final PsiFileStub[] rootsArray = roots.toArray(new PsiFileStub[roots.size()]); + for (PsiFileStub root : rootsArray) { + if (root instanceof PsiFileStubImpl) { + ((PsiFileStubImpl)root).setStubRoots(rootsArray); + } + } + } } if (stubTree == null && psiFile == null) { @@ -81,7 +101,7 @@ public abstract class StubProcessingHelperBase { return processor.process((Psi)psiFile); // e.g. dom indices } stubTree = (StubTree)objectStubTree; - final List> plained = stubTree.getPlainList(); + final List> plained = stubTree.getPlainListFromAllRoots(); for (int i = 0, size = value.size(); i < size; i++) { final int stubTreeIndex = value.get(i); if (stubTreeIndex >= plained.size()) { @@ -128,7 +148,7 @@ public abstract class StubProcessingHelperBase { } } else { - final List> plained = stubTree.getPlainList(); + final List> plained = stubTree.getPlainListFromAllRoots(); for (int i = 0, size = value.size(); i < size; i++) { final int stubTreeIndex = value.get(i); if (stubTreeIndex >= plained.size()) { diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index 85d51fce9cc4..f782634897e5 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -348,7 +348,10 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi if (!data.isEmpty()) { final SerializedStubTree stub = data.values().iterator().next(); ObjectStubBase root = (ObjectStubBase)stub.getStub(true); - Map> map = new ObjectStubTree(root, false).indexStubTree(); + + ObjectStubTree objectStubTree = root instanceof PsiFileStub ? new StubTree((PsiFileStub)root, false) : + new ObjectStubTree(root, false); + Map> map = objectStubTree.indexStubTree(); // xxx:fix refs inplace stubTree = (Map)map; diff --git a/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java b/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java index 00f8cfe409eb..2e814f9f2290 100644 --- a/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java +++ b/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java @@ -32,7 +32,7 @@ import com.intellij.psi.impl.source.DummyHolder; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.tree.IFileElementType; +import com.intellij.psi.tree.IStubFileElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.testFramework.LightVirtualFile; import com.intellij.util.CharTable; @@ -46,7 +46,7 @@ import javax.swing.*; /** * @author peter */ -public class TemplateDataElementType extends IFileElementType implements ITemplateDataElementType { +public class TemplateDataElementType extends IStubFileElementType implements ITemplateDataElementType { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.templateLanguages.TemplateDataElementType"); public static final LanguageExtension TREE_PATCHER = new LanguageExtension("com.intellij.lang.treePatcher", new SimpleTreePatcher()); @@ -72,7 +72,8 @@ public class TemplateDataElementType extends IFileElementType implements ITempla public ASTNode parseContents(ASTNode chameleon) { final CharTable table = SharedImplUtil.findCharTableByTree(chameleon); final FileElement treeElement = new DummyHolder(((TreeElement)chameleon).getManager(), null, table).getTreeElement(); - final PsiFile file = (PsiFile)TreeUtil.getFileElement((TreeElement)chameleon).getPsi(); + final FileElement fileElement = TreeUtil.getFileElement((TreeElement)chameleon); + final PsiFile file = (PsiFile)fileElement.getPsi(); PsiFile originalFile = file.getOriginalFile(); final TemplateLanguageFileViewProvider viewProvider = (TemplateLanguageFileViewProvider)originalFile.getViewProvider(); @@ -112,8 +113,10 @@ public class TemplateDataElementType extends IFileElementType implements ITempla DebugUtil.checkTreeStructure(parsed); DebugUtil.checkTreeStructure(treeElement); DebugUtil.checkTreeStructure(chameleon); - DebugUtil.checkTreeStructure(file.getNode()); - DebugUtil.checkTreeStructure(originalFile.getNode()); + if (fileElement != chameleon) { + DebugUtil.checkTreeStructure(file.getNode()); + DebugUtil.checkTreeStructure(originalFile.getNode()); + } return childNode; }