| /*=============================================================================# |
| # Copyright (c) 2014, 2020 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.redocs.r.core.source; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.Region; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| |
| import org.eclipse.statet.ecommons.text.core.sections.DocContentSections; |
| import org.eclipse.statet.ecommons.text.core.treepartitioner.TreePartitionNode; |
| import org.eclipse.statet.ecommons.text.core.treepartitioner.TreePartitionUtils; |
| |
| import org.eclipse.statet.r.core.source.IRDocumentConstants; |
| |
| |
| @NonNullByDefault |
| public class RweaveDocSectionTreePartImpl { |
| |
| |
| private final DocContentSections sections; |
| |
| |
| public RweaveDocSectionTreePartImpl(final DocContentSections sections) { |
| this.sections= sections; |
| } |
| |
| |
| public DocContentSections getSections() { |
| return this.sections; |
| } |
| |
| public @Nullable TreePartitionNode getRChunkRegion(final IDocument document, final int offset) |
| throws BadLocationException { |
| return TreePartitionUtils.searchNode(document, this.sections.getPartitioning(), offset, false, |
| RweaveDocumentConstants.RCHUNK_BASE_CONTENT_TYPE ); |
| } |
| |
| public List<TreePartitionNode> getRChunkRegions(final IDocument document, |
| final int offset, final int length) throws BadLocationException { |
| final List<TreePartitionNode> nodes= new ArrayList<>(); |
| final TreePartitionNode root= TreePartitionUtils.getRootNode(document, this.sections.getPartitioning()); |
| |
| addRChunkRegions(root, offset, offset + length, nodes); |
| |
| return nodes; |
| } |
| |
| private void addRChunkRegions(final TreePartitionNode node, final int startOffset, final int endOffset, |
| final List<TreePartitionNode> nodes) { |
| final int childCount= node.getChildCount(); |
| int childIdx= 0; |
| for (; childIdx < childCount; childIdx++) { |
| final TreePartitionNode child= node.getChild(childIdx); |
| if (child.getEndOffset() > startOffset) { |
| break; |
| } |
| } |
| for (; childIdx < childCount; childIdx++) { |
| final TreePartitionNode child= node.getChild(childIdx); |
| if (child.getStartOffset() >= endOffset) { |
| break; |
| } |
| if (child.getType().getPartitionType() == RweaveDocumentConstants.RCHUNK_BASE_CONTENT_TYPE) { |
| nodes.add(child); |
| } |
| else { |
| addRChunkRegions(child, startOffset, endOffset, nodes); |
| } |
| } |
| } |
| |
| public @Nullable IRegion getRChunkContentRegion(final IDocument document, final int offset) |
| throws BadLocationException { |
| final TreePartitionNode rChunk= getRChunkRegion(document, offset); |
| if (rChunk == null || rChunk.getLength() <= 2) { |
| return null; |
| } |
| final int beginLine= document.getLineOfOffset(rChunk.getStartOffset()) + 1; |
| final int beginLineOffset= document.getLineOffset(beginLine); |
| int endLine= document.getLineOfOffset(rChunk.getEndOffset()); |
| if (beginLine >= endLine) { |
| return null; |
| } |
| int endLineOffset= document.getLineOffset(endLine); |
| if (endLineOffset == rChunk.getEndOffset()) { |
| endLine--; |
| if (beginLine >= endLine) { |
| return null; |
| } |
| endLineOffset= document.getLineOffset(endLine); |
| } |
| |
| if (document.getChar(endLineOffset) == '@') { // closed |
| return new Region(beginLineOffset, endLineOffset - beginLineOffset); |
| } |
| else { // node closed |
| return new Region(beginLineOffset, rChunk.getEndOffset() - beginLineOffset); |
| } |
| } |
| |
| public List<TreePartitionNode> getRChunkCodeRegions(final IDocument document, |
| final int offset, final int length) throws BadLocationException { |
| final List<TreePartitionNode> rChunks= getRChunkRegions(document, offset, length); |
| final List<TreePartitionNode> nodes= new ArrayList<>(rChunks.size()); |
| |
| final int endOffset= offset + length; |
| for (int i= 0; i < rChunks.size(); i++) { |
| final TreePartitionNode node= rChunks.get(i); |
| final int childCount= node.getChildCount(); |
| int childIdx= 0; |
| for (; childIdx < childCount; childIdx++) { |
| final TreePartitionNode child= node.getChild(childIdx); |
| if (child.getEndOffset() > offset) { |
| break; |
| } |
| } |
| for (; childIdx < childCount; childIdx++) { |
| final TreePartitionNode child= node.getChild(childIdx); |
| if (child.getStartOffset() >= endOffset) { |
| break; |
| } |
| if (child.getType().getPartitionType() == IRDocumentConstants.R_DEFAULT_CONTENT_TYPE) { |
| nodes.add(child); |
| } |
| } |
| } |
| |
| return nodes; |
| } |
| |
| public @Nullable TreePartitionNode getRCodeRegion(final IDocument document, final int offset) |
| throws BadLocationException { |
| return TreePartitionUtils.searchNode(document, this.sections.getPartitioning(), offset, true, |
| IRDocumentConstants.R_DEFAULT_CONTENT_TYPE ); |
| } |
| |
| } |