private LeafBlockWrapper doProcessSimpleBlock( final Block rootBlock, @Nullable final CompositeBlockWrapper parent, final boolean readOnly, final int index, @Nullable Block parentBlock) { if (!INLINE_TABS_ENABLED && !myCurrentWhiteSpace.containsLineFeeds()) { myCurrentWhiteSpace.setForceSkipTabulationsUsage(true); } final LeafBlockWrapper info = new LeafBlockWrapper( rootBlock, parent, myCurrentWhiteSpace, myModel, myOptions, myPreviousBlock, readOnly); if (index == 0) { info.arrangeParentTextRange(); } switch (myFormatterTagHandler.getFormatterTag(rootBlock)) { case ON: myInsideFormatRestrictingTag = false; break; case OFF: myInsideFormatRestrictingTag = true; break; case NONE: break; } TextRange textRange = rootBlock.getTextRange(); if (textRange.getLength() == 0) { assertInvalidRanges( textRange.getStartOffset(), textRange.getEndOffset(), myModel, "empty block"); } if (myPreviousBlock != null) { myPreviousBlock.setNextBlock(info); } if (myFirstTokenBlock == null) { myFirstTokenBlock = info; } myLastTokenBlock = info; if (currentWhiteSpaceIsReadOnly()) { myCurrentWhiteSpace.setReadOnly(true); } if (myCurrentSpaceProperty != null) { myCurrentWhiteSpace.setIsSafe(myCurrentSpaceProperty.isSafe()); myCurrentWhiteSpace.setKeepFirstColumn(myCurrentSpaceProperty.shouldKeepFirstColumn()); } if (info.isEndOfCodeBlock()) { myCurrentWhiteSpace.setBeforeCodeBlockEnd(true); } info.setSpaceProperty(myCurrentSpaceProperty); myCurrentWhiteSpace = new WhiteSpace(textRange.getEndOffset(), false); if (myInsideFormatRestrictingTag) myCurrentWhiteSpace.setReadOnly(true); myPreviousBlock = info; if (myPositionOfInterest != -1 && (textRange.contains(myPositionOfInterest) || textRange.getEndOffset() == myPositionOfInterest)) { myResult.put(info, rootBlock); if (parent != null) myResult.put(parent, parentBlock); } return info; }
/** * 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; } }