use of org.eclipse.xtext.util.ITextRegion in project xtext-eclipse by eclipse.
the class XtextHyperlinkHelper method createHyperlinksByOffset.
@Override
public void createHyperlinksByOffset(XtextResource resource, int offset, IHyperlinkAcceptor acceptor) {
super.createHyperlinksByOffset(resource, offset, acceptor);
EObject objectAtOffset = eObjectAtOffsetHelper.resolveElementAt(resource, offset);
if (objectAtOffset instanceof AbstractRule) {
ITextRegion nameLocation = locationInFileProvider.getSignificantTextRegion(objectAtOffset, XtextPackage.Literals.ABSTRACT_RULE__NAME, 0);
if (nameLocation != null && nameLocation.contains(offset)) {
AbstractRule rule = (AbstractRule) objectAtOffset;
createLinksToBase(nameLocation, rule, acceptor);
if (rule.getType() != null && rule.getType().getClassifier() != null && NodeModelUtils.getNode(rule.getType()) == null) {
createHyperlinksTo(resource, toRegion(nameLocation), rule.getType().getClassifier(), acceptor);
}
}
}
}
use of org.eclipse.xtext.util.ITextRegion in project n4js by eclipse.
the class PrettyPrinter method print.
/**
* Serialize the intermediate model in the given transpiler state to <code>outCode</code> and emit source maps to
* <code>optSourceMapData</code>.
*
* @param optPreamble
* an optional preamble that will be prepended to the output code. Use '\n' as line separator. If absent,
* no preamble will be prepended.<br>
* If present, a single line break will be used to separate the preamble from the main output, but
* additional line feed characters may be added at the end of the preamble string if empty lines are
* desired between preamble and main output.
*/
public void print(TranspilerState state, Writer outCode, Optional<String> optPreamble, Optional<SourceMapInfo> optSourceMapInfo) throws IOException {
final boolean emitSourceMaps = optSourceMapInfo.isPresent();
final SourceMapAwareAppendable out = new SourceMapAwareAppendable(outCode, INDENT, emitSourceMaps);
if (optPreamble.isPresent()) {
// #append(CharSequence) will convert '\n' to correct line separator
out.append(optPreamble.get());
out.newLine();
}
PrettyPrinterSwitch.append(out, state);
if (emitSourceMaps) {
final SourceMapInfo sourceMapInfo = optSourceMapInfo.get();
final SourceMapGenerator generator = new SourceMapGeneratorDummy();
// append link to source maps to outCode
out.newLine();
out.append("//# sourceMappingURL=" + sourceMapInfo.simpleSourceMapFileName);
out.newLine();
// get the mappings collected by SourceMapAwareAppendable
final List<SourceOutputMapping> mappings = new ArrayList<>(out.getSourceMapData());
// perform some tweaks on the mappings (TEMPORARY)
removeCatchAllMapping(mappings);
sortMappings(mappings);
// Convert the source/output mappings produced by SourceMapAwareAppendable to the API of the
// Google Closure compiler source map library and add them to our SourceMapGenerator 'generator'
final PositionProvider positionProvider = PositionProvider.from(state.resource);
for (SourceOutputMapping m : mappings) {
final EObject originalASTNode = state.tracer.getOriginalASTNode(m.elementInIM);
if (// it's ok if this is null
originalASTNode != null && originalASTNode.eResource() instanceof N4JSResource) {
final ITextRegion region = locationInFileProvider.getSignificantTextRegion(originalASTNode);
// get the resource and compute the path.
final String path = sourceMapInfo.resolve((N4JSResource) originalASTNode.eResource());
final FilePosition sourceStartPosition = positionProvider.toPosition(region.getOffset());
generator.addMapping(path, // TODO source maps: support for original symbol name
null, sourceStartPosition, m.outputStart, m.outputEnd);
}
}
// append actual source maps to the buffer passed in via 'sourceMapInfo'
generator.appendTo(sourceMapInfo.sourceMapBuff, sourceMapInfo.simpleCompiledFileName);
}
}
use of org.eclipse.xtext.util.ITextRegion in project n4js by eclipse.
the class EditorContentExtractor method getDescriptorForSemanticElement.
/**
* Optionally returns with the semantic AST node element (given as the element URI) as a {@link StyledTextDescriptor
* styled text descriptor}. If the element cannot be resolved or the styled text cannot be computed this method
* returns with and {@link Optional#absent() absent} instance but never {@code null}.
*
* @param uri
* the URI of the semantic element in the AST.
* @return a styled text descriptor representing the extracted code for the semantic AST node given with its unique
* URI.
*/
public Optional<StyledTextDescriptor> getDescriptorForSemanticElement(final URI uri) {
if (null == uri) {
return absent();
}
final URI trimmedUri = uri.hasFragment() ? uri.trimFragment() : uri;
final IN4JSProject project = core.findProject(trimmedUri).orNull();
if (project == null) {
return absent();
}
final ResourceSet resSet = core.createResourceSet(Optional.of(project));
final IResourceDescriptions index = core.getXtextIndex(resSet);
final IResourceDescription resDesc = index.getResourceDescription(trimmedUri);
if (null == resDesc) {
return absent();
}
final TModule module = core.loadModuleFromIndex(resSet, resDesc, false);
if (null == module || null == module.eResource() || null == module.eResource().getResourceSet()) {
return absent();
}
final URI moduleUri = module.eResource().getURI();
final IFile file = getWorkspace().getRoot().getFile(new Path(moduleUri.toPlatformString(true)));
if (null == file || !file.exists()) {
return absent();
}
final FileEditorInput editorInput = new FileEditorInput(file);
try {
docProvider.connect(editorInput);
} catch (final CoreException e) {
LOGGER.error("Error while connecting editor input with document provider: " + e);
return absent();
}
final IDocument doc = docProvider.getDocument(editorInput);
if (null == doc) {
return absent();
}
final XtextResource xtextResource = (XtextResource) module.eResource();
final ResourceSet resourceSet = xtextResource.getResourceSet();
final EObject object = resourceSet.getEObject(uri, true);
if (null == object) {
return absent();
}
final ITextRegion textRegion = locationInFileProvider.getFullTextRegion(object);
if (null == textRegion) {
return absent();
}
try {
final int lineOfOffset = doc.getLineOfOffset(textRegion.getOffset());
final int lineOffset = doc.getLineOffset(lineOfOffset);
final int offset = lineOffset;
final int length = textRegion.getLength() + (textRegion.getOffset() - lineOffset);
final String text = doc.get(offset, length);
final IPresentationRepairer repairer = repairerProvider.get();
final IPresentationDamager damager = damagerProvider.get();
for (final String contentType : partitionTypeMapper.getSupportedPartitionTypes()) {
reconciler.setRepairer(repairer, contentType);
repairer.setDocument(doc);
reconciler.setDamager(damager, contentType);
damager.setDocument(doc);
}
final Region region = new Region(offset, length);
final TextPresentation textPresentation = reconciler.createRepairDescription(region, doc);
final Iterator<?> rangeItr = textPresentation.getAllStyleRangeIterator();
final Collection<StyleRange> ranges = newLinkedList();
while (rangeItr.hasNext()) {
final Object next = rangeItr.next();
if (next instanceof StyleRange) {
ranges.add((StyleRange) next);
}
}
final Range<Integer> textRange = Range.closed(offset, offset + length);
for (final Iterator<StyleRange> itr = ranges.iterator(); itr.hasNext(); ) /* nothing */
{
final StyleRange range = itr.next();
if (!textRange.contains(range.start) || !textRange.contains(range.start + range.length)) {
itr.remove();
} else {
range.start = range.start - offset;
}
}
return fromNullable(new StyledTextDescriptorImpl(text, ranges));
} catch (final BadLocationException e) {
LOGGER.error("Error while trying to extract text from document.", e);
return absent();
}
}
use of org.eclipse.xtext.util.ITextRegion in project n4js by eclipse.
the class AstSelectionProvider2 method getSelectedAstElement.
/**
* Tries to retrieve the selected AST element from the resource based on the current selection argument. <br>
* Clients should be aware of the followings:
* <p>
* <ul>
* <li>The {@code currentSelection} will be modified. All leading and trailing whitespace will be truncated and the
* used selection will be based on these modification.</li>
* <li>This method delegates into {@link AstSelectionProvider#getSelectedAstElements(XtextResource, ITextRegion)}
* and returns with the fist AST element.</li>
* <li>If the previous approach did not find a corresponding AST element, then the leaf AST node will be looked up
* by the modified offset. If the leaf node cannot be found or the node cannot be resolved as a semantic object then
* this method will return with {@code null}. If the leaf node exists and a corresponding semantic object was found,
* then this method calculates the {@link ITextRegion region} of the semantic object. For the sake of consistency
* this method seeks the rest of the selection from the end-offset of the semantic object region and the trimmed
* selection based on the passed in argument. If any other object than the already found semantic object can be
* resolved from the rest of the selection this method will return with {@code null}.
* </ul>
* </p>
*
* @param doc
* document to resolve the AST element from.
* @param currentSelection
* the current selection.
* @return the AST element based on the current selection or {@code null} if the AST element cannot be resolved.
*/
public EObject getSelectedAstElement(final IXtextDocument doc, final ITextRegion currentSelection) {
return doc.modify(resource -> {
final String selectedText = doc.get(currentSelection.getOffset(), currentSelection.getLength());
int offset = currentSelection.getOffset();
int length = currentSelection.getLength();
if (!isNullOrEmpty(selectedText)) {
// Initial pessimistic.
boolean containsNonWhiteSpace = false;
for (int i = 0; i < selectedText.length(); i++) {
if (containsNonWhiteSpace) {
break;
}
containsNonWhiteSpace |= !isWhitespace(selectedText.charAt(i));
}
if (!containsNonWhiteSpace) {
return null;
}
// Trim leading white space modify increase offset and shrink length
for (int i = 0; i < selectedText.length(); i++) {
if (isWhitespace(selectedText.charAt(i))) {
offset++;
length--;
} else {
break;
}
}
// Trim trailing whitespace and reduce offset
for (int i = (selectedText.length() - 1); i >= 0; i--) {
if (isWhitespace(selectedText.charAt(i))) {
length--;
} else {
break;
}
}
}
final ITextRegion trimmedRegion = new TextRegion(offset, length);
final String trimmedText = doc.get(offset, length);
// characters such as strings, numbers and underscore from either left or right.
if (isNullOrEmpty(trimmedText)) {
final int leadingCharOffset = 0 == offset ? 0 : offset - 1;
final int trailingCharOffset = leadingCharOffset == doc.getLength() ? doc.getLength() : leadingCharOffset + 1;
final String leadingChar = doc.get(leadingCharOffset, 1);
final String trailingChar = doc.get(trailingCharOffset, 1);
if (!isValidIdentifierChar(leadingChar) && !isValidIdentifierChar(trailingChar)) {
return null;
}
}
final Pair<EObject, EObject> selectedAstElements = getSelectedAstElements(resource, trimmedRegion);
if (null != selectedAstElements) {
return selectedAstElements.getFirst();
}
final IParseResult parseResult = resource.getParseResult();
if (null == parseResult) {
return null;
}
final ILeafNode node = findLeafNodeAtOffset(parseResult.getRootNode(), trimmedRegion.getOffset());
if (null == node) {
return null;
}
final EObject objectAtOffset = findActualSemanticObjectFor(node);
if (null == objectAtOffset) {
return null;
}
final ITextRegion actualTextRegion = getTextRegion(objectAtOffset);
for (int i = actualTextRegion.getOffset() + 1; i < getEndOffset(trimmedRegion); i++) {
final EObject followingObject = offsetHelper.resolveElementAt(resource, i);
if (null == followingObject || objectAtOffset != followingObject) {
return null;
}
}
return objectAtOffset;
});
}
use of org.eclipse.xtext.util.ITextRegion in project dsl-devkit by dsldevkit.
the class RegionNodeModelFormatter method format.
@Override
public IFormattedRegion format(final ICompositeNode root, final int offset, final int length) {
final TokenStringBuffer buf = new TokenStringBuffer();
final ITokenStream out = offset == 0 ? buf : new FilterStream(buf);
final ITokenStream formatStream = formatter.createFormatterStream(null, out, false);
if (!(formatStream instanceof IDelegatingTokenStream)) {
return super.format(root, offset, length);
}
try {
ITextRegion range;
if (offset > 0) {
// Keep the new line
int noffset = root.getText().lastIndexOf('\n', offset) + 1;
// Always start in the beginning of the line
int nlength = length + (offset - noffset);
range = nodeModelStreamer.feedTokenStream(formatStream, root, noffset, nlength);
} else {
range = nodeModelStreamer.feedTokenStream(formatStream, root, offset, length);
}
return new FormattedRegion(range.getOffset(), range.getLength(), buf.toString());
} catch (IOException e) {
// NOPMD
throw new RuntimeException(e);
}
}
Aggregations