/*
* Copyright 2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.build.docs.dsl.docbook;
import org.gradle.internal.UncheckedException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Extracts the main description of a javadoc comment from its raw text, as a stream of characters. See
* http://download.oracle.com/javase/1.5.0/docs/tooldocs/solaris/javadoc.html#documentationcomments for details.
*
* <ul>
* <li>Removes leading '*' characters.</li>
* <li>Removes block tags.</li>
* <li>Removes leading and trailing empty lines.</li>
* </ul>
*/
class JavadocScanner {
private final StringBuilder input = new StringBuilder();
private int pos;
private int markPos;
JavadocScanner(String rawCommentText) {
pushText(rawCommentText);
}
@Override
public String toString() {
return input.substring(pos);
}
public boolean isEmpty() {
return pos == input.length();
}
public void mark() {
markPos = pos;
}
public void next() {
next(1);
}
public void next(int n) {
pos += n;
}
public boolean lookingAt(char c) {
return input.charAt(pos) == c;
}
public boolean lookingAt(CharSequence prefix) {
int i = 0;
int cpos = pos;
while (i < prefix.length() && cpos < input.length()) {
if (prefix.charAt(i) != input.charAt(cpos)) {
return false;
}
i++;
cpos++;
}
return true;
}
public boolean lookingAt(Pattern pattern) {
Matcher m = pattern.matcher(input);
m.region(pos, input.length());
return m.lookingAt();
}
public String region() {
return input.substring(markPos, pos);
}
/**
* Moves the position to the next instance of the given character, or the end of the input if not found.
*/
public void find(char c) {
int cpos = pos;
while (cpos < input.length()) {
if (input.charAt(cpos) == c) {
break;
}
cpos++;
}
pos = cpos;
}
/**
* Moves the position to the start of the next instance of the given pattern, or the end of the input if not
* found.
*/
public void find(Pattern pattern) {
Matcher m = pattern.matcher(input);
m.region(pos, input.length());
if (m.find()) {
pos = m.start();
} else {
pos = input.length();
}
}
/**
* Moves the position over the given pattern if currently looking at the pattern. Does nothing if not.
*/
public void skip(Pattern pattern) {
Matcher m = pattern.matcher(input);
m.region(pos, input.length());
if (m.lookingAt()) {
pos = m.end();
}
}
public void pushText(String rawCommentText) {
if (rawCommentText == null) {
return;
}
StringBuilder builder = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new StringReader(rawCommentText));
String line;
while ((line = reader.readLine()) != null) {
line = line.replaceFirst("\\s*\\* ?", "");
if (line.startsWith("@")) {
// Ignore the tag section of the comment
break;
}
builder.append(line);
builder.append("\n");
}
} catch (IOException e) {
throw UncheckedException.throwAsUncheckedException(e);
}
input.insert(pos, builder.toString().trim());
}
public char getFirst() {
return input.charAt(pos);
}
}