/** * Returns the extended start position of the given node. Unlike {@link ASTNode#getStart()} and * {@link ASTNode#getLength()}, the extended source range may include comments and whitespace * immediately before or after the normal source range for the node. * * @param node the node * @return the 0-based character index, or <code>-1</code> if no source position information is * recorded for this node * @see #getExtendedLength(ASTNode) * @since 3.0 */ public int getExtendedStartPosition(ASTNode node) { if (this.leadingPtr >= 0) { long range = -1; for (int i = 0; range < 0 && i <= this.leadingPtr; i++) { if (this.leadingNodes[i] == node) range = this.leadingIndexes[i]; } if (range >= 0) { return this.comments[(int) (range >> 32)].getStart(); } } return node.getStart(); }
@Override public Object getReducedValue( final Object ctx, final Object thisValue, final VariableResolverFactory factory) { try { final String i = String.valueOf(soundslike.getReducedValue(ctx, thisValue, factory)); if (i == null) { throw new ClassCastException(); } final String x = (String) stmt.getReducedValue(ctx, thisValue, factory); if (x == null) { throw new CompileException("not a string: " + stmt.getName(), stmt.getExpr(), getStart()); } return similarity(i, x); } catch (final ClassCastException e) { throw new CompileException( "not a string: " + soundslike.getName(), soundslike.getExpr(), soundslike.getStart()); } }
protected void addError(String msg, ASTNode expr) { int line = expr.getLineNumber(); int col = expr.getColumnNumber(); // GRECLIPSE int start = expr.getStart(); int end = expr.getEnd() - 1; if (expr instanceof ClassNode) { // assume we have a class declaration ClassNode cn = (ClassNode) expr; if (cn.getNameEnd() > 0) { start = cn.getNameStart(); end = cn.getNameEnd(); } else if (cn.getComponentType() != null) { // avoid extra whitespace after closing ] end--; } } else if (expr instanceof DeclarationExpression) { // assume that we just want to underline the variable declaration DeclarationExpression decl = (DeclarationExpression) expr; Expression lhs = decl.getLeftExpression(); start = lhs.getStart(); // avoid extra space before = if a variable end = lhs instanceof VariableExpression ? start + lhs.getText().length() - 1 : lhs.getEnd() - 1; } // end SourceUnit source = getSourceUnit(); source .getErrorCollector() .addErrorAndContinue( // GRECLIPSE: start new SyntaxErrorMessage( new PreciseSyntaxException(msg + '\n', line, col, start, end), source) // end ); }
protected boolean apply(ASTNode node) { // Get default previous end ASTNode parent = node.getParent(); int previousEnd = parent.getStart(); // Look for sibling node ASTNode sibling = parent == this.topSiblingParent ? (ASTNode) this.siblings[this.siblingPtr] : null; if (sibling != null) { // Found one previous sibling, so compute its trailing comments // using current node start position try { previousEnd = storeTrailingComments( sibling, node.getStart(), false, this.parentLineRange[this.siblingPtr]); } catch (Exception ex) { // Give up extended ranges at this level if unexpected // exception happens... } } // Stop visit for malformed node (see bug // https://bugs.eclipse.org/bugs/show_bug.cgi?id=84049) if (node.getType() == ASTNode.AST_ERROR) { return false; } // Compute leading comments for current node int[] previousLineRange = this.siblingPtr > -1 ? this.parentLineRange[this.siblingPtr] : new int[] {1, DefaultCommentMapper.this.document.getNumberOfLines()}; try { storeLeadingComments(node, previousEnd, previousLineRange); } catch (Exception ex) { // Give up extended ranges at this level if unexpected exception // happens... } // Store current node as waiting sibling for its parent if (this.topSiblingParent != parent) { if (this.siblings.length == ++this.siblingPtr) { System.arraycopy( this.siblings, 0, this.siblings = new ASTNode[this.siblingPtr * 2], 0, this.siblingPtr); System.arraycopy( this.parentLineRange, 0, this.parentLineRange = new int[this.siblingPtr * 2][], 0, this.siblingPtr); } if (this.topSiblingParent == null) { // node is a CompilationUnit this.parentLineRange[this.siblingPtr] = previousLineRange; } else { int parentStart = parent.getStart(); int firstLine = getLineNumber(parentStart, previousLineRange); int lastLine = getLineNumber(parentStart + parent.getLength() - 1, previousLineRange); if (this.parentLineRange[this.siblingPtr] == null) { this.parentLineRange[this.siblingPtr] = new int[] {firstLine, lastLine}; } else { int[] lineRange = this.parentLineRange[this.siblingPtr]; lineRange[0] = firstLine; lineRange[1] = lastLine; } } this.topSiblingParent = parent; } this.siblings[this.siblingPtr] = node; // We're always ok to visit sub-levels return true; }
/** * Search and store node leading comments. Comments are searched in position range from previous * extended position to node start position. If one or several comment are found, returns first * comment start position, otherwise returns node start position. * * <p>Starts to search for first comment before node start position and return if none was * found... * * <p>When first comment is found before node, goes up in comment list until one of following * conditions becomes true: * * <ol> * <li>comment end is before previous end * <li>comment start and previous end is on the same line but not on same line of node start * <li>there's other than white characters between current node and comment * <li>TODO : there's more than 1 line between current node and comment * </ol> * * If some comment have been found, then no token should be on on the same line before, so remove * all comments which do not verify this assumption. * * <p>If finally there's leading still comments, then stores indexes of the first and last one in * leading comments table. */ int storeLeadingComments(ASTNode node, int previousEnd, int[] parentLineRange) { // Init extended position int nodeStart = node.getStart(); int extended = nodeStart; // Get line of node start position int previousEndLine = getLineNumber(previousEnd, parentLineRange); int nodeStartLine = getLineNumber(nodeStart, parentLineRange); // Find first comment index int idx = getCommentIndex(0, nodeStart, -1); if (idx == -1) { return nodeStart; } // Look after potential comments int startIdx = -1; int endIdx = idx; int previousStart = nodeStart; while (idx >= 0 && previousStart >= previousEnd) { // Verify for each comment that there's only white spaces between // end and start of {following comment|node} Comment comment = this.comments[idx]; int commentStart = comment.getStart(); int end = commentStart + comment.getLength() - 1; int commentLine = getLineNumber(commentStart, parentLineRange); if (end <= previousEnd || (commentLine == previousEndLine && commentLine != nodeStartLine)) { // stop search on condition 1) and 2) break; } else if ((end + 1) < previousStart) { // may be equals => then no // scan is necessary try { resetTo(end + 1, previousStart); this.scanner.next_token(); String token = this.scanner.yytext(); if (token != null && token.trim().length() > 0) { // stop search on condition 3) // if first comment fails, then there's no extended // position in fact if (idx == endIdx) { return nodeStart; } break; } } catch (Exception e) { // Should not happen, but return no extended position... assert false; return nodeStart; } } // Store previous infos previousStart = commentStart; startIdx = idx--; } if (startIdx != -1) { // Store leading comments indexes if (startIdx <= endIdx) { if (++this.leadingPtr == 0) { this.leadingNodes = new ASTNode[STORAGE_INCREMENT]; this.leadingIndexes = new long[STORAGE_INCREMENT]; } else if (this.leadingPtr == this.leadingNodes.length) { int newLength = (this.leadingPtr * 3 / 2) + STORAGE_INCREMENT; System.arraycopy( this.leadingNodes, 0, this.leadingNodes = new ASTNode[newLength], 0, this.leadingPtr); System.arraycopy( this.leadingIndexes, 0, this.leadingIndexes = new long[newLength], 0, this.leadingPtr); } this.leadingNodes[this.leadingPtr] = node; this.leadingIndexes[this.leadingPtr] = (((long) startIdx) << 32) + endIdx; extended = this.comments[endIdx].getStart(); } } return extended; }