public LocalSearchScope(@NotNull PsiElement[] scope, @Nullable final String displayName, final boolean ignoreInjectedPsi) { myIgnoreInjectedPsi = ignoreInjectedPsi; myDisplayName = displayName; Set<PsiElement> localScope = new LinkedHashSet<PsiElement>(scope.length); for (final PsiElement element : scope) { LOG.assertTrue(element != null, "null element"); LOG.assertTrue(element.getContainingFile() != null, element.getClass().getName()); if (element instanceof PsiFile) { for (PsiFile file : ((PsiFile)element).getViewProvider().getAllFiles()) { if (file == null) throw new IllegalArgumentException("file "+element+" returned null in its getAllFiles()"); localScope.add(file); } } else if (element instanceof StubBasedPsiElement || element.getTextRange() != null){ localScope.add(element); } } myScope = PsiUtilCore.toPsiElementArray(localScope); }
@Override @Nullable public SmartPointerElementInfo createElementInfo(@NotNull PsiElement element, @NotNull PsiFile containingFile) { if (element instanceof StubBasedPsiElement && containingFile instanceof PsiFileWithStubSupport) { PsiFileWithStubSupport stubFile = (PsiFileWithStubSupport)containingFile; StubTree stubTree = stubFile.getStubTree(); if (stubTree != null) { // use stubs when tree is not loaded StubBasedPsiElement stubPsi = (StubBasedPsiElement)element; int stubId = PsiAnchor.calcStubIndex(stubPsi); IStubElementType myStubElementType = stubPsi.getElementType(); IElementType contentElementType = ((PsiFileImpl)containingFile).getContentElementType(); if (stubId != -1 && contentElementType instanceof IStubFileElementType) { // TemplateDataElementType is not IStubFileElementType return new AnchorElementInfo(element, stubFile, stubId, myStubElementType); } } } PsiElement anchor = getAnchor(element); if (anchor != null) { return new AnchorElementInfo(anchor, containingFile); } return null; }
public PyClass getContainingClass() { final PyFunctionStub stub = getStub(); if (stub != null) { final StubElement parentStub = stub.getParentStub(); if (parentStub instanceof PyClassStub) { return ((PyClassStub)parentStub).getPsi(); } return null; } final PsiElement parent = PsiTreeUtil.getParentOfType(this, StubBasedPsiElement.class); if (parent instanceof PyClass) { return (PyClass)parent; } return null; }
@Nullable private StubElement createStub(StubElement parentStub, ASTNode node) { IElementType nodeType = node.getElementType(); if (nodeType instanceof IStubElementType) { final IStubElementType type = (IStubElementType)nodeType; if (type.shouldCreateStub(node)) { PsiElement element = node.getPsi(); if (!(element instanceof StubBasedPsiElement)) { LOG.error("Non-StubBasedPsiElement requests stub creation. Stub type: " + type + ", PSI: " + element); } @SuppressWarnings("unchecked") StubElement stub = type.createStub(element, parentStub); //noinspection ConstantConditions LOG.assertTrue(stub != null, element); return stub; } } return null; }
@Override public StubBasedPsiElement findStubbedElementAtOffset(final int offset, final Class<? extends StubBasedPsiElement> clazz) { final StubElement stub = getStub(); if(stub != null) { final List<StubElement> children = stub.getChildrenStubs(); for(StubElement child : children) { final PsiElement psi = child.getPsi(); if(psi.getTextRange().getStartOffset() == offset && clazz.isInstance(psi)) { return (StubBasedPsiElement) psi; } } } return null; }
@Nullable @RequiredReadAction public static JavaScriptTypeElement findTypeElement(@NotNull PsiElement element) { if(element instanceof StubBasedPsiElement) { StubElement<?> stub = ((StubBasedPsiElement) element).getStub(); if(stub != null) { List<StubElement> childrenStubs = stub.getChildrenStubs(); for(StubElement childrenStub : childrenStubs) { IStubElementType stubType = childrenStub.getStubType(); if(stubType instanceof BaseJavaScriptElementType) { return (JavaScriptTypeElement) stub.getPsi(); } } } } return findChildrenByClass(element, JavaScriptTypeElement.class); }
@NotNull protected StubElement buildStubTreeFor(@NotNull ASTNode root, @NotNull StubElement parentStub) { Stack<StubElement> parentStubs = new Stack<StubElement>(); Stack<ASTNode> parentNodes = new Stack<ASTNode>(); parentNodes.push(root); parentStubs.push(parentStub); while (!parentStubs.isEmpty()) { StubElement stub = parentStubs.pop(); ASTNode node = parentNodes.pop(); IElementType nodeType = node.getElementType(); if (nodeType instanceof IStubElementType) { final IStubElementType type = (IStubElementType)nodeType; if (type.shouldCreateStub(node)) { PsiElement element = node.getPsi(); if (!(element instanceof StubBasedPsiElement)) { LOG.error("Non-StubBasedPsiElement requests stub creation. Stub type: " + type + ", PSI: " + element); } @SuppressWarnings("unchecked") StubElement s = type.createStub(element, stub); stub = s; LOG.assertTrue(stub != null, element); } } for (ASTNode childNode = node.getLastChildNode(); childNode != null; childNode = childNode.getTreePrev()) { if (!skipChildProcessingWhenBuildingStubs(node, childNode)) { parentNodes.push(childNode); parentStubs.push(stub); } } } return parentStub; }
@Override @NotNull public Collection<AbstractTreeNode> getChildren() { if (ourSettingsModificationCount != modificationCountForChildren) { resetChildren(); modificationCountForChildren = ourSettingsModificationCount; } final Object o = unwrapValue(getValue()); long currentStamp = -1; if (o instanceof StubBasedPsiElement && ((StubBasedPsiElement)o).getStub() != null) { currentStamp = ((StubBasedPsiElement)o).getContainingFile().getModificationStamp(); } else if (o instanceof PsiElement && ((PsiElement)o).getNode() instanceof CompositeElement) { currentStamp = ((CompositeElement)((PsiElement)o).getNode()).getModificationCount(); } else if (o instanceof ModificationTracker) { currentStamp = ((ModificationTracker)o).getModificationCount(); } if (childrenStamp != currentStamp) { resetChildren(); childrenStamp = currentStamp; } try { return super.getChildren(); } catch (IndexNotReadyException ignore) { return Collections.emptyList(); } }
@Nullable @Override public PsiElement getContainer(@NotNull PsiElement item) { if (item instanceof PyElement && item instanceof StubBasedPsiElement) { return getContainerByStub((StubBasedPsiElement)item); } return null; }
@Nullable private static PsiElement getContainerByStub(@NotNull StubBasedPsiElement element) { final StubElement stub = element.getStub(); if (stub != null) { final StubElement parentStub = stub.getParentStub(); if (parentStub != null) { return parentStub.getPsi(); } } return null; }
protected StubElement buildStubTreeFor(@NotNull ASTNode root, @NotNull StubElement parentStub) { Stack<StubElement> parentStubs = new Stack<StubElement>(); Stack<ASTNode> parentNodes = new Stack<ASTNode>(); parentNodes.push(root); parentStubs.push(parentStub); while (!parentStubs.isEmpty()) { StubElement stub = parentStubs.pop(); ASTNode node = parentNodes.pop(); IElementType nodeType = node.getElementType(); if (nodeType instanceof IStubElementType) { final IStubElementType type = (IStubElementType)nodeType; if (type.shouldCreateStub(node)) { PsiElement element = node.getPsi(); if (!(element instanceof StubBasedPsiElement)) { LOG.error("Non-StubBasedPsiElement requests stub creation. Stub type: " + type + ", PSI: " + element); } @SuppressWarnings("unchecked") StubElement s = type.createStub(element, stub); stub = s; LOG.assertTrue(stub != null, element); } } for (ASTNode childNode = node.getLastChildNode(); childNode != null; childNode = childNode.getTreePrev()) { if (!skipChildProcessingWhenBuildingStubs(node, childNode)) { parentNodes.push(childNode); parentStubs.push(stub); } } } return parentStub; }
@NotNull public static DotNetType createMaybeStubType(@NotNull Project project, @NotNull String typeText, @Nullable DotNetType oldType) { if(oldType instanceof StubBasedPsiElement) { CSharpFieldDeclaration field = createField(project, typeText + " _dummy"); return field.getType(); } else { CSharpLocalVariableDeclarationStatement statement = (CSharpLocalVariableDeclarationStatement) createStatement(project, typeText + " i;"); CSharpLocalVariable localVariable = statement.getVariables()[0]; return localVariable.getType(); } }
@Override @RequiredReadAction public boolean isMemberInplaceRenameAvailable(PsiElement element, PsiElement context) { if(element instanceof DotNetParameter && element instanceof StubBasedPsiElement) { return true; } if(element instanceof CSharpTypeDeclaration && ((CSharpTypeDeclaration) element).hasModifier(CSharpModifier.PARTIAL)) { return false; } return element instanceof DotNetQualifiedElement && !(element instanceof DotNetNamespaceAsElement); }
public static int countChildrenOfType(@NotNull StubBasedPsiElement<?> psiElement, @NotNull Class<? extends PsiElement> classOfElement) { StubElement stub = psiElement.getStub(); if(stub != null) { return countChildrenOfType(stub, classOfElement); } return countChildrenOfType(psiElement.getNode(), classOfElement); }
public static int countChildrenOfType(@NotNull StubBasedPsiElement<?> psiElement, @NotNull IElementType elementType) { StubElement stub = psiElement.getStub(); if(stub != null) { return countChildrenOfType(stub, elementType); } return countChildrenOfType(psiElement.getNode(), elementType); }
public static int countChildrenOfType(@NotNull StubBasedPsiElement<?> psiElement, @NotNull TokenSet tokenSet) { StubElement stub = psiElement.getStub(); if(stub != null) { return countChildrenOfType(stub, tokenSet); } return countChildrenOfType(psiElement.getNode(), tokenSet); }
@RequiredReadAction public static boolean hasAttribute(@NotNull final PsiElement owner, @NotNull final String qName) { ConcurrentMap<String, CachedValue<Boolean>> map = owner.getUserData(ourAttributesKey); if(map == null) { owner.putUserData(ourAttributesKey, map = new ConcurrentHashMap<String, CachedValue<Boolean>>()); } CachedValue<Boolean> provider = map.get(qName); if(provider != null) { return provider.getValue(); } else { provider = CachedValuesManager.getManager(owner.getProject()).createCachedValue(new CachedValueProvider<Boolean>() { @Nullable @Override @RequiredReadAction public Result<Boolean> compute() { Key key = PsiModificationTracker.MODIFICATION_COUNT; if(owner instanceof StubBasedPsiElement) { key = PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT; } return Result.create(findAttribute(owner, qName) != null, key); } }, false); map.putIfAbsent(qName, provider); return provider.getValue(); } }
StubBasedPsiElement findStubbedElementAtOffset(final int offset, final Class<? extends StubBasedPsiElement> clazz);