* @param originalEnd the offset in the original source of the last character that was modified
*/
@SuppressWarnings("unchecked")
public <E extends AstNode> E reparse(E originalStructure, Token leftToken, Token rightToken,
int originalStart, int originalEnd) {
AstNode oldNode = null;
AstNode newNode = null;
//
// Find the first token that needs to be re-parsed.
//
Token firstToken = leftToken.getNext();
if (firstToken == rightToken) {
// If there are no new tokens, then we need to include at least one copied node in the range.
firstToken = leftToken;
}
//
// Find the smallest AST node that encompasses the range of re-scanned tokens.
//
if (originalEnd < originalStart) {
oldNode = new NodeLocator(originalStart).searchWithin(originalStructure);
} else {
oldNode = new NodeLocator(originalStart, originalEnd).searchWithin(originalStructure);
}
//
// Find the token at which parsing is to begin.
//
int originalOffset = oldNode.getOffset();
Token parseToken = findTokenAt(firstToken, originalOffset);
if (parseToken == null) {
return null;
}
//
// Parse the appropriate AST structure starting at the appropriate place.
//
Parser parser = new Parser(source, errorListener);
parser.setCurrentToken(parseToken);
while (newNode == null) {
AstNode parent = oldNode.getParent();
if (parent == null) {
parseToken = findFirstToken(parseToken);
parser.setCurrentToken(parseToken);
return (E) parser.parseCompilationUnit();
}
boolean advanceToParent = false;
try {
IncrementalParseDispatcher dispatcher = new IncrementalParseDispatcher(parser, oldNode);
newNode = parent.accept(dispatcher);
//
// Validate that the new node can replace the old node.
//
Token mappedToken = tokenMap.get(oldNode.getEndToken().getNext());
if (mappedToken == null