/** * Returns a list of {@link VarComment}s within a specified start and end offsets. * * @param comments A sorted list of comments * @param start * @param end */ public static List<VarComment> findTypedVarComments(List<Comment> comments, int start, int end) { List<VarComment> result = new LinkedList<VarComment>(); // locate the last comment in the given list and create a result list from all the VarComments // on top of it, // till we hit the start offset. // We use a linked list to append comments at the start of the result with better performance. int commentIndex = findUpperComment(comments, end); if (commentIndex < 0) { // The nearest comment we found should always have a negative value, as it should never // overlap with the // given offset commentIndex = -commentIndex - 1; } if (commentIndex >= comments.size()) { // off bounds return result; } for (; commentIndex > -1; commentIndex--) { Comment comment = comments.get(commentIndex); if (comment.getStart() < start) { break; } if (comment instanceof VarComment) { result.add(0, (VarComment) comment); } } return result; }
private Collection<Task> processCommentNode( final Program program, final String source, final boolean isCaseSensitive, final Collection<TaskTag> tags, final Comment commentNode) { Collection<Task> tasks = new ArrayList<Task>(); // Explicitly make copies of substrings here and with message to avoid holding ref to underlying // char[] for // entire source string (or full line for message)! String text = new String(source.substring(commentNode.getStart(), commentNode.getEnd() + 1)); if (!isCaseSensitive) { text = text.toLowerCase(); } int offset = 0; String[] lines = NEWLINE_SPLIT.split(text); for (String line : lines) { for (TaskTag entry : tags) { String tag = entry.getName(); if (!isCaseSensitive) { tag = tag.toLowerCase(); } int index = line.indexOf(tag); if (index == -1) { continue; } String message = line.substring(index).trim(); // Remove "**/" from the end of the line! if (message.endsWith("**/")) // $NON-NLS-1$ { message = message.substring(0, message.length() - 3).trim(); } // Remove "*/" from the end of the line! if (message.endsWith("*/")) // $NON-NLS-1$ { message = message.substring(0, message.length() - 2).trim(); } int start = commentNode.getStart() + offset + index; tasks.add( new Task( entry.getName(), new String(message), entry.getPriority(), start, start + line.length() - index, program.getLineNumber(start))); } // FIXME If newline is \r\n, this means we're one off per line in our offsets... offset += line.length() + 1; } return tasks; }
/** Perform a binary search for a comment that appears right on top of the given offset */ private static int findUpperComment(List<Comment> comments, int offset) { int low = 0; int high = comments.size() - 1; while (low <= high) { int mid = (low + high) >>> 1; Comment midVal = (Comment) comments.get(mid); int cmp = midVal.getStart() - offset; if (cmp < 0) { low = mid + 1; } else if (cmp > 0) { high = mid - 1; } else { return mid; // key found } } return -low; // key not found. }
/** * Locate a comment that appears right above the given index (separated only with whitespace * chars). * * @param comments * @param offset * @param content * @param type The comment's type (e.g. Comment.TYPE_PHPDOC, Comment.TYPE_PHPDOC, * Comment.TYPE_SINGLE_LINE). -1 for any type. * @return A comment, or null if none was found. */ public static Comment getCommentByType( List<Comment> comments, int offset, String content, int type) { if (comments == null || comments.isEmpty()) { return null; } Comment nearestComment = null; int commentIndex = findUpperComment(comments, offset); if (commentIndex < 0) { // The nearest comment we found should always have a negative value, as it should never // overlap with the // given offset nearestComment = comments.get(-commentIndex - 1); } if (nearestComment == null) { return null; } if (type != -1 && (nearestComment.getCommentType() & type) == 0) { return null; } if (content != null) { // checking if we have anything but whitespace between comment end and // offset if (offset - 2 < 0 || nearestComment.getEnd() >= content.length() || offset - 2 >= content.length()) { return null; } // checking if we have anything but white spaces between comment end and offset for (int i = nearestComment.getEnd() + 1; i < offset - 1; i++) { char ch = content.charAt(i); if (!Character.isWhitespace(ch)) { return null; } } } return nearestComment; }
/** * Performs a binary search for a specific comment. * * @return The index of the comment that holds the offset; In case no such comment exists, the * return value will be <code>(-(insertion point) - 1)</code>. The insertion point is defined * as the point at which a comment would be inserted into the list in case it was matching the * offset. */ public static int findComment(List<Comment> comments, int offset) { int low = 0; int high = comments.size() - 1; while (low <= high) { int mid = (low + high) >> 1; Comment midVal = comments.get(mid); int cmp; if (offset >= midVal.getStart() && offset < midVal.getEnd()) { return mid; // Found the comment! } cmp = midVal.getStart() - offset; if (cmp < 0) { low = mid + 1; } else if (cmp > 0) { high = mid - 1; } } return -(low + 1); // Can't find a match }