public CommentsCollection parse(final InputStream in, final String charsetName) throws IOException, UnsupportedEncodingException { boolean lastWasASlashR = false; BufferedReader br = new BufferedReader(new InputStreamReader(in, charsetName)); CommentsCollection comments = new CommentsCollection(); int r; Deque prevTwoChars = new LinkedList<Character>(Arrays.asList('z', 'z')); State state = State.CODE; LineComment currentLineComment = null; BlockComment currentBlockComment = null; StringBuffer currentContent = null; int currLine = 1; int currCol = 1; while ((r = br.read()) != -1) { char c = (char) r; if (c == '\r') { lastWasASlashR = true; } else if (c == '\n' && lastWasASlashR) { lastWasASlashR = false; continue; } else { lastWasASlashR = false; } switch (state) { case CODE: if (prevTwoChars.peekLast().equals('/') && c == '/') { currentLineComment = new LineComment(); currentLineComment.setBeginLine(currLine); currentLineComment.setBeginColumn(currCol - 1); state = State.IN_LINE_COMMENT; currentContent = new StringBuffer(); } else if (prevTwoChars.peekLast().equals('/') && c == '*') { currentBlockComment = new BlockComment(); currentBlockComment.setBeginLine(currLine); currentBlockComment.setBeginColumn(currCol - 1); state = State.IN_BLOCK_COMMENT; currentContent = new StringBuffer(); } else if (c == '"') { state = State.IN_STRING; } else { // nothing to do } break; case IN_LINE_COMMENT: if (c == '\n' || c == '\r') { currentLineComment.setContent(currentContent.toString()); currentLineComment.setEndLine(currLine); currentLineComment.setEndColumn(currCol); comments.addComment(currentLineComment); state = State.CODE; } else { currentContent.append(c); } break; case IN_BLOCK_COMMENT: if (prevTwoChars.peekLast().equals('*') && c == '/' && !prevTwoChars.peekFirst().equals('/')) { // delete last character String content = currentContent.deleteCharAt(currentContent.toString().length() - 1).toString(); if (content.startsWith("*")) { JavadocComment javadocComment = new JavadocComment(); javadocComment.setContent(content.substring(1)); javadocComment.setBeginLine(currentBlockComment.getBeginLine()); javadocComment.setBeginColumn(currentBlockComment.getBeginColumn()); javadocComment.setEndLine(currLine); javadocComment.setEndColumn(currCol + 1); comments.addComment(javadocComment); } else { currentBlockComment.setContent(content); currentBlockComment.setEndLine(currLine); currentBlockComment.setEndColumn(currCol + 1); comments.addComment(currentBlockComment); } state = State.CODE; } else { currentContent.append(c == '\r' ? '\n' : c); } break; case IN_STRING: if (!prevTwoChars.peekLast().equals('\\') && c == '"') { state = State.CODE; } break; default: throw new RuntimeException("Unexpected"); } switch (c) { case '\n': case '\r': currLine += 1; currCol = 1; break; case '\t': currCol += COLUMNS_PER_TAB; break; default: currCol += 1; } prevTwoChars.remove(); prevTwoChars.add(c); } if (state == State.IN_LINE_COMMENT) { currentLineComment.setContent(currentContent.toString()); currentLineComment.setEndLine(currLine); currentLineComment.setEndColumn(currCol); comments.addComment(currentLineComment); } return comments; }
/** * * * <h1>Parse a raw comment.</h1> * * <p>Create an instance the same as the argument comment but with the revision year <br> * updated if needed. Return the default comment if the argument comment is null <br> * or an empty string. * * @param comment the original comment from the file. * @param commentStyle the comment style. {@link CopyrightComment} * @return {@link AdvancedCopyrightComment} an copyright comment with the year updated. */ public static AdvancedCopyrightComment parse(BlockComment commentBock, int commentStyle) { // If the given comment is empty, return the default comment. if (commentBock == null) { return defaultComment(commentStyle); } String comment = commentBock.getContents(); // identify which line delimiter is used. (for writing back to file ) String fileLineDelimiter = TextUtilities.determineLineDelimiter(comment, "\n"); // $NON-NLS-1$ // Split Comment into Seperate lines for easier proccessing: String commentLines[] = comment.split("\\r?\\n"); // $NON-NLS-1$ // lines before the line with the year comment on it. StringBuilder preYearLines = new StringBuilder(); // line with the year(s) on it. 'copyright 2002, 2010-2011 ... etc.. String yearLine = null; // Lines after the line with the year comment on it. StringBuilder postYearLines = new StringBuilder(); // Break down the comment into the three sections. boolean yearFound = false; String line; for (int i = 0; i < commentLines.length; i++) { line = commentLines[i]; // for clarity. if (yearFound) { // We have already found the year line and are just appending the last lines. // Conditionally append a newline delimiter. if (i != (commentLines.length - 1)) { // normally, append a new line. postYearLines.append(line + fileLineDelimiter); } else { // for the last line, only append if the original comment had a newline delimiter. Character lastchar = comment.charAt(comment.length() - 1); if (Character.isWhitespace(lastchar)) { postYearLines.append(line + lastchar); } else { postYearLines.append(line); } } } else if (line.matches(".*" + YEAR_REGEX + ".*")) { // $NON-NLS-1$ //$NON-NLS-2$ // We found the line with the copy-right years on it. yearFound = true; yearLine = line + fileLineDelimiter; } else { // We are parsting the top part of the comment and have not reached the year-line yet. preYearLines.append(line + fileLineDelimiter); } } // The comment didn't contain any years that we can update. if (!yearFound) { return null; } // Determine first year. int createdYear = getFirstYear(yearLine); if (createdYear == 0) { return null; // Failed to read a year. } int yearsOnLine = countYearsOnLine(yearLine); // Determine the last year int revisedYear; if (yearsOnLine == 1) { revisedYear = -1; } else { revisedYear = getLastYear(yearLine); } return new AdvancedCopyrightComment( commentStyle, createdYear, revisedYear, yearsOnLine, preYearLines.toString(), yearLine, postYearLines.toString()); }