blob: a1a1bd4ceb1f81f37158d51c7d72567213a20854 [file] [log] [blame]
/*=============================================================================#
# 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 );
}
}