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" /**
* jsdoc-style comment
* */
* 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;
}
Aggregations