diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaCompilerElementRetriever.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaCompilerElementRetriever.java index 0e46ea92dfea..207d0112276c 100644 --- a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaCompilerElementRetriever.java +++ b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/JavaCompilerElementRetriever.java @@ -23,14 +23,13 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiAnonymousClass; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFunctionalExpression; -import com.intellij.psi.impl.java.stubs.PsiClassStub; -import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.psi.impl.source.Constants; import com.intellij.psi.impl.source.PsiFileWithStubSupport; +import com.intellij.psi.impl.source.StubbedSpine; import com.intellij.psi.impl.source.tree.JavaElementType; -import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.stubs.StubTree; import com.intellij.psi.tree.TokenSet; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; @@ -48,18 +47,14 @@ public class JavaCompilerElementRetriever { @NotNull static PsiFunctionalExpression[] retrieveFunExpressionsByIndices(@NotNull TIntHashSet indices, @NotNull PsiFileWithStubSupport psiFile) { - StubTree tree = psiFile.getStubTree(); - boolean foreign = tree == null; - if (foreign) { - tree = ((PsiFileImpl)psiFile).calcStubTree(); - } + StubbedSpine spine = psiFile.getStubbedSpine(); PsiFunctionalExpression[] result = new PsiFunctionalExpression[indices.size()]; int resIdx = 0; int funExprIdx = 0; - for (StubElement element : tree.getPlainList()) { - if (FUN_EXPR.contains(element.getStubType()) && indices.contains(funExprIdx++)) { - result[resIdx++] = (PsiFunctionalExpression)element.getPsi(); + for (int i = 0; i < spine.getStubCount(); i++) { + if (FUN_EXPR.contains(spine.getStubType(i)) && indices.contains(funExprIdx++)) { + result[resIdx++] = (PsiFunctionalExpression)spine.getStubPsi(i); } } @@ -88,7 +83,7 @@ public class JavaCompilerElementRetriever { } private interface InternalNameMatcher { - boolean matches(PsiClassStub stub); + boolean matches(PsiClass psiClass); class ByName implements InternalNameMatcher { private final String myName; @@ -96,8 +91,8 @@ public class JavaCompilerElementRetriever { public ByName(String name) {myName = name;} @Override - public boolean matches(PsiClassStub stub) { - return myName.equals(stub.getName()); + public boolean matches(PsiClass psiClass) { + return myName.equals(psiClass.getName()); } } @@ -107,8 +102,8 @@ public class JavaCompilerElementRetriever { public ByQualifiedName(String name) {myQName = name;} @Override - public boolean matches(PsiClassStub stub) { - return myQName.equals(stub.getQualifiedName()); + public boolean matches(PsiClass psiClass) { + return myQName.equals(psiClass.getQualifiedName()); } } } @@ -127,35 +122,32 @@ public class JavaCompilerElementRetriever { private PsiClass[] retrieveClasses(PsiFileWithStubSupport file) { - StubTree tree = file.getStubTree(); - boolean foreign = tree == null; - if (foreign) { - tree = ((PsiFileImpl)file).calcStubTree(); - } + StubbedSpine spine = file.getStubbedSpine(); List result = new ArrayList<>(myClassNameMatchers.size() + (myAnonymousIndices == null ? 0 : myAnonymousIndices.size())); int anonymousId = 0; - for (StubElement element : tree.getPlainList()) { - if (element instanceof PsiClassStub) { - if (((PsiClassStub)element).isAnonymous()) { + for (int i = 0; i < spine.getStubCount(); i++) { + if (Constants.CLASS_BIT_SET.contains(spine.getStubType(i))) { + PsiClass element = (PsiClass)spine.getStubPsi(i); + if (element instanceof PsiAnonymousClass) { if (myAnonymousIndices != null && !myAnonymousIndices.isEmpty()) { if (myAnonymousIndices.contains(anonymousId)) { - result.add((PsiClass)element.getPsi()); + result.add(element); } anonymousId++; } } - else if (match((PsiClassStub)element, myClassNameMatchers)) { - result.add((PsiClass)element.getPsi()); + else if (match(element, myClassNameMatchers)) { + result.add(element); } } } return result.toArray(PsiClass.EMPTY_ARRAY); } - private static boolean match(PsiClassStub stub, Collection matchers) { + private static boolean match(PsiClass psiClass, Collection matchers) { for (InternalNameMatcher matcher : matchers) { - if (matcher.matches(stub)) { + if (matcher.matches(psiClass)) { //qualified name is unique among file's classes if (matcher instanceof InternalNameMatcher.ByQualifiedName) { matchers.remove(matcher); diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/AnchorRepository.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/AnchorRepository.java index cd3a8bccf079..09a4e3376240 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/AnchorRepository.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/AnchorRepository.java @@ -22,10 +22,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; -import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.PsiFileWithStubSupport; -import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.stubs.StubTree; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.IntIntHashMap; import gnu.trove.TByteArrayList; @@ -33,8 +30,6 @@ import gnu.trove.TIntArrayList; import gnu.trove.TIntIntHashMap; import org.jetbrains.annotations.NotNull; -import java.util.List; - /** * @author peter */ @@ -97,30 +92,10 @@ class AnchorRepository { static PsiClass retrieveClass(@NotNull Project project, int fileId, int stubId) { PsiFile psiFile = PsiManager.getInstance(project).findFile(retrieveFile(fileId)); assert psiFile != null : anchorToString(stubId, fileId); - PsiElement element = restoreFromStubIndex((PsiFileWithStubSupport)psiFile, stubId); + PsiElement element = ((PsiFileWithStubSupport)psiFile).getStubbedSpine().getStubPsi(stubId); if (!(element instanceof PsiClass)) { throw new AssertionError(anchorToString(stubId, fileId) + "; " + psiFile); } return (PsiClass)element; } - - private static PsiElement restoreFromStubIndex(PsiFileWithStubSupport fileImpl, int index) { - StubTree tree = fileImpl.getStubTree(); - if (tree == null) { - if (fileImpl instanceof PsiFileImpl) { - tree = ((PsiFileImpl)fileImpl).calcStubTree(); - } - else { - return null; - } - } - - List> list = tree.getPlainList(); - if (index >= list.size()) { - return null; - } - - return ((StubElement)list.get(index)).getPsi(); - } - } diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/test/TestStubHierarchyAction.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/test/TestStubHierarchyAction.java index bc2b0c8f350a..771c45366293 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/test/TestStubHierarchyAction.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/test/TestStubHierarchyAction.java @@ -24,15 +24,10 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.CommonClassNames; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiTypeParameter; -import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.psi.*; import com.intellij.psi.impl.source.PsiFileWithStubSupport; +import com.intellij.psi.impl.source.StubbedSpine; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.stubs.StubTree; import com.intellij.psi.stubsHierarchy.ClassHierarchy; import com.intellij.psi.stubsHierarchy.HierarchyService; import com.intellij.psi.stubsHierarchy.SmartClassAnchor; @@ -51,7 +46,7 @@ public class TestStubHierarchyAction extends InheritanceAction { public void actionPerformed(AnActionEvent e) { final Project project = e.getData(CommonDataKeys.PROJECT); if (project != null) { - ProgressManager.getInstance().runProcessWithProgressSynchronously((Runnable)() -> ReadAction.run(new TestHierarchy(project)::run), + ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> ReadAction.run(new TestHierarchy(project)::run), "Testing Hierarchy", true, project); } } @@ -89,8 +84,9 @@ public class TestStubHierarchyAction extends InheritanceAction { } private void checkFile(MultiMap supers, ClassHierarchy hierarchy, VirtualFile vFile) { - for (StubElement element : getStubTree(vFile).getPlainListFromAllRoots()) { - Object psi = element.getPsi(); + StubbedSpine spine = getStubTree(vFile); + for (int i = 0; i < spine.getStubCount(); i++) { + PsiElement psi = spine.getStubPsi(i); if (psi instanceof PsiClass && !(psi instanceof PsiTypeParameter)) { SmartClassAnchor anchor = hierarchy.findAnchor((PsiClass)psi); if (anchor == null) { @@ -116,11 +112,10 @@ public class TestStubHierarchyAction extends InheritanceAction { } @NotNull - private StubTree getStubTree(VirtualFile vFile) { + private StubbedSpine getStubTree(VirtualFile vFile) { PsiFileWithStubSupport psiFile = (PsiFileWithStubSupport)PsiManager.getInstance(myProject).findFile(vFile); assert psiFile != null : "No PSI for " + vFile; - StubTree stubTree = psiFile.getStubTree(); - return stubTree != null ? stubTree : ((PsiFileImpl)psiFile).calcStubTree(); + return psiFile.getStubbedSpine(); } private void compareSupers(final SmartClassAnchor anchor, final Collection superAnchors) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java index f78a18d33b05..e156a47a2832 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java @@ -52,6 +52,7 @@ import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.PsiFileWithStubSupport; import com.intellij.psi.impl.source.SourceTreeToPsiMap; +import com.intellij.psi.impl.source.StubbedSpine; import com.intellij.psi.impl.source.resolve.FileContextUtil; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.TreeElement; @@ -561,6 +562,12 @@ public class ClsFileImpl extends ClsRepositoryPsiElement return null; } + @NotNull + @Override + public StubbedSpine getStubbedSpine() { + return getStubTree().getSpine(); + } + @Override public boolean isContentsLoaded() { return myStub != null; diff --git a/java/java-psi-impl/src/com/intellij/psi/stub/JavaStubImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/stub/JavaStubImplUtil.java index 9b997c580403..d8c197c65ee9 100644 --- a/java/java-psi-impl/src/com/intellij/psi/stub/JavaStubImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/stub/JavaStubImplUtil.java @@ -15,31 +15,27 @@ */ package com.intellij.psi.stub; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.PsiMethodImpl; +import com.intellij.psi.impl.source.StubbedSpine; import com.intellij.psi.impl.source.tree.JavaElementType; -import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.stubs.StubTree; -import com.intellij.util.ArrayUtil; public class JavaStubImplUtil { public static int getMethodStubIndex(PsiMethod method) { if (!(method instanceof PsiMethodImpl)) return -1; PsiFileImpl file = (PsiFileImpl)method.getContainingFile(); - if (file.getElementTypeForStubBuilder() == null) return -1; - StubTree stubTree = file.getStubTree(); - if (stubTree == null) { - stubTree = file.calcStubTree(); - } + StubbedSpine spine = file.getStubbedSpine(); - PsiElement[] stubs = stubTree - .getPlainList() - .stream() - .filter(e -> e.getStubType() == JavaElementType.METHOD) - .map(StubElement::getPsi) - .toArray(PsiElement[]::new); - return ArrayUtil.indexOf(stubs, method); + int result = 0; + for (int i = 0; i < spine.getStubCount(); i++) { + if (spine.getStubType(i) == JavaElementType.METHOD) { + if (spine.getStubPsi(i) == method) { + return result; + } + result++; + } + } + return -1; } } diff --git a/platform/core-impl/src/com/intellij/psi/PsiAnchor.java b/platform/core-impl/src/com/intellij/psi/PsiAnchor.java index 1e2bc94c4f10..8e6a6a4622c5 100644 --- a/platform/core-impl/src/com/intellij/psi/PsiAnchor.java +++ b/platform/core-impl/src/com/intellij/psi/PsiAnchor.java @@ -33,19 +33,16 @@ import com.intellij.psi.impl.smartPointers.SelfElementInfo; import com.intellij.psi.impl.smartPointers.SmartPointerAnchorProvider; import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.impl.source.PsiFileWithStubSupport; -import com.intellij.psi.impl.source.tree.CompositeElement; -import com.intellij.psi.impl.source.tree.FileElement; +import com.intellij.psi.impl.source.StubbedSpine; import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.stubs.StubTree; import com.intellij.psi.tree.IStubFileElementType; import com.intellij.psi.util.PsiUtilCore; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; import java.util.Set; /** @@ -167,8 +164,7 @@ public abstract class PsiAnchor { return ((StubBase)liveStub).id; } - PsiFileImpl file = (PsiFileImpl)psi.getContainingFile(); - return file.calcTreeElement().getStubbedDescendants().indexOf((CompositeElement)psi.getNode()); + return ((PsiFileImpl)psi.getContainingFile()).calcTreeElement().getStubbedSpine().getStubIndex(psi); } private static class TreeRangeReference extends PsiAnchor { @@ -400,51 +396,20 @@ public abstract class PsiAnchor { if (throwIfNull) throw new AssertionError("Null file"); return null; } - StubTree tree = fileImpl.getStubTree(); - if (tree != null) { - return findByStubs(index, elementType, throwIfNull, tree); - } - - if (fileImpl instanceof PsiFileImpl) { - return findByAst(index, elementType, throwIfNull, ((PsiFileImpl)fileImpl).calcTreeElement()); - } - else { - if (throwIfNull) throw new AssertionError("Not PsiFileImpl: " + fileImpl.getClass()); - return null; - } - } - @Nullable - private static PsiElement findByStubs(int index, @NotNull IStubElementType elementType, boolean throwIfNull, StubTree tree) { - List> list = tree.getPlainList(); - if (index >= list.size()) { - if (throwIfNull) throw new AssertionError("Too large index: " + index + ">=" + list.size()); - return null; - } - StubElement stub = list.get(index); - - if (stub.getStubType() != elementType) { - if (throwIfNull) throw new AssertionError("Element type mismatch: " + stub.getStubType() + "!=" + elementType); + StubbedSpine spine = fileImpl.getStubbedSpine(); + StubBasedPsiElement psi = spine.getStubPsi(index); + if (psi == null) { + if (throwIfNull) throw new AssertionError("Too large index: " + index + ">=" + spine.getStubCount()); return null; } - return stub.getPsi(); - } - @Nullable - private static PsiElement findByAst(int index, @NotNull IStubElementType elementType, boolean throwIfNull, FileElement tree) { - List list = tree.getStubbedDescendants(); - if (index >= list.size()) { - if (throwIfNull) throw new AssertionError("Too large index: " + index + ">=" + list.size()); - return null; - } - CompositeElement node = list.get(index); - - if (node.getElementType() != elementType) { - if (throwIfNull) throw new AssertionError("Element type mismatch: " + node.getElementType() + "!=" + elementType); + if (psi.getElementType() != elementType) { + if (throwIfNull) throw new AssertionError("Element type mismatch: " + psi.getElementType() + "!=" + elementType); return null; } - return node.getPsi(); + return psi; } public static class StubIndexReference extends PsiAnchor { 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 14817553e1e8..28866280f025 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 @@ -238,6 +238,13 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF return findTreeForStub(ast, stubs, stub); } + @NotNull + @Override + public StubbedSpine getStubbedSpine() { + StubTree tree = getGreenStubTree(); + return tree != null ? tree.getSpine() : calcTreeElement().getStubbedSpine(); + } + @Nullable private static ASTNode findTreeForStub(ASTNode tree, final Iterator> stubs, final StubElement stub) { final IElementType type = tree.getElementType(); diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileWithStubSupport.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileWithStubSupport.java index 89a5db223365..6ff3d2e123cb 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileWithStubSupport.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileWithStubSupport.java @@ -24,6 +24,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubTree; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -44,4 +45,10 @@ public interface PsiFileWithStubSupport extends PsiFile { */ @Nullable ASTNode findTreeForStub(StubTree tree, StubElement stub); + + /** + * @return StubbedSpine for accessing stubbed PSI, which can be backed up by stubs or AST + */ + @NotNull + StubbedSpine getStubbedSpine(); } \ No newline at end of file diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/StubbedSpine.java b/platform/core-impl/src/com/intellij/psi/impl/source/StubbedSpine.java new file mode 100644 index 000000000000..0be5b73b54c8 --- /dev/null +++ b/platform/core-impl/src/com/intellij/psi/impl/source/StubbedSpine.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.impl.source; + +import com.intellij.psi.StubBasedPsiElement; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.Nullable; + +/** + * Represents the list of stubbed PSI elements in the file, backed by either AST or stubs. + */ +public interface StubbedSpine { + + /** @return the number of stubbed elements */ + int getStubCount(); + + /** @return the stubbed PSI element at the given index or null if index is greater than the spine size */ + @Nullable + StubBasedPsiElement getStubPsi(int index); + + /** + * @return the stubbed PSI element's type at the given index or null if index is greater than the spine size. + * This method avoids PSI element allocation if possible. + */ + @Nullable + IElementType getStubType(int index); +} diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/AstSpine.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/AstSpine.java new file mode 100644 index 000000000000..1ca5ddf18706 --- /dev/null +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/AstSpine.java @@ -0,0 +1,62 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.impl.source.tree; + +import com.intellij.psi.StubBasedPsiElement; +import com.intellij.psi.impl.source.StubbedSpine; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +/** + * @author peter + */ +public class AstSpine implements StubbedSpine { + static final AstSpine EMPTY_SPINE = new AstSpine(Collections.emptyList()); + private final List myNodes; + + AstSpine(@NotNull List nodes) { + myNodes = nodes; + } + + @Override + public int getStubCount() { + return myNodes.size(); + } + + @Nullable + @Override + public StubBasedPsiElement getStubPsi(int index) { + return index >= myNodes.size() ? null : (StubBasedPsiElement)myNodes.get(index).getPsi(); + } + + public int getStubIndex(@NotNull StubBasedPsiElement psi) { + return myNodes.indexOf((CompositeElement)psi.getNode()); + } + + @Nullable + @Override + public IElementType getStubType(int index) { + return index >= myNodes.size() ? null : myNodes.get(index).getElementType(); + } + + List getNodes() { + return myNodes; + } +} diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java index db27a442560d..60988897c194 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/FileElement.java @@ -34,14 +34,13 @@ import org.jetbrains.annotations.NotNull; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Collections; import java.util.List; public class FileElement extends LazyParseableElement implements FileASTNode, Getter { public static final FileElement[] EMPTY_ARRAY = new FileElement[0]; private volatile CharTable myCharTable = new CharTableImpl(); private volatile boolean myDetached; - private volatile Reference> myStubbedDescendants; + private volatile Reference myStubbedSpine; @Override protected PsiElement createPsiNoLock() { @@ -104,18 +103,18 @@ public class FileElement extends LazyParseableElement implements FileASTNode, Ge @Override public void clearCaches() { super.clearCaches(); - myStubbedDescendants = null; + myStubbedSpine = null; } @NotNull - public final List getStubbedDescendants() { - List result = SoftReference.dereference(myStubbedDescendants); + public final AstSpine getStubbedSpine() { + AstSpine result = SoftReference.dereference(myStubbedSpine); if (result == null) { IStubFileElementType type = ((PsiFileImpl)getPsi()).getElementTypeForStubBuilder(); - if (type == null) return Collections.emptyList(); + if (type == null) return AstSpine.EMPTY_SPINE; - result = calcStubbedDescendants(type.getBuilder()); - myStubbedDescendants = getManager().isBatchFilesProcessingMode() ? new WeakReference<>(result) : new SoftReference<>(result); + result = new AstSpine(calcStubbedDescendants(type.getBuilder())); + myStubbedSpine = getManager().isBatchFilesProcessingMode() ? new WeakReference<>(result) : new SoftReference<>(result); } return result; } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java index 4798266e8325..a6ee984780a4 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java @@ -462,7 +462,7 @@ public class TreeUtil { @NotNull public static List> calcStubAstBindings(@NotNull StubTree stubTree, @NotNull FileElement tree) throws StubBindingException { PsiFile file = (PsiFile)tree.getPsi(); - List nodes = tree.getStubbedDescendants(); + List nodes = tree.getStubbedSpine().getNodes(); List> stubs = stubTree.getPlainList(); if (stubs.size() != nodes.size()) { throw new StubBindingException("Stub list in " + file.getName() + " length differs from PSI"); diff --git a/platform/core-impl/src/com/intellij/psi/stubs/StubSpine.java b/platform/core-impl/src/com/intellij/psi/stubs/StubSpine.java new file mode 100644 index 000000000000..ce9d5ee219a3 --- /dev/null +++ b/platform/core-impl/src/com/intellij/psi/stubs/StubSpine.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.stubs; + +import com.intellij.psi.StubBasedPsiElement; +import com.intellij.psi.impl.source.StubbedSpine; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author peter + */ +class StubSpine implements StubbedSpine { + private final StubTree myTree; + + StubSpine(@NotNull StubTree tree) { + myTree = tree; + } + + @Override + public int getStubCount() { + return myTree.getPlainList().size(); + } + + @Nullable + @Override + public StubBasedPsiElement getStubPsi(int index) { + List> stubs = myTree.getPlainList(); + return index >= stubs.size() ? null : (StubBasedPsiElement)stubs.get(index).getPsi(); + } + + @Nullable + @Override + public IElementType getStubType(int index) { + List> stubs = myTree.getPlainList(); + return index >= stubs.size() ? null : stubs.get(index).getStubType(); + } +} 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 fe3161994d6a..7ad83b011c6c 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java @@ -19,14 +19,14 @@ */ package com.intellij.psi.stubs; -import com.intellij.util.Function; +import com.intellij.psi.impl.source.StubbedSpine; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import java.util.Collection; import java.util.List; public class StubTree extends ObjectStubTree> { + private final StubSpine mySpine = new StubSpine(this); public StubTree(@NotNull final PsiFileStub root) { this(root, true); @@ -54,4 +54,9 @@ public class StubTree extends ObjectStubTree> { public PsiFileStub getRoot() { return (PsiFileStub)myRoot; } + + @NotNull + public StubbedSpine getSpine() { + return mySpine; + } }