public boolean isChildOf(@Nullable final WrapImpl wrap, LeafBlockWrapper leaf) { if (getIgnoreParentWraps()) return false; if (leaf != null && myIgnoredWraps != null) { Collection<LeafBlockWrapper> leaves = myIgnoredWraps.get(wrap); if (leaves != null && leaves.contains(leaf)) { return false; } } for (WrapImpl parent : myParents) { if (parent == wrap) return true; if (parent.isChildOf(wrap, leaf)) return true; } return false; }
/** * Allows to register given wrap as a parent of the current wrap. * * <p><code>'Parent'</code> wrap registration here means that {@link #isChildOf(WrapImpl, * LeafBlockWrapper)} returns <code>'true'</code> if given wrap is used as a <code>'parent'</code> * argument. * * @param parent parent wrap to register for the current wrap */ void registerParent(@Nullable WrapImpl parent) { if (parent == this) return; if (parent == null) return; if (parent.isChildOf(this, null)) return; if (myParents == emptyParentsSet) myParents = new HashSet<WrapImpl>(5); myParents.add(parent); }
/** * Wraps given root block and all of its descendants and returns root block wrapper. * * <p>This method performs necessary infrastructure actions and delegates actual processing to * {@link #buildCompositeBlock(Block, CompositeBlockWrapper, int, WrapImpl, boolean)} and {@link * #processSimpleBlock(Block, CompositeBlockWrapper, boolean, int, Block)}. * * @param rootBlock block to wrap * @param index index of the current block at its parent block. <code>-1</code> may be used here * if we don't have information about parent block * @param parent parent block wrapper. <code>null</code> may be used here we no parent block * wrapper exists * @param currentWrapParent parent wrap if any; <code>null</code> otherwise * @param parentBlock parent block of the block to wrap * @param rootBlockIsRightBlock flag that shows if target block is the right-most block * @return wrapper for the given <code>'rootBlock'</code> */ private AbstractBlockWrapper buildFrom( final Block rootBlock, final int index, @Nullable final CompositeBlockWrapper parent, @Nullable WrapImpl currentWrapParent, @Nullable final Block parentBlock, boolean rootBlockIsRightBlock) { final WrapImpl wrap = (WrapImpl) rootBlock.getWrap(); if (wrap != null) { wrap.registerParent(currentWrapParent); currentWrapParent = wrap; } TextRange textRange = rootBlock.getTextRange(); final int blockStartOffset = textRange.getStartOffset(); if (parent != null) { if (textRange.getStartOffset() < parent.getStartOffset()) { assertInvalidRanges( textRange.getStartOffset(), parent.getStartOffset(), myModel, "child block start is less than parent block start"); } if (textRange.getEndOffset() > parent.getEndOffset()) { assertInvalidRanges( textRange.getEndOffset(), parent.getEndOffset(), myModel, "child block end is after parent block end"); } } myCurrentWhiteSpace.append(blockStartOffset, myModel, myOptions); if (myCollectAlignmentsInsideFormattingRange && rootBlock.getAlignment() != null && isAffectedByFormatting(rootBlock) && !myInsideFormatRestrictingTag) { myAlignmentsInsideRangeToModify.add(rootBlock.getAlignment()); } if (rootBlock.getAlignment() != null) { myBlocksToAlign.putValue(rootBlock.getAlignment(), rootBlock); } ReadOnlyBlockInformationProvider previousProvider = myReadOnlyBlockInformationProvider; try { if (rootBlock instanceof ReadOnlyBlockInformationProvider) { myReadOnlyBlockInformationProvider = (ReadOnlyBlockInformationProvider) rootBlock; } if (isInsideFormattingRanges(rootBlock, rootBlockIsRightBlock) || myCollectAlignmentsInsideFormattingRange && isInsideExtendedAffectedRange(rootBlock)) { final List<Block> subBlocks = rootBlock.getSubBlocks(); if (subBlocks.isEmpty() || myReadOnlyBlockInformationProvider != null && myReadOnlyBlockInformationProvider.isReadOnly(rootBlock)) { final AbstractBlockWrapper wrapper = processSimpleBlock(rootBlock, parent, false, index, parentBlock); if (!subBlocks.isEmpty()) { wrapper.setIndent((IndentImpl) subBlocks.get(0).getIndent()); } return wrapper; } return buildCompositeBlock( rootBlock, parent, index, currentWrapParent, rootBlockIsRightBlock); } else { // block building is skipped return processSimpleBlock(rootBlock, parent, true, index, parentBlock); } } finally { myReadOnlyBlockInformationProvider = previousProvider; } }