Search in sources :

Example 1 with LeafNodeWithSyntaxError

use of org.eclipse.xtext.nodemodel.impl.LeafNodeWithSyntaxError in project n4js by eclipse.

the class N4JSDocumentationProvider method searchLeafNodeDocumentation.

/**
 * This is a fix for shadowed jsdoc-style documentation. Example:
 *
 * <pre>
 * "use strict" /&#42;&#42;
 * jsdoc-style comment
 * &#42;/
 * class A {
 * }
 * </pre>
 *
 * Parsing the snippet above will trigger automatic semicolon insertion (ASI) in the first line. Currently ASI
 * replaces the HiddenLeaf MultiLine comment starting in the same line as the missing ';' by a
 * {@link LeafNodeWithSyntaxError} which is not hidden. It also transfers the "ownership" from the class-node to the
 * directive-statement in the parse-tree. The text of the LeafNodeWithSyntaxError is still the original
 * comment-text.
 *
 * Giving the concrete node for "class A", this method will return the LeafNodeWithSyntaxError representing an ASI
 * and having the textual content of the jsdoc.
 *
 * <p>
 * Looking for lost documentation due to ASI. Goes backward in the AST unless an ASI-modified
 * {@link LeafNodeWithSyntaxError} is encountered.
 *
 * @return A hidden leaf node with jsdoc-documentation or a LeafNodeWithSyntaxError containing the documentation.
 *         {@code null} if no jsdoc-style documentation could be found.
 */
private LeafNode searchLeafNodeDocumentation(ICompositeNode ptNodeOfASTNode) {
    BidiTreeIterator<INode> rootIterator = ptNodeOfASTNode.getRootNode().getAsTreeIterable().iterator();
    // First linearly search the current node, then go back until a documentation or a non-hidden node is
    // encountered.
    // First search:
    int counter = 0;
    // flag for finding right position in iterator.
    boolean found = false;
    while (rootIterator.hasNext()) {
        INode next = rootIterator.next();
        counter++;
        dump(counter, next);
        if (next == ptNodeOfASTNode) {
            found = true;
            break;
        }
    }
    if (!found) {
        throw new IllegalStateException("Node model broken. Unable to find the current node in the node model by traversing from root.");
    }
    // Second search:
    // go back until we find a LeafNodeWithSyntaxErrors or a different non-hidden leaf.
    // .getParent();
    ICompositeNode directParent = ptNodeOfASTNode;
    boolean beforeDirectParentNode = false;
    // direct parent. This is marked in beforDirectParentNode
    while (rootIterator.hasPrevious()) {
        INode prev = rootIterator.previous();
        counter--;
        dump(counter, prev);
        if (!beforeDirectParentNode) {
            if (!hasAsParent(prev, directParent)) {
                beforeDirectParentNode = true;
            } else {
                continue;
            }
        }
        if (prev instanceof LeafNodeWithSyntaxError) {
            if (((LeafNodeWithSyntaxError) prev).getSyntaxErrorMessage().getIssueCode() != InternalSemicolonInjectingParser.SEMICOLON_INSERTED) {
                // Some other error, not ASI, stop looking.
                return null;
            }
            // Two cases can happen:
            // 1) it is a ML-documentation
            // 2) it is a line-break
            // single-line documentations don't match the
            String text = prev.getText();
            if (isDocumentationStyle(text)) {
                // found a documentation
                return (LeafNodeWithSyntaxError) prev;
            } else {
            // not a documentation, then continue
            }
        } else if (prev instanceof LeafNode) {
            LeafNode ln = (LeafNode) prev;
            if (!ln.isHidden()) {
                // found a non-hidden node, stop looking!
                return null;
            } else {
                // hidden leaf-node, check for comment.
                String text = prev.getText();
                if (isDocumentationStyle(text)) {
                    // found a documentation
                    return (LeafNode) prev;
                }
            }
        }
    // other wise keep looking.
    }
    return null;
}
Also used : INode(org.eclipse.xtext.nodemodel.INode) LeafNode(org.eclipse.xtext.nodemodel.impl.LeafNode) ICompositeNode(org.eclipse.xtext.nodemodel.ICompositeNode) LeafNodeWithSyntaxError(org.eclipse.xtext.nodemodel.impl.LeafNodeWithSyntaxError)

Aggregations

ICompositeNode (org.eclipse.xtext.nodemodel.ICompositeNode)1 INode (org.eclipse.xtext.nodemodel.INode)1 LeafNode (org.eclipse.xtext.nodemodel.impl.LeafNode)1 LeafNodeWithSyntaxError (org.eclipse.xtext.nodemodel.impl.LeafNodeWithSyntaxError)1