mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
7104201: Refactor DocCommentScanner
Add new Comment helper class to parse contents of comments in source code Reviewed-by: jjg
This commit is contained in:
parent
dae561e3ea
commit
be5a83c8ce
7 changed files with 638 additions and 588 deletions
|
@ -25,10 +25,11 @@
|
||||||
|
|
||||||
package com.sun.tools.javac.parser;
|
package com.sun.tools.javac.parser;
|
||||||
|
|
||||||
import java.nio.CharBuffer;
|
|
||||||
import com.sun.tools.javac.code.Source;
|
import com.sun.tools.javac.code.Source;
|
||||||
|
import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
|
||||||
import com.sun.tools.javac.util.*;
|
import com.sun.tools.javac.util.*;
|
||||||
|
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
|
||||||
import static com.sun.tools.javac.parser.Tokens.*;
|
import static com.sun.tools.javac.parser.Tokens.*;
|
||||||
import static com.sun.tools.javac.util.LayoutCharacters.*;
|
import static com.sun.tools.javac.util.LayoutCharacters.*;
|
||||||
|
@ -65,9 +66,6 @@ public class JavaTokenizer {
|
||||||
*/
|
*/
|
||||||
private final Log log;
|
private final Log log;
|
||||||
|
|
||||||
/** The name table. */
|
|
||||||
private final Names names;
|
|
||||||
|
|
||||||
/** The token factory. */
|
/** The token factory. */
|
||||||
private final Tokens tokens;
|
private final Tokens tokens;
|
||||||
|
|
||||||
|
@ -87,18 +85,12 @@ public class JavaTokenizer {
|
||||||
*/
|
*/
|
||||||
protected int errPos = Position.NOPOS;
|
protected int errPos = Position.NOPOS;
|
||||||
|
|
||||||
/** Has a @deprecated been encountered in last doc comment?
|
/** The Unicode reader (low-level stream reader).
|
||||||
* this needs to be reset by client.
|
|
||||||
*/
|
*/
|
||||||
protected boolean deprecatedFlag = false;
|
|
||||||
|
|
||||||
/** A character buffer for saved chars.
|
|
||||||
*/
|
|
||||||
protected char[] sbuf = new char[128];
|
|
||||||
protected int sp;
|
|
||||||
|
|
||||||
protected UnicodeReader reader;
|
protected UnicodeReader reader;
|
||||||
|
|
||||||
|
protected ScannerFactory fac;
|
||||||
|
|
||||||
private static final boolean hexFloatsWork = hexFloatsWork();
|
private static final boolean hexFloatsWork = hexFloatsWork();
|
||||||
private static boolean hexFloatsWork() {
|
private static boolean hexFloatsWork() {
|
||||||
try {
|
try {
|
||||||
|
@ -129,14 +121,14 @@ public class JavaTokenizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JavaTokenizer(ScannerFactory fac, UnicodeReader reader) {
|
protected JavaTokenizer(ScannerFactory fac, UnicodeReader reader) {
|
||||||
log = fac.log;
|
this.fac = fac;
|
||||||
names = fac.names;
|
this.log = fac.log;
|
||||||
tokens = fac.tokens;
|
this.tokens = fac.tokens;
|
||||||
source = fac.source;
|
this.source = fac.source;
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
allowBinaryLiterals = source.allowBinaryLiterals();
|
this.allowBinaryLiterals = source.allowBinaryLiterals();
|
||||||
allowHexFloats = source.allowHexFloats();
|
this.allowHexFloats = source.allowHexFloats();
|
||||||
allowUnderscoresInLiterals = source.allowUnderscoresInLiterals();
|
this.allowUnderscoresInLiterals = source.allowUnderscoresInLiterals();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Report an error at the given position using the provided arguments.
|
/** Report an error at the given position using the provided arguments.
|
||||||
|
@ -147,38 +139,13 @@ public class JavaTokenizer {
|
||||||
errPos = pos;
|
errPos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read next character in comment, skipping over double '\' characters.
|
|
||||||
*/
|
|
||||||
protected void scanCommentChar() {
|
|
||||||
reader.scanChar();
|
|
||||||
if (reader.ch == '\\') {
|
|
||||||
if (reader.peekChar() == '\\' && !reader.isUnicode()) {
|
|
||||||
reader.skipChar();
|
|
||||||
} else {
|
|
||||||
reader.convertUnicode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Append a character to sbuf.
|
|
||||||
*/
|
|
||||||
private void putChar(char ch) {
|
|
||||||
if (sp == sbuf.length) {
|
|
||||||
char[] newsbuf = new char[sbuf.length * 2];
|
|
||||||
System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
|
|
||||||
sbuf = newsbuf;
|
|
||||||
}
|
|
||||||
sbuf[sp++] = ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Read next character in character or string literal and copy into sbuf.
|
/** Read next character in character or string literal and copy into sbuf.
|
||||||
*/
|
*/
|
||||||
private void scanLitChar(int pos) {
|
private void scanLitChar(int pos) {
|
||||||
if (reader.ch == '\\') {
|
if (reader.ch == '\\') {
|
||||||
if (reader.peekChar() == '\\' && !reader.isUnicode()) {
|
if (reader.peekChar() == '\\' && !reader.isUnicode()) {
|
||||||
reader.skipChar();
|
reader.skipChar();
|
||||||
putChar('\\');
|
reader.putChar('\\', true);
|
||||||
reader.scanChar();
|
|
||||||
} else {
|
} else {
|
||||||
reader.scanChar();
|
reader.scanChar();
|
||||||
switch (reader.ch) {
|
switch (reader.ch) {
|
||||||
|
@ -195,30 +162,30 @@ public class JavaTokenizer {
|
||||||
reader.scanChar();
|
reader.scanChar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
putChar((char)oct);
|
reader.putChar((char)oct);
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
putChar('\b'); reader.scanChar(); break;
|
reader.putChar('\b', true); break;
|
||||||
case 't':
|
case 't':
|
||||||
putChar('\t'); reader.scanChar(); break;
|
reader.putChar('\t', true); break;
|
||||||
case 'n':
|
case 'n':
|
||||||
putChar('\n'); reader.scanChar(); break;
|
reader.putChar('\n', true); break;
|
||||||
case 'f':
|
case 'f':
|
||||||
putChar('\f'); reader.scanChar(); break;
|
reader.putChar('\f', true); break;
|
||||||
case 'r':
|
case 'r':
|
||||||
putChar('\r'); reader.scanChar(); break;
|
reader.putChar('\r', true); break;
|
||||||
case '\'':
|
case '\'':
|
||||||
putChar('\''); reader.scanChar(); break;
|
reader.putChar('\'', true); break;
|
||||||
case '\"':
|
case '\"':
|
||||||
putChar('\"'); reader.scanChar(); break;
|
reader.putChar('\"', true); break;
|
||||||
case '\\':
|
case '\\':
|
||||||
putChar('\\'); reader.scanChar(); break;
|
reader.putChar('\\', true); break;
|
||||||
default:
|
default:
|
||||||
lexError(reader.bp, "illegal.esc.char");
|
lexError(reader.bp, "illegal.esc.char");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (reader.bp != reader.buflen) {
|
} else if (reader.bp != reader.buflen) {
|
||||||
putChar(reader.ch); reader.scanChar();
|
reader.putChar(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +194,7 @@ public class JavaTokenizer {
|
||||||
int savePos;
|
int savePos;
|
||||||
do {
|
do {
|
||||||
if (reader.ch != '_') {
|
if (reader.ch != '_') {
|
||||||
putChar(reader.ch);
|
reader.putChar(false);
|
||||||
} else {
|
} else {
|
||||||
if (!allowUnderscoresInLiterals) {
|
if (!allowUnderscoresInLiterals) {
|
||||||
lexError(pos, "unsupported.underscore.lit", source.name);
|
lexError(pos, "unsupported.underscore.lit", source.name);
|
||||||
|
@ -246,12 +213,10 @@ public class JavaTokenizer {
|
||||||
*/
|
*/
|
||||||
private void scanHexExponentAndSuffix(int pos) {
|
private void scanHexExponentAndSuffix(int pos) {
|
||||||
if (reader.ch == 'p' || reader.ch == 'P') {
|
if (reader.ch == 'p' || reader.ch == 'P') {
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
skipIllegalUnderscores();
|
skipIllegalUnderscores();
|
||||||
if (reader.ch == '+' || reader.ch == '-') {
|
if (reader.ch == '+' || reader.ch == '-') {
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
}
|
}
|
||||||
skipIllegalUnderscores();
|
skipIllegalUnderscores();
|
||||||
if ('0' <= reader.ch && reader.ch <= '9') {
|
if ('0' <= reader.ch && reader.ch <= '9') {
|
||||||
|
@ -268,14 +233,12 @@ public class JavaTokenizer {
|
||||||
lexError(pos, "malformed.fp.lit");
|
lexError(pos, "malformed.fp.lit");
|
||||||
}
|
}
|
||||||
if (reader.ch == 'f' || reader.ch == 'F') {
|
if (reader.ch == 'f' || reader.ch == 'F') {
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
tk = TokenKind.FLOATLITERAL;
|
tk = TokenKind.FLOATLITERAL;
|
||||||
radix = 16;
|
radix = 16;
|
||||||
} else {
|
} else {
|
||||||
if (reader.ch == 'd' || reader.ch == 'D') {
|
if (reader.ch == 'd' || reader.ch == 'D') {
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
}
|
}
|
||||||
tk = TokenKind.DOUBLELITERAL;
|
tk = TokenKind.DOUBLELITERAL;
|
||||||
radix = 16;
|
radix = 16;
|
||||||
|
@ -289,14 +252,12 @@ public class JavaTokenizer {
|
||||||
if ('0' <= reader.ch && reader.ch <= '9') {
|
if ('0' <= reader.ch && reader.ch <= '9') {
|
||||||
scanDigits(pos, 10);
|
scanDigits(pos, 10);
|
||||||
}
|
}
|
||||||
int sp1 = sp;
|
int sp1 = reader.sp;
|
||||||
if (reader.ch == 'e' || reader.ch == 'E') {
|
if (reader.ch == 'e' || reader.ch == 'E') {
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
skipIllegalUnderscores();
|
skipIllegalUnderscores();
|
||||||
if (reader.ch == '+' || reader.ch == '-') {
|
if (reader.ch == '+' || reader.ch == '-') {
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
}
|
}
|
||||||
skipIllegalUnderscores();
|
skipIllegalUnderscores();
|
||||||
if ('0' <= reader.ch && reader.ch <= '9') {
|
if ('0' <= reader.ch && reader.ch <= '9') {
|
||||||
|
@ -304,7 +265,7 @@ public class JavaTokenizer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lexError(pos, "malformed.fp.lit");
|
lexError(pos, "malformed.fp.lit");
|
||||||
sp = sp1;
|
reader.sp = sp1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,13 +275,11 @@ public class JavaTokenizer {
|
||||||
radix = 10;
|
radix = 10;
|
||||||
scanFraction(pos);
|
scanFraction(pos);
|
||||||
if (reader.ch == 'f' || reader.ch == 'F') {
|
if (reader.ch == 'f' || reader.ch == 'F') {
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
tk = TokenKind.FLOATLITERAL;
|
tk = TokenKind.FLOATLITERAL;
|
||||||
} else {
|
} else {
|
||||||
if (reader.ch == 'd' || reader.ch == 'D') {
|
if (reader.ch == 'd' || reader.ch == 'D') {
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
}
|
}
|
||||||
tk = TokenKind.DOUBLELITERAL;
|
tk = TokenKind.DOUBLELITERAL;
|
||||||
}
|
}
|
||||||
|
@ -331,8 +290,7 @@ public class JavaTokenizer {
|
||||||
private void scanHexFractionAndSuffix(int pos, boolean seendigit) {
|
private void scanHexFractionAndSuffix(int pos, boolean seendigit) {
|
||||||
radix = 16;
|
radix = 16;
|
||||||
Assert.check(reader.ch == '.');
|
Assert.check(reader.ch == '.');
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
skipIllegalUnderscores();
|
skipIllegalUnderscores();
|
||||||
if (reader.digit(pos, 16) >= 0) {
|
if (reader.digit(pos, 16) >= 0) {
|
||||||
seendigit = true;
|
seendigit = true;
|
||||||
|
@ -369,8 +327,7 @@ public class JavaTokenizer {
|
||||||
} else if (seendigit && radix == 16 && (reader.ch == 'p' || reader.ch == 'P')) {
|
} else if (seendigit && radix == 16 && (reader.ch == 'p' || reader.ch == 'P')) {
|
||||||
scanHexExponentAndSuffix(pos);
|
scanHexExponentAndSuffix(pos);
|
||||||
} else if (digitRadix == 10 && reader.ch == '.') {
|
} else if (digitRadix == 10 && reader.ch == '.') {
|
||||||
putChar(reader.ch);
|
reader.putChar(true);
|
||||||
reader.scanChar();
|
|
||||||
scanFractionAndSuffix(pos);
|
scanFractionAndSuffix(pos);
|
||||||
} else if (digitRadix == 10 &&
|
} else if (digitRadix == 10 &&
|
||||||
(reader.ch == 'e' || reader.ch == 'E' ||
|
(reader.ch == 'e' || reader.ch == 'E' ||
|
||||||
|
@ -393,10 +350,7 @@ public class JavaTokenizer {
|
||||||
boolean isJavaIdentifierPart;
|
boolean isJavaIdentifierPart;
|
||||||
char high;
|
char high;
|
||||||
do {
|
do {
|
||||||
if (sp == sbuf.length) putChar(reader.ch); else sbuf[sp++] = reader.ch;
|
reader.putChar(true);
|
||||||
// optimization, was: putChar(reader.ch);
|
|
||||||
|
|
||||||
reader.scanChar();
|
|
||||||
switch (reader.ch) {
|
switch (reader.ch) {
|
||||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||||
|
@ -423,7 +377,7 @@ public class JavaTokenizer {
|
||||||
break;
|
break;
|
||||||
case '\u001A': // EOI is also a legal identifier part
|
case '\u001A': // EOI is also a legal identifier part
|
||||||
if (reader.bp >= reader.buflen) {
|
if (reader.bp >= reader.buflen) {
|
||||||
name = names.fromChars(sbuf, 0, sp);
|
name = reader.name();
|
||||||
tk = tokens.lookupKind(name);
|
tk = tokens.lookupKind(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -435,11 +389,7 @@ public class JavaTokenizer {
|
||||||
} else {
|
} else {
|
||||||
high = reader.scanSurrogates();
|
high = reader.scanSurrogates();
|
||||||
if (high != 0) {
|
if (high != 0) {
|
||||||
if (sp == sbuf.length) {
|
reader.putChar(high);
|
||||||
putChar(high);
|
|
||||||
} else {
|
|
||||||
sbuf[sp++] = high;
|
|
||||||
}
|
|
||||||
isJavaIdentifierPart = Character.isJavaIdentifierPart(
|
isJavaIdentifierPart = Character.isJavaIdentifierPart(
|
||||||
Character.toCodePoint(high, reader.ch));
|
Character.toCodePoint(high, reader.ch));
|
||||||
} else {
|
} else {
|
||||||
|
@ -447,7 +397,7 @@ public class JavaTokenizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isJavaIdentifierPart) {
|
if (!isJavaIdentifierPart) {
|
||||||
name = names.fromChars(sbuf, 0, sp);
|
name = reader.name();
|
||||||
tk = tokens.lookupKind(name);
|
tk = tokens.lookupKind(name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -474,11 +424,11 @@ public class JavaTokenizer {
|
||||||
*/
|
*/
|
||||||
private void scanOperator() {
|
private void scanOperator() {
|
||||||
while (true) {
|
while (true) {
|
||||||
putChar(reader.ch);
|
reader.putChar(false);
|
||||||
Name newname = names.fromChars(sbuf, 0, sp);
|
Name newname = reader.name();
|
||||||
TokenKind tk1 = tokens.lookupKind(newname);
|
TokenKind tk1 = tokens.lookupKind(newname);
|
||||||
if (tk1 == TokenKind.IDENTIFIER) {
|
if (tk1 == TokenKind.IDENTIFIER) {
|
||||||
sp--;
|
reader.sp--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tk = tk1;
|
tk = tk1;
|
||||||
|
@ -487,111 +437,17 @@ public class JavaTokenizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Scan a documentation comment; determine if a deprecated tag is present.
|
|
||||||
* Called once the initial /, * have been skipped, positioned at the second *
|
|
||||||
* (which is treated as the beginning of the first line).
|
|
||||||
* Stops positioned at the closing '/'.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("fallthrough")
|
|
||||||
private void scanDocComment() {
|
|
||||||
boolean deprecatedPrefix = false;
|
|
||||||
|
|
||||||
forEachLine:
|
|
||||||
while (reader.bp < reader.buflen) {
|
|
||||||
|
|
||||||
// Skip optional WhiteSpace at beginning of line
|
|
||||||
while (reader.bp < reader.buflen && (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF)) {
|
|
||||||
scanCommentChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip optional consecutive Stars
|
|
||||||
while (reader.bp < reader.buflen && reader.ch == '*') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.ch == '/') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip optional WhiteSpace after Stars
|
|
||||||
while (reader.bp < reader.buflen && (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF)) {
|
|
||||||
scanCommentChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
deprecatedPrefix = false;
|
|
||||||
// At beginning of line in the JavaDoc sense.
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == '@' && !deprecatedFlag) {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 'd') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 'e') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 'p') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 'r') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 'e') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 'c') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 'a') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 't') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 'e') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.bp < reader.buflen && reader.ch == 'd') {
|
|
||||||
deprecatedPrefix = true;
|
|
||||||
scanCommentChar();
|
|
||||||
}}}}}}}}}}}
|
|
||||||
if (deprecatedPrefix && reader.bp < reader.buflen) {
|
|
||||||
if (Character.isWhitespace(reader.ch)) {
|
|
||||||
deprecatedFlag = true;
|
|
||||||
} else if (reader.ch == '*') {
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.ch == '/') {
|
|
||||||
deprecatedFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip rest of line
|
|
||||||
while (reader.bp < reader.buflen) {
|
|
||||||
switch (reader.ch) {
|
|
||||||
case '*':
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.ch == '/') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CR: // (Spec 3.4)
|
|
||||||
scanCommentChar();
|
|
||||||
if (reader.ch != LF) {
|
|
||||||
continue forEachLine;
|
|
||||||
}
|
|
||||||
/* fall through to LF case */
|
|
||||||
case LF: // (Spec 3.4)
|
|
||||||
scanCommentChar();
|
|
||||||
continue forEachLine;
|
|
||||||
default:
|
|
||||||
scanCommentChar();
|
|
||||||
}
|
|
||||||
} // rest of line
|
|
||||||
} // forEachLine
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Read token.
|
/** Read token.
|
||||||
*/
|
*/
|
||||||
public Token readToken() {
|
public Token readToken() {
|
||||||
|
|
||||||
sp = 0;
|
reader.sp = 0;
|
||||||
name = null;
|
name = null;
|
||||||
deprecatedFlag = false;
|
|
||||||
radix = 0;
|
radix = 0;
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
int endPos = 0;
|
int endPos = 0;
|
||||||
|
List<Comment> comments = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
loop: while (true) {
|
loop: while (true) {
|
||||||
|
@ -656,7 +512,7 @@ public class JavaTokenizer {
|
||||||
scanNumber(pos, 2);
|
scanNumber(pos, 2);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
putChar('0');
|
reader.putChar('0');
|
||||||
if (reader.ch == '_') {
|
if (reader.ch == '_') {
|
||||||
int savePos = reader.bp;
|
int savePos = reader.bp;
|
||||||
do {
|
do {
|
||||||
|
@ -676,14 +532,13 @@ public class JavaTokenizer {
|
||||||
case '.':
|
case '.':
|
||||||
reader.scanChar();
|
reader.scanChar();
|
||||||
if ('0' <= reader.ch && reader.ch <= '9') {
|
if ('0' <= reader.ch && reader.ch <= '9') {
|
||||||
putChar('.');
|
reader.putChar('.');
|
||||||
scanFractionAndSuffix(pos);
|
scanFractionAndSuffix(pos);
|
||||||
} else if (reader.ch == '.') {
|
} else if (reader.ch == '.') {
|
||||||
putChar('.'); putChar('.');
|
reader.putChar('.'); reader.putChar('.', true);
|
||||||
reader.scanChar();
|
|
||||||
if (reader.ch == '.') {
|
if (reader.ch == '.') {
|
||||||
reader.scanChar();
|
reader.scanChar();
|
||||||
putChar('.');
|
reader.putChar('.');
|
||||||
tk = TokenKind.ELLIPSIS;
|
tk = TokenKind.ELLIPSIS;
|
||||||
} else {
|
} else {
|
||||||
lexError(pos, "malformed.fp.lit");
|
lexError(pos, "malformed.fp.lit");
|
||||||
|
@ -712,32 +567,36 @@ public class JavaTokenizer {
|
||||||
reader.scanChar();
|
reader.scanChar();
|
||||||
if (reader.ch == '/') {
|
if (reader.ch == '/') {
|
||||||
do {
|
do {
|
||||||
scanCommentChar();
|
reader.scanCommentChar();
|
||||||
} while (reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen);
|
} while (reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen);
|
||||||
if (reader.bp < reader.buflen) {
|
if (reader.bp < reader.buflen) {
|
||||||
processComment(pos, reader.bp, CommentStyle.LINE);
|
comments = addDocReader(comments, processComment(pos, reader.bp, CommentStyle.LINE));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (reader.ch == '*') {
|
} else if (reader.ch == '*') {
|
||||||
|
boolean isEmpty = false;
|
||||||
reader.scanChar();
|
reader.scanChar();
|
||||||
CommentStyle style;
|
CommentStyle style;
|
||||||
if (reader.ch == '*') {
|
if (reader.ch == '*') {
|
||||||
style = CommentStyle.JAVADOC;
|
style = CommentStyle.JAVADOC;
|
||||||
scanDocComment();
|
reader.scanCommentChar();
|
||||||
|
if (reader.ch == '/') {
|
||||||
|
isEmpty = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
style = CommentStyle.BLOCK;
|
style = CommentStyle.BLOCK;
|
||||||
while (reader.bp < reader.buflen) {
|
}
|
||||||
if (reader.ch == '*') {
|
while (!isEmpty && reader.bp < reader.buflen) {
|
||||||
reader.scanChar();
|
if (reader.ch == '*') {
|
||||||
if (reader.ch == '/') break;
|
reader.scanChar();
|
||||||
} else {
|
if (reader.ch == '/') break;
|
||||||
scanCommentChar();
|
} else {
|
||||||
}
|
reader.scanCommentChar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reader.ch == '/') {
|
if (reader.ch == '/') {
|
||||||
reader.scanChar();
|
reader.scanChar();
|
||||||
processComment(pos, reader.bp, style);
|
comments = addDocReader(comments, processComment(pos, reader.bp, style));
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
lexError(pos, "unclosed.comment");
|
lexError(pos, "unclosed.comment");
|
||||||
|
@ -789,11 +648,7 @@ public class JavaTokenizer {
|
||||||
} else {
|
} else {
|
||||||
char high = reader.scanSurrogates();
|
char high = reader.scanSurrogates();
|
||||||
if (high != 0) {
|
if (high != 0) {
|
||||||
if (sp == sbuf.length) {
|
reader.putChar(high);
|
||||||
putChar(high);
|
|
||||||
} else {
|
|
||||||
sbuf[sp++] = high;
|
|
||||||
}
|
|
||||||
|
|
||||||
isJavaIdentifierStart = Character.isJavaIdentifierStart(
|
isJavaIdentifierStart = Character.isJavaIdentifierStart(
|
||||||
Character.toCodePoint(high, reader.ch));
|
Character.toCodePoint(high, reader.ch));
|
||||||
|
@ -816,10 +671,10 @@ public class JavaTokenizer {
|
||||||
}
|
}
|
||||||
endPos = reader.bp;
|
endPos = reader.bp;
|
||||||
switch (tk.tag) {
|
switch (tk.tag) {
|
||||||
case DEFAULT: return new Token(tk, pos, endPos, deprecatedFlag);
|
case DEFAULT: return new Token(tk, pos, endPos, comments);
|
||||||
case NAMED: return new NamedToken(tk, pos, endPos, name, deprecatedFlag);
|
case NAMED: return new NamedToken(tk, pos, endPos, name, comments);
|
||||||
case STRING: return new StringToken(tk, pos, endPos, new String(sbuf, 0, sp), deprecatedFlag);
|
case STRING: return new StringToken(tk, pos, endPos, reader.chars(), comments);
|
||||||
case NUMERIC: return new NumericToken(tk, pos, endPos, new String(sbuf, 0, sp), radix, deprecatedFlag);
|
case NUMERIC: return new NumericToken(tk, pos, endPos, reader.chars(), radix, comments);
|
||||||
default: throw new AssertionError();
|
default: throw new AssertionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -832,6 +687,12 @@ public class JavaTokenizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//where
|
||||||
|
List<Comment> addDocReader(List<Comment> docReaders, Comment docReader) {
|
||||||
|
return docReaders == null ?
|
||||||
|
List.of(docReader) :
|
||||||
|
docReaders.prepend(docReader);
|
||||||
|
}
|
||||||
|
|
||||||
/** Return the position where a lexical error occurred;
|
/** Return the position where a lexical error occurred;
|
||||||
*/
|
*/
|
||||||
|
@ -845,22 +706,18 @@ public class JavaTokenizer {
|
||||||
errPos = pos;
|
errPos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum CommentStyle {
|
|
||||||
LINE,
|
|
||||||
BLOCK,
|
|
||||||
JAVADOC,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a complete comment has been scanned. pos and endPos
|
* Called when a complete comment has been scanned. pos and endPos
|
||||||
* will mark the comment boundary.
|
* will mark the comment boundary.
|
||||||
*/
|
*/
|
||||||
protected void processComment(int pos, int endPos, CommentStyle style) {
|
protected Tokens.Comment processComment(int pos, int endPos, CommentStyle style) {
|
||||||
if (scannerDebug)
|
if (scannerDebug)
|
||||||
System.out.println("processComment(" + pos
|
System.out.println("processComment(" + pos
|
||||||
+ "," + endPos + "," + style + ")=|"
|
+ "," + endPos + "," + style + ")=|"
|
||||||
+ new String(reader.getRawCharacters(pos, endPos))
|
+ new String(reader.getRawCharacters(pos, endPos))
|
||||||
+ "|");
|
+ "|");
|
||||||
|
char[] buf = reader.getRawCharacters(pos, endPos);
|
||||||
|
return new BasicComment<UnicodeReader>(new UnicodeReader(fac, buf, buf.length), style);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -893,4 +750,125 @@ public class JavaTokenizer {
|
||||||
public Position.LineMap getLineMap() {
|
public Position.LineMap getLineMap() {
|
||||||
return Position.makeLineMap(reader.getRawCharacters(), reader.buflen, false);
|
return Position.makeLineMap(reader.getRawCharacters(), reader.buflen, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan a documentation comment; determine if a deprecated tag is present.
|
||||||
|
* Called once the initial /, * have been skipped, positioned at the second *
|
||||||
|
* (which is treated as the beginning of the first line).
|
||||||
|
* Stops positioned at the closing '/'.
|
||||||
|
*/
|
||||||
|
protected class BasicComment<U extends UnicodeReader> implements Comment {
|
||||||
|
|
||||||
|
CommentStyle cs;
|
||||||
|
U comment_reader;
|
||||||
|
|
||||||
|
protected boolean deprecatedFlag = false;
|
||||||
|
protected boolean scanned = false;
|
||||||
|
|
||||||
|
protected BasicComment(U comment_reader, CommentStyle cs) {
|
||||||
|
this.comment_reader = comment_reader;
|
||||||
|
this.cs = cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommentStyle getStyle() {
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDeprecated() {
|
||||||
|
if (!scanned && cs == CommentStyle.JAVADOC) {
|
||||||
|
scanDocComment();
|
||||||
|
}
|
||||||
|
return deprecatedFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("fallthrough")
|
||||||
|
protected void scanDocComment() {
|
||||||
|
try {
|
||||||
|
boolean deprecatedPrefix = false;
|
||||||
|
|
||||||
|
comment_reader.bp += 3; // '/**'
|
||||||
|
comment_reader.ch = comment_reader.buf[comment_reader.bp];
|
||||||
|
|
||||||
|
forEachLine:
|
||||||
|
while (comment_reader.bp < comment_reader.buflen) {
|
||||||
|
|
||||||
|
// Skip optional WhiteSpace at beginning of line
|
||||||
|
while (comment_reader.bp < comment_reader.buflen && (comment_reader.ch == ' ' || comment_reader.ch == '\t' || comment_reader.ch == FF)) {
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip optional consecutive Stars
|
||||||
|
while (comment_reader.bp < comment_reader.buflen && comment_reader.ch == '*') {
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
if (comment_reader.ch == '/') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip optional WhiteSpace after Stars
|
||||||
|
while (comment_reader.bp < comment_reader.buflen && (comment_reader.ch == ' ' || comment_reader.ch == '\t' || comment_reader.ch == FF)) {
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
deprecatedPrefix = false;
|
||||||
|
// At beginning of line in the JavaDoc sense.
|
||||||
|
if (!deprecatedFlag) {
|
||||||
|
String deprecated = "@deprecated";
|
||||||
|
int i = 0;
|
||||||
|
while (comment_reader.bp < comment_reader.buflen && comment_reader.ch == deprecated.charAt(i)) {
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
i++;
|
||||||
|
if (i == deprecated.length()) {
|
||||||
|
deprecatedPrefix = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deprecatedPrefix && comment_reader.bp < comment_reader.buflen) {
|
||||||
|
if (Character.isWhitespace(comment_reader.ch)) {
|
||||||
|
deprecatedFlag = true;
|
||||||
|
} else if (comment_reader.ch == '*') {
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
if (comment_reader.ch == '/') {
|
||||||
|
deprecatedFlag = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip rest of line
|
||||||
|
while (comment_reader.bp < comment_reader.buflen) {
|
||||||
|
switch (comment_reader.ch) {
|
||||||
|
case '*':
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
if (comment_reader.ch == '/') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CR: // (Spec 3.4)
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
if (comment_reader.ch != LF) {
|
||||||
|
continue forEachLine;
|
||||||
|
}
|
||||||
|
/* fall through to LF case */
|
||||||
|
case LF: // (Spec 3.4)
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
continue forEachLine;
|
||||||
|
default:
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
}
|
||||||
|
} // rest of line
|
||||||
|
} // forEachLine
|
||||||
|
return;
|
||||||
|
} finally {
|
||||||
|
scanned = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.*;
|
||||||
|
|
||||||
import com.sun.tools.javac.code.*;
|
import com.sun.tools.javac.code.*;
|
||||||
import com.sun.tools.javac.parser.Tokens.*;
|
import com.sun.tools.javac.parser.Tokens.*;
|
||||||
|
import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
|
||||||
import com.sun.tools.javac.tree.*;
|
import com.sun.tools.javac.tree.*;
|
||||||
import com.sun.tools.javac.tree.JCTree.*;
|
import com.sun.tools.javac.tree.JCTree.*;
|
||||||
import com.sun.tools.javac.util.*;
|
import com.sun.tools.javac.util.*;
|
||||||
|
@ -1584,7 +1585,7 @@ public class JavacParser implements Parser {
|
||||||
break;
|
break;
|
||||||
case MONKEYS_AT:
|
case MONKEYS_AT:
|
||||||
case FINAL: {
|
case FINAL: {
|
||||||
String dc = token.docComment;
|
String dc = token.comment(CommentStyle.JAVADOC);
|
||||||
JCModifiers mods = modifiersOpt();
|
JCModifiers mods = modifiersOpt();
|
||||||
if (token.kind == INTERFACE ||
|
if (token.kind == INTERFACE ||
|
||||||
token.kind == CLASS ||
|
token.kind == CLASS ||
|
||||||
|
@ -1601,21 +1602,21 @@ public class JavacParser implements Parser {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ABSTRACT: case STRICTFP: {
|
case ABSTRACT: case STRICTFP: {
|
||||||
String dc = token.docComment;
|
String dc = token.comment(CommentStyle.JAVADOC);
|
||||||
JCModifiers mods = modifiersOpt();
|
JCModifiers mods = modifiersOpt();
|
||||||
stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
|
stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INTERFACE:
|
case INTERFACE:
|
||||||
case CLASS:
|
case CLASS:
|
||||||
String dc = token.docComment;
|
String dc = token.comment(CommentStyle.JAVADOC);
|
||||||
stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
|
stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
|
||||||
break;
|
break;
|
||||||
case ENUM:
|
case ENUM:
|
||||||
case ASSERT:
|
case ASSERT:
|
||||||
if (allowEnums && token.kind == ENUM) {
|
if (allowEnums && token.kind == ENUM) {
|
||||||
error(token.pos, "local.enum");
|
error(token.pos, "local.enum");
|
||||||
dc = token.docComment;
|
dc = token.comment(CommentStyle.JAVADOC);
|
||||||
stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
|
stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
|
||||||
break;
|
break;
|
||||||
} else if (allowAsserts && token.kind == ASSERT) {
|
} else if (allowAsserts && token.kind == ASSERT) {
|
||||||
|
@ -1991,7 +1992,7 @@ public class JavacParser implements Parser {
|
||||||
annotations.appendList(partial.annotations);
|
annotations.appendList(partial.annotations);
|
||||||
pos = partial.pos;
|
pos = partial.pos;
|
||||||
}
|
}
|
||||||
if (token.deprecatedFlag) {
|
if (token.deprecatedFlag()) {
|
||||||
flags |= Flags.DEPRECATED;
|
flags |= Flags.DEPRECATED;
|
||||||
}
|
}
|
||||||
int lastPos = Position.NOPOS;
|
int lastPos = Position.NOPOS;
|
||||||
|
@ -2271,9 +2272,9 @@ public class JavacParser implements Parser {
|
||||||
seenImport = true;
|
seenImport = true;
|
||||||
defs.append(importDeclaration());
|
defs.append(importDeclaration());
|
||||||
} else {
|
} else {
|
||||||
String docComment = token.docComment;
|
String docComment = token.comment(CommentStyle.JAVADOC);
|
||||||
if (firstTypeDecl && !seenImport && !seenPackage) {
|
if (firstTypeDecl && !seenImport && !seenPackage) {
|
||||||
docComment = firstToken.docComment;
|
docComment = firstToken.comment(CommentStyle.JAVADOC);
|
||||||
consumedToplevelDoc = true;
|
consumedToplevelDoc = true;
|
||||||
}
|
}
|
||||||
JCTree def = typeDeclaration(mods, docComment);
|
JCTree def = typeDeclaration(mods, docComment);
|
||||||
|
@ -2288,7 +2289,7 @@ public class JavacParser implements Parser {
|
||||||
}
|
}
|
||||||
JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
|
JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
|
||||||
if (!consumedToplevelDoc)
|
if (!consumedToplevelDoc)
|
||||||
attach(toplevel, firstToken.docComment);
|
attach(toplevel, firstToken.comment(CommentStyle.JAVADOC));
|
||||||
if (defs.elems.isEmpty())
|
if (defs.elems.isEmpty())
|
||||||
storeEnd(toplevel, S.prevToken().endPos);
|
storeEnd(toplevel, S.prevToken().endPos);
|
||||||
if (keepDocComments)
|
if (keepDocComments)
|
||||||
|
@ -2498,9 +2499,9 @@ public class JavacParser implements Parser {
|
||||||
/** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
|
/** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
|
||||||
*/
|
*/
|
||||||
JCTree enumeratorDeclaration(Name enumName) {
|
JCTree enumeratorDeclaration(Name enumName) {
|
||||||
String dc = token.docComment;
|
String dc = token.comment(CommentStyle.JAVADOC);
|
||||||
int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
|
int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
|
||||||
if (token.deprecatedFlag) {
|
if (token.deprecatedFlag()) {
|
||||||
flags |= Flags.DEPRECATED;
|
flags |= Flags.DEPRECATED;
|
||||||
}
|
}
|
||||||
int pos = token.pos;
|
int pos = token.pos;
|
||||||
|
@ -2587,7 +2588,7 @@ public class JavacParser implements Parser {
|
||||||
nextToken();
|
nextToken();
|
||||||
return List.<JCTree>nil();
|
return List.<JCTree>nil();
|
||||||
} else {
|
} else {
|
||||||
String dc = token.docComment;
|
String dc = token.comment(CommentStyle.JAVADOC);
|
||||||
int pos = token.pos;
|
int pos = token.pos;
|
||||||
JCModifiers mods = modifiersOpt();
|
JCModifiers mods = modifiersOpt();
|
||||||
if (token.kind == CLASS ||
|
if (token.kind == CLASS ||
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
|
|
||||||
package com.sun.tools.javac.parser;
|
package com.sun.tools.javac.parser;
|
||||||
|
|
||||||
import com.sun.tools.javac.file.JavacFileManager;
|
import com.sun.tools.javac.parser.Tokens.Comment;
|
||||||
import com.sun.tools.javac.parser.Tokens.Token;
|
import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
|
||||||
import com.sun.tools.javac.util.*;
|
import com.sun.tools.javac.util.*;
|
||||||
|
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
|
@ -59,352 +59,295 @@ public class JavadocTokenizer extends JavaTokenizer {
|
||||||
super(fac, input, inputLength);
|
super(fac, input, inputLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The comment input buffer, index of next chacter to be read,
|
@Override
|
||||||
* index of one past last character in buffer.
|
protected Comment processComment(int pos, int endPos, CommentStyle style) {
|
||||||
*/
|
char[] buf = reader.getRawCharacters(pos, endPos);
|
||||||
private char[] buf;
|
return new JavadocComment(new ColReader(fac, buf, buf.length), style);
|
||||||
private int bp;
|
|
||||||
private int buflen;
|
|
||||||
|
|
||||||
/** The current character.
|
|
||||||
*/
|
|
||||||
private char ch;
|
|
||||||
|
|
||||||
/** The column number position of the current character.
|
|
||||||
*/
|
|
||||||
private int col;
|
|
||||||
|
|
||||||
/** The buffer index of the last converted Unicode character
|
|
||||||
*/
|
|
||||||
private int unicodeConversionBp = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Buffer for doc comment.
|
|
||||||
*/
|
|
||||||
private char[] docCommentBuffer = new char[1024];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of characters in doc comment buffer.
|
|
||||||
*/
|
|
||||||
private int docCommentCount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translated and stripped contents of doc comment
|
|
||||||
*/
|
|
||||||
private String docComment = null;
|
|
||||||
|
|
||||||
|
|
||||||
/** Unconditionally expand the comment buffer.
|
|
||||||
*/
|
|
||||||
private void expandCommentBuffer() {
|
|
||||||
char[] newBuffer = new char[docCommentBuffer.length * 2];
|
|
||||||
System.arraycopy(docCommentBuffer, 0, newBuffer,
|
|
||||||
0, docCommentBuffer.length);
|
|
||||||
docCommentBuffer = newBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert an ASCII digit from its base (8, 10, or 16)
|
/**
|
||||||
* to its value.
|
* This is a specialized version of UnicodeReader that keeps track of the
|
||||||
|
* column position within a given character stream (used for Javadoc processing).
|
||||||
*/
|
*/
|
||||||
private int digit(int base) {
|
static class ColReader extends UnicodeReader {
|
||||||
char c = ch;
|
|
||||||
int result = Character.digit(c, base);
|
int col;
|
||||||
if (result >= 0 && c > 0x7f) {
|
|
||||||
ch = "0123456789abcdef".charAt(result);
|
ColReader(ScannerFactory fac, char[] input, int inputLength) {
|
||||||
|
super(fac, input, inputLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void convertUnicode() {
|
||||||
|
if (ch == '\\' && unicodeConversionBp != bp) {
|
||||||
|
bp++; ch = buf[bp]; col++;
|
||||||
|
if (ch == 'u') {
|
||||||
|
do {
|
||||||
|
bp++; ch = buf[bp]; col++;
|
||||||
|
} while (ch == 'u');
|
||||||
|
int limit = bp + 3;
|
||||||
|
if (limit < buflen) {
|
||||||
|
int d = digit(bp, 16);
|
||||||
|
int code = d;
|
||||||
|
while (bp < limit && d >= 0) {
|
||||||
|
bp++; ch = buf[bp]; col++;
|
||||||
|
d = digit(bp, 16);
|
||||||
|
code = (code << 4) + d;
|
||||||
|
}
|
||||||
|
if (d >= 0) {
|
||||||
|
ch = (char)code;
|
||||||
|
unicodeConversionBp = bp;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// "illegal.Unicode.esc", reported by base scanner
|
||||||
|
} else {
|
||||||
|
bp--;
|
||||||
|
ch = '\\';
|
||||||
|
col--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void scanCommentChar() {
|
||||||
|
scanChar();
|
||||||
|
if (ch == '\\') {
|
||||||
|
if (peekChar() == '\\' && !isUnicode()) {
|
||||||
|
putChar(ch, false);
|
||||||
|
bp++; col++;
|
||||||
|
} else {
|
||||||
|
convertUnicode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void scanChar() {
|
||||||
|
bp++;
|
||||||
|
ch = buf[bp];
|
||||||
|
switch (ch) {
|
||||||
|
case '\r': // return
|
||||||
|
col = 0;
|
||||||
|
break;
|
||||||
|
case '\n': // newline
|
||||||
|
if (bp == 0 || buf[bp-1] != '\r') {
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '\t': // tab
|
||||||
|
col = (col / TabInc * TabInc) + TabInc;
|
||||||
|
break;
|
||||||
|
case '\\': // possible Unicode
|
||||||
|
col++;
|
||||||
|
convertUnicode();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
col++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class JavadocComment extends JavaTokenizer.BasicComment<ColReader> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translated and stripped contents of doc comment
|
||||||
|
*/
|
||||||
|
private String docComment = null;
|
||||||
|
|
||||||
|
JavadocComment(ColReader comment_reader, CommentStyle cs) {
|
||||||
|
super(comment_reader, cs);
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convert Unicode escape; bp points to initial '\' character
|
public String getText() {
|
||||||
* (Spec 3.3).
|
if (!scanned && cs == CommentStyle.JAVADOC) {
|
||||||
*/
|
scanDocComment();
|
||||||
private void convertUnicode() {
|
}
|
||||||
if (ch == '\\' && unicodeConversionBp != bp) {
|
return docComment;
|
||||||
bp++; ch = buf[bp]; col++;
|
}
|
||||||
if (ch == 'u') {
|
|
||||||
do {
|
@Override
|
||||||
bp++; ch = buf[bp]; col++;
|
@SuppressWarnings("fallthrough")
|
||||||
} while (ch == 'u');
|
protected void scanDocComment() {
|
||||||
int limit = bp + 3;
|
try {
|
||||||
if (limit < buflen) {
|
boolean firstLine = true;
|
||||||
int d = digit(16);
|
|
||||||
int code = d;
|
// Skip over first slash
|
||||||
while (bp < limit && d >= 0) {
|
comment_reader.scanCommentChar();
|
||||||
bp++; ch = buf[bp]; col++;
|
// Skip over first star
|
||||||
d = digit(16);
|
comment_reader.scanCommentChar();
|
||||||
code = (code << 4) + d;
|
|
||||||
}
|
// consume any number of stars
|
||||||
if (d >= 0) {
|
while (comment_reader.bp < comment_reader.buflen && comment_reader.ch == '*') {
|
||||||
ch = (char)code;
|
comment_reader.scanCommentChar();
|
||||||
unicodeConversionBp = bp;
|
}
|
||||||
return;
|
// is the comment in the form /**/, /***/, /****/, etc. ?
|
||||||
}
|
if (comment_reader.bp < comment_reader.buflen && comment_reader.ch == '/') {
|
||||||
|
docComment = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip a newline on the first line of the comment.
|
||||||
|
if (comment_reader.bp < comment_reader.buflen) {
|
||||||
|
if (comment_reader.ch == LF) {
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
firstLine = false;
|
||||||
|
} else if (comment_reader.ch == CR) {
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
if (comment_reader.ch == LF) {
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
firstLine = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outerLoop:
|
||||||
|
|
||||||
|
// The outerLoop processes the doc comment, looping once
|
||||||
|
// for each line. For each line, it first strips off
|
||||||
|
// whitespace, then it consumes any stars, then it
|
||||||
|
// puts the rest of the line into our buffer.
|
||||||
|
while (comment_reader.bp < comment_reader.buflen) {
|
||||||
|
|
||||||
|
// The wsLoop consumes whitespace from the beginning
|
||||||
|
// of each line.
|
||||||
|
wsLoop:
|
||||||
|
|
||||||
|
while (comment_reader.bp < comment_reader.buflen) {
|
||||||
|
switch(comment_reader.ch) {
|
||||||
|
case ' ':
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
comment_reader.col = ((comment_reader.col - 1) / TabInc * TabInc) + TabInc;
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
break;
|
||||||
|
case FF:
|
||||||
|
comment_reader.col = 0;
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
break;
|
||||||
|
// Treat newline at beginning of line (blank line, no star)
|
||||||
|
// as comment text. Old Javadoc compatibility requires this.
|
||||||
|
/*---------------------------------*
|
||||||
|
case CR: // (Spec 3.4)
|
||||||
|
doc_reader.scanCommentChar();
|
||||||
|
if (ch == LF) {
|
||||||
|
col = 0;
|
||||||
|
doc_reader.scanCommentChar();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LF: // (Spec 3.4)
|
||||||
|
doc_reader.scanCommentChar();
|
||||||
|
break;
|
||||||
|
*---------------------------------*/
|
||||||
|
default:
|
||||||
|
// we've seen something that isn't whitespace;
|
||||||
|
// jump out.
|
||||||
|
break wsLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Are there stars here? If so, consume them all
|
||||||
|
// and check for the end of comment.
|
||||||
|
if (comment_reader.ch == '*') {
|
||||||
|
// skip all of the stars
|
||||||
|
do {
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
} while (comment_reader.ch == '*');
|
||||||
|
|
||||||
|
// check for the closing slash.
|
||||||
|
if (comment_reader.ch == '/') {
|
||||||
|
// We're done with the doc comment
|
||||||
|
// scanChar() and breakout.
|
||||||
|
break outerLoop;
|
||||||
|
}
|
||||||
|
} else if (! firstLine) {
|
||||||
|
//The current line does not begin with a '*' so we will indent it.
|
||||||
|
for (int i = 1; i < comment_reader.col; i++) {
|
||||||
|
comment_reader.putChar(' ', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The textLoop processes the rest of the characters
|
||||||
|
// on the line, adding them to our buffer.
|
||||||
|
textLoop:
|
||||||
|
while (comment_reader.bp < comment_reader.buflen) {
|
||||||
|
switch (comment_reader.ch) {
|
||||||
|
case '*':
|
||||||
|
// Is this just a star? Or is this the
|
||||||
|
// end of a comment?
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
if (comment_reader.ch == '/') {
|
||||||
|
// This is the end of the comment,
|
||||||
|
// set ch and return our buffer.
|
||||||
|
break outerLoop;
|
||||||
|
}
|
||||||
|
// This is just an ordinary star. Add it to
|
||||||
|
// the buffer.
|
||||||
|
comment_reader.putChar('*', false);
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
comment_reader.putChar(comment_reader.ch, false);
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
break;
|
||||||
|
case FF:
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
break textLoop; // treat as end of line
|
||||||
|
case CR: // (Spec 3.4)
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
if (comment_reader.ch != LF) {
|
||||||
|
// Canonicalize CR-only line terminator to LF
|
||||||
|
comment_reader.putChar((char)LF, false);
|
||||||
|
break textLoop;
|
||||||
|
}
|
||||||
|
/* fall through to LF case */
|
||||||
|
case LF: // (Spec 3.4)
|
||||||
|
// We've seen a newline. Add it to our
|
||||||
|
// buffer and break out of this loop,
|
||||||
|
// starting fresh on a new line.
|
||||||
|
comment_reader.putChar(comment_reader.ch, false);
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
break textLoop;
|
||||||
|
default:
|
||||||
|
// Add the character to our buffer.
|
||||||
|
comment_reader.putChar(comment_reader.ch, false);
|
||||||
|
comment_reader.scanCommentChar();
|
||||||
|
}
|
||||||
|
} // end textLoop
|
||||||
|
firstLine = false;
|
||||||
|
} // end outerLoop
|
||||||
|
|
||||||
|
if (comment_reader.sp > 0) {
|
||||||
|
int i = comment_reader.sp - 1;
|
||||||
|
trailLoop:
|
||||||
|
while (i > -1) {
|
||||||
|
switch (comment_reader.sbuf[i]) {
|
||||||
|
case '*':
|
||||||
|
i--;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break trailLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
comment_reader.sp = i + 1;
|
||||||
|
|
||||||
|
// Store the text of the doc comment
|
||||||
|
docComment = comment_reader.chars();
|
||||||
|
} else {
|
||||||
|
docComment = "";
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
scanned = true;
|
||||||
|
if (docComment != null &&
|
||||||
|
docComment.matches("(?sm).*^\\s*@deprecated( |$).*")) {
|
||||||
|
deprecatedFlag = true;
|
||||||
}
|
}
|
||||||
// "illegal.Unicode.esc", reported by base scanner
|
|
||||||
} else {
|
|
||||||
bp--;
|
|
||||||
ch = '\\';
|
|
||||||
col--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Read next character.
|
|
||||||
*/
|
|
||||||
private void scanChar() {
|
|
||||||
bp++;
|
|
||||||
ch = buf[bp];
|
|
||||||
switch (ch) {
|
|
||||||
case '\r': // return
|
|
||||||
col = 0;
|
|
||||||
break;
|
|
||||||
case '\n': // newline
|
|
||||||
if (bp == 0 || buf[bp-1] != '\r') {
|
|
||||||
col = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '\t': // tab
|
|
||||||
col = (col / TabInc * TabInc) + TabInc;
|
|
||||||
break;
|
|
||||||
case '\\': // possible Unicode
|
|
||||||
col++;
|
|
||||||
convertUnicode();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
col++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Token readToken() {
|
|
||||||
docComment = null;
|
|
||||||
Token tk = super.readToken();
|
|
||||||
tk.docComment = docComment;
|
|
||||||
return tk;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read next character in doc comment, skipping over double '\' characters.
|
|
||||||
* If a double '\' is skipped, put in the buffer and update buffer count.
|
|
||||||
*/
|
|
||||||
private void scanDocCommentChar() {
|
|
||||||
scanChar();
|
|
||||||
if (ch == '\\') {
|
|
||||||
if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
|
|
||||||
if (docCommentCount == docCommentBuffer.length)
|
|
||||||
expandCommentBuffer();
|
|
||||||
docCommentBuffer[docCommentCount++] = ch;
|
|
||||||
bp++; col++;
|
|
||||||
} else {
|
|
||||||
convertUnicode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process a doc comment and make the string content available.
|
|
||||||
* Strips leading whitespace and stars.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("fallthrough")
|
|
||||||
protected void processComment(int pos, int endPos, CommentStyle style) {
|
|
||||||
if (style != CommentStyle.JAVADOC) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = reader.getRawCharacters(pos, endPos);
|
|
||||||
buflen = buf.length;
|
|
||||||
bp = 0;
|
|
||||||
col = 0;
|
|
||||||
|
|
||||||
docCommentCount = 0;
|
|
||||||
|
|
||||||
boolean firstLine = true;
|
|
||||||
|
|
||||||
// Skip over first slash
|
|
||||||
scanDocCommentChar();
|
|
||||||
// Skip over first star
|
|
||||||
scanDocCommentChar();
|
|
||||||
|
|
||||||
// consume any number of stars
|
|
||||||
while (bp < buflen && ch == '*') {
|
|
||||||
scanDocCommentChar();
|
|
||||||
}
|
|
||||||
// is the comment in the form /**/, /***/, /****/, etc. ?
|
|
||||||
if (bp < buflen && ch == '/') {
|
|
||||||
docComment = "";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip a newline on the first line of the comment.
|
|
||||||
if (bp < buflen) {
|
|
||||||
if (ch == LF) {
|
|
||||||
scanDocCommentChar();
|
|
||||||
firstLine = false;
|
|
||||||
} else if (ch == CR) {
|
|
||||||
scanDocCommentChar();
|
|
||||||
if (ch == LF) {
|
|
||||||
scanDocCommentChar();
|
|
||||||
firstLine = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
outerLoop:
|
|
||||||
|
|
||||||
// The outerLoop processes the doc comment, looping once
|
|
||||||
// for each line. For each line, it first strips off
|
|
||||||
// whitespace, then it consumes any stars, then it
|
|
||||||
// puts the rest of the line into our buffer.
|
|
||||||
while (bp < buflen) {
|
|
||||||
|
|
||||||
// The wsLoop consumes whitespace from the beginning
|
|
||||||
// of each line.
|
|
||||||
wsLoop:
|
|
||||||
|
|
||||||
while (bp < buflen) {
|
|
||||||
switch(ch) {
|
|
||||||
case ' ':
|
|
||||||
scanDocCommentChar();
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
col = ((col - 1) / TabInc * TabInc) + TabInc;
|
|
||||||
scanDocCommentChar();
|
|
||||||
break;
|
|
||||||
case FF:
|
|
||||||
col = 0;
|
|
||||||
scanDocCommentChar();
|
|
||||||
break;
|
|
||||||
// Treat newline at beginning of line (blank line, no star)
|
|
||||||
// as comment text. Old Javadoc compatibility requires this.
|
|
||||||
/*---------------------------------*
|
|
||||||
case CR: // (Spec 3.4)
|
|
||||||
scanDocCommentChar();
|
|
||||||
if (ch == LF) {
|
|
||||||
col = 0;
|
|
||||||
scanDocCommentChar();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LF: // (Spec 3.4)
|
|
||||||
scanDocCommentChar();
|
|
||||||
break;
|
|
||||||
*---------------------------------*/
|
|
||||||
default:
|
|
||||||
// we've seen something that isn't whitespace;
|
|
||||||
// jump out.
|
|
||||||
break wsLoop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Are there stars here? If so, consume them all
|
|
||||||
// and check for the end of comment.
|
|
||||||
if (ch == '*') {
|
|
||||||
// skip all of the stars
|
|
||||||
do {
|
|
||||||
scanDocCommentChar();
|
|
||||||
} while (ch == '*');
|
|
||||||
|
|
||||||
// check for the closing slash.
|
|
||||||
if (ch == '/') {
|
|
||||||
// We're done with the doc comment
|
|
||||||
// scanChar() and breakout.
|
|
||||||
break outerLoop;
|
|
||||||
}
|
|
||||||
} else if (! firstLine) {
|
|
||||||
//The current line does not begin with a '*' so we will indent it.
|
|
||||||
for (int i = 1; i < col; i++) {
|
|
||||||
if (docCommentCount == docCommentBuffer.length)
|
|
||||||
expandCommentBuffer();
|
|
||||||
docCommentBuffer[docCommentCount++] = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The textLoop processes the rest of the characters
|
|
||||||
// on the line, adding them to our buffer.
|
|
||||||
textLoop:
|
|
||||||
while (bp < buflen) {
|
|
||||||
switch (ch) {
|
|
||||||
case '*':
|
|
||||||
// Is this just a star? Or is this the
|
|
||||||
// end of a comment?
|
|
||||||
scanDocCommentChar();
|
|
||||||
if (ch == '/') {
|
|
||||||
// This is the end of the comment,
|
|
||||||
// set ch and return our buffer.
|
|
||||||
break outerLoop;
|
|
||||||
}
|
|
||||||
// This is just an ordinary star. Add it to
|
|
||||||
// the buffer.
|
|
||||||
if (docCommentCount == docCommentBuffer.length)
|
|
||||||
expandCommentBuffer();
|
|
||||||
docCommentBuffer[docCommentCount++] = '*';
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
case '\t':
|
|
||||||
if (docCommentCount == docCommentBuffer.length)
|
|
||||||
expandCommentBuffer();
|
|
||||||
docCommentBuffer[docCommentCount++] = ch;
|
|
||||||
scanDocCommentChar();
|
|
||||||
break;
|
|
||||||
case FF:
|
|
||||||
scanDocCommentChar();
|
|
||||||
break textLoop; // treat as end of line
|
|
||||||
case CR: // (Spec 3.4)
|
|
||||||
scanDocCommentChar();
|
|
||||||
if (ch != LF) {
|
|
||||||
// Canonicalize CR-only line terminator to LF
|
|
||||||
if (docCommentCount == docCommentBuffer.length)
|
|
||||||
expandCommentBuffer();
|
|
||||||
docCommentBuffer[docCommentCount++] = (char)LF;
|
|
||||||
break textLoop;
|
|
||||||
}
|
|
||||||
/* fall through to LF case */
|
|
||||||
case LF: // (Spec 3.4)
|
|
||||||
// We've seen a newline. Add it to our
|
|
||||||
// buffer and break out of this loop,
|
|
||||||
// starting fresh on a new line.
|
|
||||||
if (docCommentCount == docCommentBuffer.length)
|
|
||||||
expandCommentBuffer();
|
|
||||||
docCommentBuffer[docCommentCount++] = ch;
|
|
||||||
scanDocCommentChar();
|
|
||||||
break textLoop;
|
|
||||||
default:
|
|
||||||
// Add the character to our buffer.
|
|
||||||
if (docCommentCount == docCommentBuffer.length)
|
|
||||||
expandCommentBuffer();
|
|
||||||
docCommentBuffer[docCommentCount++] = ch;
|
|
||||||
scanDocCommentChar();
|
|
||||||
}
|
|
||||||
} // end textLoop
|
|
||||||
firstLine = false;
|
|
||||||
} // end outerLoop
|
|
||||||
|
|
||||||
if (docCommentCount > 0) {
|
|
||||||
int i = docCommentCount - 1;
|
|
||||||
trailLoop:
|
|
||||||
while (i > -1) {
|
|
||||||
switch (docCommentBuffer[i]) {
|
|
||||||
case '*':
|
|
||||||
i--;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break trailLoop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
docCommentCount = i + 1;
|
|
||||||
|
|
||||||
// Store the text of the doc comment
|
|
||||||
docComment = new String(docCommentBuffer, 0 , docCommentCount);
|
|
||||||
} else {
|
|
||||||
docComment = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Build a map for translating between line numbers and
|
|
||||||
* positions in the input.
|
|
||||||
*
|
|
||||||
* @return a LineMap */
|
|
||||||
public Position.LineMap getLineMap() {
|
public Position.LineMap getLineMap() {
|
||||||
char[] buf = reader.getRawCharacters();
|
char[] buf = reader.getRawCharacters();
|
||||||
return Position.makeLineMap(buf, buf.length, true);
|
return Position.makeLineMap(buf, buf.length, true);
|
||||||
|
|
|
@ -30,8 +30,10 @@ import java.util.Locale;
|
||||||
import com.sun.tools.javac.api.Formattable;
|
import com.sun.tools.javac.api.Formattable;
|
||||||
import com.sun.tools.javac.api.Messages;
|
import com.sun.tools.javac.api.Messages;
|
||||||
import com.sun.tools.javac.parser.Tokens.Token.Tag;
|
import com.sun.tools.javac.parser.Tokens.Token.Tag;
|
||||||
|
import com.sun.tools.javac.util.List;
|
||||||
import com.sun.tools.javac.util.Name;
|
import com.sun.tools.javac.util.Name;
|
||||||
import com.sun.tools.javac.util.Context;
|
import com.sun.tools.javac.util.Context;
|
||||||
|
import com.sun.tools.javac.util.ListBuffer;
|
||||||
import com.sun.tools.javac.util.Names;
|
import com.sun.tools.javac.util.Names;
|
||||||
|
|
||||||
/** A class that defines codes/utilities for Java source tokens
|
/** A class that defines codes/utilities for Java source tokens
|
||||||
|
@ -281,6 +283,19 @@ public class Tokens {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface Comment {
|
||||||
|
|
||||||
|
enum CommentStyle {
|
||||||
|
LINE,
|
||||||
|
BLOCK,
|
||||||
|
JAVADOC,
|
||||||
|
}
|
||||||
|
|
||||||
|
String getText();
|
||||||
|
CommentStyle getStyle();
|
||||||
|
boolean isDeprecated();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the class representing a javac token. Each token has several fields
|
* This is the class representing a javac token. Each token has several fields
|
||||||
* that are set by the javac lexer (i.e. start/end position, string value, etc).
|
* that are set by the javac lexer (i.e. start/end position, string value, etc).
|
||||||
|
@ -304,18 +319,14 @@ public class Tokens {
|
||||||
/** The end position of this token */
|
/** The end position of this token */
|
||||||
public final int endPos;
|
public final int endPos;
|
||||||
|
|
||||||
/** Is this token preceeded by a deprecated comment? */
|
/** Comment reader associated with this token */
|
||||||
public final boolean deprecatedFlag;
|
public final List<Comment> comments;
|
||||||
|
|
||||||
/** Is this token preceeded by a deprecated comment? */
|
Token(TokenKind kind, int pos, int endPos, List<Comment> comments) {
|
||||||
public String docComment;
|
|
||||||
|
|
||||||
Token(TokenKind kind, int pos, int endPos,
|
|
||||||
boolean deprecatedFlag) {
|
|
||||||
this.kind = kind;
|
this.kind = kind;
|
||||||
this.pos = pos;
|
this.pos = pos;
|
||||||
this.endPos = endPos;
|
this.endPos = endPos;
|
||||||
this.deprecatedFlag = deprecatedFlag;
|
this.comments = comments;
|
||||||
checkKind();
|
checkKind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,8 +342,8 @@ public class Tokens {
|
||||||
throw new AssertionError("Cant split - bad subtokens");
|
throw new AssertionError("Cant split - bad subtokens");
|
||||||
}
|
}
|
||||||
return new Token[] {
|
return new Token[] {
|
||||||
new Token(t1, pos, pos + t1.name.length(), deprecatedFlag),
|
new Token(t1, pos, pos + t1.name.length(), comments),
|
||||||
new Token(t2, pos + t1.name.length(), endPos, false)
|
new Token(t2, pos + t1.name.length(), endPos, null)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,14 +364,52 @@ public class Tokens {
|
||||||
public int radix() {
|
public int radix() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preserve classic semantics - if multiple javadocs are found on the token
|
||||||
|
* the last one is returned
|
||||||
|
*/
|
||||||
|
public String comment(Comment.CommentStyle style) {
|
||||||
|
List<Comment> readers = getReaders(Comment.CommentStyle.JAVADOC);
|
||||||
|
return readers.isEmpty() ?
|
||||||
|
null :
|
||||||
|
readers.head.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preserve classic semantics - deprecated should be set if at least one
|
||||||
|
* javadoc comment attached to this token contains the '@deprecated' string
|
||||||
|
*/
|
||||||
|
public boolean deprecatedFlag() {
|
||||||
|
for (Comment r : getReaders(Comment.CommentStyle.JAVADOC)) {
|
||||||
|
if (r.isDeprecated()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Comment> getReaders(Comment.CommentStyle style) {
|
||||||
|
if (comments == null) {
|
||||||
|
return List.nil();
|
||||||
|
} else {
|
||||||
|
ListBuffer<Comment> buf = ListBuffer.lb();
|
||||||
|
for (Comment r : comments) {
|
||||||
|
if (r.getStyle() == style) {
|
||||||
|
buf.add(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final static class NamedToken extends Token {
|
final static class NamedToken extends Token {
|
||||||
/** The name of this token */
|
/** The name of this token */
|
||||||
public final Name name;
|
public final Name name;
|
||||||
|
|
||||||
public NamedToken(TokenKind kind, int pos, int endPos, Name name, boolean deprecatedFlag) {
|
public NamedToken(TokenKind kind, int pos, int endPos, Name name, List<Comment> comments) {
|
||||||
super(kind, pos, endPos, deprecatedFlag);
|
super(kind, pos, endPos, comments);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,8 +429,8 @@ public class Tokens {
|
||||||
/** The string value of this token */
|
/** The string value of this token */
|
||||||
public final String stringVal;
|
public final String stringVal;
|
||||||
|
|
||||||
public StringToken(TokenKind kind, int pos, int endPos, String stringVal, boolean deprecatedFlag) {
|
public StringToken(TokenKind kind, int pos, int endPos, String stringVal, List<Comment> comments) {
|
||||||
super(kind, pos, endPos, deprecatedFlag);
|
super(kind, pos, endPos, comments);
|
||||||
this.stringVal = stringVal;
|
this.stringVal = stringVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,8 +450,8 @@ public class Tokens {
|
||||||
/** The 'radix' value of this token */
|
/** The 'radix' value of this token */
|
||||||
public final int radix;
|
public final int radix;
|
||||||
|
|
||||||
public NumericToken(TokenKind kind, int pos, int endPos, String stringVal, int radix, boolean deprecatedFlag) {
|
public NumericToken(TokenKind kind, int pos, int endPos, String stringVal, int radix, List<Comment> comments) {
|
||||||
super(kind, pos, endPos, stringVal, deprecatedFlag);
|
super(kind, pos, endPos, stringVal, comments);
|
||||||
this.radix = radix;
|
this.radix = radix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,5 +468,5 @@ public class Tokens {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Token DUMMY =
|
public static final Token DUMMY =
|
||||||
new Token(TokenKind.ERROR, 0, 0, false);
|
new Token(TokenKind.ERROR, 0, 0, null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,12 @@
|
||||||
package com.sun.tools.javac.parser;
|
package com.sun.tools.javac.parser;
|
||||||
|
|
||||||
import com.sun.tools.javac.file.JavacFileManager;
|
import com.sun.tools.javac.file.JavacFileManager;
|
||||||
import java.nio.CharBuffer;
|
|
||||||
import com.sun.tools.javac.util.Log;
|
import com.sun.tools.javac.util.Log;
|
||||||
|
import com.sun.tools.javac.util.Name;
|
||||||
|
import com.sun.tools.javac.util.Names;
|
||||||
|
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
|
||||||
import static com.sun.tools.javac.util.LayoutCharacters.*;
|
import static com.sun.tools.javac.util.LayoutCharacters.*;
|
||||||
|
|
||||||
/** The char reader used by the javac lexer/tokenizer. Returns the sequence of
|
/** The char reader used by the javac lexer/tokenizer. Returns the sequence of
|
||||||
|
@ -58,6 +62,12 @@ public class UnicodeReader {
|
||||||
protected int unicodeConversionBp = -1;
|
protected int unicodeConversionBp = -1;
|
||||||
|
|
||||||
protected Log log;
|
protected Log log;
|
||||||
|
protected Names names;
|
||||||
|
|
||||||
|
/** A character buffer for saved chars.
|
||||||
|
*/
|
||||||
|
protected char[] sbuf = new char[128];
|
||||||
|
protected int sp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a scanner from the input array. This method might
|
* Create a scanner from the input array. This method might
|
||||||
|
@ -76,6 +86,7 @@ public class UnicodeReader {
|
||||||
|
|
||||||
protected UnicodeReader(ScannerFactory sf, char[] input, int inputLength) {
|
protected UnicodeReader(ScannerFactory sf, char[] input, int inputLength) {
|
||||||
log = sf.log;
|
log = sf.log;
|
||||||
|
names = sf.names;
|
||||||
if (inputLength == input.length) {
|
if (inputLength == input.length) {
|
||||||
if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
|
if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) {
|
||||||
inputLength--;
|
inputLength--;
|
||||||
|
@ -103,6 +114,48 @@ public class UnicodeReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Read next character in comment, skipping over double '\' characters.
|
||||||
|
*/
|
||||||
|
protected void scanCommentChar() {
|
||||||
|
scanChar();
|
||||||
|
if (ch == '\\') {
|
||||||
|
if (peekChar() == '\\' && !isUnicode()) {
|
||||||
|
skipChar();
|
||||||
|
} else {
|
||||||
|
convertUnicode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Append a character to sbuf.
|
||||||
|
*/
|
||||||
|
protected void putChar(char ch, boolean scan) {
|
||||||
|
if (sp == sbuf.length) {
|
||||||
|
char[] newsbuf = new char[sbuf.length * 2];
|
||||||
|
System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
|
||||||
|
sbuf = newsbuf;
|
||||||
|
}
|
||||||
|
sbuf[sp++] = ch;
|
||||||
|
if (scan)
|
||||||
|
scanChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void putChar(char ch) {
|
||||||
|
putChar(ch, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void putChar(boolean scan) {
|
||||||
|
putChar(ch, scan);
|
||||||
|
}
|
||||||
|
|
||||||
|
Name name() {
|
||||||
|
return names.fromChars(sbuf, 0, sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
String chars() {
|
||||||
|
return new String(sbuf, 0, sp);
|
||||||
|
}
|
||||||
|
|
||||||
/** Convert unicode escape; bp points to initial '\' character
|
/** Convert unicode escape; bp points to initial '\' character
|
||||||
* (Spec 3.3).
|
* (Spec 3.3).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @bug 7104201
|
||||||
|
* @summary Refactor DocCommentScanner
|
||||||
|
* @compile/fail/ref=DeprecatedDocComment4.out -XDrawDiagnostics -Werror -Xlint:dep-ann DeprecatedDocComment4.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DeprecatedDocComment4 {
|
||||||
|
/** @deprecated **/
|
||||||
|
/* block */
|
||||||
|
void test1() {};
|
||||||
|
|
||||||
|
/** @deprecated **/
|
||||||
|
/** double javadoc */
|
||||||
|
void test2() {};
|
||||||
|
|
||||||
|
/** @deprecated **/
|
||||||
|
//line comment
|
||||||
|
void test3() {};
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
DeprecatedDocComment4.java:11:10: compiler.warn.missing.deprecated.annotation
|
||||||
|
DeprecatedDocComment4.java:15:10: compiler.warn.missing.deprecated.annotation
|
||||||
|
DeprecatedDocComment4.java:19:10: compiler.warn.missing.deprecated.annotation
|
||||||
|
- compiler.err.warnings.and.werror
|
||||||
|
1 error
|
||||||
|
3 warnings
|
Loading…
Add table
Add a link
Reference in a new issue