X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fparser%2FAbstractCommentParser.java;fp=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fparser%2FAbstractCommentParser.java;h=0000000000000000000000000000000000000000;hb=6f0cd02d46e011bd5599e1b7fefc6159cb811135;hp=ca99505046d030ce44c45db9500b2092b4a82321;hpb=622d0e5a4b1b35b6918a516a79a0cc22272a919e;p=org.ibex.tool.git diff --git a/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java b/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java deleted file mode 100644 index ca99505..0000000 --- a/src/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java +++ /dev/null @@ -1,1402 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2004 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.internal.compiler.parser; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.jdt.core.compiler.CharOperation; -import org.eclipse.jdt.core.compiler.InvalidInputException; -import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; - -/** - * Parser specialized for decoding javadoc comments - */ -public abstract class AbstractCommentParser { - - // 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[] TAG_LINK = "link".toCharArray(); //$NON-NLS-1$ - public static final char[] TAG_LINKPLAIN = "linkplain".toCharArray(); //$NON-NLS-1$ - public static final char[] TAG_INHERITDOC = "inheritDoc".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; - - // Kind of comment parser - public final static int COMPIL_PARSER = 0x00000001; - public final static int DOM_PARSER = 0x00000002; - - // Public fields - public Scanner scanner; - public boolean checkDocComment = false; - - // Protected fields - protected boolean inherited, deprecated; - protected char[] source; - protected int index, endComment, lineEnd; - protected int tokenPreviousPosition, lastIdentifierEndPosition, starPosition; - protected int textStart, memberStart; - protected int tagSourceStart, tagSourceEnd; - protected int inlineTagStart; - protected Parser sourceParser; - protected Object returnStatement; - protected boolean lineStarted = false, inlineTagStarted = false; - protected int kind; - protected int[] lineEnds; - - // Private fields - private int currentTokenType = -1; - - // Line pointers - private int linePtr, lastLinePtr; - - // Identifier stack - protected int identifierPtr; - protected char[][] identifierStack; - protected int identifierLengthPtr; - protected int[] identifierLengthStack; - protected long[] identifierPositionStack; - // Ast stack - protected static int AstStackIncrement = 10; - protected int astPtr; - protected Object[] astStack; - protected int astLengthPtr; - protected int[] astLengthStack; - - protected AbstractCommentParser(Parser sourceParser) { - this.sourceParser = sourceParser; - this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3, null, null, true/*taskCaseSensitive*/); - this.identifierStack = new char[20][]; - this.identifierPositionStack = new long[20]; - this.identifierLengthStack = new int[10]; - this.astStack = new Object[30]; - this.astLengthStack = new int[20]; - } - - /* (non-Javadoc) - * Returns true if tag @deprecated is present in javadoc comment. - * - * If javadoc checking is enabled, will also construct an Javadoc node, which will be stored into Parser.javadoc - * slot for being consumed later on. - */ - protected boolean parseComment(int javadocStart, int javadocEnd) { - - boolean validComment = true; - try { - // Init scanner position - this.scanner.resetTo(javadocStart, javadocEnd); - this.endComment = javadocEnd; - this.index = javadocStart; - readChar(); // starting '/' - int previousPosition = this.index; - readChar(); // first '*' - char nextCharacter= readChar(); // second '*' - - // Init local variables - this.astLengthPtr = -1; - this.astPtr = -1; - this.currentTokenType = -1; - this.inlineTagStarted = false; - this.inlineTagStart = -1; - this.lineStarted = false; - this.returnStatement = null; - this.inherited = false; - this.deprecated = false; - this.linePtr = getLineNumber(javadocStart); - this.lastLinePtr = getLineNumber(javadocEnd); - this.lineEnd = (this.linePtr == this.lastLinePtr) ? this.endComment : this.scanner.getLineEnd(this.linePtr); - this.textStart = -1; - char previousChar = 0; - int invalidTagLineEnd = -1; - int invalidInlineTagLineEnd = -1; - - // Loop on each comment character - while (this.index < this.endComment) { - previousPosition = this.index; - previousChar = nextCharacter; - - // Calculate line end (cannot use this.scanner.linePtr as scanner does not parse line ends again) - if (this.index > (this.lineEnd+1)) { - updateLineEnd(); - } - - // Read next char only if token was consumed - if (this.currentTokenType < 0) { - nextCharacter = readChar(); // consider unicodes - } else { - previousPosition = this.scanner.getCurrentTokenStartPosition(); - switch (this.currentTokenType) { - case TerminalTokens.TokenNameRBRACE: - nextCharacter = '}'; - break; - case TerminalTokens.TokenNameMULTIPLY: - nextCharacter = '*'; - break; - default: - nextCharacter = this.scanner.currentCharacter; - } - consumeToken(); - } - - if (this.index >= this.endComment) { - break; - } - - switch (nextCharacter) { - case '@' : - boolean valid = false; - // Start tag parsing only if we have a java identifier start character and if we are on line beginning or at inline tag beginning - if ((!this.lineStarted || previousChar == '{')) { - this.lineStarted = true; - if (this.inlineTagStarted) { - this.inlineTagStarted = false; - // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53279 - // Cannot have @ inside inline comment - if (this.sourceParser != null) { - int end = previousPosition, * chars and spaces are not allowed in tag names - switch (pc) { - case '}': - case '!': - case '#': - case '%': - case '&': - case '\'': - case ':': - // case '-': allowed in tag names as this character is often used in doclets (bug 68087) - case '<': - case '>': - case '*': // break for '*' as this is perhaps the end of comment (bug 65288) - break tagNameToken; - default: - if (pc == ' ' || Character.isWhitespace(pc)) break tagNameToken; - } - tk = readTokenAndConsume(); - pc = peekChar(); - } - int length = this.tagSourceEnd-this.tagSourceStart+1; - tag = new char[length]; - System.arraycopy(this.source, this.tagSourceStart, tag, 0, length); - this.index = this.tagSourceEnd+1; - this.scanner.currentPosition = this.tagSourceEnd+1; - this.tagSourceStart = previousPosition; - this.lineEnd = le; - } - switch (token) { - case TerminalTokens.TokenNameIdentifier : - if (CharOperation.equals(tag, TAG_DEPRECATED)) { - this.deprecated = true; - if (this.kind == DOM_PARSER) { - valid = parseTag(); - } else { - valid = true; - } - } else if (CharOperation.equals(tag, TAG_INHERITDOC)) { - // inhibits inherited flag when tags have been already stored - // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51606 - // Note that for DOM_PARSER, nodes stack may be not empty even no '@' tag - // was encountered in comment. But it cannot be the case for COMPILER_PARSER - // and so is enough as it is only this parser which signals the missing tag warnings... - this.inherited = this.astPtr==-1; - if (this.kind == DOM_PARSER) { - valid = parseTag(); - } else { - valid = true; - } - } else if (CharOperation.equals(tag, TAG_PARAM)) { - valid = parseParam(); - } else if (CharOperation.equals(tag, TAG_EXCEPTION)) { - valid = parseThrows(false); - } else if (CharOperation.equals(tag, TAG_SEE)) { - if (this.inlineTagStarted) { - // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290 - // Cannot have @see inside inline comment - valid = false; - if (this.sourceParser != null) - this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); - } else { - valid = parseSee(false); - } - } else if (CharOperation.equals(tag, TAG_LINK)) { - if (this.inlineTagStarted) { - valid = parseSee(false); - } else { - // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290 - // Cannot have @link outside inline comment - valid = false; - if (this.sourceParser != null) - this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd); - } - } else if (CharOperation.equals(tag, TAG_LINKPLAIN)) { - if (this.inlineTagStarted) { - valid = parseSee(true); - } else { - valid = parseTag(); - } - } else { - valid = parseTag(); - } - break; - case TerminalTokens.TokenNamereturn : - valid = parseReturn(); - // verify characters after return tag (we're expecting text description) - if(!verifyCharsAfterReturnTag(this.index)) { - if (this.sourceParser != null) { - int end = this.starPosition == -1 || this.lineEnd= this.endComment) end = invalidInlineTagLineEnd; - this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end); - } - if (this.lineStarted && this.textStart != -1 && this.textStart < previousPosition) { - pushText(this.textStart, previousPosition); - } - if (this.kind == DOM_PARSER) { - refreshInlineTagPosition(previousPosition); - } - } else if (this.lineStarted && this.textStart < previousPosition) { - pushText(this.textStart, previousPosition); - } - updateDocComment(); - } catch (Exception ex) { - validComment = false; - } - return validComment; - } - - private void consumeToken() { - this.currentTokenType = -1; // flush token cache - updateLineEnd(); - } - - protected abstract Object createArgumentReference(char[] name, int dim, Object typeRef, long[] dimPos, long argNamePos) throws InvalidInputException; - protected abstract Object createFieldReference(Object receiver) throws InvalidInputException; - protected abstract Object createMethodReference(Object receiver, List arguments) throws InvalidInputException; - protected Object createReturnStatement() { return null; } - protected abstract Object createTypeReference(int primitiveToken); - - private int getEndPosition() { - if (this.scanner.getCurrentTokenEndPosition() > this.lineEnd) { - return this.lineEnd; - } else { - return this.scanner.getCurrentTokenEndPosition(); - } - } - - /* - * Search the source position corresponding to the end of a given line number. - * Warning: returned position is 1-based index! - * @see Scanner#getLineEnd(int) We cannot directly use this method - * when linePtr field is not initialized. - * - private int getLineEnd(int lineNumber) { - - if (this.scanner.linePtr != -1) { - return this.scanner.getLineEnd(lineNumber); - } - if (this.lineEnds == null) - return -1; - if (lineNumber > this.lineEnds.length+1) - return -1; - if (lineNumber <= 0) - return -1; - if (lineNumber == this.lineEnds.length + 1) - return this.scanner.eofPosition; - return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line - } - */ - - /** - * Search the line number corresponding to a specific position. - * Warning: returned position is 1-based index! - * @see Scanner#getLineNumber(int) We cannot directly use this method - * when linePtr field is not initialized. - */ - private int getLineNumber(int position) { - - if (this.scanner.linePtr != -1) { - return this.scanner.getLineNumber(position); - } - if (this.lineEnds == null) - return 1; - int length = this.lineEnds.length; - if (length == 0) - return 1; - int g = 0, d = length - 1; - int m = 0; - while (g <= d) { - m = (g + d) /2; - if (position < this.lineEnds[m]) { - d = m-1; - } else if (position > this.lineEnds[m]) { - g = m+1; - } else { - return m + 1; - } - } - if (position < this.lineEnds[m]) { - return m+1; - } - return m+2; - } - - /* - * Parse argument in @see tag method reference - */ - private Object parseArguments(Object receiver) throws InvalidInputException { - - // Init - int modulo = 0; // should be 2 for (Type,Type,...) or 3 for (Type arg,Type arg,...) - int iToken = 0; - char[] argName = null; - List arguments = new ArrayList(10); - int start = this.scanner.getCurrentTokenStartPosition(); - - // Parse arguments declaration if method reference - nextArg : while (this.index < this.scanner.eofPosition) { - - // Read argument type reference - Object typeRef; - try { - typeRef = 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 (typeRef == null) { - if (firstArg && this.currentTokenType == TerminalTokens.TokenNameRPAREN) { - // verify characters after arguments declaration (expecting white space or end comment) - if (!verifySpaceOrEndComment()) { - int end = this.starPosition == -1 ? this.lineEnd : this.starPosition; - if (this.source[end]=='\n') end--; - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end); - return null; - } - this.lineStarted = true; - return createMethodReference(receiver, null); - } - break nextArg; - } - iToken++; - - // Read possible array declaration - int dim = 0; - long[] dimPositions = new long[20]; // assume that there won't be more than 20 dimensions... - if (readToken() == TerminalTokens.TokenNameLBRACKET) { - int dimStart = this.scanner.getCurrentTokenStartPosition(); - while (readToken() == TerminalTokens.TokenNameLBRACKET) { - consumeToken(); - if (readToken() != TerminalTokens.TokenNameRBRACKET) { - break nextArg; - } - consumeToken(); - dimPositions[dim++] = (((long) dimStart) << 32) + this.scanner.getCurrentTokenEndPosition(); - } - } - - // Read argument name - long argNamePos = -1; - 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.getCurrentIdentifierSource(); - argNamePos = (((long)this.scanner.getCurrentTokenStartPosition())<<32)+this.scanner.getCurrentTokenEndPosition(); - 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(); - char[] name = argName == null ? new char[0] : argName; - if (token == TerminalTokens.TokenNameCOMMA) { - // Create new argument - Object argument = createArgumentReference(name, dim, typeRef, dimPositions, argNamePos); - arguments.add(argument); - consumeToken(); - iToken++; - } else if (token == TerminalTokens.TokenNameRPAREN) { - // verify characters after arguments declaration (expecting white space or end comment) - if (!verifySpaceOrEndComment()) { - int end = this.starPosition == -1 ? this.lineEnd : this.starPosition; - if (this.source[end]=='\n') end--; - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end); - return null; - } - // Create new argument - Object argument = createArgumentReference(name, dim, typeRef, dimPositions, argNamePos); - arguments.add(argument); - consumeToken(); - return createMethodReference(receiver, arguments); - } else { - break nextArg; - } - } - - // Something wrong happened => Invalid input - throw new InvalidInputException(); - } - - /* - * Parse an URL link reference in @see tag - */ - private boolean parseHref() throws InvalidInputException { - int start = this.scanner.getCurrentTokenStartPosition(); - if (Character.toLowerCase(readChar()) == 'a') { - this.scanner.currentPosition = this.index; - if (readToken() == TerminalTokens.TokenNameIdentifier) { - this.currentTokenType = -1; // do not update line end - try { - if (CharOperation.equals(this.scanner.getCurrentIdentifierSource(), new char[]{'h', 'r', 'e', 'f'}, false) && - readToken() == TerminalTokens.TokenNameEQUAL) { - this.currentTokenType = -1; // do not update line end - if (readToken() == TerminalTokens.TokenNameStringLiteral) { - this.currentTokenType = -1; // do not update line end - // Skip all characters after string literal until closing '>' (see bug 68726) - while (this.index <= this.lineEnd && readToken() != TerminalTokens.TokenNameGREATER) { - this.currentTokenType = -1; // do not update line end - } - if (this.currentTokenType == TerminalTokens.TokenNameGREATER) { - consumeToken(); // update line end as new lines are allowed in URL description - while (readToken() != TerminalTokens.TokenNameLESS) { - if (this.scanner.currentPosition >= this.scanner.eofPosition || this.scanner.currentCharacter == '@') { - // Reset position: we want to rescan last token - this.index = this.tokenPreviousPosition; - this.scanner.currentPosition = this.tokenPreviousPosition; - this.currentTokenType = -1; - // Signal syntax error - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd); - return false; - } - consumeToken(); - } - this.currentTokenType = -1; // do not update line end - if (readChar() == '/') { - if (Character.toLowerCase(readChar()) == 'a') { - if (readChar() == '>') { - // Valid href - return true; - } - } - } - } - } - } - } catch (InvalidInputException ex) { - // Do nothing as we want to keep positions for error message - } - } - } - // Reset position: we want to rescan last token - this.index = this.tokenPreviousPosition; - this.scanner.currentPosition = this.tokenPreviousPosition; - this.currentTokenType = -1; - // Signal syntax error - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd); - return false; - } - - /* - * Parse a method reference in @see tag - */ - private Object parseMember(Object receiver) throws InvalidInputException { - // Init - this.identifierPtr = -1; - this.identifierLengthPtr = -1; - int start = this.scanner.getCurrentTokenStartPosition(); - this.memberStart = start; - - // Get member identifier - if (readToken() == TerminalTokens.TokenNameIdentifier) { - consumeToken(); - pushIdentifier(true); - // Look for next token to know whether it's a field or method reference - int previousPosition = this.index; - if (readToken() == TerminalTokens.TokenNameLPAREN) { - consumeToken(); - start = this.scanner.getCurrentTokenStartPosition(); - try { - return parseArguments(receiver); - } catch (InvalidInputException e) { - int end = this.scanner.getCurrentTokenEndPosition() < this.lineEnd ? - this.scanner.getCurrentTokenEndPosition() : - this.scanner.getCurrentTokenStartPosition(); - end = end < this.lineEnd ? end : this.lineEnd; - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReferenceArgs(start, end); - } - return null; - } - - // Reset position: we want to rescan last token - this.index = previousPosition; - this.scanner.currentPosition = previousPosition; - this.currentTokenType = -1; - - // Verify character(s) after identifier (expecting space or end comment) - if (!verifySpaceOrEndComment()) { - int end = this.starPosition == -1 ? this.lineEnd : this.starPosition; - if (this.source[end]=='\n') end--; - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end); - return null; - } - return createFieldReference(receiver); - } - int end = getEndPosition() - 1; - end = start > end ? start : end; - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, end); - // Reset position: we want to rescan last token - this.index = this.tokenPreviousPosition; - this.scanner.currentPosition = this.tokenPreviousPosition; - this.currentTokenType = -1; - return null; - } - - /* - * Parse @param tag declaration - */ - protected boolean parseParam() { - - // Store current token state - int start = this.tagSourceStart; - int end = this.tagSourceEnd; - - try { - // Push identifier next - int token = readToken(); - switch (token) { - case TerminalTokens.TokenNameIdentifier : - consumeToken(); - return pushParamName(); - case TerminalTokens.TokenNameEOF : - break; - default : - start = this.scanner.getCurrentTokenStartPosition(); - end = getEndPosition(); - if (end < start) start = this.tagSourceStart; - break; - } - } catch (InvalidInputException e) { - end = getEndPosition(); - } - - // Reset position to avoid missing tokens when new line was encountered - this.index = this.tokenPreviousPosition; - this.scanner.currentPosition = this.tokenPreviousPosition; - this.currentTokenType = -1; - - // Report problem - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingParamName(start, end); - return false; - } - - /* - * Parse a qualified name and built a type reference if the syntax is valid. - */ - protected Object parseQualifiedName(boolean reset) throws InvalidInputException { - - // Reset identifier stack if requested - if (reset) { - this.identifierPtr = -1; - this.identifierLengthPtr = -1; - } - - // Scan tokens - int primitiveToken = -1; - nextToken : for (int iToken = 0; ; iToken++) { - int token = readToken(); - switch (token) { - case TerminalTokens.TokenNameIdentifier : - if (((iToken % 2) > 0)) { // identifiers must be odd tokens - break nextToken; - } - pushIdentifier(iToken == 0); - consumeToken(); - break; - - case TerminalTokens.TokenNameDOT : - if ((iToken % 2) == 0) { // dots must be even tokens - throw new InvalidInputException(); - } - consumeToken(); - break; - - case TerminalTokens.TokenNamevoid : - case TerminalTokens.TokenNameboolean : - case TerminalTokens.TokenNamebyte : - case TerminalTokens.TokenNamechar : - case TerminalTokens.TokenNamedouble : - case TerminalTokens.TokenNamefloat : - case TerminalTokens.TokenNameint : - case TerminalTokens.TokenNamelong : - case TerminalTokens.TokenNameshort : - if (iToken > 0) { - throw new InvalidInputException(); - } - pushIdentifier(true); - primitiveToken = token; - consumeToken(); - break nextToken; - - default : - if (iToken == 0) { - return null; - } - if ((iToken % 2) == 0) { // cannot leave on a dot - // Reset position: we want to rescan last token - if (this.kind == DOM_PARSER && this.currentTokenType != -1) { - this.index = this.tokenPreviousPosition; - this.scanner.currentPosition = this.tokenPreviousPosition; - this.currentTokenType = -1; - } - throw new InvalidInputException(); - } - break nextToken; - } - } - // Reset position: we want to rescan last token - if (this.currentTokenType != -1) { - this.index = this.tokenPreviousPosition; - this.scanner.currentPosition = this.tokenPreviousPosition; - this.currentTokenType = -1; - } - this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr]; - return createTypeReference(primitiveToken); - } - - /* - * Parse a reference in @see tag - */ - protected boolean parseReference(boolean plain) throws InvalidInputException { - Object typeRef = null; - Object reference = null; - int previousPosition = -1; - int typeRefStartPosition = -1; - nextToken : while (this.index < this.scanner.eofPosition) { - previousPosition = this.index; - int token = readToken(); - switch (token) { - case TerminalTokens.TokenNameStringLiteral : // @see "string" - int start = this.scanner.getCurrentTokenStartPosition(); - consumeToken(); - // If typeRef != null we may raise a warning here to let user know there's an unused reference... - // Currently as javadoc 1.4.2 ignore it, we do the same (see bug 69302) - if (typeRef != null) { - start = this.tagSourceEnd+1; - previousPosition = start; - typeRef = null; - } - // verify end line (expecting empty or end comment) - if (verifyEndLine(previousPosition)) { - return true; - } - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd); - return false; - case TerminalTokens.TokenNameLESS : // @see "label - consumeToken(); - start = this.scanner.getCurrentTokenStartPosition(); - if (parseHref()) { - consumeToken(); - // If typeRef != null we may raise a warning here to let user know there's an unused reference... - // Currently as javadoc 1.4.2 ignore it, we do the same (see bug 69302) - if (typeRef != null) { - start = this.tagSourceEnd+1; - previousPosition = start; - typeRef = null; - } - // verify end line (expecting empty or end comment) - if (verifyEndLine(previousPosition)) { - return true; - } - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd); - } - return false; - case TerminalTokens.TokenNameERROR : - if (this.scanner.currentCharacter == '#') { // @see ...#member - consumeToken(); - reference = parseMember(typeRef); - if (reference != null) { - return pushSeeRef(reference, plain); - } - return false; - } - break nextToken; - case TerminalTokens.TokenNameIdentifier : - if (typeRef == null) { - typeRefStartPosition = this.scanner.getCurrentTokenStartPosition(); - typeRef = parseQualifiedName(true); - break; - } - break nextToken; - default : - break nextToken; - } - } - - // Verify that we got a reference - if (reference == null) reference = typeRef; - if (reference == null) { - this.index = this.tokenPreviousPosition; - this.scanner.currentPosition = this.tokenPreviousPosition; - this.currentTokenType = -1; - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingSeeReference(this.tagSourceStart, this.tagSourceEnd); - return false; - } - - // Reset position at the end of type reference - this.index = this.lastIdentifierEndPosition+1; - this.scanner.currentPosition = this.index; - this.currentTokenType = -1; - - // Verify that line end does not start with an open parenthese (which could be a constructor reference wrongly written...) - // See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=47215 - char ch = peekChar(); - if (ch == '(') { - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(typeRefStartPosition, this.lineEnd); - return false; - } - - // Verify that we get white space after reference - if (!verifySpaceOrEndComment()) { - this.index = this.tokenPreviousPosition; - this.scanner.currentPosition = this.tokenPreviousPosition; - this.currentTokenType = -1; - int end = this.starPosition == -1 ? this.lineEnd : this.starPosition; - if (this.source[end]=='\n') end--; - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(typeRefStartPosition, end); - return false; - } - - // Everything is OK, store reference - return pushSeeRef(reference, plain); - } - - /* - * Parse @return tag declaration - */ - protected abstract boolean parseReturn(); - - /* - * Parse @see tag declaration - */ - protected boolean parseSee(boolean plain) { - int start = this.scanner.currentPosition; - try { - return parseReference(plain); - } catch (InvalidInputException ex) { - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, getEndPosition()); - } - // Reset position to avoid missing tokens when new line was encountered - this.index = this.tokenPreviousPosition; - this.scanner.currentPosition = this.tokenPreviousPosition; - this.currentTokenType = -1; - return false; - } - - /* - * Parse @return tag declaration - */ - protected abstract boolean parseTag(); - - /* - * Parse @throws tag declaration - */ - protected boolean parseThrows(boolean real) { - int start = this.scanner.currentPosition; - try { - Object typeRef = parseQualifiedName(true); - if (typeRef == null) { - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingThrowsClassName(this.tagSourceStart, this.tagSourceEnd); - } else { - return pushThrowName(typeRef, real); - } - } catch (InvalidInputException ex) { - if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidThrowsClass(start, getEndPosition()); - } - return false; - } - - /* - * Return current character without move index position. - */ - private char peekChar() { - int idx = this.index; - char c = this.source[idx++]; - if (c == '\\' && this.source[idx] == 'u') { - int c1, c2, c3, c4; - idx++; - while (this.source[idx] == 'u') - idx++; - if (!(((c1 = Character.getNumericValue(this.source[idx++])) > 15 || c1 < 0) - || ((c2 = Character.getNumericValue(this.source[idx++])) > 15 || c2 < 0) - || ((c3 = Character.getNumericValue(this.source[idx++])) > 15 || c3 < 0) || ((c4 = Character.getNumericValue(this.source[idx++])) > 15 || c4 < 0))) { - c = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4); - } - } - return c; - } - - /* - * push the consumeToken on the identifier stack. Increase the total number of identifier in the stack. - */ - protected void pushIdentifier(boolean newLength) { - - int stackLength = this.identifierStack.length; - if (++this.identifierPtr >= stackLength) { - System.arraycopy( - this.identifierStack, 0, - this.identifierStack = new char[stackLength + 10][], 0, - stackLength); - System.arraycopy( - this.identifierPositionStack, 0, - this.identifierPositionStack = new long[stackLength + 10], 0, - stackLength); - } - this.identifierStack[this.identifierPtr] = this.scanner.getCurrentIdentifierSource(); - this.identifierPositionStack[this.identifierPtr] = (((long) this.scanner.startPosition) << 32) + (this.scanner.currentPosition - 1); - - if (newLength) { - stackLength = this.identifierLengthStack.length; - if (++this.identifierLengthPtr >= stackLength) { - System.arraycopy( - this.identifierLengthStack, 0, - this.identifierLengthStack = new int[stackLength + 10], 0, - stackLength); - } - 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. - */ - protected void pushOnAstStack(Object node, boolean newLength) { - - if (node == null) { - this.astLengthStack[++this.astLengthPtr] = 0; - return; - } - - int stackLength = this.astStack.length; - if (++this.astPtr >= stackLength) { - System.arraycopy( - this.astStack, 0, - this.astStack = new Object[stackLength + AstStackIncrement], 0, - stackLength); - this.astPtr = stackLength; - } - this.astStack[this.astPtr] = node; - - if (newLength) { - stackLength = this.astLengthStack.length; - if (++this.astLengthPtr >= stackLength) { - System.arraycopy( - this.astLengthStack, 0, - this.astLengthStack = new int[stackLength + AstStackIncrement], 0, - stackLength); - } - this.astLengthStack[this.astLengthPtr] = 1; - } else { - this.astLengthStack[this.astLengthPtr]++; - } - } - - /* - * Push a param name in ast node stack. - */ - protected abstract boolean pushParamName(); - - /* - * Push a reference statement in ast node stack. - */ - protected abstract boolean pushSeeRef(Object statement, boolean plain); - - /* - * Push a text element in ast node stack - */ - protected abstract void pushText(int start, int end); - - /* - * Push a throws type ref in ast node stack. - */ - protected abstract boolean pushThrowName(Object typeRef, boolean real); - - /* - * Read current character and move index position. - * Warning: scanner position is unchanged using this method! - */ - protected char readChar() { - - char c = this.source[this.index++]; - if (c == '\\' && this.source[this.index] == 'u') { - int c1, c2, c3, c4; - int pos = this.index; - 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); - } else { - // TODO (frederic) currently reset to previous position, perhaps signal a syntax error would be more appropriate - this.index = pos; - } - } - return c; - } - - /* - * Read token only if previous was consumed - */ - private int readToken() throws InvalidInputException { - if (this.currentTokenType < 0) { - this.tokenPreviousPosition = this.scanner.currentPosition; - this.currentTokenType = this.scanner.getNextToken(); - if (this.scanner.currentPosition > (this.lineEnd+1)) { // be sure to be on next line (lineEnd is still on the same line) - this.lineStarted = false; - while (this.currentTokenType == TerminalTokens.TokenNameMULTIPLY) { - this.currentTokenType = this.scanner.getNextToken(); - } - } - this.index = this.scanner.currentPosition; - this.lineStarted = true; // after having read a token, line is obviously started... - } - return this.currentTokenType; - } - - private int readTokenAndConsume() throws InvalidInputException { - int token = readToken(); - consumeToken(); - return token; - } - - /* - * Refresh start position and length of an inline tag. - */ - protected void refreshInlineTagPosition(int previousPosition) { - // do nothing by default - } - - public String toString() { - StringBuffer buffer = new StringBuffer(); - int startPos = this.scanner.currentPosition this.source.length) - return "behind the EOF\n\n" + new String(this.source); //$NON-NLS-1$ - - char front[] = new char[startPos]; - System.arraycopy(this.source, 0, front, 0, startPos); - - int middleLength = (endPos - 1) - startPos + 1; - char middle[]; - if (middleLength > -1) { - middle = new char[middleLength]; - System.arraycopy( - this.source, - startPos, - middle, - 0, - middleLength); - } else { - middle = CharOperation.NO_CHAR; - } - - char end[] = new char[this.source.length - (endPos - 1)]; - System.arraycopy( - this.source, - (endPos - 1) + 1, - end, - 0, - this.source.length - (endPos - 1) - 1); - - buffer.append(front); - if (this.scanner.currentPosition"); //$NON-NLS-1$ - } else { - buffer.append("\n===============================\nParser index here -->"); //$NON-NLS-1$ - } - buffer.append(middle); - if (this.scanner.currentPosition (this.lineEnd+1)) { // be sure to be on next line (lineEnd is still on the same line) - if (this.linePtr < this.lastLinePtr) { - this.lineEnd = this.scanner.getLineEnd(++this.linePtr) - 1; - } else { - this.lineEnd = this.endComment; - return; - } - } - } - - /* - * Verify that end of the line only contains space characters or end of comment. - * Note that end of comment may be preceeding by several contiguous '*' chars. - */ - private boolean verifyEndLine(int textPosition) { - int startPosition = this.index; - int previousPosition = this.index; - this.starPosition = -1; - char ch = readChar(); - nextChar: while (true) { - switch (ch) { - case '\r': - case '\n': - if (this.kind == DOM_PARSER) { - parseTag(); - pushText(textPosition, previousPosition); - } - this.index = previousPosition; - return true; - case '\u000c' : /* FORM FEED */ - case ' ' : /* SPACE */ - case '\t' : /* HORIZONTAL TABULATION */ - if (this.starPosition >= 0) break nextChar; - break; - case '*': - this.starPosition = previousPosition; - break; - case '/': - if (this.starPosition >= textPosition) { - if (this.kind == DOM_PARSER) { - parseTag(); - pushText(textPosition, this.starPosition); - } - return true; - } - default : - // leave loop - break nextChar; - - } - previousPosition = this.index; - ch = readChar(); - } - this.index = startPosition; - return false; - } - - /* - * Verify that some text exists after a @return tag. Text must be different than - * end of comment which may be preceeding by several '*' chars. - */ - private boolean verifyCharsAfterReturnTag(int startPosition) { - // Whitespace or inline tag closing brace - int previousPosition = this.index; - char ch = readChar(); - boolean malformed = true; - while (Character.isWhitespace(ch)) { - malformed = false; - previousPosition = this.index; - ch = readChar(); - } - // End of comment - this.starPosition = -1; - nextChar: while (this.index= startPosition) { // valid only if a star was previous character - return false; - } - default : - // valid if any other character is encountered, even white spaces - this.index = startPosition; - return !malformed; - - } - previousPosition = this.index; - ch = readChar(); - } - this.index = startPosition; - return false; - } - - /* - * Verify characters after a name matches one of following conditions: - * 1- first character is a white space - * 2- first character is a closing brace *and* we're currently parsing an inline tag - * 3- are the end of comment (several contiguous star ('*') characters may be - * found before the last slash ('/') character). - */ - private boolean verifySpaceOrEndComment() { - int startPosition = this.index; - // Whitespace or inline tag closing brace - char ch = peekChar(); - switch (ch) { - case '}': - return this.inlineTagStarted; - default: - if (Character.isWhitespace(ch)) { - return true; - } - } - // End of comment - int previousPosition = this.index; - this.starPosition = -1; - ch = readChar(); - nextChar: while (this.index= startPosition) { // valid only if a star was previous character - return true; - } - default : - // invalid whatever other character, even white spaces - this.index = startPosition; - return false; - - } - previousPosition = this.index; - ch = readChar(); - } - this.index = startPosition; - return false; - } -}