Index: codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java =================================================================== retrieving revision 1.34 diff -u -r1.34 CompletionScanner.java --- codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java 17 Nov 2003 10:17:08 -0000 1.34 +++ codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java 1 Dec 2003 18:29:22 -0000 @@ -544,7 +544,7 @@ currentPosition++; } //jump over the \\ } - recordComment(false); + recordComment(TokenNameCOMMENT_LINE); if (startPosition <= cursorLocation && cursorLocation < currentPosition-1){ throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT); } @@ -556,7 +556,7 @@ return TokenNameCOMMENT_LINE; } } catch (IndexOutOfBoundsException e) { - recordComment(false); + recordComment(TokenNameCOMMENT_LINE); if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition-1); if (tokenizeComments) { this.currentPosition--; // reset one character behind @@ -650,14 +650,18 @@ currentPosition++; } //jump over the \\ } - recordComment(isJavadoc); + int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK; + recordComment(token); if (startPosition <= cursorLocation && cursorLocation < currentPosition-1){ throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT); } if (tokenizeComments) { + /* if (isJavadoc) return TokenNameCOMMENT_JAVADOC; return TokenNameCOMMENT_BLOCK; + */ + return token; } } catch (IndexOutOfBoundsException e) { throw new InvalidInputException(UNTERMINATED_COMMENT); Index: compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java =================================================================== retrieving revision 1.33 diff -u -r1.33 CompilationUnitDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java 22 Nov 2003 16:01:00 -0000 1.33 +++ compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java 1 Dec 2003 18:29:22 -0000 @@ -23,6 +23,7 @@ public ImportReference currentPackage; public ImportReference[] imports; public TypeDeclaration[] types; + public int[][] comments; public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors public boolean ignoreMethodBodies = false; Index: compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java =================================================================== retrieving revision 1.4 diff -u -r1.4 JavadocParser.java --- compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java 1 Dec 2003 09:45:32 -0000 1.4 +++ compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java 1 Dec 2003 18:29:23 -0000 @@ -529,7 +529,7 @@ if (iToken == 0) { return null; } - if ((iToken % 2) == 0) { // dots must be followed by an identifier + if ((iToken % 2) == 0) { // cannot leave on a dot throw new InvalidInputException(); } break nextToken; Index: compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java =================================================================== retrieving revision 1.101 diff -u -r1.101 Scanner.java --- compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java 21 Nov 2003 01:34:38 -0000 1.101 +++ compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java 1 Dec 2003 18:29:23 -0000 @@ -23,6 +23,8 @@ * The mirror implementation is using the backward compatible ITerminalSymbols constant * definitions (stable with 2.0), whereas the internal implementation uses TerminalTokens * which constant values reflect the latest parser generation state. + * @see org.eclipse.jdt.core.compiler.ITerminalSymbols + * @see org.eclipse.jdt.internal.core.util.PublicScanner */ public class Scanner implements TerminalTokens { @@ -395,7 +397,7 @@ } public final char[] getRawTokenSourceEnd() { - int length = this.eofPosition - this.currentPosition; + int length = this.eofPosition - this.currentPosition - 1; char[] sourceEnd = new char[length]; System.arraycopy(source, this.currentPosition, sourceEnd, 0, length); return sourceEnd; @@ -1312,7 +1314,7 @@ } } } - recordComment(false); + recordComment(TokenNameCOMMENT_LINE); if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition); if ((currentCharacter == '\r') || (currentCharacter == '\n')) { checkNonExternalizedString(); @@ -1331,7 +1333,7 @@ } } catch (IndexOutOfBoundsException e) { currentPosition--; - recordComment(false); + recordComment(TokenNameCOMMENT_LINE); if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition); if (tokenizeComments) { return TokenNameCOMMENT_LINE; @@ -1386,6 +1388,12 @@ if (source[currentPosition] == '\\') currentPosition++; //jump over the \\ } + + // In case of /**/ set back to non-javadoc comment + if (currentCharacter == '/') { + isJavadoc = false; + } + //loop until end of comment */ while ((currentCharacter != '/') || (!star)) { if ((currentCharacter == '\r') || (currentCharacter == '\n')) { @@ -1414,12 +1422,16 @@ currentPosition++; } //jump over the \\ } - recordComment(isJavadoc); + int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK; + recordComment(token); if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition); if (tokenizeComments) { + /* if (isJavadoc) return TokenNameCOMMENT_JAVADOC; return TokenNameCOMMENT_BLOCK; + */ + return token; } } catch (IndexOutOfBoundsException e) { throw new InvalidInputException(UNTERMINATED_COMMENT); @@ -2217,17 +2229,17 @@ } } } -public final void recordComment(boolean isJavadoc) { +public void recordComment(int token) { // a new comment is recorded try { - this.commentStops[++this.commentPtr] = isJavadoc ? this.currentPosition : -this.currentPosition; + this.commentStops[++this.commentPtr] = (token==TokenNameCOMMENT_JAVADOC) ? this.currentPosition : -this.currentPosition; } catch (IndexOutOfBoundsException e) { int oldStackLength = this.commentStops.length; int[] oldStack = this.commentStops; this.commentStops = new int[oldStackLength + 30]; System.arraycopy(oldStack, 0, this.commentStops, 0, oldStackLength); - this.commentStops[this.commentPtr] = isJavadoc ? this.currentPosition : -this.currentPosition; + this.commentStops[this.commentPtr] = (token==TokenNameCOMMENT_JAVADOC) ? this.currentPosition : -this.currentPosition; //grows the positions buffers too int[] old = this.commentStarts; this.commentStarts = new int[oldStackLength + 30]; Index: dom/org/eclipse/jdt/core/dom/AST.java =================================================================== retrieving revision 1.58 diff -u -r1.58 AST.java --- dom/org/eclipse/jdt/core/dom/AST.java 20 Nov 2003 20:39:52 -0000 1.58 +++ dom/org/eclipse/jdt/core/dom/AST.java 1 Dec 2003 18:29:23 -0000 @@ -14,20 +14,11 @@ import java.util.Map; import org.eclipse.jdt.core.*; -import org.eclipse.jdt.core.IClassFile; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; -import org.eclipse.jdt.internal.compiler.parser.Scanner; import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.core.*; -import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner; -import org.eclipse.jdt.internal.core.JavaModelManager; -import org.eclipse.jdt.internal.core.NameLookup; /** * Umbrella owner and abstract syntax tree node factory. @@ -69,7 +60,7 @@ * subclassed. *
* - * @see #parseCompilationUnit(ICompilationUnit, boolean) + * @see #parseCompilationUnit(char[]) and other similar methods * @see ASTNode * @since 2.0 */ @@ -85,9 +76,19 @@ * Java Scanner used to validate preconditions for the creation of specific nodes * like CharacterLiteral, NumberLiteral, StringLiteral or SimpleName. */ - Scanner scanner; + DOMScanner scanner; /** + * Flags to set options while DOM parsing. + */ + public final static int ResolveBindings = 0x00000001; + + /** + * + */ + public final static int InsideComments = 0x00000002; + + /** * Creates a new, empty abstract syntax tree using default options. * * @see JavaCore#getDefaultOptions() @@ -116,7 +117,7 @@ * @see JavaCore#getDefaultOptions() */ public AST(Map options) { - this.scanner = new Scanner( + this.scanner = new DOMScanner( true /*comment*/, true /*whitespace*/, false /*nls*/, @@ -151,7 +152,7 @@ * this AST */ public long modificationCount() { - return modCount; + return this.modCount; } /** @@ -181,7 +182,7 @@ */ void modifying() { // increase the modification count - modCount++; + this.modCount++; } /** @@ -235,16 +236,91 @@ * @return the compilation unit node * @exception IllegalArgumentException if the given Java element does not * exist or if its source string cannot be obtained + * @deprecated Use #parseCompilationUnit(CompilationUnit, int) + */ + public static CompilationUnit parseCompilationUnit( + ICompilationUnit unit, + boolean resolveBindings) { + + return parseCompilationUnit(unit, resolveBindings?ResolveBindings:0); + } + + /** + * Parses the source string of the given Java model compilation unit element + * and creates and returns a corresponding abstract syntax tree. The source + * string is obtained from the Java model element using + *ICompilationUnit.getSource()
.
+ *
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the source string (the source string is not remembered
+ * with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as MALFORMED
.
+ *
+ * Several options are available while parsing the compilation unit: + *
ResolveBindings
+ * When this flag is set, the various names and types appearing in
+ * the compilation unit can be resolved to "bindings" by calling
+ * the resolveBinding
methods. These bindings draw
+ * connections between the different parts of a program, and generally
+ * afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come
+ * at a considerable cost in both time and space, however, and should
+ * not be requested frivolously. The additional space is not reclaimed
+ * until the AST, all its nodes, and all its bindings become garbage.
+ * So it is very important to not retain any of these objects longer
+ * than absolutely necessary. Bindings are resolved at the time the
+ * AST is created. Subsequent modifications to the AST do not affect
+ * the bindings returned by resolveBinding
methods in
+ * any way; these methods return the same binding as before the AST
+ * was modified (including modifications that rearrange subtrees by
+ * reparenting nodes).
+ * When this flag is not set, the analysis does not go beyond parsing
+ * and building the tree, and all resolveBinding
methods
+ * return null
from the outset.
+ * InsideComments
+ * When this flag is set, all comments of the compilation unit are stored
+ * and parsed to identify possible Javadoc tags.
+ * Comments are stored in a list comments
of Comment
.
+ * There are three different kind of comments: line, block and javadoc.
+ * Javadoc comments are those which were already defined since version 2.0,
+ * but they are now structured and not only a flat text.
+ * @see Javadoc for more details on this AST node structure
+ * ResolveBindings | InsideComments
+ *
+ *
+ * @param unit the Java model compilation unit whose source code is to be parsed
+ * @param options an integer which sets parse options.
+ * @return the compilation unit node
+ * @exception IllegalArgumentException if the given Java element does not
+ * exist or if its source string cannot be obtained
* @see ASTNode#getFlags()
* @see ASTNode#MALFORMED
* @see ASTNode#getStartPosition()
* @see ASTNode#getLength()
+ * @since 3.0
*/
- public static CompilationUnit parseCompilationUnit(
- ICompilationUnit unit,
- boolean resolveBindings) {
+ public static CompilationUnit parseCompilationUnit(ICompilationUnit unit, int options) {
- return parseCompilationUnit(unit, resolveBindings, DefaultWorkingCopyOwner.PRIMARY);
+ return parseCompilationUnit(unit, options, DefaultWorkingCopyOwner.PRIMARY);
}
/**
@@ -311,11 +387,102 @@
* @see ASTNode#getStartPosition()
* @see ASTNode#getLength()
* @see WorkingCopyOwner
+ * @deprecated Use #parseCompilationUnit(CompilationUnit, int, WorkingCopyOwner)
+ * @since 3.0
+ * TODO (frederic) remove for 3.0
+ */
+ public static CompilationUnit parseCompilationUnit(
+ ICompilationUnit unit,
+ boolean resolveBindings,
+ WorkingCopyOwner owner) {
+ return parseCompilationUnit(unit, resolveBindings?ResolveBindings:0, owner);
+ }
+
+ /**
+ * Parses the source string of the given Java model compilation unit element
+ * and creates and returns a corresponding abstract syntax tree. The source
+ * string is obtained from the Java model element using
+ * ICompilationUnit.getSource()
.
+ *
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the source string (the source string is not remembered
+ * with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as MALFORMED
.
+ *
+ * Several options are available while parsing the compilation unit: + *
ResolveBindings
+ * When this flag is set, the various names and types appearing in
+ * the compilation unit can be resolved to "bindings" by calling
+ * the resolveBinding
methods. These bindings draw
+ * connections between the different parts of a program, and generally
+ * afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come
+ * at a considerable cost in both time and space, however, and should
+ * not be requested frivolously. The additional space is not reclaimed
+ * until the AST, all its nodes, and all its bindings become garbage.
+ * So it is very important to not retain any of these objects longer
+ * than absolutely necessary. Bindings are resolved at the time the
+ * AST is created. Subsequent modifications to the AST do not affect
+ * the bindings returned by resolveBinding
methods in
+ * any way; these methods return the same binding as before the AST
+ * was modified (including modifications that rearrange subtrees by
+ * reparenting nodes).
+ * When this flag is not set, the analysis does not go beyond parsing
+ * and building the tree, and all resolveBinding
methods
+ * return null
from the outset.
+ * InsideComments
+ * When this flag is set, all comments of the compilation unit are stored
+ * and parsed to identify possible Javadoc tags.
+ * Comments are stored in a list comments
of Comment
.
+ * There are three different kind of comments: line, block and javadoc.
+ * Javadoc comments are those which were already defined since version 2.0,
+ * but they are now structured and not only a flat text.
+ * @see Javadoc for more details on this AST node structure
+ * ResolveBindings | InsideComments
+ *
+ *
+ * When bindings are created, instead of considering compilation units on disk only
+ * one can supply a WorkingCopyOwner
. Working copies owned
+ * by this owner take precedence over the underlying compilation units when looking
+ * up names and drawing the connections.
+ *
IClassFile.getSource()
, and is only available for a class
+ * files with attached source.
+ *
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the source string (the source string is not remembered
+ * with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as MALFORMED
.
+ *
+ * Several options are available while parsing the compilation unit: + *
ResolveBindings
+ * When this flag is set, the various names and types appearing in
+ * the compilation unit can be resolved to "bindings" by calling
+ * the resolveBinding
methods. These bindings draw
+ * connections between the different parts of a program, and generally
+ * afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come
+ * at a considerable cost in both time and space, however, and should
+ * not be requested frivolously. The additional space is not reclaimed
+ * until the AST, all its nodes, and all its bindings become garbage.
+ * So it is very important to not retain any of these objects longer
+ * than absolutely necessary. Bindings are resolved at the time the
+ * AST is created. Subsequent modifications to the AST do not affect
+ * the bindings returned by resolveBinding
methods in
+ * any way; these methods return the same binding as before the AST
+ * was modified (including modifications that rearrange subtrees by
+ * reparenting nodes).
+ * When this flag is not set, the analysis does not go beyond parsing
+ * and building the tree, and all resolveBinding
methods
+ * return null
from the outset.
+ * InsideComments
+ * When this flag is set, all comments of the compilation unit are stored
+ * and parsed to identify possible Javadoc tags.
+ * Comments are stored in a list comments
of Comment
.
+ * There are three different kind of comments: line, block and javadoc.
+ * Javadoc comments are those which were already defined since version 2.0,
+ * but they are now structured and not only a flat text.
+ * @see Javadoc for more details on this AST node structure
+ * ResolveBindings | InsideComments
+ *
+ *
+ * @param classFile the Java model compilation unit whose source code is to be parsed
+ * @param options an integer which sets parse options.
+ * @return the compilation unit node
+ * @exception IllegalArgumentException if the given Java element does not
+ * exist or if its source string cannot be obtained
+ * @see ASTNode#getFlags()
+ * @see ASTNode#MALFORMED
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ * @since 3.0
+ */
+ public static CompilationUnit parseCompilationUnit(IClassFile classFile, int options) {
+
+ return parseCompilationUnit(classFile, options, DefaultWorkingCopyOwner.PRIMARY);
+ }
+
/**
* Parses the source string corresponding to the given Java class file
* element and creates and returns a corresponding abstract syntax tree.
@@ -505,10 +752,102 @@
* @see ASTNode#getLength()
* @see WorkingCopyOwner
* @since 3.0
+ * @deprecated Use #parseCompilationUnit(IClassFile, int, WorkingCopyOwner)
+ * TODO (frederic) remove for 3.0
+ */
+ public static CompilationUnit parseCompilationUnit(
+ IClassFile classFile,
+ boolean resolveBindings,
+ WorkingCopyOwner owner) {
+ return parseCompilationUnit(classFile, resolveBindings?ResolveBindings:0, owner);
+ }
+
+ /**
+ * Parses the source string corresponding to the given Java class file
+ * element and creates and returns a corresponding abstract syntax tree.
+ * The source string is obtained from the Java model element using
+ * IClassFile.getSource()
, and is only available for a class
+ * files with attached source.
+ *
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the source string (the source string is not remembered
+ * with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as MALFORMED
.
+ *
+ * Several options are available while parsing the compilation unit: + *
ResolveBindings
+ * When this flag is set, the various names and types appearing in
+ * the compilation unit can be resolved to "bindings" by calling
+ * the resolveBinding
methods. These bindings draw
+ * connections between the different parts of a program, and generally
+ * afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come
+ * at a considerable cost in both time and space, however, and should
+ * not be requested frivolously. The additional space is not reclaimed
+ * until the AST, all its nodes, and all its bindings become garbage.
+ * So it is very important to not retain any of these objects longer
+ * than absolutely necessary. Bindings are resolved at the time the
+ * AST is created. Subsequent modifications to the AST do not affect
+ * the bindings returned by resolveBinding
methods in
+ * any way; these methods return the same binding as before the AST
+ * was modified (including modifications that rearrange subtrees by
+ * reparenting nodes).
+ * When this flag is not set, the analysis does not go beyond parsing
+ * and building the tree, and all resolveBinding
methods
+ * return null
from the outset.
+ * InsideComments
+ * When this flag is set, all comments of the compilation unit are stored
+ * and parsed to identify possible Javadoc tags.
+ * Comments are stored in a list comments
of Comment
.
+ * There are three different kind of comments: line, block and javadoc.
+ * Javadoc comments are those which were already defined since version 2.0,
+ * but they are now structured and not only a flat text.
+ * @see Javadoc for more details on this AST node structure
+ * ResolveBindings | InsideComments
+ *
+ *
+ * When bindings are created, instead of considering compilation units on disk only
+ * one can supply a WorkingCopyOwner
. Working copies owned
+ * by this owner take precedence over the underlying compilation units when looking
+ * up names and drawing the connections.
+ *
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the given source string (the given source string itself
+ * is not remembered with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as MALFORMED
.
+ *
+ * If the given project is not null
, the various names
+ * and types appearing in the compilation unit can be resolved to "bindings"
+ * by calling the resolveBinding
methods. These bindings
+ * draw connections between the different parts of a program, and
+ * generally afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come at a
+ * considerable cost in both time and space, however, and should not be
+ * requested frivolously. The additional space is not reclaimed until the
+ * AST, all its nodes, and all its bindings become garbage. So it is very
+ * important to not retain any of these objects longer than absolutely
+ * necessary. Bindings are resolved at the time the AST is created. Subsequent
+ * modifications to the AST do not affect the bindings returned by
+ * resolveBinding
methods in any way; these methods return the
+ * same binding as before the AST was modified (including modifications
+ * that rearrange subtrees by reparenting nodes).
+ * If the given project is null
, the analysis
+ * does not go beyond parsing and building the tree, and all
+ * resolveBinding
methods return null
from the
+ * outset.
+ *
+ * The name of the compilation unit must be supplied for resolving bindings. + * This name should include the ".java" suffix and match the name of the main + * (public) class or interface declared in the source. For example, if the source + * declares a public class named "Foo", the name of the compilation should be + * "Foo.java". For the purposes of resolving bindings, types declared in the + * source string hide types by the same name available through the classpath + * of the given project. + *
+ * + * @param source the string to be parsed as a Java compilation unit + * @param unitName the name of the compilation unit that would contain the source + * string, ornull
if javaProject
is also null
+ * @param project the Java project used to resolve names, or
+ * null
if bindings are not resolved
+ * @return the compilation unit node
+ * @see ASTNode#getFlags()
+ * @see ASTNode#MALFORMED
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ * @deprecated Use #parseCompilationUnit(char(], int, String, JavaProject)
+ */
+ public static CompilationUnit parseCompilationUnit(
+ char[] source,
+ String unitName,
+ IJavaProject project) {
+
+ return parseCompilationUnit(source, unitName, project, DefaultWorkingCopyOwner.PRIMARY);
+ }
+
+ /**
+ * Parses the given string as the hypothetical contents of the named
+ * compilation unit and creates and returns a corresponding abstract syntax tree.
+ *
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the given source string (the given source string itself
+ * is not remembered with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as MALFORMED
.
+ *
+ * If the given project is not null
, the various names
+ * and types appearing in the compilation unit can be resolved to "bindings"
+ * by calling the resolveBinding
methods. These bindings
+ * draw connections between the different parts of a program, and
+ * generally afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come at a
+ * considerable cost in both time and space, however, and should not be
+ * requested frivolously. The additional space is not reclaimed until the
+ * AST, all its nodes, and all its bindings become garbage. So it is very
+ * important to not retain any of these objects longer than absolutely
+ * necessary. Bindings are resolved at the time the AST is created. Subsequent
+ * modifications to the AST do not affect the bindings returned by
+ * resolveBinding
methods in any way; these methods return the
+ * same binding as before the AST was modified (including modifications
+ * that rearrange subtrees by reparenting nodes).
+ * If the given project is null
, the analysis
+ * does not go beyond parsing and building the tree, and all
+ * resolveBinding
methods return null
from the
+ * outset.
+ *
+ * Several options are available while parsing the compilation unit: + *
ResolveBindings
+ * When this flag is set, the various names and types appearing in
+ * the compilation unit can be resolved to "bindings" by calling
+ * the resolveBinding
methods. These bindings draw
+ * connections between the different parts of a program, and generally
+ * afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come
+ * at a considerable cost in both time and space, however, and should
+ * not be requested frivolously. The additional space is not reclaimed
+ * until the AST, all its nodes, and all its bindings become garbage.
+ * So it is very important to not retain any of these objects longer
+ * than absolutely necessary. Bindings are resolved at the time the
+ * AST is created. Subsequent modifications to the AST do not affect
+ * the bindings returned by resolveBinding
methods in
+ * any way; these methods return the same binding as before the AST
+ * was modified (including modifications that rearrange subtrees by
+ * reparenting nodes).
+ * When this flag is not set, the analysis does not go beyond parsing
+ * and building the tree, and all resolveBinding
methods
+ * return null
from the outset.
+ * InsideComments
+ * When this flag is set, all comments of the compilation unit are stored
+ * and parsed to identify possible Javadoc tags.
+ * Comments are stored in a list comments
of Comment
.
+ * There are three different kind of comments: line, block and javadoc.
+ * Javadoc comments are those which were already defined since version 2.0,
+ * but they are now structured and not only a flat text.
+ * @see Javadoc for more details on this AST node structure
+ * ResolveBindings | InsideComments
.
+ * Note that if the given project is null
, bindings won't be
+ * resolved even if resolve binding option is set.
+ *
+ * + * The name of the compilation unit must be supplied for resolving bindings. + * This name should include the ".java" suffix and match the name of the main + * (public) class or interface declared in the source. For example, if the source + * declares a public class named "Foo", the name of the compilation should be + * "Foo.java". For the purposes of resolving bindings, types declared in the + * source string hide types by the same name available through the classpath + * of the given project. + *
+ * + * @param source the string to be parsed as a Java compilation unit + * @param options an integer which sets parse options. + * @param unitName the name of the compilation unit that would contain the source + * string, ornull
if javaProject
is also null
+ * @param project the Java project used to resolve names, or
+ * null
if bindings are not resolved
+ * @return the compilation unit node
+ * @see ASTNode#getFlags()
+ * @see ASTNode#MALFORMED
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ * @since 3.0
+ */
+ public static CompilationUnit parseCompilationUnit(
+ char[] source,
+ int options,
+ String unitName,
+ IJavaProject project) {
+
+ return parseCompilationUnit(source, options, unitName, project, DefaultWorkingCopyOwner.PRIMARY);
}
-
+
/**
* Parses the given string as the hypothetical contents of the named
* compilation unit and creates and returns a corresponding abstract syntax tree.
@@ -622,6 +1147,12 @@
* outset.
*
*
+ * When bindings are created, instead of considering compilation units on disk only
+ * one can supply a WorkingCopyOwner
. Working copies owned
+ * by this owner take precedence over the underlying compilation units when looking
+ * up names and drawing the connections.
+ *
* The name of the compilation unit must be supplied for resolving bindings.
* This name should include the ".java" suffix and match the name of the main
* (public) class or interface declared in the source. For example, if the source
@@ -636,20 +1167,26 @@
* string, or null
if javaProject
is also null
* @param project the Java project used to resolve names, or
* null
if bindings are not resolved
+ * @param owner the owner of working copies that take precedence over underlying
+ * compilation units
* @return the compilation unit node
* @see ASTNode#getFlags()
* @see ASTNode#MALFORMED
* @see ASTNode#getStartPosition()
* @see ASTNode#getLength()
+ * @see WorkingCopyOwner
+ * @since 3.0
+ * @deprecated Use #parseCompilationUnit(char(], int, String, JavaProject, WorkingCopyOwner)
+ * TODO (frederic) remove for 3.0
*/
public static CompilationUnit parseCompilationUnit(
- char[] source,
- String unitName,
- IJavaProject project) {
-
- return parseCompilationUnit(source, unitName, project, DefaultWorkingCopyOwner.PRIMARY);
+ char[] source,
+ String unitName,
+ IJavaProject project,
+ WorkingCopyOwner owner) {
+ return parseCompilationUnit(source, ResolveBindings, unitName, project, owner);
}
-
+
/**
* Parses the given string as the hypothetical contents of the named
* compilation unit and creates and returns a corresponding abstract syntax tree.
@@ -672,25 +1209,44 @@
* tree will be flagged as MALFORMED
.
*
- * If the given project is not null
, the various names
- * and types appearing in the compilation unit can be resolved to "bindings"
- * by calling the resolveBinding
methods. These bindings
- * draw connections between the different parts of a program, and
- * generally afford a more powerful vantage point for clients who wish to
- * analyze a program's structure more deeply. These bindings come at a
- * considerable cost in both time and space, however, and should not be
- * requested frivolously. The additional space is not reclaimed until the
- * AST, all its nodes, and all its bindings become garbage. So it is very
- * important to not retain any of these objects longer than absolutely
- * necessary. Bindings are resolved at the time the AST is created. Subsequent
- * modifications to the AST do not affect the bindings returned by
- * resolveBinding
methods in any way; these methods return the
- * same binding as before the AST was modified (including modifications
- * that rearrange subtrees by reparenting nodes).
- * If the given project is null
, the analysis
- * does not go beyond parsing and building the tree, and all
- * resolveBinding
methods return null
from the
- * outset.
+ * Several options are available while parsing the compilation unit:
+ *
ResolveBindings
+ * When this flag is set, the various names and types appearing in
+ * the compilation unit can be resolved to "bindings" by calling
+ * the resolveBinding
methods. These bindings draw
+ * connections between the different parts of a program, and generally
+ * afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come
+ * at a considerable cost in both time and space, however, and should
+ * not be requested frivolously. The additional space is not reclaimed
+ * until the AST, all its nodes, and all its bindings become garbage.
+ * So it is very important to not retain any of these objects longer
+ * than absolutely necessary. Bindings are resolved at the time the
+ * AST is created. Subsequent modifications to the AST do not affect
+ * the bindings returned by resolveBinding
methods in
+ * any way; these methods return the same binding as before the AST
+ * was modified (including modifications that rearrange subtrees by
+ * reparenting nodes).
+ * When this flag is not set, the analysis does not go beyond parsing
+ * and building the tree, and all resolveBinding
methods
+ * return null
from the outset.
+ * InsideComments
+ * When this flag is set, all comments of the compilation unit are stored
+ * and parsed to identify possible Javadoc tags.
+ * Comments are stored in a list comments
of Comment
.
+ * There are three different kind of comments: line, block and javadoc.
+ * Javadoc comments are those which were already defined since version 2.0,
+ * but they are now structured and not only a flat text.
+ * @see Javadoc for more details on this AST node structure
+ * ResolveBindings | InsideComments
.
+ * Note that if the given project is null
, bindings won't be
+ * resolved even if resolve binding option is set.
*
* * When bindings are created, instead of considering compilation units on disk only @@ -709,6 +1265,7 @@ *
* * @param source the string to be parsed as a Java compilation unit + * @param options an integer which sets parse options. * @param unitName the name of the compilation unit that would contain the source * string, ornull
if javaProject
is also null
* @param project the Java project used to resolve names, or
@@ -725,6 +1282,7 @@
*/
public static CompilationUnit parseCompilationUnit(
char[] source,
+ int options,
String unitName,
IJavaProject project,
WorkingCopyOwner owner) {
@@ -759,7 +1317,7 @@
unitName,
project,
false/*don't cleanup*/);
- ASTConverter converter = new ASTConverter(project.getOptions(true), true);
+ ASTConverter converter = new ASTConverter(project.getOptions(true), (ResolveBindings | options));
AST ast = new AST();
BindingResolver resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope);
ast.setBindingResolver(resolver);
@@ -784,7 +1342,7 @@
}
}
}
-
+
/**
* Parses the given string as a Java compilation unit and creates and
* returns a corresponding abstract syntax tree.
@@ -819,13 +1377,85 @@
* @see ASTNode#getLength()
*/
public static CompilationUnit parseCompilationUnit(char[] source) {
+ return parseCompilationUnit(source, 0); // No bindings, no comments
+ }
+
+ /**
+ * Parses the given string as a Java compilation unit and creates and
+ * returns a corresponding abstract syntax tree.
+ *
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the given source string (the given source string itself
+ * is not remembered with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included. There are a handful of exceptions
+ * (including compilation units and the various body declarations); the
+ * specification for these node type spells out the details.
+ * Source ranges nest properly: the source range for a child is always
+ * within the source range of its parent, and the source ranges of sibling
+ * nodes never overlap.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as MALFORMED
.
+ *
+ * Several options are available while parsing the source: + *
ResolveBindings
+ * When this flag is set, the various names and types appearing in
+ * the compilation unit can be resolved to "bindings" by calling
+ * the resolveBinding
methods. These bindings draw
+ * connections between the different parts of a program, and generally
+ * afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come
+ * at a considerable cost in both time and space, however, and should
+ * not be requested frivolously. The additional space is not reclaimed
+ * until the AST, all its nodes, and all its bindings become garbage.
+ * So it is very important to not retain any of these objects longer
+ * than absolutely necessary. Bindings are resolved at the time the
+ * AST is created. Subsequent modifications to the AST do not affect
+ * the bindings returned by resolveBinding
methods in
+ * any way; these methods return the same binding as before the AST
+ * was modified (including modifications that rearrange subtrees by
+ * reparenting nodes).
+ * When this flag is not set, the analysis does not go beyond parsing
+ * and building the tree, and all resolveBinding
methods
+ * return null
from the outset.
+ * InsideComments
+ * When this flag is set, all comments of the compilation unit are stored
+ * and parsed to identify possible Javadoc tags.
+ * Comments are stored in a list comments
of Comment
.
+ * There are three different kind of comments: line, block and javadoc.
+ * Javadoc comments are those which were already defined since version 2.0,
+ * but they are now structured and not only a flat text.
+ * @see Javadoc for more details on this AST node structure
+ * ResolveBindings | InsideComments
.
+ *
+ *
+ * @param source the string to be parsed as a Java compilation unit
+ * @param options an integer which sets parse options.
+ * @return CompilationUnit
+ * @see ASTNode#getFlags()
+ * @see ASTNode#MALFORMED
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ */
+ public static CompilationUnit parseCompilationUnit(char[] source, int options) {
if (source == null) {
throw new IllegalArgumentException();
}
CompilationUnitDeclaration compilationUnitDeclaration =
CompilationUnitResolver.parse(source, JavaCore.getOptions()); // no better custom options
- ASTConverter converter = new ASTConverter(JavaCore.getOptions(), false);
+ ASTConverter converter = new ASTConverter(JavaCore.getOptions(), options);
AST ast = new AST();
ast.setBindingResolver(new BindingResolver());
converter.setAST(ast);
@@ -926,15 +1556,132 @@
* @see ASTNode#getStartPosition()
* @see ASTNode#getLength()
* @since 3.0
+ * @deprecated Use parsePartialCompilationUnit(ICompilationUnit, int, int)
+ * TODO (frederic) remove for 3.0
*/
public static CompilationUnit parsePartialCompilationUnit(
ICompilationUnit unit,
int position,
boolean resolveBindings) {
- return parsePartialCompilationUnit(unit, position, resolveBindings, DefaultWorkingCopyOwner.PRIMARY);
+ return parsePartialCompilationUnit(
+ unit,
+ position,
+ resolveBindings?ResolveBindings:0);
}
/**
+ * Parses the source string of the given Java model compilation unit element
+ * and creates and returns an abridged abstract syntax tree. This method
+ * differs from
+ * {@link #parseCompilationUnit(ICompilationUnit,boolean)
+ * parseCompilationUnit(ICompilationUnit,boolean)} only in
+ * that the resulting AST does not have nodes for the entire compilation
+ * unit. Rather, the AST is only fleshed out for the node that include
+ * the given source position. This kind of limited AST is sufficient for
+ * certain purposes but totally unsuitable for others. In places where it
+ * can be used, the limited AST offers the advantage of being smaller and
+ * faster to faster to construct.
+ *
+ * + * The resulting AST always includes nodes for all of the compilation unit's + * package, import, and top-level type declarations. It also always contains + * nodes for all the body declarations for those top-level types, as well + * as body declarations for any member types. However, some of the body + * declarations may be abridged. In particular, the statements ordinarily + * found in the body of a method declaration node will not be included + * (the block will be empty) unless the source position falls somewhere + * within the source range of that method declaration node. The same is true + * for initializer declarations; the statements ordinarily found in the body + * of initializer node will not be included unless the source position falls + * somewhere within the source range of that initializer declaration node. + * Field declarations are never abridged. Note that the AST for the body of + * that one unabridged method (or initializer) is 100% complete; it has all + * its statements, including any local or anonymous type declarations + * embedded within them. When the the given position is not located within + * the source range of any body declaration of a top-level type, the AST + * returned is a skeleton that includes nodes for all and only the major + * declarations; this kind of AST is still quite useful because it contains + * all the constructs that introduce names visible to the world outside the + * compilation unit. + *
+ *
+ * In all other respects, this method works the same as
+ * {@link #parseCompilationUnit(ICompilationUnit,boolean)
+ * parseCompilationUnit(ICompilationUnit,boolean)}.
+ * The source string is obtained from the Java model element using
+ * ICompilationUnit.getSource()
.
+ *
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the source string (the source string is not remembered
+ * with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as MALFORMED
.
+ *
+ * Several options are available while parsing the source: + *
ResolveBindings
+ * When this flag is set, the various names and types appearing in
+ * the compilation unit can be resolved to "bindings" by calling
+ * the resolveBinding
methods. These bindings draw
+ * connections between the different parts of a program, and generally
+ * afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come
+ * at a considerable cost in both time and space, however, and should
+ * not be requested frivolously. The additional space is not reclaimed
+ * until the AST, all its nodes, and all its bindings become garbage.
+ * So it is very important to not retain any of these objects longer
+ * than absolutely necessary. Bindings are resolved at the time the
+ * AST is created. Subsequent modifications to the AST do not affect
+ * the bindings returned by resolveBinding
methods in
+ * any way; these methods return the same binding as before the AST
+ * was modified (including modifications that rearrange subtrees by
+ * reparenting nodes).
+ * When this flag is not set, the analysis does not go beyond parsing
+ * and building the tree, and all resolveBinding
methods
+ * return null
from the outset.
+ * InsideComments
+ * When this flag is set, all comments of the compilation unit are stored
+ * and parsed to identify possible Javadoc tags.
+ * Comments are stored in a list comments
of Comment
.
+ * There are three different kind of comments: line, block and javadoc.
+ * Javadoc comments are those which were already defined since version 2.0,
+ * but they are now structured and not only a flat text.
+ * @see Javadoc for more details on this AST node structure
+ * ResolveBindings | InsideComments
.
+ *
+ *
+ * @param unit the Java model compilation unit whose source code is to be parsed
+ * @param position a position into the corresponding body declaration
+ * @param options an integer which sets parse options.
+ * @return the abridged compilation unit node
+ * @exception IllegalArgumentException if the given Java element does not
+ * exist or if its source string cannot be obtained
+ * @see ASTNode#getFlags()
+ * @see ASTNode#MALFORMED
+ * @see ASTNode#getStartPosition()
+ * @see ASTNode#getLength()
+ * @since 3.0
+ */
+ public static CompilationUnit parsePartialCompilationUnit(
+ ICompilationUnit unit,
+ int position,
+ int options) {
+ return parsePartialCompilationUnit(unit, position, options, DefaultWorkingCopyOwner.PRIMARY);
+ }
+
/**
* Parses the source string of the given Java model compilation unit element
* and creates and returns an abridged abstract syntax tree. This method
@@ -1032,11 +1779,138 @@
* @see ASTNode#getStartPosition()
* @see ASTNode#getLength()
* @since 3.0
+ * @deprecated Use parsePartialCompilationUnit(ICompilationUnit, int, int, WorkingCopyOwner)
+ * TODO (frederic) remove for 3.0
+ */
+ public static CompilationUnit parsePartialCompilationUnit(
+ ICompilationUnit unit,
+ int position,
+ boolean resolveBindings,
+ WorkingCopyOwner owner) {
+ return parsePartialCompilationUnit(
+ unit,
+ position,
+ resolveBindings ? ResolveBindings : 0,
+ DefaultWorkingCopyOwner.PRIMARY);
+ }
+ /**
+ * Parses the source string of the given Java model compilation unit element
+ * and creates and returns an abridged abstract syntax tree. This method
+ * differs from
+ * {@link #parseCompilationUnit(ICompilationUnit,boolean,WorkingCopyOwner)
+ * parseCompilationUnit(ICompilationUnit,boolean,WorkingCopyOwner)} only in
+ * that the resulting AST does not have nodes for the entire compilation
+ * unit. Rather, the AST is only fleshed out for the node that include
+ * the given source position. This kind of limited AST is sufficient for
+ * certain purposes but totally unsuitable for others. In places where it
+ * can be used, the limited AST offers the advantage of being smaller and
+ * faster to faster to construct.
+ *
+ * + * The resulting AST always includes nodes for all of the compilation unit's + * package, import, and top-level type declarations. It also always contains + * nodes for all the body declarations for those top-level types, as well + * as body declarations for any member types. However, some of the body + * declarations may be abridged. In particular, the statements ordinarily + * found in the body of a method declaration node will not be included + * (the block will be empty) unless the source position falls somewhere + * within the source range of that method declaration node. The same is true + * for initializer declarations; the statements ordinarily found in the body + * of initializer node will not be included unless the source position falls + * somewhere within the source range of that initializer declaration node. + * Field declarations are never abridged. Note that the AST for the body of + * that one unabridged method (or initializer) is 100% complete; it has all + * its statements, including any local or anonymous type declarations + * embedded within them. When the the given position is not located within + * the source range of any body declaration of a top-level type, the AST + * returned is a skeleton that includes nodes for all and only the major + * declarations; this kind of AST is still quite useful because it contains + * all the constructs that introduce names visible to the world outside the + * compilation unit. + *
+ *
+ * In all other respects, this method works the same as
+ * {@link #parseCompilationUnit(ICompilationUnit,boolean,WorkingCopyOwner)
+ * parseCompilationUnit(ICompilationUnit,boolean,WorkingCopyOwner)}.
+ * The source string is obtained from the Java model element using
+ * ICompilationUnit.getSource()
.
+ *
+ * The returned compilation unit node is the root node of a new AST.
+ * Each node in the subtree carries source range(s) information relating back
+ * to positions in the source string (the source string is not remembered
+ * with the AST).
+ * The source range usually begins at the first character of the first token
+ * corresponding to the node; leading whitespace and comments are not
+ * included. The source range usually extends through the last character of
+ * the last token corresponding to the node; trailing whitespace and
+ * comments are not included.
+ * If a syntax error is detected while parsing, the relevant node(s) of the
+ * tree will be flagged as MALFORMED
.
+ *
+ * Several options are available while parsing the source: + *
ResolveBindings
+ * When this flag is set, the various names and types appearing in
+ * the compilation unit can be resolved to "bindings" by calling
+ * the resolveBinding
methods. These bindings draw
+ * connections between the different parts of a program, and generally
+ * afford a more powerful vantage point for clients who wish to
+ * analyze a program's structure more deeply. These bindings come
+ * at a considerable cost in both time and space, however, and should
+ * not be requested frivolously. The additional space is not reclaimed
+ * until the AST, all its nodes, and all its bindings become garbage.
+ * So it is very important to not retain any of these objects longer
+ * than absolutely necessary. Bindings are resolved at the time the
+ * AST is created. Subsequent modifications to the AST do not affect
+ * the bindings returned by resolveBinding
methods in
+ * any way; these methods return the same binding as before the AST
+ * was modified (including modifications that rearrange subtrees by
+ * reparenting nodes).
+ * When this flag is not set, the analysis does not go beyond parsing
+ * and building the tree, and all resolveBinding
methods
+ * return null
from the outset.
+ * InsideComments
+ * When this flag is set, all comments of the compilation unit are stored
+ * and parsed to identify possible Javadoc tags.
+ * Comments are stored in a list comments
of Comment
.
+ * There are three different kind of comments: line, block and javadoc.
+ * Javadoc comments are those which were already defined since version 2.0,
+ * but they are now structured and not only a flat text.
+ * @see Javadoc for more details on this AST node structure
+ * ResolveBindings | InsideComments
.
+ *
+ *
+ * When bindings are created, instead of considering compilation units on disk only
+ * one can supply a WorkingCopyOwner
. Working copies owned
+ * by this owner take precedence over the underlying compilation units when looking
+ * up names and drawing the connections.
+ *
false
if they do not match or the other object has a
* different node type or is null
*/
+ public boolean match(Comment node, Object other) {
+ if (!(other instanceof Comment)) {
+ return false;
+ }
+ Comment o = (Comment) other;
+ return safeSubtreeListMatch(node.tags(), o.tags());
+ }
public boolean match(Javadoc node, Object other) {
if (!(other instanceof Javadoc)) {
return false;
}
Javadoc o = (Javadoc) other;
- return safeEquals(node.getComment(), o.getComment());
+ return safeSubtreeListMatch(node.tags(), o.tags());
}
-
+ public boolean match(JavadocTag node, Object other) {
+ if (!(other instanceof JavadocTag)) {
+ return false;
+ }
+ JavadocTag o = (JavadocTag) other;
+ return (node.getIdentifier().equals(o.getIdentifier()) &&
+ safeEquals(node.getDescription(), o.getDescription()) &&
+ safeSubtreeMatch(node.getReference(), o.getReference()));
+ }
+ public boolean match(JavadocEmbeddedTag node, Object other) {
+ if (!(other instanceof JavadocEmbeddedTag)) {
+ return false;
+ }
+ JavadocEmbeddedTag o = (JavadocEmbeddedTag) other;
+ return (node.getIdentifier().equals(o.getIdentifier()) &&
+ safeSubtreeMatch(node.getTag(), o.getTag()));
+ }
+ public boolean match(JavadocArgument node, Object other) {
+ if (!(other instanceof JavadocArgument)) {
+ return false;
+ }
+ JavadocArgument o = (JavadocArgument) other;
+ return (node.getArgument().equals(o.getArgument()));
+ }
+
/**
* Returns whether the given node and the other object match.
* Index: dom/org/eclipse/jdt/core/dom/ASTNode.java =================================================================== retrieving revision 1.32 diff -u -r1.32 ASTNode.java --- dom/org/eclipse/jdt/core/dom/ASTNode.java 25 Nov 2003 17:22:15 -0000 1.32 +++ dom/org/eclipse/jdt/core/dom/ASTNode.java 1 Dec 2003 18:29:23 -0000 @@ -108,7 +108,7 @@ * problem (support for this is planned for a future release). *
* - * @see AST#parseCompilationUnit + * @see AST#parseCompilationUnit(char[]) and other similar methods * @see ASTVisitor * @since 2.0 */ @@ -549,6 +549,34 @@ public static final int INSTANCEOF_EXPRESSION = 62; /** + * Node type constant indicating a node of type + *Comment
.
+ * @see Comment
+ */
+ public static final int COMMENT = 63;
+
+ /**
+ * Node type constant indicating a node of type
+ * JavadocTag
.
+ * @see JavadocTag
+ */
+ public static final int JAVADOC_TAG = 64;
+
+ /**
+ * Node type constant indicating a node of type
+ * JavadocTag
.
+ * @see JavadocTag
+ */
+ public static final int JAVADOC_EMBEDDED_TAG = 65;
+
+ /**
+ * Node type constant indicating a node of type
+ * JavadocTag
.
+ * @see JavadocTag
+ */
+ public static final int JAVADOC_ARGUMENT = 66;
+
+ /**
* Owning AST.
*/
private final AST owner;
@@ -562,7 +590,7 @@
/**
* An unmodifiable empty map (used to implement properties()
).
*
- * @see #properties
+ * @see #properties()
*/
private static Map UNMODIFIABLE_EMPTY_MAP
= Collections.unmodifiableMap(new HashMap(1));
@@ -927,7 +955,7 @@
public ASTNode getParent() {
return parent;
}
-
+
/**
* Returns the root node at or above this node; returns this node if
* it is a root.
@@ -947,6 +975,23 @@
}
/**
+ * Returns the compilation unit which owns this node; returns this node if
+ * it is a compilation unit or null if none was found.
+ *
+ * @return the compilation unit node founds in node hierarchy or null if none was found
+ */
+ public CompilationUnit getCompilationUnit() {
+ ASTNode candidate = this;
+ while (candidate != null) {
+ if (candidate instanceof CompilationUnit) {
+ return (CompilationUnit) candidate;
+ }
+ candidate = candidate.getParent();
+ }
+ return null;
+ }
+
+ /**
* Internal callback indicating that a field of this node is about to
* be modified.
*/
@@ -1062,7 +1107,7 @@
*
* @param propertyName the property name
* @return the property value, or null
if none
- * @see #setProperty
+ * @see #setProperty(String, Object)
*/
public Object getProperty(String propertyName) {
if (propertyName == null) {
@@ -1102,7 +1147,7 @@
*
* @param propertyName the property name
* @param data the new property value, or null
if none
- * @see #getProperty
+ * @see #getProperty(String)
*/
public void setProperty(String propertyName, Object data) {
if (propertyName == null) {
@@ -1208,7 +1253,7 @@
*
*
* @return the bitwise-or of individual flags
- * @see #setFlags
+ * @see #setFlags(int)
* @see #MALFORMED
*/
public int getFlags() {
@@ -1228,7 +1273,7 @@
*
*
* @param flags the bitwise-or of individual flags
- * @see #getFlags
+ * @see #getFlags()
* @see #MALFORMED
*/
public void setFlags(int flags) {
@@ -1438,11 +1483,27 @@
*
* @return the 0-based character index, or -1
* if no source position information is recorded for this node
- * @see #getLength
+ * @see #getLength()
* @see AST#parseCompilationUnit
*/
public int getStartPosition() {
- return startPosition;
+ return this.startPosition;
+ }
+
+ /**
+ * Returns the character index into the original source file indicating
+ * where the source fragment corresponding to this node ends.
+ *
+ * @return the 0-based character index, or -1
+ * if no source position information is recorded for this node
+ * @see #getLength()
+ */
+ public int getEndPosition() {
+ if (this.length==0) {
+ return -1;
+ }else {
+ return this.startPosition+this.length-1;
+ }
}
/**
@@ -1460,7 +1521,7 @@
* @see AST#parseCompilationUnit
*/
public int getLength() {
- return length;
+ return this.length;
}
/**
@@ -1477,8 +1538,8 @@
* @param length a (possibly 0) length,
* or 0
if no source position information is recorded
* for this node
- * @see #getStartPosition
- * @see #getLength
+ * @see #getStartPosition()
+ * @see #getLength()
* @see AST#parseCompilationUnit
*/
public void setSourceRange(int startPosition, int length) {
@@ -1537,7 +1598,7 @@
// print the subtree by default
appendPrintString(buffer);
}
-
+
/**
* Appends a standard Java source code representation of this subtree to the given
* string buffer.
@@ -1549,19 +1610,19 @@
this.accept(printer);
buffer.append(printer.getResult());
}
-
+
/**
* Estimate of size of an object header in bytes.
*/
static final int HEADERS = 12;
-
+
/**
* Approximate base size of an AST node instance in bytes,
* including object header and instance fields.
* That is, HEADERS + (# instance vars in ASTNode)*4.
*/
static final int BASE_NODE_SIZE = HEADERS + 7 * 4;
-
+
/**
* Returns an estimate of the memory footprint in bytes of the entire
* subtree rooted at this node.
@@ -1571,7 +1632,7 @@
public final int subtreeBytes() {
return treeSize();
}
-
+
/**
* Returns an estimate of the memory footprint in bytes of the entire
* subtree rooted at this node.
Index: dom/org/eclipse/jdt/core/dom/ASTVisitor.java
===================================================================
retrieving revision 1.10
diff -u -r1.10 ASTVisitor.java
--- dom/org/eclipse/jdt/core/dom/ASTVisitor.java 28 Jul 2003 14:51:30 -0000 1.10
+++ dom/org/eclipse/jdt/core/dom/ASTVisitor.java 1 Dec 2003 18:29:23 -0000
@@ -93,7 +93,7 @@
*
*
*
- * @see ASTNode#accept
+ * @see ASTNode#accept(ASTVisitor)
*/
public abstract class ASTVisitor {
@@ -165,6 +165,9 @@
public boolean visit(ClassInstanceCreation node) {
return true;
}
+ public boolean visit(Comment node) {
+ return true;
+ }
public boolean visit(CompilationUnit node) {
return true;
}
@@ -213,6 +216,15 @@
public boolean visit(Javadoc node) {
return true;
}
+ public boolean visit(JavadocTag node) {
+ return true;
+ }
+ public boolean visit(JavadocEmbeddedTag node) {
+ return true;
+ }
+ public boolean visit(JavadocArgument node) {
+ return true;
+ }
public boolean visit(LabeledStatement node) {
return true;
}
@@ -355,6 +367,9 @@
public void endVisit(CompilationUnit node) {
// default implementation: do nothing
}
+ public void endVisit(Comment node) {
+ // default implementation: do nothing
+ }
public void endVisit(ConditionalExpression node) {
// default implementation: do nothing
}
@@ -398,6 +413,15 @@
// default implementation: do nothing
}
public void endVisit(Javadoc node) {
+ // default implementation: do nothing
+ }
+ public void endVisit(JavadocTag node) {
+ // default implementation: do nothing
+ }
+ public void endVisit(JavadocEmbeddedTag node) {
+ // default implementation: do nothing
+ }
+ public void endVisit(JavadocArgument node) {
// default implementation: do nothing
}
public void endVisit(LabeledStatement node) {
Index: dom/org/eclipse/jdt/core/dom/BodyDeclaration.java
===================================================================
retrieving revision 1.6
diff -u -r1.6 BodyDeclaration.java
--- dom/org/eclipse/jdt/core/dom/BodyDeclaration.java 15 Nov 2003 02:12:57 -0000 1.6
+++ dom/org/eclipse/jdt/core/dom/BodyDeclaration.java 1 Dec 2003 18:29:23 -0000
@@ -72,9 +72,17 @@
* Returns the Javadoc comment node.
*
* @return the javadoc comment node, or null
if none
+ * TODO (frederic) See if it could be interesting to store the javadoc comment instead of looking for it systematically...
*/
public Javadoc getJavadoc() {
- return optionalJavadoc;
+ CompilationUnit unit = getCompilationUnit();
+ if (unit != null) {
+ Comment comment = unit.getComment(getStartPosition());
+ if (comment != null && comment.isJavadoc()) {
+ return (Javadoc) comment;
+ }
+ }
+ return this.optionalJavadoc;
}
/**
Index: dom/org/eclipse/jdt/core/dom/CompilationUnit.java
===================================================================
retrieving revision 1.33
diff -u -r1.33 CompilationUnit.java
--- dom/org/eclipse/jdt/core/dom/CompilationUnit.java 15 Nov 2003 02:11:09 -0000 1.33
+++ dom/org/eclipse/jdt/core/dom/CompilationUnit.java 1 Dec 2003 18:29:23 -0000
@@ -55,6 +55,13 @@
new ASTNode.NodeList(false, TypeDeclaration.class);
/**
+ * The list of comments in textual order;
+ * initially none (elementType: Javadoc
)
+ */
+ private ASTNode.NodeList comments =
+ new ASTNode.NodeList(false, Comment.class);
+
+ /**
* Line end table. If lineEndTable[i] == p
then the
* line number i+1
ends at character position
* p
. Except for the last line, the positions are that
@@ -92,7 +99,7 @@
* For example, the source string A\nB\nC
has
* line end table {1, 3, 4}.
*
- * @param lineEndtable the line end table
+ * @param lineEndTable the line end table
*/
void setLineEndTable(int[] lineEndTable) {
if (lineEndTable == null) {
@@ -213,6 +220,17 @@
}
/**
+ * Returns the live list of nodes for all comments declared in this
+ * compilation unit, in order of appearance.
+ *
+ * @return the live list of comment nodes
+ * (elementType: Comment
)
+ */
+ public List comments() {
+ return comments;
+ }
+
+ /**
* Finds the corresponding AST node in the given compilation unit from
* which the given binding originated. Returns null
if the
* binding does not correspond to any node in this compilation unit.
@@ -293,7 +311,7 @@
* key is declared, or null
if the key is null
* or if the key does not correspond to a node in this compilation unit
* or if bindings were not requested when this AST was built
- * @see IBinding#getKey
+ * @see IBinding#getKey()
* @since 2.1
*/
public ASTNode findDeclaringNode(String key) {
@@ -318,7 +336,7 @@
* position does not correspond to a source line in the original
* source file or if line number information is not known for this
* compilation unit
- * @see AST#parseCompilationUnit
+ * @see AST#parseCompilationUnit(char[]) and other similar methods
*/
public int lineNumber(int position) {
int length = lineEndTable.length;
@@ -384,8 +402,8 @@
*
*
* @return the list of messages, possibly empty
- * @see #getProblems
- * @see AST#parseCompilationUnit
+ * @see #getProblems()
+ * @see AST#parseCompilationUnit(char[]) and other similar methods
*/
public Message[] getMessages() {
if (this.messages == null) {
@@ -416,8 +434,8 @@
*
*
* @return the list of detailed problem objects, possibly empty
- * @see #getMessages
- * @see AST#parseCompilationUnit
+ * @see #getMessages()
+ * @see AST#parseCompilationUnit(char[]) and other similar methods
* @since 2.1
*/
public IProblem[] getProblems() {
@@ -474,6 +492,50 @@
+ (optionalPackageDeclaration == null ? 0 : getPackage().treeSize())
+ imports.listSize()
+ types.listSize();
+ }
+
+ /**
+ * Get comment of the list which includes a given position
+ *
+ * @param position The position belonging to the looked up comment
+ * @return Javadoc The comment which includes the given position or null if none was found
+ */
+ public Comment getComment(int position) {
+
+ if (this.comments == null) {
+ return null;
+ }
+ int size = this.comments.size();
+ if (size == 0) {
+ return null;
+ }
+ int bottom = 0, top = size - 1;
+ int i = 0, index = -1;
+ Comment comment = null;
+ while (bottom <= top) {
+ i = (bottom + top) /2;
+ comment = (Comment) this.comments.get(i);
+ if (position < comment.getStartPosition()) {
+ top = i-1;
+ } else if (position >= comment.getEndPosition()) {
+ bottom = i+1;
+ } else {
+ index = i;
+ break;
+ }
+ }
+ if (index<0) {
+ /*
+ comment = (Comment) this.comments.get(i);
+ if (position < comment.getStartPosition()) {
+ index = i;
+ } else {
+ index = i+1;
+ }
+ */
+ return null;
+ }
+ return (Comment) this.comments.get(index);
}
}
Index: dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
===================================================================
retrieving revision 1.50
diff -u -r1.50 CompilationUnitResolver.java
--- dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java 22 Nov 2003 16:01:01 -0000 1.50
+++ dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java 1 Dec 2003 18:29:23 -0000
@@ -11,22 +11,21 @@
package org.eclipse.jdt.core.dom;
-import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.core.ICompilationUnit;
+import java.util.Map;
+
import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.env.ISourceType;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
import org.eclipse.jdt.internal.compiler.problem.*;
-
-import java.util.*;
+import org.eclipse.jdt.internal.core.*;
class CompilationUnitResolver extends Compiler {
@@ -77,6 +76,8 @@
/**
* Add additional source types
+ * @param sourceTypes
+ * @param packageBinding
*/
public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
CompilationResult result =
@@ -97,50 +98,6 @@
}
}
- private static Parser createDomParser(ProblemReporter problemReporter) {
-
- return new Parser(problemReporter, false) {
- // old annotation style check which doesn't include all leading comments into declaration
- // for backward compatibility with 2.1 DOM
- public void checkComment() {
-
- if (this.currentElement != null && this.scanner.commentPtr >= 0) {
- flushCommentsDefinedPriorTo(endStatementPosition); // discard obsolete comments
- }
- boolean deprecated = false;
- boolean checkDeprecated = false;
- int lastCommentIndex = -1;
-
- //since jdk1.2 look only in the last java doc comment...
- //look for @deprecated into the first javadoc comment preceeding the declaration
- int commentSourceStart = scanner.commentStarts[lastCommentIndex];
- // javadoc only (non javadoc comment have negative end positions.)
- if (modifiersSourceStart != -1 && modifiersSourceStart < commentSourceStart) {
- continue nextComment;
- }
- if (scanner.commentStops[lastCommentIndex] < 0) {
- continue nextComment;
- }
- checkDeprecated = true;
- int commentSourceEnd = scanner.commentStops[lastCommentIndex] - 1; //stop is one over
-
- deprecated =
- this.javadocParser.checkDeprecation(commentSourceStart, commentSourceEnd);
- this.javadoc = this.javadocParser.javadoc;
- break nextComment;
- }
- if (deprecated) {
- checkAndSetModifiers(AccDeprecated);
- }
- // modify the modifier source start to point at the first comment
- if (lastCommentIndex >= 0 && checkDeprecated) {
- modifiersSourceStart = scanner.commentStarts[lastCommentIndex];
- }
-
- }
- };
- }
/*
* Low-level API performing the actual compilation
@@ -185,7 +142,7 @@
* @see org.eclipse.jdt.internal.compiler.Compiler#initializeParser()
*/
public void initializeParser() {
- this.parser = createDomParser(this.problemReporter);
+ this.parser = new DOMParser(this.problemReporter, false);
}
/*
* Compiler crash recovery in case of unexpected runtime exceptions
@@ -260,11 +217,11 @@
throw new IllegalArgumentException();
}
CompilerOptions compilerOptions = new CompilerOptions(settings);
- Parser parser = createDomParser(
+ DOMParser parser = new DOMParser(
new ProblemReporter(
DefaultErrorHandlingPolicies.proceedWithAllProblems(),
compilerOptions,
- new DefaultProblemFactory()));
+ new DefaultProblemFactory()), false);
org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit =
new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(
source,
@@ -294,11 +251,11 @@
throw new IllegalArgumentException();
}
CompilerOptions compilerOptions = new CompilerOptions(settings);
- Parser parser = createDomParser(
+ DOMParser parser = new DOMParser(
new ProblemReporter(
DefaultErrorHandlingPolicies.proceedWithAllProblems(),
compilerOptions,
- new DefaultProblemFactory()));
+ new DefaultProblemFactory()), false);
org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit =
new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(
source,
@@ -500,7 +457,7 @@
}
}
- /**
+ /*
* Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
*/
public CompilationUnitDeclaration resolve(
@@ -576,7 +533,7 @@
// this.reset();
}
}
- /**
+ /*
* Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
*/
public CompilationUnitDeclaration resolve(
@@ -593,7 +550,7 @@
generateCode);
}
- /**
+ /*
* Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
*/
public CompilationUnitDeclaration resolve(
Index: dom/org/eclipse/jdt/core/dom/IBinding.java
===================================================================
retrieving revision 1.9
diff -u -r1.9 IBinding.java
--- dom/org/eclipse/jdt/core/dom/IBinding.java 26 Nov 2003 14:21:08 -0000 1.9
+++ dom/org/eclipse/jdt/core/dom/IBinding.java 1 Dec 2003 18:29:23 -0000
@@ -33,7 +33,7 @@
* Kind constant (value 1) indicating a package binding.
* Bindings of this kind can be safely cast to IPackageBinding
.
*
- * @see #getKind
+ * @see #getKind()
* @see IPackageBinding
*/
public static final int PACKAGE = 1;
@@ -42,7 +42,7 @@
* Kind constant (value 2) indicating a type binding.
* Bindings of this kind can be safely cast to ITypeBinding
.
*
- * @see #getKind
+ * @see #getKind()
* @see ITypeBinding
*/
public static final int TYPE = 2;
@@ -51,7 +51,7 @@
* Kind constant (value 3) indicating a field or local variable binding.
* Bindings of this kind can be safely cast to IVariableBinding
.
*
- * @see #getKind
+ * @see #getKind()
* @see IVariableBinding
*/
public static final int VARIABLE = 3;
@@ -60,7 +60,7 @@
* Kind constant (value 4) indicating a method or constructor binding.
* Bindings of this kind can be safely cast to IMethodBinding
.
*
- * @see #getKind
+ * @see #getKind()
* @see IMethodBinding
*/
public static final int METHOD = 4;
@@ -172,7 +172,10 @@
* not be different; in these cases, the client should compare bindings
* via their binding keys (getKey
) if available.
*
- * @see #getKey
+ * @see #getKey()
+ *
+ * @param obj
+ * @return
*/
public boolean equals(Object obj);
Index: dom/org/eclipse/jdt/core/dom/Javadoc.java
===================================================================
retrieving revision 1.15
diff -u -r1.15 Javadoc.java
--- dom/org/eclipse/jdt/core/dom/Javadoc.java 11 Mar 2003 15:03:51 -0000 1.15
+++ dom/org/eclipse/jdt/core/dom/Javadoc.java 1 Dec 2003 18:29:23 -0000
@@ -8,26 +8,29 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
-
package org.eclipse.jdt.core.dom;
-import org.eclipse.jdt.core.compiler.InvalidInputException;
-import org.eclipse.jdt.internal.compiler.parser.Scanner;
-import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
/**
* AST node for a Javadoc comment.
*
* @since 2.0
*/
-public class Javadoc extends ASTNode {
+public class Javadoc extends Comment {
/**
- * The javadoc comment string, including opening and closing comment
- * delimiters; defaults to an unspecified, but legal, Javadoc comment.
+ * First non-empty line of comment text before the first Javadoc tag;
+ * default is empty string.
*/
- private String comment = "/** */";//$NON-NLS-1$
-
+ //String title = "";//$NON-NLS-1$
+
+ /**
+ * Non-empty lines of comment text after the title and before the first
+ * Javadoc tag; default is empty string.
+ */
+ //String[] description = { "" }; //$NON-NLS-1$
+ //String description = ""; //$NON-NLS-1$
+
/**
* Creates a new AST node for a Javadoc comment owned by the given AST.
* The new node has an unspecified, but legal, Javadoc comment.
@@ -41,6 +44,8 @@
*/
Javadoc(AST ast) {
super(ast);
+ this.block = true;
+ this.text = "/** */"; //$NON-NLS-1$
}
/* (omit javadoc for this method)
@@ -56,7 +61,9 @@
ASTNode clone(AST target) {
Javadoc result = new Javadoc(target);
result.setSourceRange(this.getStartPosition(), this.getLength());
- result.setComment(getComment());
+ result.setText(this.text);
+ //result.setTitle(this.title);
+ //result.setDescription(this.description);
return result;
}
@@ -81,66 +88,61 @@
* and ending comment delimiters, and any embedded line breaks.
*
* @return the javadoc comment string
+ * @deprecated Use #getText() instead
*/
public String getComment() {
- return comment;
+ return getText();
}
/**
- * Sets or clears the Javadoc comment string. The documentation
- * string must include the starting and ending comment delimiters,
- * and any embedded line breaks.
- *
- * @param javadocComment the javadoc comment string
- * @exception IllegalArgumentException if the Java comment string is invalid
+ * Returns whether the comment is a javadoc comment or not.
+ * @return true if the comment is a Javadoc one, false otherwise.
+ */
+ public boolean isJavadoc() {
+ return true;
+ }
+
+ /**
+ * @return Returns the description as string.
*/
- public void setComment(String javadocComment) {
- if (javadocComment == null) {
- throw new IllegalArgumentException();
+ public String getDescription() {
+ JavadocTag tag = getFirstSentence(false);
+ if (tag != null) {
+ return tag.getDescription();
}
- char[] source = javadocComment.toCharArray();
- Scanner scanner = this.getAST().scanner;
- scanner.resetTo(0, source.length);
- scanner.setSource(source);
- try {
- int token;
- boolean onlyOneComment = false;
- while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
- switch(token) {
- case TerminalTokens.TokenNameCOMMENT_JAVADOC :
- if (onlyOneComment) {
- throw new IllegalArgumentException();
- }
- onlyOneComment = true;
- break;
- default:
- onlyOneComment = false;
- }
- }
- if (!onlyOneComment) {
- throw new IllegalArgumentException();
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Return the first sengtence of Javadoc comment.
+ * This is the first tag of the list which has no identifier.
+ * @param setIfNull Tells whether the first sentence should be created if none was found
+ * @return The first sentence of the Javadoc as a JavadocTag
+ * @see JavadocTag
+ */
+ public JavadocTag getFirstSentence(boolean setIfNull) {
+ if (this.tags.size() > 0) {
+ JavadocTag tag = (JavadocTag) tags().get(0);
+ if (tag.getIdentifier().length() == 0) {
+ return tag;
}
- } catch (InvalidInputException e) {
- throw new IllegalArgumentException();
}
- modifying();
- this.comment = javadocComment;
- }
-
- /* (omit javadoc for this method)
- * Method declared on ASTNode.
- */
- int memSize() {
- int size = BASE_NODE_SIZE + 1 * 4;
- size += HEADERS + 2 * 4 + HEADERS + 2 * comment.length();
- return size;
+ if (setIfNull) {
+ JavadocTag tag = getAST().newJavadocTag();
+ this.tags.add(0, tag);
+ return tag;
+ } else {
+ return null;
+ }
}
- /* (omit javadoc for this method)
- * Method declared on ASTNode.
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.Comment#isBlock()
*/
- int treeSize() {
- return memSize();
+ public boolean isBlock() {
+ // Javadoc comment is always considered as a block comment
+ return true;
}
+
}
Index: dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java
===================================================================
retrieving revision 1.14
diff -u -r1.14 NaiveASTFlattener.java
--- dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java 25 Nov 2003 17:22:15 -0000 1.14
+++ dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java 1 Dec 2003 18:29:23 -0000
@@ -54,14 +54,14 @@
* @return the serialized
*/
public String getResult() {
- return buffer.toString();
+ return this.buffer.toString();
}
/**
* Resets this printer so that it can be used again.
*/
public void reset() {
- buffer.setLength(0);
+ this.buffer.setLength(0);
}
/**
@@ -71,37 +71,37 @@
*/
void printModifiers(int modifiers) {
if (Modifier.isPublic(modifiers)) {
- buffer.append("public ");//$NON-NLS-1$
+ this.buffer.append("public ");//$NON-NLS-1$
}
if (Modifier.isProtected(modifiers)) {
- buffer.append("protected ");//$NON-NLS-1$
+ this.buffer.append("protected ");//$NON-NLS-1$
}
if (Modifier.isPrivate(modifiers)) {
- buffer.append("private ");//$NON-NLS-1$
+ this.buffer.append("private ");//$NON-NLS-1$
}
if (Modifier.isStatic(modifiers)) {
- buffer.append("static ");//$NON-NLS-1$
+ this.buffer.append("static ");//$NON-NLS-1$
}
if (Modifier.isAbstract(modifiers)) {
- buffer.append("abstract ");//$NON-NLS-1$
+ this.buffer.append("abstract ");//$NON-NLS-1$
}
if (Modifier.isFinal(modifiers)) {
- buffer.append("final ");//$NON-NLS-1$
+ this.buffer.append("final ");//$NON-NLS-1$
}
if (Modifier.isSynchronized(modifiers)) {
- buffer.append("synchronized ");//$NON-NLS-1$
+ this.buffer.append("synchronized ");//$NON-NLS-1$
}
if (Modifier.isVolatile(modifiers)) {
- buffer.append("volatile ");//$NON-NLS-1$
+ this.buffer.append("volatile ");//$NON-NLS-1$
}
if (Modifier.isNative(modifiers)) {
- buffer.append("native ");//$NON-NLS-1$
+ this.buffer.append("native ");//$NON-NLS-1$
}
if (Modifier.isStrictfp(modifiers)) {
- buffer.append("strictfp ");//$NON-NLS-1$
+ this.buffer.append("strictfp ");//$NON-NLS-1$
}
if (Modifier.isTransient(modifiers)) {
- buffer.append("transient ");//$NON-NLS-1$
+ this.buffer.append("transient ");//$NON-NLS-1$
}
}
@@ -109,12 +109,12 @@
* @see ASTVisitor#visit(AnonymousClassDeclaration)
*/
public boolean visit(AnonymousClassDeclaration node) {
- buffer.append("{");//$NON-NLS-1$
+ this.buffer.append("{");//$NON-NLS-1$
for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
BodyDeclaration b = (BodyDeclaration) it.next();
b.accept(this);
}
- buffer.append("}");//$NON-NLS-1$
+ this.buffer.append("}");//$NON-NLS-1$
return false;
}
@@ -123,9 +123,9 @@
*/
public boolean visit(ArrayAccess node) {
node.getArray().accept(this);
- buffer.append("[");//$NON-NLS-1$
+ this.buffer.append("[");//$NON-NLS-1$
node.getIndex().accept(this);
- buffer.append("]");//$NON-NLS-1$
+ this.buffer.append("]");//$NON-NLS-1$
return false;
}
@@ -133,24 +133,24 @@
* @see ASTVisitor#visit(ArrayCreation)
*/
public boolean visit(ArrayCreation node) {
- buffer.append("new ");//$NON-NLS-1$
+ this.buffer.append("new ");//$NON-NLS-1$
ArrayType at = node.getType();
int dims = at.getDimensions();
Type elementType = at.getElementType();
elementType.accept(this);
for (Iterator it = node.dimensions().iterator(); it.hasNext(); ) {
- buffer.append("[");//$NON-NLS-1$
+ this.buffer.append("[");//$NON-NLS-1$
Expression e = (Expression) it.next();
e.accept(this);
- buffer.append("]");//$NON-NLS-1$
+ this.buffer.append("]");//$NON-NLS-1$
dims--;
}
// add empty "[]" for each extra array dimension
for (int i= 0; i < dims; i++) {
- buffer.append("[]");//$NON-NLS-1$
+ this.buffer.append("[]");//$NON-NLS-1$
}
if (node.getInitializer() != null) {
- buffer.append("=");//$NON-NLS-1$
+ this.buffer.append("=");//$NON-NLS-1$
node.getInitializer().accept(this);
}
return false;
@@ -160,13 +160,13 @@
* @see ASTVisitor#visit(ArrayInitializer)
*/
public boolean visit(ArrayInitializer node) {
- buffer.append("{");//$NON-NLS-1$
+ this.buffer.append("{");//$NON-NLS-1$
for (Iterator it = node.expressions().iterator(); it.hasNext(); ) {
Expression e = (Expression) it.next();
e.accept(this);
- buffer.append(",");//$NON-NLS-1$
+ this.buffer.append(",");//$NON-NLS-1$
}
- buffer.append("}");//$NON-NLS-1$
+ this.buffer.append("}");//$NON-NLS-1$
return false;
}
@@ -175,7 +175,7 @@
*/
public boolean visit(ArrayType node) {
node.getComponentType().accept(this);
- buffer.append("[]");//$NON-NLS-1$
+ this.buffer.append("[]");//$NON-NLS-1$
return false;
}
@@ -183,13 +183,13 @@
* @see ASTVisitor#visit(AssertStatement)
*/
public boolean visit(AssertStatement node) {
- buffer.append("assert ");//$NON-NLS-1$
+ this.buffer.append("assert ");//$NON-NLS-1$
node.getExpression().accept(this);
if (node.getMessage() != null) {
node.getMessage().accept(this);
}
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -198,7 +198,7 @@
*/
public boolean visit(Assignment node) {
node.getLeftHandSide().accept(this);
- buffer.append(node.getOperator().toString());
+ this.buffer.append(node.getOperator().toString());
node.getRightHandSide().accept(this);
return false;
}
@@ -207,12 +207,12 @@
* @see ASTVisitor#visit(Block)
*/
public boolean visit(Block node) {
- buffer.append("{");//$NON-NLS-1$
+ this.buffer.append("{");//$NON-NLS-1$
for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
Statement s = (Statement) it.next();
s.accept(this);
}
- buffer.append("}");//$NON-NLS-1$
+ this.buffer.append("}");//$NON-NLS-1$
return false;
}
@@ -221,9 +221,9 @@
*/
public boolean visit(BooleanLiteral node) {
if (node.booleanValue() == true) {
- buffer.append("true");//$NON-NLS-1$
+ this.buffer.append("true");//$NON-NLS-1$
} else {
- buffer.append("false");//$NON-NLS-1$
+ this.buffer.append("false");//$NON-NLS-1$
}
return false;
}
@@ -232,12 +232,12 @@
* @see ASTVisitor#visit(BreakStatement)
*/
public boolean visit(BreakStatement node) {
- buffer.append("break");//$NON-NLS-1$
+ this.buffer.append("break");//$NON-NLS-1$
if (node.getLabel() != null) {
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
node.getLabel().accept(this);
}
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -245,9 +245,9 @@
* @see ASTVisitor#visit(CastExpression)
*/
public boolean visit(CastExpression node) {
- buffer.append("(");//$NON-NLS-1$
+ this.buffer.append("(");//$NON-NLS-1$
node.getType().accept(this);
- buffer.append(")");//$NON-NLS-1$
+ this.buffer.append(")");//$NON-NLS-1$
node.getExpression().accept(this);
return false;
}
@@ -256,9 +256,9 @@
* @see ASTVisitor#visit(CatchClause)
*/
public boolean visit(CatchClause node) {
- buffer.append("catch (");//$NON-NLS-1$
+ this.buffer.append("catch (");//$NON-NLS-1$
node.getException().accept(this);
- buffer.append(") ");//$NON-NLS-1$
+ this.buffer.append(") ");//$NON-NLS-1$
node.getBody().accept(this);
return false;
}
@@ -267,7 +267,7 @@
* @see ASTVisitor#visit(CharacterLiteral)
*/
public boolean visit(CharacterLiteral node) {
- buffer.append(node.getEscapedValue());
+ this.buffer.append(node.getEscapedValue());
return false;
}
@@ -277,19 +277,19 @@
public boolean visit(ClassInstanceCreation node) {
if (node.getExpression() != null) {
node.getExpression().accept(this);
- buffer.append(".");//$NON-NLS-1$
+ this.buffer.append(".");//$NON-NLS-1$
}
- buffer.append("new ");//$NON-NLS-1$
+ this.buffer.append("new ");//$NON-NLS-1$
node.getName().accept(this);
- buffer.append("(");//$NON-NLS-1$
+ this.buffer.append("(");//$NON-NLS-1$
for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
Expression e = (Expression) it.next();
e.accept(this);
if (it.hasNext()) {
- buffer.append(",");//$NON-NLS-1$
+ this.buffer.append(",");//$NON-NLS-1$
}
}
- buffer.append(")");//$NON-NLS-1$
+ this.buffer.append(")");//$NON-NLS-1$
if (node.getAnonymousClassDeclaration() != null) {
node.getAnonymousClassDeclaration().accept(this);
}
@@ -319,9 +319,9 @@
*/
public boolean visit(ConditionalExpression node) {
node.getExpression().accept(this);
- buffer.append("?");//$NON-NLS-1$
+ this.buffer.append("?");//$NON-NLS-1$
node.getThenExpression().accept(this);
- buffer.append(":");//$NON-NLS-1$
+ this.buffer.append(":");//$NON-NLS-1$
node.getElseExpression().accept(this);
return false;
}
@@ -330,15 +330,15 @@
* @see ASTVisitor#visit(ConstructorInvocation)
*/
public boolean visit(ConstructorInvocation node) {
- buffer.append("this(");//$NON-NLS-1$
+ this.buffer.append("this(");//$NON-NLS-1$
for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
Expression e = (Expression) it.next();
e.accept(this);
if (it.hasNext()) {
- buffer.append(",");//$NON-NLS-1$
+ this.buffer.append(",");//$NON-NLS-1$
}
}
- buffer.append(");");//$NON-NLS-1$
+ this.buffer.append(");");//$NON-NLS-1$
return false;
}
@@ -346,12 +346,12 @@
* @see ASTVisitor#visit(ContinueStatement)
*/
public boolean visit(ContinueStatement node) {
- buffer.append("continue");//$NON-NLS-1$
+ this.buffer.append("continue");//$NON-NLS-1$
if (node.getLabel() != null) {
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
node.getLabel().accept(this);
}
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -359,11 +359,11 @@
* @see ASTVisitor#visit(DoStatement)
*/
public boolean visit(DoStatement node) {
- buffer.append("do ");//$NON-NLS-1$
+ this.buffer.append("do ");//$NON-NLS-1$
node.getBody().accept(this);
- buffer.append(" while (");//$NON-NLS-1$
+ this.buffer.append(" while (");//$NON-NLS-1$
node.getExpression().accept(this);
- buffer.append(");");//$NON-NLS-1$
+ this.buffer.append(");");//$NON-NLS-1$
return false;
}
@@ -371,7 +371,7 @@
* @see ASTVisitor#visit(EmptyStatement)
*/
public boolean visit(EmptyStatement node) {
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -380,7 +380,7 @@
*/
public boolean visit(ExpressionStatement node) {
node.getExpression().accept(this);
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -389,7 +389,7 @@
*/
public boolean visit(FieldAccess node) {
node.getExpression().accept(this);
- buffer.append(".");//$NON-NLS-1$
+ this.buffer.append(".");//$NON-NLS-1$
node.getName().accept(this);
return false;
}
@@ -403,15 +403,15 @@
}
printModifiers(node.getModifiers());
node.getType().accept(this);
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
f.accept(this);
if (it.hasNext()) {
- buffer.append(", ");//$NON-NLS-1$
+ this.buffer.append(", ");//$NON-NLS-1$
}
}
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -419,21 +419,21 @@
* @see ASTVisitor#visit(ForStatement)
*/
public boolean visit(ForStatement node) {
- buffer.append("for (");//$NON-NLS-1$
+ this.buffer.append("for (");//$NON-NLS-1$
for (Iterator it = node.initializers().iterator(); it.hasNext(); ) {
Expression e = (Expression) it.next();
e.accept(this);
}
- buffer.append("; ");//$NON-NLS-1$
+ this.buffer.append("; ");//$NON-NLS-1$
if (node.getExpression() != null) {
node.getExpression().accept(this);
}
- buffer.append("; ");//$NON-NLS-1$
+ this.buffer.append("; ");//$NON-NLS-1$
for (Iterator it = node.updaters().iterator(); it.hasNext(); ) {
Expression e = (Expression) it.next();
e.accept(this);
}
- buffer.append(") ");//$NON-NLS-1$
+ this.buffer.append(") ");//$NON-NLS-1$
node.getBody().accept(this);
return false;
}
@@ -442,12 +442,12 @@
* @see ASTVisitor#visit(IfStatement)
*/
public boolean visit(IfStatement node) {
- buffer.append("if (");//$NON-NLS-1$
+ this.buffer.append("if (");//$NON-NLS-1$
node.getExpression().accept(this);
- buffer.append(") ");//$NON-NLS-1$
+ this.buffer.append(") ");//$NON-NLS-1$
node.getThenStatement().accept(this);
if (node.getElseStatement() != null) {
- buffer.append(" else ");//$NON-NLS-1$
+ this.buffer.append(" else ");//$NON-NLS-1$
node.getElseStatement().accept(this);
}
return false;
@@ -457,12 +457,12 @@
* @see ASTVisitor#visit(ImportDeclaration)
*/
public boolean visit(ImportDeclaration node) {
- buffer.append("import ");//$NON-NLS-1$
+ this.buffer.append("import ");//$NON-NLS-1$
node.getName().accept(this);
if (node.isOnDemand()) {
- buffer.append(".*");//$NON-NLS-1$
+ this.buffer.append(".*");//$NON-NLS-1$
}
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -471,10 +471,10 @@
*/
public boolean visit(InfixExpression node) {
node.getLeftOperand().accept(this);
- buffer.append(node.getOperator().toString());
+ this.buffer.append(node.getOperator().toString());
node.getRightOperand().accept(this);
for (Iterator it = node.extendedOperands().iterator(); it.hasNext(); ) {
- buffer.append(node.getOperator().toString());
+ this.buffer.append(node.getOperator().toString());
Expression e = (Expression) it.next();
e.accept(this);
}
@@ -486,7 +486,7 @@
*/
public boolean visit(InstanceofExpression node) {
node.getLeftOperand().accept(this);
- buffer.append(" instanceof ");//$NON-NLS-1$
+ this.buffer.append(" instanceof ");//$NON-NLS-1$
node.getRightOperand().accept(this);
return false;
}
@@ -507,16 +507,65 @@
* @see ASTVisitor#visit(Javadoc)
*/
public boolean visit(Javadoc node) {
- buffer.append(node.getComment());
+ this.buffer.append("[block: "+node.isBlock()); //$NON-NLS-1$
+ this.buffer.append("][javadoc: "+node.isJavadoc()); //$NON-NLS-1$
+ this.buffer.append("][tags:"+node.tags().size()); //$NON-NLS-1$
+ this.buffer.append("]"); //$NON-NLS-1$
+ for (Iterator it = node.tags().iterator(); it.hasNext(); ) {
+ JavadocTag tag = (JavadocTag) it.next();
+ this.buffer.append("\n * "); //$NON-NLS-1$
+ tag.accept(this);
+ }
+ this.buffer.append("\nText:"); //$NON-NLS-1$
+ this.buffer.append(node.getText());
return false;
}
-
+ public boolean visit(JavadocTag node) {
+ boolean hasIdentifier = node.getIdentifier().length() > 0;
+ if (hasIdentifier) {
+ this.buffer.append('@');
+ this.buffer.append(node.getIdentifier());
+ }
+ boolean hasReference = node.getReference() != null;
+ if (hasReference) {
+ if (hasIdentifier) {
+ this.buffer.append(' ');
+ }
+ node.getReference().accept(this);
+ }
+ String txt = node.getDescription();
+ if (txt.length() > 0) {
+ if (hasIdentifier || hasReference) {
+ this.buffer.append(' ');
+ }
+ this.buffer.append(txt);
+ }
+ return false;
+ }
+ public boolean visit(JavadocEmbeddedTag node) {
+ boolean hasIdentifier = node.getIdentifier().length() > 0;
+ this.buffer.append('{');
+ if (hasIdentifier) {
+ this.buffer.append('@');
+ this.buffer.append(node.getIdentifier());
+ }
+ boolean hasTag = node.getTag() != null;
+ if (hasTag) {
+ if (hasIdentifier) {
+ this.buffer.append(' ');
+ }
+ node.getTag().accept(this);
+ }
+ this.buffer.append('}');
+ return false;
+ }
+
/*
* @see ASTVisitor#visit(LabeledStatement)
*/
public boolean visit(LabeledStatement node) {
node.getLabel().accept(this);
- buffer.append(": ");//$NON-NLS-1$
+ this.buffer.append(": ");//$NON-NLS-1$
node.getBody().accept(this);
return false;
}
@@ -531,31 +580,31 @@
printModifiers(node.getModifiers());
if (!node.isConstructor()) {
node.getReturnType().accept(this);
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
}
node.getName().accept(this);
- buffer.append("(");//$NON-NLS-1$
+ this.buffer.append("(");//$NON-NLS-1$
for (Iterator it = node.parameters().iterator(); it.hasNext(); ) {
SingleVariableDeclaration v = (SingleVariableDeclaration) it.next();
v.accept(this);
if (it.hasNext()) {
- buffer.append(",");//$NON-NLS-1$
+ this.buffer.append(",");//$NON-NLS-1$
}
}
- buffer.append(")");//$NON-NLS-1$
+ this.buffer.append(")");//$NON-NLS-1$
if (!node.thrownExceptions().isEmpty()) {
- buffer.append(" throws ");//$NON-NLS-1$
+ this.buffer.append(" throws ");//$NON-NLS-1$
for (Iterator it = node.thrownExceptions().iterator(); it.hasNext(); ) {
Name n = (Name) it.next();
n.accept(this);
if (it.hasNext()) {
- buffer.append(", ");//$NON-NLS-1$
+ this.buffer.append(", ");//$NON-NLS-1$
}
}
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
}
if (node.getBody() == null) {
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
} else {
node.getBody().accept(this);
}
@@ -568,18 +617,18 @@
public boolean visit(MethodInvocation node) {
if (node.getExpression() != null) {
node.getExpression().accept(this);
- buffer.append(".");//$NON-NLS-1$
+ this.buffer.append(".");//$NON-NLS-1$
}
node.getName().accept(this);
- buffer.append("(");//$NON-NLS-1$
+ this.buffer.append("(");//$NON-NLS-1$
for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
Expression e = (Expression) it.next();
e.accept(this);
if (it.hasNext()) {
- buffer.append(",");//$NON-NLS-1$
+ this.buffer.append(",");//$NON-NLS-1$
}
}
- buffer.append(")");//$NON-NLS-1$
+ this.buffer.append(")");//$NON-NLS-1$
return false;
}
@@ -587,7 +636,7 @@
* @see ASTVisitor#visit(NullLiteral)
*/
public boolean visit(NullLiteral node) {
- buffer.append("null");//$NON-NLS-1$
+ this.buffer.append("null");//$NON-NLS-1$
return false;
}
@@ -595,7 +644,7 @@
* @see ASTVisitor#visit(NumberLiteral)
*/
public boolean visit(NumberLiteral node) {
- buffer.append(node.getToken());
+ this.buffer.append(node.getToken());
return false;
}
@@ -603,9 +652,9 @@
* @see ASTVisitor#visit(PackageDeclaration)
*/
public boolean visit(PackageDeclaration node) {
- buffer.append("package ");//$NON-NLS-1$
+ this.buffer.append("package ");//$NON-NLS-1$
node.getName().accept(this);
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -613,9 +662,9 @@
* @see ASTVisitor#visit(ParenthesizedExpression)
*/
public boolean visit(ParenthesizedExpression node) {
- buffer.append("(");//$NON-NLS-1$
+ this.buffer.append("(");//$NON-NLS-1$
node.getExpression().accept(this);
- buffer.append(")");//$NON-NLS-1$
+ this.buffer.append(")");//$NON-NLS-1$
return false;
}
@@ -624,7 +673,7 @@
*/
public boolean visit(PostfixExpression node) {
node.getOperand().accept(this);
- buffer.append(node.getOperator().toString());
+ this.buffer.append(node.getOperator().toString());
return false;
}
@@ -632,7 +681,7 @@
* @see ASTVisitor#visit(PrefixExpression)
*/
public boolean visit(PrefixExpression node) {
- buffer.append(node.getOperator().toString());
+ this.buffer.append(node.getOperator().toString());
node.getOperand().accept(this);
return false;
}
@@ -641,7 +690,7 @@
* @see ASTVisitor#visit(PrimitiveType)
*/
public boolean visit(PrimitiveType node) {
- buffer.append(node.getPrimitiveTypeCode().toString());
+ this.buffer.append(node.getPrimitiveTypeCode().toString());
return false;
}
@@ -650,7 +699,7 @@
*/
public boolean visit(QualifiedName node) {
node.getQualifier().accept(this);
- buffer.append(".");//$NON-NLS-1$
+ this.buffer.append(".");//$NON-NLS-1$
node.getName().accept(this);
return false;
}
@@ -659,12 +708,12 @@
* @see ASTVisitor#visit(ReturnStatement)
*/
public boolean visit(ReturnStatement node) {
- buffer.append("return");//$NON-NLS-1$
+ this.buffer.append("return");//$NON-NLS-1$
if (node.getExpression() != null) {
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
node.getExpression().accept(this);
}
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -672,7 +721,7 @@
* @see ASTVisitor#visit(SimpleName)
*/
public boolean visit(SimpleName node) {
- buffer.append(node.getIdentifier());
+ this.buffer.append(node.getIdentifier());
return false;
}
@@ -689,10 +738,10 @@
public boolean visit(SingleVariableDeclaration node) {
printModifiers(node.getModifiers());
node.getType().accept(this);
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
node.getName().accept(this);
if (node.getInitializer() != null) {
- buffer.append("=");//$NON-NLS-1$
+ this.buffer.append("=");//$NON-NLS-1$
node.getInitializer().accept(this);
}
return false;
@@ -702,7 +751,7 @@
* @see ASTVisitor#visit(StringLiteral)
*/
public boolean visit(StringLiteral node) {
- buffer.append(node.getEscapedValue());
+ this.buffer.append(node.getEscapedValue());
return false;
}
@@ -712,17 +761,17 @@
public boolean visit(SuperConstructorInvocation node) {
if (node.getExpression() != null) {
node.getExpression().accept(this);
- buffer.append(".");//$NON-NLS-1$
+ this.buffer.append(".");//$NON-NLS-1$
}
- buffer.append("super(");//$NON-NLS-1$
+ this.buffer.append("super(");//$NON-NLS-1$
for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
Expression e = (Expression) it.next();
e.accept(this);
if (it.hasNext()) {
- buffer.append(",");//$NON-NLS-1$
+ this.buffer.append(",");//$NON-NLS-1$
}
}
- buffer.append(");");//$NON-NLS-1$
+ this.buffer.append(");");//$NON-NLS-1$
return false;
}
@@ -732,9 +781,9 @@
public boolean visit(SuperFieldAccess node) {
if (node.getQualifier() != null) {
node.getQualifier().accept(this);
- buffer.append(".");//$NON-NLS-1$
+ this.buffer.append(".");//$NON-NLS-1$
}
- buffer.append("super.");//$NON-NLS-1$
+ this.buffer.append("super.");//$NON-NLS-1$
node.getName().accept(this);
return false;
}
@@ -745,19 +794,19 @@
public boolean visit(SuperMethodInvocation node) {
if (node.getQualifier() != null) {
node.getQualifier().accept(this);
- buffer.append(".");//$NON-NLS-1$
+ this.buffer.append(".");//$NON-NLS-1$
}
- buffer.append("super.");//$NON-NLS-1$
+ this.buffer.append("super.");//$NON-NLS-1$
node.getName().accept(this);
- buffer.append("(");//$NON-NLS-1$
+ this.buffer.append("(");//$NON-NLS-1$
for (Iterator it = node.arguments().iterator(); it.hasNext(); ) {
Expression e = (Expression) it.next();
e.accept(this);
if (it.hasNext()) {
- buffer.append(",");//$NON-NLS-1$
+ this.buffer.append(",");//$NON-NLS-1$
}
}
- buffer.append(")");//$NON-NLS-1$
+ this.buffer.append(")");//$NON-NLS-1$
return false;
}
@@ -766,11 +815,11 @@
*/
public boolean visit(SwitchCase node) {
if (node.isDefault()) {
- buffer.append("default :");//$NON-NLS-1$
+ this.buffer.append("default :");//$NON-NLS-1$
} else {
- buffer.append("case ");//$NON-NLS-1$
+ this.buffer.append("case ");//$NON-NLS-1$
node.getExpression().accept(this);
- buffer.append(":");//$NON-NLS-1$
+ this.buffer.append(":");//$NON-NLS-1$
}
return false;
}
@@ -779,15 +828,15 @@
* @see ASTVisitor#visit(SwitchStatement)
*/
public boolean visit(SwitchStatement node) {
- buffer.append("switch (");//$NON-NLS-1$
+ this.buffer.append("switch (");//$NON-NLS-1$
node.getExpression().accept(this);
- buffer.append(") ");//$NON-NLS-1$
- buffer.append("{");//$NON-NLS-1$
+ this.buffer.append(") ");//$NON-NLS-1$
+ this.buffer.append("{");//$NON-NLS-1$
for (Iterator it = node.statements().iterator(); it.hasNext(); ) {
Statement s = (Statement) it.next();
s.accept(this);
}
- buffer.append("}");//$NON-NLS-1$
+ this.buffer.append("}");//$NON-NLS-1$
return false;
}
@@ -795,9 +844,9 @@
* @see ASTVisitor#visit(SynchronizedStatement)
*/
public boolean visit(SynchronizedStatement node) {
- buffer.append("synchronized (");//$NON-NLS-1$
+ this.buffer.append("synchronized (");//$NON-NLS-1$
node.getExpression().accept(this);
- buffer.append(") ");//$NON-NLS-1$
+ this.buffer.append(") ");//$NON-NLS-1$
node.getBody().accept(this);
return false;
}
@@ -808,9 +857,9 @@
public boolean visit(ThisExpression node) {
if (node.getQualifier() != null) {
node.getQualifier().accept(this);
- buffer.append(".");//$NON-NLS-1$
+ this.buffer.append(".");//$NON-NLS-1$
}
- buffer.append("this");//$NON-NLS-1$
+ this.buffer.append("this");//$NON-NLS-1$
return false;
}
@@ -818,9 +867,9 @@
* @see ASTVisitor#visit(ThrowStatement)
*/
public boolean visit(ThrowStatement node) {
- buffer.append("throw ");//$NON-NLS-1$
+ this.buffer.append("throw ");//$NON-NLS-1$
node.getExpression().accept(this);
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -828,15 +877,15 @@
* @see ASTVisitor#visit(TryStatement)
*/
public boolean visit(TryStatement node) {
- buffer.append("try ");//$NON-NLS-1$
+ this.buffer.append("try ");//$NON-NLS-1$
node.getBody().accept(this);
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
for (Iterator it = node.catchClauses().iterator(); it.hasNext(); ) {
CatchClause cc = (CatchClause) it.next();
cc.accept(this);
}
if (node.getFinally() != null) {
- buffer.append("finally ");//$NON-NLS-1$
+ this.buffer.append("finally ");//$NON-NLS-1$
node.getFinally().accept(this);
}
return false;
@@ -850,31 +899,31 @@
node.getJavadoc().accept(this);
}
printModifiers(node.getModifiers());
- buffer.append(node.isInterface() ? "interface " : "class ");//$NON-NLS-2$//$NON-NLS-1$
+ this.buffer.append(node.isInterface() ? "interface " : "class ");//$NON-NLS-2$//$NON-NLS-1$
node.getName().accept(this);
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
if (node.getSuperclass() != null) {
- buffer.append("extends ");//$NON-NLS-1$
+ this.buffer.append("extends ");//$NON-NLS-1$
node.getSuperclass().accept(this);
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
}
if (!node.superInterfaces().isEmpty()) {
- buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
+ this.buffer.append(node.isInterface() ? "extends " : "implements ");//$NON-NLS-2$//$NON-NLS-1$
for (Iterator it = node.superInterfaces().iterator(); it.hasNext(); ) {
Name n = (Name) it.next();
n.accept(this);
if (it.hasNext()) {
- buffer.append(", ");//$NON-NLS-1$
+ this.buffer.append(", ");//$NON-NLS-1$
}
}
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
}
- buffer.append("{");//$NON-NLS-1$
+ this.buffer.append("{");//$NON-NLS-1$
for (Iterator it = node.bodyDeclarations().iterator(); it.hasNext(); ) {
BodyDeclaration d = (BodyDeclaration) it.next();
d.accept(this);
}
- buffer.append("}");//$NON-NLS-1$
+ this.buffer.append("}");//$NON-NLS-1$
return false;
}
@@ -883,7 +932,7 @@
*/
public boolean visit(TypeDeclarationStatement node) {
node.getTypeDeclaration().accept(this);
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -892,7 +941,7 @@
*/
public boolean visit(TypeLiteral node) {
node.getType().accept(this);
- buffer.append(".class");//$NON-NLS-1$
+ this.buffer.append(".class");//$NON-NLS-1$
return false;
}
@@ -902,15 +951,15 @@
public boolean visit(VariableDeclarationExpression node) {
printModifiers(node.getModifiers());
node.getType().accept(this);
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
f.accept(this);
if (it.hasNext()) {
- buffer.append(", ");//$NON-NLS-1$
+ this.buffer.append(", ");//$NON-NLS-1$
}
}
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -920,10 +969,10 @@
public boolean visit(VariableDeclarationFragment node) {
node.getName().accept(this);
for (int i = 0; i < node.getExtraDimensions(); i++) {
- buffer.append("[]");//$NON-NLS-1$
+ this.buffer.append("[]");//$NON-NLS-1$
}
if (node.getInitializer() != null) {
- buffer.append("=");//$NON-NLS-1$
+ this.buffer.append("=");//$NON-NLS-1$
node.getInitializer().accept(this);
}
return false;
@@ -935,15 +984,15 @@
public boolean visit(VariableDeclarationStatement node) {
printModifiers(node.getModifiers());
node.getType().accept(this);
- buffer.append(" ");//$NON-NLS-1$
+ this.buffer.append(" ");//$NON-NLS-1$
for (Iterator it = node.fragments().iterator(); it.hasNext(); ) {
VariableDeclarationFragment f = (VariableDeclarationFragment) it.next();
f.accept(this);
if (it.hasNext()) {
- buffer.append(", ");//$NON-NLS-1$
+ this.buffer.append(", ");//$NON-NLS-1$
}
}
- buffer.append(";");//$NON-NLS-1$
+ this.buffer.append(";");//$NON-NLS-1$
return false;
}
@@ -951,9 +1000,9 @@
* @see ASTVisitor#visit(WhileStatement)
*/
public boolean visit(WhileStatement node) {
- buffer.append("while (");//$NON-NLS-1$
+ this.buffer.append("while (");//$NON-NLS-1$
node.getExpression().accept(this);
- buffer.append(") ");//$NON-NLS-1$
+ this.buffer.append(") ");//$NON-NLS-1$
node.getBody().accept(this);
return false;
}
Index: dom/org/eclipse/jdt/core/dom/QualifiedName.java
===================================================================
retrieving revision 1.20
diff -u -r1.20 QualifiedName.java
--- dom/org/eclipse/jdt/core/dom/QualifiedName.java 15 Nov 2003 01:29:00 -0000 1.20
+++ dom/org/eclipse/jdt/core/dom/QualifiedName.java 1 Dec 2003 18:29:23 -0000
@@ -112,7 +112,7 @@
/**
* Sets the qualifier of this qualified name to the given name.
*
- * @param the qualifier of this qualified name
+ * @param qualifier the qualifier of this qualified name
* @exception IllegalArgumentException if:
* ITerminalSymbols.TokenNameEOF
).
*
- * @param startPosition the given start position
- * @param endPosition the given end position
+ * @param begin the given start position
+ * @param end the given end position
*/
public void resetTo(int begin, int end) {
//reset the scanner to a given position where it may rescan again
@@ -3036,6 +3039,8 @@
/**
* Search the line number corresponding to a specific position
*
+ * @param position
+ * @return int
*/
public final int getLineNumber(int position) {
Index: dom/org/eclipse/jdt/core/dom/Comment.java
===================================================================
RCS file: dom/org/eclipse/jdt/core/dom/Comment.java
diff -N dom/org/eclipse/jdt/core/dom/Comment.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ dom/org/eclipse/jdt/core/dom/Comment.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * AST node for a comment.
+ * This is a concrete class which represents line comments: // comment
+ * and block comments /* comment \*\/
.
+ *
+ * Javadoc comment are still representated with Javadoc class which is now a sub-class
+ * of this class.
+ * @see Javadoc
+ *
+ * @since 3.0
+ */
+public class Comment extends ASTNode {
+
+ /**
+ * The comment text, including opening and closing comment
+ * delimiters; defaults to an empty, but legal, line comment.
+ */
+ String text = "//";//$NON-NLS-1$
+
+ /**
+ * Indicates whether the comment is a block or a line comment;
+ * defaults to an unspecified, but legal, comment.
+ * Note that Javadoc comment are considered as block comments
+ * @see Javadoc
+ */
+ boolean block = false;
+
+ /**
+ * The tags included in the comment (element type: JavadocTag
).
+ * Defaults to none.
+ */
+ ASTNode.NodeList tags = new ASTNode.NodeList(true, JavadocTag.class);
+
+ /**
+ * Creates a new AST node for a Javadoc comment owned by the given AST.
+ * The new node has an unspecified, but legal, Javadoc comment.
+ * + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + *
+ * + * @param ast the AST that is to own this node + */ + Comment(AST ast) { + super(ast); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + public int getNodeType() { + return COMMENT; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + ASTNode clone(AST target) { + Comment result = new Comment(target); + result.setSourceRange(this.getStartPosition(), this.getLength()); + result.setText(this.text); + result.setBlock(this.block); + return result; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + public boolean subtreeMatch(ASTMatcher matcher, Object other) { + // dispatch to correct overloaded match method + return matcher.match(this, other); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + void accept0(ASTVisitor visitor) { + visitor.visit(this); + visitor.endVisit(this); + } + + /** + * Returns the Javadoc comment string, including the starting + * and ending comment delimiters, and any embedded line breaks. + * + * @return the javadoc comment string + */ + public String getText() { + return this.text; + } + + /** + * Sets or clears the Javadoc comment string. The documentation + * string must include the starting and ending comment delimiters, + * and any embedded line breaks. + * + * @param textComment the javadoc comment string + * @exception IllegalArgumentException if the Java comment string is invalid + */ + public void setText(String textComment) { + if (textComment == null) { + throw new IllegalArgumentException(); + } + modifying(); + this.text = textComment; + } + + /** + * Sets or clears the Javadoc comment string. The documentation + * string must include the starting and ending comment delimiters, + * and any embedded line breaks. + * + * @param comment the javadoc comment string + * @exception IllegalArgumentException if the Java comment string is invalid + */ + public void setComment(String comment) { + setText(comment); + //this.block = (comment.indexOf('\r') >= 0 || comment.indexOf('\n') >= 0); + if (this.block) { + DOMCommentParser parser = new DOMCommentParser(this.getAST()); + if (parser.parse(this)) { + if ((getStartPosition() > 0) && (this.tags != null)) { + for(Iterator it = this.tags.iterator(); it.hasNext(); ) { + JavadocTag tag = (JavadocTag) it.next(); + tag.setSourceRange(tag.getStartPosition()+getStartPosition(), tag.getLength()); + } + } + } else { + throw new IllegalArgumentException(); + } + } + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int memSize() { + int size = BASE_NODE_SIZE; + if (this.text != null) { + // Strings usually have 4 instance fields, one of which is a char[] + size += HEADERS + 4 * 4; + // char[] has 2 bytes per character + size += HEADERS + 2 * this.text.length(); + } + size += 4; // size for block + size += 4; // size for tags + return size; + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + int treeSize() { + return memSize() + tags.listSize(); + } + + /** + * @return Returns the tagDeclarations. + */ + public List tags() { + return tags; + } + + /** + * @return Returns the isBlock. + */ + public boolean isBlock() { + return block; + } + + /** + * @param isBlock The isBlock to set. + */ + public void setBlock(boolean isBlock) { + modifying(); + this.block = isBlock; + } + + /** + * Returns whether the comment is a javadoc comment or not. + * @return true if the comment is a Javadoc one, false otherwise. + */ + public boolean isJavadoc() { + return false; + } + + /** + * Returns whether the comment has tags or not. + * @return true if some tags are written in the comment, false otherwise. + */ + public boolean hasTags() { + return (this.tags != null) && (this.tags.size() > 0); + } +} + Index: dom/org/eclipse/jdt/core/dom/DOMCommentParser.java =================================================================== RCS file: dom/org/eclipse/jdt/core/dom/DOMCommentParser.java diff -N dom/org/eclipse/jdt/core/dom/DOMCommentParser.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dom/org/eclipse/jdt/core/dom/DOMCommentParser.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,928 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.dom; + +import java.util.ArrayList; + +import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.core.compiler.InvalidInputException; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; + +/** + * Parser specialized for decoding comments. + */ +public class DOMCommentParser { + + // recognized tags + public static final char[] TAG_DEPRECATED = "deprecated".toCharArray(); //$NON-NLS-1$ + public static final char[] TAG_PARAM = "param".toCharArray(); //$NON-NLS-1$ + public static final char[] TAG_RETURN = "return".toCharArray(); //$NON-NLS-1$ + public static final char[] TAG_THROWS = "throws".toCharArray(); //$NON-NLS-1$ + public static final char[] TAG_EXCEPTION = "exception".toCharArray(); //$NON-NLS-1$ + public static final char[] TAG_SEE = "see".toCharArray(); //$NON-NLS-1$ + public static final char[] EMBEDDED_TAG_INHERIT_DOC = "inheritdDoc".toCharArray(); //$NON-NLS-1$ + public static final char[] EMBEDDED_TAG_LINK = "link".toCharArray(); //$NON-NLS-1$ + public static final char[] EMBEDDED_TAG_LINKPLAIN = "linkplain".toCharArray(); //$NON-NLS-1$ + + // tags expected positions + public final static int ORDERED_TAGS_NUMBER = 3; + public final static int PARAM_TAG_EXPECTED_ORDER = 0; + public final static int THROWS_TAG_EXPECTED_ORDER = 1; + public final static int SEE_TAG_EXPECTED_ORDER = 2; + + // Public fields + private Comment comment; + private DOMScanner scanner; + private AST ast; + + // Private fields + private int currentTokenType = -1; + private int index, linePtr; + private char[] source; + + // Identifier stack + protected int identifierPtr; + protected String[] identifierStack; + protected int identifierLengthPtr; + protected int[] identifierLengthStack; + protected long[] identifierPositionStack; + // Ast stack + protected static int AstStackIncrement = 10; + protected int astPtr; + protected ASTNode[] astStack; + //protected int astLengthPtr; + //protected int[] astLengthStack; + + DOMCommentParser(AST ast) { + this.ast = ast; + this.scanner = new DOMScanner(true, true, false, ClassFileConstants.JDK1_3, null, null); + this.scanner.recordLineSeparator = true; + this.identifierStack = new String[10]; + this.identifierPositionStack = new long[10]; + this.identifierLengthStack = new int[20]; + this.astStack = new ASTNode[20]; + //this.astLengthStack = new int[30]; + } + + /* (non-Javadoc) + * Returns true if tag @deprecated is present in annotation. + * + * If annotation checking is enabled, will also construct an Annotation node, which will be stored into Parser.annotation + * slot for being consumed later on. + */ + public boolean parse(Comment astComment) { + + // Init + this.scanner.setSource(astComment.getText().toCharArray()); + reset(); + boolean valid = false; + this.comment = astComment; + Javadoc javadoc = astComment.isJavadoc() ? (Javadoc) astComment : null; + + // Parse + try { + // Verify first characters + if (readChar() != '/' || readChar() != '*') { + return false; + } + + // Go to first non blank char + if (this.source[this.index] == '*') { + readChar(); + if (!astComment.isJavadoc()) { + return readChar() == '/' && this.index == this.scanner.eofPosition; + } + } + this.scanner.restartFrom(this.index); + skipWhiteChars(true); + int tagStart = this.index; + + // We got some text before first tag declaration + if (this.source[this.index] != '@') { + // read sentences before first tag + int textStart = this.index; + this.linePtr = this.scanner.linePtr; + boolean endComment = false; + while (!endComment && (this.source[this.index] != '@') && (this.index < this.scanner.eofPosition)) { + endComment = readLine(true); // skip '*' after line + } + + // Store first sentence in javadoc + if (javadoc != null) { + // description + int textEnd = this.scanner.getCurrentTokenEndPosition(); + if (this.scanner.linePtr > this.linePtr) { + textEnd = this.scanner.getLineEnd(this.scanner.linePtr+1); + } + JavadocTag firstSentence = javadoc.getFirstSentence(true/*instanciate if null*/); + firstSentence.setSourceRange(textStart, textEnd-textStart+1); + firstSentence.setDescription(new String(this.source, textStart, textEnd-textStart+1)); + + // embedded tags + if (this.scanner.embeddedPtr >= 0) { + for (int i=0; i<=this.scanner.embeddedPtr; i++) { + JavadocEmbeddedTag embeddedTag = parseEmbeddedTag(this.scanner.embeddedTagStarts[i], this.scanner.embeddedTagStops[i]); + firstSentence.embedded().add(embeddedTag); + } + } + } + + // verify end of comment + if (this.index >= this.scanner.eofPosition) { + return endComment; + } + if (endComment) { + skipWhiteChars(false); + return this.index == this.scanner.eofPosition; + } + } + + // Loop on each @tag + this.linePtr = this.scanner.linePtr; + loopTag: while (this.index < this.scanner.eofPosition) { + + // We should be at the beginning of a tag declaration... + skipWhiteChars(false); + if (this.source[this.index] != '@') { + break; + } + tagStart = this.index; + readChar(); + this.scanner.restartFrom(this.index); + + // Consume tag declaration + int tk = readTokenAndConsume(); // tag name + JavadocTag javadocTag = null; + switch (tk) { + case TerminalTokens.TokenNameIdentifier : + char[] tag = this.scanner.getCurrentIdentifierSource(); + skipWhiteChars(false); + if (CharOperation.equals(tag, TAG_PARAM)) { + javadocTag = parseParam(); + } else if (CharOperation.equals(tag, TAG_EXCEPTION)) { + javadocTag = parseThrows(); + } else if (CharOperation.equals(tag, TAG_SEE)) { + javadocTag = parseSee(); + } else { + javadocTag = parseTag(new String(tag)); + } + break; + case TerminalTokens.TokenNamereturn : + javadocTag = parseTag(new String(TAG_RETURN)); + break; + case TerminalTokens.TokenNamethrows : + javadocTag = parseThrows(); + break; + } + if (javadocTag == null) { + break; + } + + // Consume tag description + int textStart = this.index; + if (this.currentTokenType == -1) { + skipWhiteChars(false); + textStart = this.index; // store start again as it might be changed + } else { + if (this.currentTokenType != TerminalTokens.TokenNameWHITESPACE) { + textStart = this.scanner.getCurrentTokenStartPosition(); // one token was already read, start is at the beginning of this token + } + consumeToken(); + } + + // If new line was encountered while parsing tag declaration then do not read the first line + // (if this happens, this means that first line of description was empty and we're already on the second one) + boolean firstLineEmpty = this.scanner.linePtr > this.linePtr; + + // Loop on lines for tag description + loopText: while (this.index < this.scanner.eofPosition) { + this.linePtr = this.scanner.linePtr; + if (!firstLineEmpty) { + // stop right now if end of the comment is encountered + if (readLine(false/*keep '*' after line*/)) { + setJavadocTagText(javadocTag, tagStart, textStart); + skipWhiteChars(false); + valid = this.index == this.scanner.eofPosition; + break loopTag; + } + + // add embedded tags if necessary + if (this.scanner.embeddedPtr >= 0) { + for (int i=0; i<=this.scanner.embeddedPtr; i++) { + JavadocEmbeddedTag embeddedTag = parseEmbeddedTag(this.scanner.embeddedTagStarts[i], this.scanner.embeddedTagStops[i]); + javadocTag.embedded().add(embeddedTag); + } + } + + } + + // after reading a line, we should have a new line starting with a '*' or a new tag + // (since JDK 1.4 '*' is not mandatory at the beginning of the line...) + switch (this.source[this.index]) { + case '*' : + readChar(); + if (this.source[this.index] == '/') { + // sounds like end of comment, prepare to leave + readChar(); + skipWhiteChars(false); + valid = this.index == this.scanner.eofPosition; + } else { + skipWhiteChars(false); + if (this.source[this.index] != '@') { + // we're not on a new tag declaration, then read following line of description + break; + } + } + // fall through following case as we got a new tag or end of comment + case '@': + if (firstLineEmpty && (javadocTag.getReference() != null)) { // we're on an empty first line, end of text is on previous line... + int textEnd = javadocTag.getReference().getEndPosition(); + javadocTag.setSourceRange(tagStart, textEnd-tagStart+1); + //javadocTag.setDescription(new String(this.source, textStart, textEnd-textStart+1)); + this.linePtr = this.scanner.linePtr; + //this.linesPtr = -1; + } else { + setJavadocTagText(javadocTag, tagStart, textStart); + } + this.comment.tags().add(javadocTag); + break loopText; + default : + break loopTag; + } + firstLineEmpty = false; // we only want to skip first line read + } + } + } catch (Exception e) { + valid = false; + } finally { + this.source = null; // release source as soon as finished + } + return valid; + } + + private void consumeToken() { + this.currentTokenType = -1; // flush token cache + } + + private SimpleType getEnclosingType() { + ASTNode parent = this.comment.getParent(); + while (parent != null) { + if (parent instanceof SimpleType) { + return (SimpleType) parent; + } + parent = parent.getParent(); + } + return null; + } + + /* + * Parse argument in @see tag method reference + */ + private Expression parseArguments(SimpleType receiver) throws InvalidInputException { + + // Init + int modulo = 0; // should be 2 for (Type,Type,...) or 3 for (Type arg,Type arg,...) + int iToken = 0; + String argName = null; + int ptr = this.astPtr; + //int lptr = this.astLengthPtr; + int start = this.scanner.getCurrentTokenStartPosition(); + + // Decide whether we have a constructor or not + SimpleName simpleName = null; + Name receiverName = receiver.getName(); + if (receiverName.isQualifiedName()) { + simpleName = ((QualifiedName) receiverName).getName(); + } else { + simpleName = (SimpleName) receiverName; + } + boolean isConstructor = simpleName.getIdentifier().equals(this.identifierStack[0]); + + // Parse arguments declaration if method reference + nextArg : while (this.index < this.scanner.eofPosition) { + + // Read argument type reference + Type type; + try { + type = parseQualifiedName(false); + } catch (InvalidInputException e) { + break nextArg; + } + boolean firstArg = modulo == 0; + if (firstArg) { // verify position + if (iToken != 0) + break nextArg; + } else if ((iToken % modulo) != 0) { + break nextArg; + } + if (type == null) { + if (firstArg && this.currentTokenType == TerminalTokens.TokenNameRPAREN) { + int idStart = (int) (this.identifierPositionStack[0] >>> 32); + int idLength = ((int) this.identifierPositionStack[0]) - idStart + 1; + if (isConstructor) { + ClassInstanceCreation invocation = this.ast.newClassInstanceCreation(); + invocation.setSourceRange(idStart, idLength); + invocation.setName(receiver.getName()); + return invocation; + } else { + SimpleName methodName = this.ast.newSimpleName(this.identifierStack[0]); + methodName.setSourceRange(idStart, idLength); + MethodInvocation invocation = this.ast.newMethodInvocation(); + invocation.setName(methodName); + invocation.setSourceRange(start, this.scanner.getCurrentTokenEndPosition()-start+1); + return invocation; + } + } + break nextArg; + } + int argStart = type.getStartPosition(); + int argLength = type.getLength(); + iToken++; + + // Read possible array declaration + if (readToken() == TerminalTokens.TokenNameLBRACKET) { + while (readToken() == TerminalTokens.TokenNameLBRACKET) { + consumeToken(); + if (readToken() != TerminalTokens.TokenNameRBRACKET) { + break nextArg; + } + consumeToken(); + type = this.ast.newArrayType(type); + } + type.setSourceRange(argStart, this.scanner.getCurrentTokenEndPosition()-argStart+1); + } + + // Read argument name + if (readToken() == TerminalTokens.TokenNameIdentifier) { + consumeToken(); + if (firstArg) { // verify position + if (iToken != 1) + break nextArg; + } else if ((iToken % modulo) != 1) { + break nextArg; + } + if (argName == null) { // verify that all arguments name are declared + if (!firstArg) { + break nextArg; + } + } + argName = this.scanner.getCurrentIdentifierSourceAsString(); + argLength = this.scanner.getCurrentTokenEndPosition()-argStart+1; + iToken++; + } else if (argName != null) { // verify that no argument name is declared + break nextArg; + } + + // Verify token position + if (firstArg) { + modulo = iToken + 1; + } else { + if ((iToken % modulo) != (modulo - 1)) { + break nextArg; + } + } + + // Read separator or end arguments declaration + int token = readToken(); + String name = argName == null ? new String() : argName; + if (token == TerminalTokens.TokenNameCOMMA) { + // Create new argument + SingleVariableDeclaration variable = this.ast.newSingleVariableDeclaration(); + variable.setSourceRange(argStart, argLength); + variable.setName(this.ast.newSimpleName(name)); + variable.setType(type); + JavadocArgument argument = this.ast.newJavadocArgument(); + argument.setSourceRange(argStart, argLength); + argument.setArgument(variable); + pushOnAstStack(argument); + consumeToken(); + iToken++; + } else if (token == TerminalTokens.TokenNameRPAREN) { + // Create new argument + SingleVariableDeclaration variable = this.ast.newSingleVariableDeclaration(); + variable.setSourceRange(argStart, argLength); + variable.setName(this.ast.newSimpleName(name)); + variable.setType(type); + JavadocArgument argument = this.ast.newJavadocArgument(); + argument.setSourceRange(argStart, argLength); + argument.setArgument(variable); + pushOnAstStack(argument); + // Build arguments array + //int size = this.astLengthStack[this.astLengthPtr--]; + ArrayList arguments = new ArrayList(this.astPtr); + while (this.astPtr >=0) { + arguments.add(this.astStack[this.astPtr--]); + } + // Create message send + if (isConstructor) { + ClassInstanceCreation invocation = this.ast.newClassInstanceCreation(); + invocation.setSourceRange(start, this.scanner.getCurrentTokenEndPosition()-start+1); + invocation.setName(receiver.getName()); + invocation.arguments().addAll(arguments); + return invocation; + } else { + int idStart = (int) (this.identifierPositionStack[0] >>> 32); + int idLength = ((int) this.identifierPositionStack[0]) - idStart + 1; + SimpleName methodName = this.ast.newSimpleName(this.identifierStack[0]); + methodName.setSourceRange(idStart, idLength); + MethodInvocation invocation = this.ast.newMethodInvocation(); + invocation.setSourceRange(start, this.scanner.getCurrentTokenEndPosition()-start+1); + invocation.setName(methodName); + invocation.arguments().addAll(arguments); + return invocation; + } + } else { + break nextArg; + } + } + + // Invalid input: reset ast stacks pointers + consumeToken(); + if (iToken > 0) { + this.astPtr = ptr; + //this.astLengthPtr = lptr; + } + throw new InvalidInputException(); + } + + private JavadocEmbeddedTag parseEmbeddedTag(int start, int end) throws InvalidInputException { + // Init specific scanner with text wihtout braces + int sourceLength = end - (start+1); + char[] tagSource = new char[sourceLength]; + System.arraycopy(this.source, start+1, tagSource, 0, sourceLength); + DOMCommentParser parser = new DOMCommentParser(this.ast); + parser.scanner.setSource(tagSource); + parser.reset(); + + // Read embedded tag identifier + if (parser.readChar() != '@') { + throw new InvalidInputException(); + } + parser.scanner.restartFrom(parser.index); + if (parser.readTokenAndConsume() != TerminalTokens.TokenNameIdentifier) { + throw new InvalidInputException(); + } + + // Read embedded tag declaration + JavadocTag tag = null; + char[] tagName = parser.scanner.getCurrentIdentifierSource(); + parser.skipWhiteChars(false); + if (CharOperation.equals(tagName, EMBEDDED_TAG_INHERIT_DOC)) { + if (!parser.scanner.atEnd()) { + throw new InvalidInputException(); + } + } + else if (CharOperation.equals(tagName, EMBEDDED_TAG_LINK) || + (CharOperation.equals(tagName, EMBEDDED_TAG_LINKPLAIN))) + { + tag = parser.parseSee(); + if (tag == null) { + throw new InvalidInputException(); + } + tag.setIdentifier(JavadocTag.NO_IDENTIFIER); + if (parser.index < parser.scanner.eofPosition) { + int textStart = parser.index; + if (parser.currentTokenType == -1) { + parser.skipWhiteChars(false); + textStart = parser.index; + } else { + if (parser.currentTokenType != TerminalTokens.TokenNameWHITESPACE) { + textStart = parser.scanner.getCurrentTokenStartPosition(); + } + } + tag.setDescription(new String(parser.source, textStart, sourceLength-textStart)); + } + } + + // Build embedded tag + JavadocEmbeddedTag embeddedTag = this.ast.newJavadocEmbeddedTag(); + embeddedTag.setSourceRange(start, end-start+1); + embeddedTag.setTag(tag); + embeddedTag.setIdentifier(new String(tagName)); + return embeddedTag; + } + + /* + * Parse a method reference in @see tag + */ + private Expression parseMember(SimpleType receiver) throws InvalidInputException { + // Init + this.identifierPtr = -1; + this.identifierLengthPtr = -1; + + // Get type ref + SimpleType type = receiver; + if (type == null) { + type = getEnclosingType(); + if (type == null) { + return null; + } + } + + // Get member identifier + if (readTokenAndConsume() == TerminalTokens.TokenNameIdentifier) { + pushIdentifier(true); + if (readTokenAndConsume() == TerminalTokens.TokenNameLPAREN) { + try { + return parseArguments(type); + } catch (InvalidInputException e) { + // ignore + } + return null; + } + FieldAccess fieldAccess = this.ast.newFieldAccess(); + fieldAccess.setName(this.ast.newSimpleName(this.identifierStack[0])); + int idStart = (int) (this.identifierPositionStack[0] >>> 32); + int idLength = ((int) this.identifierPositionStack[0]) - idStart + 1; + fieldAccess.setSourceRange(idStart, idLength); + return fieldAccess; + } + return null; + } + + /* + * Parse @param tag declaration + */ + private JavadocTag parseParam() { + try { + int token = readTokenAndConsume(); + if (token == TerminalTokens.TokenNameIdentifier) { + JavadocTag tag = this.ast.newJavadocTag(); + tag.setIdentifier(new String(TAG_PARAM)); + SimpleName name = this.ast.newSimpleName(new String(this.scanner.getCurrentIdentifierSource())); + VariableDeclarationFragment variable = this.ast.newVariableDeclarationFragment(); + variable.setSourceRange(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition()-this.scanner.getCurrentTokenStartPosition()+1); + variable.setName(name); + tag.setReference(variable); + return tag; + } + } catch (InvalidInputException e) { + consumeToken(); + } + return null; + } + + /* + * Parse a qualified name and built a type reference if the syntax is valid. + */ + private Type parseQualifiedName(boolean reset) throws InvalidInputException { + + // Reset identifier stack if requested + int start = this.scanner.getCurrentTokenStartPosition(); + if (reset) { + this.identifierPtr = -1; + this.identifierLengthPtr = -1; + } + + // Scan tokens + int typeTokenEnd = -1; + nextToken : for (int iToken = 0; ; iToken++) { + int lptr = this.scanner.linePtr; + int token = readToken(); + switch (token) { + case TerminalTokens.TokenNameIdentifier : + if (((iToken % 2) > 0)) { // identifiers must be odd tokens + break nextToken; + } + pushIdentifier(iToken == 0); + consumeToken(); + typeTokenEnd = this.scanner.getCurrentTokenEndPosition(); + break; + + case TerminalTokens.TokenNameDOT : + if ((iToken % 2) == 0) { // dots must be even tokens + throw new InvalidInputException(); + } + consumeToken(); + break; + + case TerminalTokens.TokenNamevoid : + if (iToken > 0) throw new InvalidInputException(); + PrimitiveType type = this.ast.newPrimitiveType(PrimitiveType.VOID); + consumeToken(); + return type; + case TerminalTokens.TokenNameboolean : + if (iToken > 0) throw new InvalidInputException(); + type = this.ast.newPrimitiveType(PrimitiveType.BOOLEAN); + consumeToken(); + return type; + case TerminalTokens.TokenNamebyte : + if (iToken > 0) throw new InvalidInputException(); + type = this.ast.newPrimitiveType(PrimitiveType.BYTE); + consumeToken(); + return type; + case TerminalTokens.TokenNamechar : + if (iToken > 0) throw new InvalidInputException(); + type = this.ast.newPrimitiveType(PrimitiveType.CHAR); + consumeToken(); + return type; + case TerminalTokens.TokenNamedouble : + if (iToken > 0) throw new InvalidInputException(); + type = this.ast.newPrimitiveType(PrimitiveType.DOUBLE); + consumeToken(); + return type; + case TerminalTokens.TokenNamefloat : + if (iToken > 0) throw new InvalidInputException(); + type = this.ast.newPrimitiveType(PrimitiveType.FLOAT); + consumeToken(); + return type; + case TerminalTokens.TokenNameint : + if (iToken > 0) throw new InvalidInputException(); + type = this.ast.newPrimitiveType(PrimitiveType.INT); + consumeToken(); + return type; + case TerminalTokens.TokenNamelong : + if (iToken > 0) throw new InvalidInputException(); + type = this.ast.newPrimitiveType(PrimitiveType.LONG); + consumeToken(); + return type; + case TerminalTokens.TokenNameshort : + if (iToken > 0) throw new InvalidInputException(); + type = this.ast.newPrimitiveType(PrimitiveType.SHORT); + consumeToken(); + return type; + + case TerminalTokens.TokenNameWHITESPACE: + // Ignore white spaces + if (this.scanner.linePtr > lptr) { + // Leave if new line was encountered + break nextToken; + } + iToken--; + consumeToken(); + break; + default : + if (iToken == 0) { + return null; + } + if ((iToken % 2) == 0) { // cannot leave on a dot + throw new InvalidInputException(); + } + break nextToken; + } + } + + // We should have stored a end position for the type + if (typeTokenEnd == -1) { + throw new InvalidInputException(); + } + + // Build type reference from read tokens + int size = this.identifierLengthStack[this.identifierLengthPtr--]; + String[] identifiers = new String[size]; + int pos = this.identifierPtr - size + 1; + System.arraycopy(this.identifierStack, pos, identifiers, 0, size); + SimpleType type = this.ast.newSimpleType( this.ast.newName(identifiers)); + type.setSourceRange(start, typeTokenEnd-start+1); + this.identifierPtr -= size; + return type; + } + + /* + * Parse a reference in @see tag + */ + private ASTNode parseReference() throws InvalidInputException { + SimpleType type = null; + nextToken : while (this.index < this.scanner.eofPosition) { + int token = readToken(); + int start = this.scanner.getCurrentTokenStartPosition(); + switch (token) { + case TerminalTokens.TokenNameStringLiteral : + // @see "string" + if (type == null) { + consumeToken(); + try { + if (readToken() == TerminalTokens.TokenNameEOF) { + StringLiteral node = this.ast.newStringLiteral(); + node.setLiteralValue(this.scanner.getCurrentTokenSourceAsString()); + node.setSourceRange(start, this.scanner.getCurrentTokenEndPosition()-start+1); + } + } catch (InvalidInputException e) {// Do nothing as we want to underline from the beginning of the string + } + } + return null; + case TerminalTokens.TokenNameLESS : + // @see label + consumeToken(); + return null; + case TerminalTokens.TokenNameERROR : + consumeToken(); + if (this.scanner.currentCharacter == '#') { // @see ...#member + return parseMember(type); + } + break nextToken; + case TerminalTokens.TokenNameIdentifier : + if (type == null) { + Type refType = parseQualifiedName(true); + if (refType instanceof SimpleType) { + type = (SimpleType) refType; + break; + } + } + default : + break nextToken; + } + } + return type; + } + + /* + * Parse @return tag declaration + */ + private JavadocTag parseTag(String tagName) { + JavadocTag tag = this.ast.newJavadocTag(); + tag.setIdentifier(tagName); + return tag; + } + + /* + * Parse @see tag declaration + */ + private JavadocTag parseSee() { + int start = this.scanner.currentPosition; + try { + JavadocTag tag = this.ast.newJavadocTag(); + tag.setIdentifier(new String(TAG_SEE)); + ASTNode ref = parseReference(); + if (ref != null) { + ref.setSourceRange(start, this.scanner.getCurrentTokenEndPosition()-start+1); + tag.setReference(ref); + return tag; + } + } catch (InvalidInputException ex) { + // ignore + } + return null; + } + + /* + * Parse @throws tag declaration + */ + private JavadocTag parseThrows() { + try { + JavadocTag tag = this.ast.newJavadocTag(); + tag.setIdentifier(new String(TAG_THROWS)); + Type type = parseQualifiedName(true); + if (type != null && type instanceof SimpleType) { + tag.setReference(type); + return tag; + } + } catch (InvalidInputException ex) { + // ignore + } + return null; + } + + /* + * push the consumeToken on the identifier stack. Increase the total number of identifier in the stack. + */ + private void pushIdentifier(boolean newLength) { + + String identifier = new String(this.scanner.getCurrentTokenSource()); + try { + this.identifierStack[++this.identifierPtr] = identifier; + this.identifierPositionStack[this.identifierPtr] = (((long) this.scanner.startPosition) << 32) + + (this.scanner.currentPosition - 1); + } catch (IndexOutOfBoundsException e) { + //---stack reallaocation (identifierPtr is correct)--- + int oldStackLength = this.identifierStack.length; + String[] oldStack = this.identifierStack; + this.identifierStack = new String[oldStackLength + 10]; + System.arraycopy(oldStack, 0, this.identifierStack, 0, oldStackLength); + this.identifierStack[this.identifierPtr] = identifier; + // identifier position stack + long[] oldPos = this.identifierPositionStack; + this.identifierPositionStack = new long[oldStackLength + 10]; + System.arraycopy(oldPos, 0, this.identifierPositionStack, 0, oldStackLength); + this.identifierPositionStack[this.identifierPtr] = (((long) this.scanner.startPosition) << 32) + + (this.scanner.currentPosition - 1); + } + + if (newLength) { + try { + this.identifierLengthStack[++this.identifierLengthPtr] = 1; + } catch (IndexOutOfBoundsException e) { + /* ---stack reallocation (identifierLengthPtr is correct)--- */ + int oldStackLength = this.identifierLengthStack.length; + int oldStack[] = this.identifierLengthStack; + this.identifierLengthStack = new int[oldStackLength + 10]; + System.arraycopy(oldStack, 0, this.identifierLengthStack, 0, oldStackLength); + this.identifierLengthStack[this.identifierLengthPtr] = 1; + } + } else { + this.identifierLengthStack[this.identifierLengthPtr]++; + } + } + + /* + * Add a new obj on top of the ast stack. + * If new length is required, then add also a new length in length stack. + */ + private void pushOnAstStack(ASTNode node) { + + try { + this.astStack[++this.astPtr] = node; + } catch (IndexOutOfBoundsException e) { + int oldStackLength = this.astStack.length; + ASTNode[] oldStack = this.astStack; + this.astStack = new ASTNode[oldStackLength + AstStackIncrement]; + System.arraycopy(oldStack, 0, this.astStack, 0, oldStackLength); + this.astPtr = oldStackLength; + this.astStack[this.astPtr] = node; + } + } + + /* + * Read next char using parser source. Do NOT change scanner current position. + */ + private char readChar() { + char c = this.source[this.index++]; + if (c == '\\') { + int c1, c2, c3, c4; + this.index++; + while (this.source[this.index] == 'u') + this.index++; + if (!(((c1 = Character.getNumericValue(this.source[this.index++])) > 15 || c1 < 0) + || ((c2 = Character.getNumericValue(this.source[this.index++])) > 15 || c2 < 0) + || ((c3 = Character.getNumericValue(this.source[this.index++])) > 15 || c3 < 0) || ((c4 = Character.getNumericValue(this.source[this.index++])) > 15 || c4 < 0))) { + c = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); + } + } + return c; + } + + /* + * Read until the end of the line. If previous token was not consumed, + * then push it at the beginning of the line. + */ + private boolean readLine(boolean skipStar) throws InvalidInputException { + //String line = (this.currentTokenType == -1) ? "" : this.scanner.getCurrentTokenSourceAsString(); //$NON-NLS-1$ + //line += this.scanner.getLineEndAsString(); + boolean endComment = this.scanner.skipCommentLine(); + this.index = this.scanner.currentPosition; + skipWhiteChars(skipStar); + return endComment; + } + + /* + * Read token only if previous was consumed + */ + private int readToken() throws InvalidInputException { + if (this.currentTokenType < 0) { + this.currentTokenType = this.scanner.getNextToken(); + this.index = this.scanner.currentPosition; + } + return this.currentTokenType; + } + + private int readTokenAndConsume() throws InvalidInputException { + int token = readToken(); + consumeToken(); + return token; + } + + private void reset() { + this.scanner.embeddedPtr = -1; + this.source = this.scanner.source; + this.index = 0; + this.source = this.scanner.source; + //this.astLengthPtr = -1; + this.astPtr = -1; + this.identifierPtr = -1; + this.linePtr = -1; + this.currentTokenType = -1; + } + + private void setJavadocTagText(JavadocTag javadocTag, int tagStart, int textStart) { + int textEnd = this.scanner.getCurrentTokenEndPosition(); + if (this.scanner.linePtr > this.linePtr) { + textEnd = this.scanner.getLineEnd(this.scanner.linePtr+1); + } + javadocTag.setSourceRange(tagStart, textEnd-tagStart+1); + javadocTag.setDescription(new String(this.source, textStart, textEnd-textStart+1)); + this.linePtr = this.scanner.linePtr; + } + + private void skipWhiteChars(boolean skipStar) { + while (this.indexJavadocTag
).
+ * Defaults to none.
+ */
+ ASTNode.NodeList embedded = new ASTNode.NodeList(true, JavadocEmbeddedTag.class);
+
+
+ /**
+ * Creates a new AST node for a Javadoc tag owned by the given Javadoc comment.
+ * The new node has an unspecified, but legal, Javadoc comment.
+ * + * N.B. This constructor is package-private; all subclasses must be + * declared in the same package; clients are unable to declare + * additional subclasses. + *
+ * + * @param ast the AST that is to own this node + */ + JavadocTag(AST ast) { + super(ast); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + void accept0(ASTVisitor visitor) { + visitor.visit(this); + visitor.endVisit(this); + } + + /* (omit javadoc for this method) + * Method declared on ASTNode. + */ + public int getNodeType() { + return JAVADOC_TAG; + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.core.dom.ASTNode#clone(org.eclipse.jdt.core.dom.AST) + */ + ASTNode clone(AST target) { + JavadocTag result = new JavadocTag(target); + result.setSourceRange(this.getStartPosition(), this.getLength()); + result.setIdentifier(this.identifier); + result.setDescription(getDescription()); + result.setReference(getReference()); + return result; + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.core.dom.ASTNode#memSize() + */ + int memSize() { + int size = BASE_NODE_SIZE; + if (this.identifier!= null) { + // Strings usually have 4 instance fields, one of which is a char[] + size += HEADERS + 4 * 4; + // char[] has 2 bytes per character + size += HEADERS + 2 * this.identifier.length(); + } + size += 4; // reference + if (this.description!= null) { + // Strings usually have 4 instance fields, one of which is a char[] + size += HEADERS + 4 * 4; + // char[] has 2 bytes per character + size += HEADERS + 2 * this.description.length(); + } + size += 4; // embedded + return size; + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.core.dom.ASTNode#subtreeMatch(org.eclipse.jdt.core.dom.ASTMatcher, java.lang.Object) + */ + public boolean subtreeMatch(ASTMatcher matcher, Object other) { + return matcher.match(this, other); + } + + /* (non-Javadoc) + * @see org.eclipse.jdt.core.dom.ASTNode#treeSize() + */ + int treeSize() { + return memSize() + + (this.reference == null ? 0 : this.reference.treeSize()) + + (this.embedded == null ? 0 : this.embedded.listSize()); + } + + /** + * @return Returns the reference. + */ + public ASTNode getReference() { + return this.reference; + } + + /** + * @param reference The reference to set. + */ + public void setReference(ASTNode reference) { + if (reference == null) { + throw new IllegalArgumentException(); + } + replaceChild(this.reference, reference, false); + this.reference = reference; + } + + /** + * @return Returns the name. + */ + public String getIdentifier() { + return this.identifier; + } + + /** + * @param id The name to set. + */ + public void setIdentifier(String id) { + if (id == null) { + throw new IllegalArgumentException(); + } + modifying(); + this.identifier = id; + } + + /** + * @return Returns the text. + */ + public String getDescription() { + return this.description; + } + + /** + * @param text The text to set. + */ + public void setDescription(String text) { + if (text == null) { + throw new IllegalArgumentException(); + } + modifying(); + this.description = text; + } + + /** + * @return Returns the tagDeclarations. + */ + public List embedded() { + return this.embedded; + } +}