private List<Pair<StubBasedPsiElementBase, CompositeElement>> calcStubAstBindings( final ASTNode root, final Document cachedDocument) { final StubTree stubTree = derefStub(); if (stubTree == null) { return Collections.emptyList(); } final Iterator<StubElement<?>> stubs = stubTree.getPlainList().iterator(); stubs.next(); // Skip file stub; final List<Pair<StubBasedPsiElementBase, CompositeElement>> result = ContainerUtil.newArrayList(); final StubBuilder builder = ((IStubFileElementType) getContentElementType()).getBuilder(); LazyParseableElement.setSuppressEagerPsiCreation(true); try { ((TreeElement) root) .acceptTree( new RecursiveTreeElementWalkingVisitor() { @Override protected void visitNode(TreeElement node) { CompositeElement parent = node.getTreeParent(); if (parent != null && builder.skipChildProcessingWhenBuildingStubs(parent, node)) { return; } IElementType type = node.getElementType(); if (type instanceof IStubElementType && ((IStubElementType) type).shouldCreateStub(node)) { if (!stubs.hasNext()) { reportStubAstMismatch( "Stub list is less than AST, last AST element: " + node.getElementType() + " " + node, stubTree, cachedDocument); } final StubElement stub = stubs.next(); if (stub.getStubType() != node.getElementType()) { reportStubAstMismatch( "Stub and PSI element type mismatch in " + getName() + ": stub " + stub + ", AST " + node.getElementType() + "; " + node, stubTree, cachedDocument); } PsiElement psi = stub.getPsi(); assert psi != null : "Stub " + stub + " (" + stub.getClass() + ") has returned null PSI"; result.add(Pair.create((StubBasedPsiElementBase) psi, (CompositeElement) node)); } super.visitNode(node); } }); } finally { LazyParseableElement.setSuppressEagerPsiCreation(false); } if (stubs.hasNext()) { reportStubAstMismatch( "Stub list in " + getName() + " has more elements than PSI", stubTree, cachedDocument); } return result; }
private static void createActionsMap( final List<ASTNode> astNodes, final FileViewProvider provider, final TreeSet<PostprocessFormattingTask> rangesToProcess) { final Set<ASTNode> nodesToProcess = new HashSet<ASTNode>(astNodes); final Document document = provider.getDocument(); for (final ASTNode node : astNodes) { nodesToProcess.remove(node); final FileElement fileElement = TreeUtil.getFileElement((TreeElement) node); if (fileElement == null || ((PsiFile) fileElement.getPsi()).getViewProvider() != provider) continue; final boolean isGenerated = CodeEditUtil.isNodeGenerated(node); ((TreeElement) node) .acceptTree( new RecursiveTreeElementVisitor() { boolean inGeneratedContext = !isGenerated; protected boolean visitNode(TreeElement element) { if (nodesToProcess.contains(element)) return false; if (CodeEditUtil.isPostponedFormattingDisabled(element)) return false; final boolean currentNodeGenerated = CodeEditUtil.isNodeGenerated(element); CodeEditUtil.setNodeGenerated(element, false); if (currentNodeGenerated && !inGeneratedContext) { rangesToProcess.add( new ReformatTask(document.createRangeMarker(element.getTextRange()))); inGeneratedContext = true; } if (!currentNodeGenerated && inGeneratedContext) { if (element.getElementType() == TokenType.WHITE_SPACE) return false; final int oldIndent = CodeEditUtil.getOldIndentation(element); LOG.assertTrue( oldIndent >= 0, "for not generated items old indentation must be defined: element " + element); rangesToProcess.add( new ReindentTask( document.createRangeMarker(element.getTextRange()), oldIndent)); inGeneratedContext = false; } return true; } @Override public void visitComposite(CompositeElement composite) { boolean oldGeneratedContext = inGeneratedContext; super.visitComposite(composite); inGeneratedContext = oldGeneratedContext; } @Override public void visitLeaf(LeafElement leaf) { boolean oldGeneratedContext = inGeneratedContext; super.visitLeaf(leaf); inGeneratedContext = oldGeneratedContext; } }); CodeEditUtil.enablePostponedFormattingInTree(node); } }
private static void createActionsMap( @NotNull List<ASTNode> astNodes, @NotNull FileViewProvider provider, @NotNull final TreeSet<PostprocessFormattingTask> rangesToProcess) { final Set<ASTNode> nodesToProcess = new HashSet<ASTNode>(astNodes); final Document document = provider.getDocument(); if (document == null) { return; } for (final ASTNode node : astNodes) { nodesToProcess.remove(node); final FileElement fileElement = TreeUtil.getFileElement((TreeElement) node); if (fileElement == null || ((PsiFile) fileElement.getPsi()).getViewProvider() != provider) continue; final boolean isGenerated = CodeEditUtil.isNodeGenerated(node); ((TreeElement) node) .acceptTree( new RecursiveTreeElementVisitor() { boolean inGeneratedContext = !isGenerated; @Override protected boolean visitNode(TreeElement element) { if (nodesToProcess.contains(element)) return false; final boolean currentNodeGenerated = CodeEditUtil.isNodeGenerated(element); CodeEditUtil.setNodeGenerated(element, false); if (currentNodeGenerated && !inGeneratedContext) { rangesToProcess.add( new ReformatTask(document.createRangeMarker(element.getTextRange()))); inGeneratedContext = true; } if (!currentNodeGenerated && inGeneratedContext) { if (element.getElementType() == TokenType.WHITE_SPACE) return false; final int oldIndent = CodeEditUtil.getOldIndentation(element); CodeEditUtil.setOldIndentation(element, -1); LOG.assertTrue( oldIndent >= 0, "for not generated items old indentation must be defined: element " + element); for (TextRange indentRange : getEnabledRanges(element.getPsi())) { rangesToProcess.add( new ReindentTask(document.createRangeMarker(indentRange), oldIndent)); } inGeneratedContext = false; } return true; } private Iterable<TextRange> getEnabledRanges(@NotNull PsiElement element) { List<TextRange> disabledRanges = new ArrayList<TextRange>(); for (DisabledIndentRangesProvider rangesProvider : DisabledIndentRangesProvider.EP_NAME.getExtensions()) { Collection<TextRange> providedDisabledRanges = rangesProvider.getDisabledIndentRanges(element); if (providedDisabledRanges != null) { disabledRanges.addAll(providedDisabledRanges); } } return TextRangeUtil.excludeRanges(element.getTextRange(), disabledRanges); } @Override public void visitComposite(CompositeElement composite) { boolean oldGeneratedContext = inGeneratedContext; super.visitComposite(composite); inGeneratedContext = oldGeneratedContext; } @Override public void visitLeaf(LeafElement leaf) { boolean oldGeneratedContext = inGeneratedContext; super.visitLeaf(leaf); inGeneratedContext = oldGeneratedContext; } }); } }