Search in sources :

Example 61 with ITextRegion

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);
            }
        }
    }
}
Also used : ITextRegion(org.eclipse.xtext.util.ITextRegion) EObject(org.eclipse.emf.ecore.EObject) AbstractRule(org.eclipse.xtext.AbstractRule)

Example 62 with ITextRegion

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);
    }
}
Also used : SourceMapGeneratorDummy(org.eclipse.n4js.transpiler.sourcemap.SourceMapGeneratorDummy) ArrayList(java.util.ArrayList) FilePosition(org.eclipse.n4js.transpiler.sourcemap.FilePosition) SourceMapInfo(org.eclipse.n4js.transpiler.AbstractTranspiler.SourceMapInfo) SourceOutputMapping(org.eclipse.n4js.transpiler.print.SourceMapAwareAppendable.SourceOutputMapping) ITextRegion(org.eclipse.xtext.util.ITextRegion) EObject(org.eclipse.emf.ecore.EObject) N4JSResource(org.eclipse.n4js.resource.N4JSResource) SourceMapGenerator(org.eclipse.n4js.transpiler.sourcemap.SourceMapGenerator)

Example 63 with ITextRegion

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();
    }
}
Also used : IFile(org.eclipse.core.resources.IFile) IResourceDescription(org.eclipse.xtext.resource.IResourceDescription) StyleRange(org.eclipse.swt.custom.StyleRange) XtextResource(org.eclipse.xtext.resource.XtextResource) URI(org.eclipse.emf.common.util.URI) IPresentationRepairer(org.eclipse.jface.text.presentation.IPresentationRepairer) IN4JSProject(org.eclipse.n4js.projectModel.IN4JSProject) EObject(org.eclipse.emf.ecore.EObject) TModule(org.eclipse.n4js.ts.types.TModule) IPresentationDamager(org.eclipse.jface.text.presentation.IPresentationDamager) TextPresentation(org.eclipse.jface.text.TextPresentation) Path(org.eclipse.core.runtime.Path) ResourceSet(org.eclipse.emf.ecore.resource.ResourceSet) CoreException(org.eclipse.core.runtime.CoreException) ITextRegion(org.eclipse.xtext.util.ITextRegion) IResourceDescriptions(org.eclipse.xtext.resource.IResourceDescriptions) FileEditorInput(org.eclipse.ui.part.FileEditorInput) Region(org.eclipse.jface.text.Region) ITextRegion(org.eclipse.xtext.util.ITextRegion) EObject(org.eclipse.emf.ecore.EObject) IDocument(org.eclipse.jface.text.IDocument) BadLocationException(org.eclipse.jface.text.BadLocationException)

Example 64 with ITextRegion

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;
    });
}
Also used : ILeafNode(org.eclipse.xtext.nodemodel.ILeafNode) TextRegion(org.eclipse.xtext.util.TextRegion) ITextRegion(org.eclipse.xtext.util.ITextRegion) ITextRegion(org.eclipse.xtext.util.ITextRegion) EObject(org.eclipse.emf.ecore.EObject) IParseResult(org.eclipse.xtext.parser.IParseResult)

Example 65 with ITextRegion

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);
    }
}
Also used : ITokenStream(org.eclipse.xtext.parsetree.reconstr.ITokenStream) ITextRegion(org.eclipse.xtext.util.ITextRegion) TokenStringBuffer(org.eclipse.xtext.parsetree.reconstr.impl.TokenStringBuffer) IOException(java.io.IOException)

Aggregations

ITextRegion (org.eclipse.xtext.util.ITextRegion)122 TextRegion (org.eclipse.xtext.util.TextRegion)44 EObject (org.eclipse.emf.ecore.EObject)33 Test (org.junit.Test)20 INode (org.eclipse.xtext.nodemodel.INode)19 XtextResource (org.eclipse.xtext.resource.XtextResource)17 ICompositeNode (org.eclipse.xtext.nodemodel.ICompositeNode)15 ILeafNode (org.eclipse.xtext.nodemodel.ILeafNode)15 BadLocationException (org.eclipse.jface.text.BadLocationException)11 Region (org.eclipse.jface.text.Region)9 XExpression (org.eclipse.xtext.xbase.XExpression)9 IOException (java.io.IOException)8 CoreException (org.eclipse.core.runtime.CoreException)8 IParseResult (org.eclipse.xtext.parser.IParseResult)7 IXtextDocument (org.eclipse.xtext.ui.editor.model.IXtextDocument)7 IRegion (org.eclipse.jface.text.IRegion)6 ITextSelection (org.eclipse.jface.text.ITextSelection)6 Collection (java.util.Collection)5 ArrayList (java.util.ArrayList)4 TextSelection (org.eclipse.jface.text.TextSelection)4