<s> 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 ; import org . eclipse . jdt . internal . compiler . util . Util ; public abstract class AbstractCommentParser implements JavadocTagConstants { public final static int COMPIL_PARSER = 0x0001 ; public final static int DOM_PARSER = 0x0002 ; public final static int SELECTION_PARSER = 0x0004 ; public final static int COMPLETION_PARSER = 0x0008 ; public final static int SOURCE_PARSER = 0x0010 ; public final static int FORMATTER_COMMENT_PARSER = 0x0020 ; protected final static int PARSER_KIND = 0x00FF ; protected final static int TEXT_PARSE = 0x0100 ; protected final static int TEXT_VERIF = 0x0200 ; protected final static int QUALIFIED_NAME_RECOVERY = 1 ; protected final static int ARGUMENT_RECOVERY = 2 ; protected final static int ARGUMENT_TYPE_RECOVERY = 3 ; protected final static int EMPTY_ARGUMENT_RECOVERY = 4 ; public Scanner scanner ; public char [ ] source ; protected Parser sourceParser ; private int currentTokenType = - 1 ; public boolean checkDocComment = false ; public boolean setJavadocPositions = false ; public boolean reportProblems ; protected long complianceLevel ; protected long sourceLevel ; protected long [ ] inheritedPositions ; protected int inheritedPositionsPtr ; private final static int INHERITED_POSITIONS_ARRAY_INCREMENT = 4 ; protected boolean deprecated ; protected Object returnStatement ; protected int javadocStart , javadocEnd ; protected int javadocTextStart , javadocTextEnd = - 1 ; protected int firstTagPosition ; protected int index , lineEnd ; protected int tokenPreviousPosition , lastIdentifierEndPosition , starPosition ; protected int textStart , memberStart ; protected int tagSourceStart , tagSourceEnd ; protected int inlineTagStart ; protected int [ ] lineEnds ; protected boolean lineStarted = false ; protected boolean inlineTagStarted = false ; protected boolean abort = false ; protected int kind ; protected int tagValue = NO_TAG_VALUE ; protected int lastBlockTagValue = NO_TAG_VALUE ; private int linePtr , lastLinePtr ; protected int identifierPtr ; protected char [ ] [ ] identifierStack ; protected int identifierLengthPtr ; protected int [ ] identifierLengthStack ; protected long [ ] identifierPositionStack ; protected final static int AST_STACK_INCREMENT = 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 ) ; 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 ] ; this . reportProblems = sourceParser != null ; if ( sourceParser != null ) { this . checkDocComment = this . sourceParser . options . docCommentSupport ; this . sourceLevel = this . sourceParser . options . sourceLevel ; this . scanner . sourceLevel = this . sourceLevel ; this . complianceLevel = this . sourceParser . options . complianceLevel ; } } protected boolean commentParse ( ) { boolean validComment = true ; try { this . astLengthPtr = - 1 ; this . astPtr = - 1 ; this . identifierPtr = - 1 ; this . currentTokenType = - 1 ; setInlineTagStarted ( false ) ; this . inlineTagStart = - 1 ; this . lineStarted = false ; this . returnStatement = null ; this . inheritedPositions = null ; this . lastBlockTagValue = NO_TAG_VALUE ; this . deprecated = false ; this . lastLinePtr = getLineNumber ( this . javadocEnd ) ; this . textStart = - 1 ; this . abort = false ; char previousChar = 0 ; int invalidTagLineEnd = - 1 ; int invalidInlineTagLineEnd = - 1 ; boolean lineHasStar = true ; boolean verifText = ( this . kind & TEXT_VERIF ) != 0 ; boolean isDomParser = ( this . kind & DOM_PARSER ) != 0 ; boolean isFormatterParser = ( this . kind & FORMATTER_COMMENT_PARSER ) != 0 ; int lastStarPosition = - 1 ; this . linePtr = getLineNumber ( this . firstTagPosition ) ; int realStart = this . linePtr == 1 ? this . javadocStart : this . scanner . getLineEnd ( this . linePtr - 1 ) + 1 ; if ( realStart < this . javadocStart ) realStart = this . javadocStart ; this . scanner . resetTo ( realStart , this . javadocEnd ) ; this . index = realStart ; if ( realStart == this . javadocStart ) { readChar ( ) ; readChar ( ) ; } int previousPosition = this . index ; char nextCharacter = 0 ; if ( realStart == this . javadocStart ) { nextCharacter = readChar ( ) ; while ( peekChar ( ) == '*' ) { nextCharacter = readChar ( ) ; } this . javadocTextStart = this . index ; } this . lineEnd = ( this . linePtr == this . lastLinePtr ) ? this . javadocEnd : this . scanner . getLineEnd ( this . linePtr ) - 1 ; this . javadocTextEnd = this . javadocEnd - 2 ; int textEndPosition = - 1 ; while ( ! this . abort && this . index < this . javadocEnd ) { previousPosition = this . index ; previousChar = nextCharacter ; if ( this . index > ( this . lineEnd + 1 ) ) { updateLineEnd ( ) ; } if ( this . currentTokenType < 0 ) { nextCharacter = readChar ( ) ; } else { previousPosition = this . scanner . getCurrentTokenStartPosition ( ) ; switch ( this . currentTokenType ) { case TerminalTokens . TokenNameRBRACE : nextCharacter = '}' ; break ; case TerminalTokens . TokenNameMULTIPLY : nextCharacter = '*' ; break ; default : nextCharacter = this . scanner . currentCharacter ; } consumeToken ( ) ; } switch ( nextCharacter ) { case '@' : if ( ( ! this . lineStarted || previousChar == '{' ) ) { if ( this . inlineTagStarted ) { setInlineTagStarted ( false ) ; if ( this . reportProblems ) { int end = previousPosition < invalidInlineTagLineEnd ? previousPosition : invalidInlineTagLineEnd ; this . sourceParser . problemReporter ( ) . javadocUnterminatedInlineTag ( this . inlineTagStart , end ) ; } validComment = false ; if ( this . textStart != - 1 && this . textStart < textEndPosition ) { pushText ( this . textStart , textEndPosition ) ; } if ( isDomParser || isFormatterParser ) { refreshInlineTagPosition ( textEndPosition ) ; } } if ( previousChar == '{' ) { if ( this . textStart != - 1 ) { if ( this . textStart < textEndPosition ) { pushText ( this . textStart , textEndPosition ) ; } } setInlineTagStarted ( true ) ; invalidInlineTagLineEnd = this . lineEnd ; } else if ( this . textStart != - 1 && this . textStart < invalidTagLineEnd ) { pushText ( this . textStart , invalidTagLineEnd ) ; } this . scanner . resetTo ( this . index , this . javadocEnd ) ; this . currentTokenType = - 1 ; try { if ( ! parseTag ( previousPosition ) ) { validComment = false ; if ( isDomParser ) { createTag ( ) ; } this . textStart = this . tagSourceEnd + 1 ; invalidTagLineEnd = this . lineEnd ; textEndPosition = this . index ; } } catch ( InvalidInputException e ) { consumeToken ( ) ; } } else { textEndPosition = this . index ; if ( verifText && this . tagValue == TAG_RETURN_VALUE && this . returnStatement != null ) { refreshReturnStatement ( ) ; } else if ( isFormatterParser ) { if ( this . textStart == - 1 ) this . textStart = previousPosition ; } } this . lineStarted = true ; break ; case '\r' : case '\n' : if ( this . lineStarted ) { if ( isFormatterParser && ! ScannerHelper . isWhitespace ( previousChar ) ) { textEndPosition = previousPosition ; } if ( this . textStart != - 1 && this . textStart < textEndPosition ) { pushText ( this . textStart , textEndPosition ) ; } } this . lineStarted = false ; lineHasStar = false ; this . textStart = - 1 ; break ; case '}' : if ( verifText && this . tagValue == TAG_RETURN_VALUE && this . returnStatement != null ) { refreshReturnStatement ( ) ; } if ( this . inlineTagStarted ) { textEndPosition = this . index - 1 ; if ( this . lineStarted && this . textStart != - 1 && this . textStart < textEndPosition ) { pushText ( this . textStart , textEndPosition ) ; } refreshInlineTagPosition ( previousPosition ) ; if ( ! isFormatterParser ) this . textStart = this . index ; setInlineTagStarted ( false ) ; } else { if ( ! this . lineStarted ) { this . textStart = previousPosition ; } } this . lineStarted = true ; textEndPosition = this . index ; break ; case '{' : if ( verifText && this . tagValue == TAG_RETURN_VALUE && this . returnStatement != null ) { refreshReturnStatement ( ) ; } if ( this . inlineTagStarted ) { setInlineTagStarted ( false ) ; if ( this . reportProblems ) { int end = previousPosition < invalidInlineTagLineEnd ? previousPosition : invalidInlineTagLineEnd ; this . sourceParser . problemReporter ( ) . javadocUnterminatedInlineTag ( this . inlineTagStart , end ) ; } if ( this . lineStarted && this . textStart != - 1 && this . textStart < textEndPosition ) { pushText ( this . textStart , textEndPosition ) ; } refreshInlineTagPosition ( textEndPosition ) ; textEndPosition = this . index ; } else if ( peekChar ( ) != '@' ) { if ( this . textStart == - 1 ) this . textStart = previousPosition ; textEndPosition = this . index ; } if ( ! this . lineStarted ) { this . textStart = previousPosition ; } this . lineStarted = true ; this . inlineTagStart = previousPosition ; break ; case '*' : lastStarPosition = previousPosition ; if ( previousChar != '*' ) { this . starPosition = previousPosition ; if ( isDomParser || isFormatterParser ) { if ( lineHasStar ) { this . lineStarted = true ; if ( this . textStart == - 1 ) { this . textStart = previousPosition ; if ( this . index <= this . javadocTextEnd ) textEndPosition = this . index ; } } if ( ! this . lineStarted ) { lineHasStar = true ; } } } break ; case ' ' : case ' ' : case '\t' : if ( isFormatterParser ) { if ( ! ScannerHelper . isWhitespace ( previousChar ) ) { textEndPosition = previousPosition ; } } else if ( this . lineStarted && isDomParser ) { textEndPosition = this . index ; } break ; case '/' : if ( previousChar == '*' ) { break ; } default : if ( isFormatterParser && nextCharacter == '<' ) { int initialIndex = this . index ; this . scanner . resetTo ( this . index , this . javadocEnd ) ; if ( ! ScannerHelper . isWhitespace ( previousChar ) ) { textEndPosition = previousPosition ; } if ( parseHtmlTag ( previousPosition , textEndPosition ) ) { break ; } if ( this . abort ) return false ; this . scanner . currentPosition = initialIndex ; this . index = initialIndex ; } if ( verifText && this . tagValue == TAG_RETURN_VALUE && this . returnStatement != null ) { refreshReturnStatement ( ) ; } if ( ! this . lineStarted || this . textStart == - 1 ) { this . textStart = previousPosition ; } this . lineStarted = true ; textEndPosition = this . index ; break ; } } this . javadocTextEnd = this . starPosition - 1 ; if ( this . inlineTagStarted ) { if ( this . reportProblems ) { int end = this . javadocTextEnd < invalidInlineTagLineEnd ? this . javadocTextEnd : invalidInlineTagLineEnd ; if ( this . index >= this . javadocEnd ) end = invalidInlineTagLineEnd ; this . sourceParser . problemReporter ( ) . javadocUnterminatedInlineTag ( this . inlineTagStart , end ) ; } if ( this . lineStarted && this . textStart != - 1 && this . textStart < textEndPosition ) { pushText ( this . textStart , textEndPosition ) ; } refreshInlineTagPosition ( textEndPosition ) ; setInlineTagStarted ( false ) ; } else if ( this . lineStarted && this . textStart != - 1 && this . textStart <= textEndPosition && ( this . textStart < this . starPosition || this . starPosition == lastStarPosition ) ) { pushText ( this . textStart , textEndPosition ) ; } updateDocComment ( ) ; } catch ( Exception ex ) { validComment = false ; } return validComment ; } protected void consumeToken ( ) { this . currentTokenType = - 1 ; updateLineEnd ( ) ; } protected abstract Object createArgumentReference ( char [ ] name , int dim , boolean isVarargs , Object typeRef , long [ ] dimPos , long argNamePos ) throws InvalidInputException ; protected boolean createFakeReference ( int start ) { return true ; } 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 void createTag ( ) ; protected abstract Object createTypeReference ( int primitiveToken ) ; private int getIndexPosition ( ) { if ( this . index > this . lineEnd ) { return this . lineEnd ; } else { return this . index - 1 ; } } private int getLineNumber ( int position ) { if ( this . scanner . linePtr != - 1 ) { return Util . getLineNumber ( position , this . scanner . lineEnds , 0 , this . scanner . linePtr ) ; } if ( this . lineEnds == null ) return 1 ; return Util . getLineNumber ( position , this . lineEnds , 0 , this . lineEnds . length - 1 ) ; } private int getTokenEndPosition ( ) { if ( this . scanner . getCurrentTokenEndPosition ( ) > this . lineEnd ) { return this . lineEnd ; } else { return this . scanner . getCurrentTokenEndPosition ( ) ; } } protected int getCurrentTokenType ( ) { return this . currentTokenType ; } protected Object parseArguments ( Object receiver ) throws InvalidInputException { int modulo = 0 ; int iToken = 0 ; char [ ] argName = null ; List arguments = new ArrayList ( 10 ) ; int start = this . scanner . getCurrentTokenStartPosition ( ) ; Object typeRef = null ; int dim = 0 ; boolean isVarargs = false ; long [ ] dimPositions = new long [ 20 ] ; char [ ] name = null ; long argNamePos = - 1 ; nextArg : while ( this . index < this . scanner . eofPosition ) { try { typeRef = parseQualifiedName ( false ) ; if ( this . abort ) return null ; } catch ( InvalidInputException e ) { break nextArg ; } boolean firstArg = modulo == 0 ; if ( firstArg ) { if ( iToken != 0 ) break nextArg ; } else if ( ( iToken % modulo ) != 0 ) { break nextArg ; } if ( typeRef == null ) { if ( firstArg && this . currentTokenType == TerminalTokens . TokenNameRPAREN ) { if ( ! verifySpaceOrEndComment ( ) ) { int end = this . starPosition == - 1 ? this . lineEnd : this . starPosition ; if ( this . source [ end ] == '\n' ) end -- ; if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocMalformedSeeReference ( start , end ) ; return null ; } this . lineStarted = true ; return createMethodReference ( receiver , null ) ; } break nextArg ; } iToken ++ ; dim = 0 ; isVarargs = false ; 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 ( ) ; } } else if ( readToken ( ) == TerminalTokens . TokenNameELLIPSIS ) { int dimStart = this . scanner . getCurrentTokenStartPosition ( ) ; dimPositions [ dim ++ ] = ( ( ( long ) dimStart ) << 32 ) + this . scanner . getCurrentTokenEndPosition ( ) ; consumeToken ( ) ; isVarargs = true ; } argNamePos = - 1 ; if ( readToken ( ) == TerminalTokens . TokenNameIdentifier ) { consumeToken ( ) ; if ( firstArg ) { if ( iToken != 1 ) break nextArg ; } else if ( ( iToken % modulo ) != 1 ) { break nextArg ; } if ( argName == null ) { if ( ! firstArg ) { break nextArg ; } } argName = this . scanner . getCurrentIdentifierSource ( ) ; argNamePos = ( ( ( long ) this . scanner . getCurrentTokenStartPosition ( ) ) << 32 ) + this . scanner . getCurrentTokenEndPosition ( ) ; iToken ++ ; } else if ( argName != null ) { break nextArg ; } if ( firstArg ) { modulo = iToken + 1 ; } else { if ( ( iToken % modulo ) != ( modulo - 1 ) ) { break nextArg ; } } int token = readToken ( ) ; name = argName == null ? CharOperation . NO_CHAR : argName ; if ( token == TerminalTokens . TokenNameCOMMA ) { Object argument = createArgumentReference ( name , dim , isVarargs , typeRef , dimPositions , argNamePos ) ; if ( this . abort ) return null ; arguments . add ( argument ) ; consumeToken ( ) ; iToken ++ ; } else if ( token == TerminalTokens . TokenNameRPAREN ) { if ( ! verifySpaceOrEndComment ( ) ) { int end = this . starPosition == - 1 ? this . lineEnd : this . starPosition ; if ( this . source [ end ] == '\n' ) end -- ; if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocMalformedSeeReference ( start , end ) ; return null ; } Object argument = createArgumentReference ( name , dim , isVarargs , typeRef , dimPositions , argNamePos ) ; if ( this . abort ) return null ; arguments . add ( argument ) ; consumeToken ( ) ; return createMethodReference ( receiver , arguments ) ; } else { break nextArg ; } } throw new InvalidInputException ( ) ; } protected boolean parseHtmlTag ( int previousPosition , int endTextPosition ) throws InvalidInputException { return false ; } protected boolean parseHref ( ) throws InvalidInputException { boolean skipComments = this . scanner . skipComments ; this . scanner . skipComments = true ; try { int start = this . scanner . getCurrentTokenStartPosition ( ) ; char currentChar = readChar ( ) ; if ( currentChar == 'a' || currentChar == 'A' ) { this . scanner . currentPosition = this . index ; if ( readToken ( ) == TerminalTokens . TokenNameIdentifier ) { consumeToken ( ) ; try { if ( CharOperation . equals ( this . scanner . getCurrentIdentifierSource ( ) , HREF_TAG , false ) && readToken ( ) == TerminalTokens . TokenNameEQUAL ) { consumeToken ( ) ; if ( readToken ( ) == TerminalTokens . TokenNameStringLiteral ) { consumeToken ( ) ; while ( this . index < this . javadocEnd ) { while ( readToken ( ) != TerminalTokens . TokenNameGREATER ) { if ( this . scanner . currentPosition >= this . scanner . eofPosition || this . scanner . currentCharacter == '@' || ( this . inlineTagStarted && this . scanner . currentCharacter == '}' ) ) { this . index = this . tokenPreviousPosition ; this . scanner . currentPosition = this . tokenPreviousPosition ; this . currentTokenType = - 1 ; if ( this . tagValue != TAG_VALUE_VALUE ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidSeeHref ( start , this . lineEnd ) ; } return false ; } this . currentTokenType = - 1 ; } consumeToken ( ) ; while ( readToken ( ) != TerminalTokens . TokenNameLESS ) { if ( this . scanner . currentPosition >= this . scanner . eofPosition || this . scanner . currentCharacter == '@' || ( this . inlineTagStarted && this . scanner . currentCharacter == '}' ) ) { this . index = this . tokenPreviousPosition ; this . scanner . currentPosition = this . tokenPreviousPosition ; this . currentTokenType = - 1 ; if ( this . tagValue != TAG_VALUE_VALUE ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidSeeHref ( start , this . lineEnd ) ; } return false ; } consumeToken ( ) ; } consumeToken ( ) ; start = this . scanner . getCurrentTokenStartPosition ( ) ; currentChar = readChar ( ) ; if ( currentChar == '/' ) { currentChar = readChar ( ) ; if ( currentChar == 'a' || currentChar == 'A' ) { currentChar = readChar ( ) ; if ( currentChar == '>' ) { return true ; } } } if ( currentChar == '\r' || currentChar == '\n' || currentChar == '\t' || currentChar == ' ' ) { break ; } } } } } catch ( InvalidInputException ex ) { } } } this . index = this . tokenPreviousPosition ; this . scanner . currentPosition = this . tokenPreviousPosition ; this . currentTokenType = - 1 ; if ( this . tagValue != TAG_VALUE_VALUE ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidSeeHref ( start , this . lineEnd ) ; } } finally { this . scanner . skipComments = skipComments ; } return false ; } protected boolean parseIdentifierTag ( boolean report ) { int token = readTokenSafely ( ) ; switch ( token ) { case TerminalTokens . TokenNameIdentifier : pushIdentifier ( true , false ) ; return true ; } if ( report ) { this . sourceParser . problemReporter ( ) . javadocMissingIdentifier ( this . tagSourceStart , this . tagSourceEnd , this . sourceParser . modifiers ) ; } return false ; } protected Object parseMember ( Object receiver ) throws InvalidInputException { this . identifierPtr = - 1 ; this . identifierLengthPtr = - 1 ; int start = this . scanner . getCurrentTokenStartPosition ( ) ; this . memberStart = start ; if ( readToken ( ) == TerminalTokens . TokenNameIdentifier ) { if ( this . scanner . currentCharacter == '.' ) { parseQualifiedName ( true ) ; } else { consumeToken ( ) ; pushIdentifier ( true , false ) ; } 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 . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidSeeReferenceArgs ( start , end ) ; } return null ; } this . index = previousPosition ; this . scanner . currentPosition = previousPosition ; this . currentTokenType = - 1 ; if ( ! verifySpaceOrEndComment ( ) ) { int end = this . starPosition == - 1 ? this . lineEnd : this . starPosition ; if ( this . source [ end ] == '\n' ) end -- ; if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocMalformedSeeReference ( start , end ) ; return null ; } return createFieldReference ( receiver ) ; } int end = getTokenEndPosition ( ) - 1 ; end = start > end ? start : end ; if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidReference ( start , end ) ; this . index = this . tokenPreviousPosition ; this . scanner . currentPosition = this . tokenPreviousPosition ; this . currentTokenType = - 1 ; return null ; } protected boolean parseParam ( ) throws InvalidInputException { int start = this . tagSourceStart ; int end = this . tagSourceEnd ; boolean tokenWhiteSpace = this . scanner . tokenizeWhiteSpace ; this . scanner . tokenizeWhiteSpace = true ; try { boolean isCompletionParser = ( this . kind & COMPLETION_PARSER ) != 0 ; if ( this . scanner . currentCharacter != ' ' && ! ScannerHelper . isWhitespace ( this . scanner . currentCharacter ) ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidTag ( start , this . scanner . getCurrentTokenEndPosition ( ) ) ; if ( ! isCompletionParser ) { this . scanner . currentPosition = start ; this . index = start ; } this . currentTokenType = - 1 ; return false ; } this . identifierPtr = - 1 ; this . identifierLengthPtr = - 1 ; boolean hasMultiLines = this . scanner . currentPosition > ( this . lineEnd + 1 ) ; boolean isTypeParam = false ; boolean valid = true , empty = true ; boolean mayBeGeneric = this . sourceLevel >= ClassFileConstants . JDK1_5 ; int token = - 1 ; nextToken : while ( true ) { this . currentTokenType = - 1 ; try { token = readToken ( ) ; } catch ( InvalidInputException e ) { valid = false ; } switch ( token ) { case TerminalTokens . TokenNameIdentifier : if ( valid ) { pushIdentifier ( true , false ) ; start = this . scanner . getCurrentTokenStartPosition ( ) ; end = hasMultiLines ? this . lineEnd : this . scanner . getCurrentTokenEndPosition ( ) ; break nextToken ; } case TerminalTokens . TokenNameLESS : if ( valid && mayBeGeneric ) { pushIdentifier ( true , true ) ; start = this . scanner . getCurrentTokenStartPosition ( ) ; end = hasMultiLines ? this . lineEnd : this . scanner . getCurrentTokenEndPosition ( ) ; isTypeParam = true ; break nextToken ; } default : if ( token == TerminalTokens . TokenNameLEFT_SHIFT ) isTypeParam = true ; if ( valid && ! hasMultiLines ) start = this . scanner . getCurrentTokenStartPosition ( ) ; valid = false ; if ( ! hasMultiLines ) { empty = false ; end = hasMultiLines ? this . lineEnd : this . scanner . getCurrentTokenEndPosition ( ) ; break ; } end = this . lineEnd ; case TerminalTokens . TokenNameWHITESPACE : if ( this . scanner . currentPosition > ( this . lineEnd + 1 ) ) hasMultiLines = true ; if ( valid ) break ; case TerminalTokens . TokenNameEOF : if ( this . reportProblems ) if ( empty ) this . sourceParser . problemReporter ( ) . javadocMissingParamName ( start , end , this . sourceParser . modifiers ) ; else if ( mayBeGeneric && isTypeParam ) this . sourceParser . problemReporter ( ) . javadocInvalidParamTypeParameter ( start , end ) ; else this . sourceParser . problemReporter ( ) . javadocInvalidParamTagName ( start , end ) ; if ( ! isCompletionParser ) { this . scanner . currentPosition = start ; this . index = start ; } this . currentTokenType = - 1 ; return false ; } } if ( isTypeParam && mayBeGeneric ) { nextToken : while ( true ) { this . currentTokenType = - 1 ; try { token = readToken ( ) ; } catch ( InvalidInputException e ) { valid = false ; } switch ( token ) { case TerminalTokens . TokenNameWHITESPACE : if ( valid && this . scanner . currentPosition <= ( this . lineEnd + 1 ) ) { break ; } case TerminalTokens . TokenNameEOF : if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidParamTypeParameter ( start , end ) ; if ( ! isCompletionParser ) { this . scanner . currentPosition = start ; this . index = start ; } this . currentTokenType = - 1 ; return false ; case TerminalTokens . TokenNameIdentifier : end = hasMultiLines ? this . lineEnd : this . scanner . getCurrentTokenEndPosition ( ) ; if ( valid ) { pushIdentifier ( false , false ) ; break nextToken ; } break ; default : end = hasMultiLines ? this . lineEnd : this . scanner . getCurrentTokenEndPosition ( ) ; valid = false ; break ; } } boolean spaces = false ; nextToken : while ( true ) { this . currentTokenType = - 1 ; try { token = readToken ( ) ; } catch ( InvalidInputException e ) { valid = false ; } switch ( token ) { case TerminalTokens . TokenNameWHITESPACE : if ( this . scanner . currentPosition > ( this . lineEnd + 1 ) ) { hasMultiLines = true ; valid = false ; } spaces = true ; if ( valid ) break ; case TerminalTokens . TokenNameEOF : if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidParamTypeParameter ( start , end ) ; if ( ! isCompletionParser ) { this . scanner . currentPosition = start ; this . index = start ; } this . currentTokenType = - 1 ; return false ; case TerminalTokens . TokenNameGREATER : end = hasMultiLines ? this . lineEnd : this . scanner . getCurrentTokenEndPosition ( ) ; if ( valid ) { pushIdentifier ( false , true ) ; break nextToken ; } break ; default : if ( ! spaces ) end = hasMultiLines ? this . lineEnd : this . scanner . getCurrentTokenEndPosition ( ) ; valid = false ; break ; } } } if ( valid ) { this . currentTokenType = - 1 ; int restart = this . scanner . currentPosition ; try { token = readTokenAndConsume ( ) ; } catch ( InvalidInputException e ) { valid = false ; } if ( token == TerminalTokens . TokenNameWHITESPACE ) { this . scanner . resetTo ( restart , this . javadocEnd ) ; this . index = restart ; return pushParamName ( isTypeParam ) ; } } this . currentTokenType = - 1 ; if ( isCompletionParser ) return false ; if ( this . reportProblems ) { end = hasMultiLines ? this . lineEnd : this . scanner . getCurrentTokenEndPosition ( ) ; try { while ( ( token = readToken ( ) ) != TerminalTokens . TokenNameWHITESPACE && token != TerminalTokens . TokenNameEOF ) { this . currentTokenType = - 1 ; end = hasMultiLines ? this . lineEnd : this . scanner . getCurrentTokenEndPosition ( ) ; } } catch ( InvalidInputException e ) { end = this . lineEnd ; } if ( mayBeGeneric && isTypeParam ) this . sourceParser . problemReporter ( ) . javadocInvalidParamTypeParameter ( start , end ) ; else this . sourceParser . problemReporter ( ) . javadocInvalidParamTagName ( start , end ) ; } this . scanner . currentPosition = start ; this . index = start ; this . currentTokenType = - 1 ; return false ; } finally { this . scanner . tokenizeWhiteSpace = tokenWhiteSpace ; } } protected Object parseQualifiedName ( boolean reset ) throws InvalidInputException { if ( reset ) { this . identifierPtr = - 1 ; this . identifierLengthPtr = - 1 ; } int primitiveToken = - 1 ; int parserKind = this . kind & PARSER_KIND ; nextToken : for ( int iToken = 0 ; ; iToken ++ ) { int token = readTokenSafely ( ) ; switch ( token ) { case TerminalTokens . TokenNameIdentifier : if ( ( ( iToken & 1 ) != 0 ) ) { break nextToken ; } pushIdentifier ( iToken == 0 , false ) ; consumeToken ( ) ; break ; case TerminalTokens . TokenNameDOT : if ( ( iToken & 1 ) == 0 ) { throw new InvalidInputException ( ) ; } consumeToken ( ) ; break ; case TerminalTokens . TokenNameabstract : case TerminalTokens . TokenNameassert : case TerminalTokens . TokenNameboolean : case TerminalTokens . TokenNamebreak : case TerminalTokens . TokenNamebyte : case TerminalTokens . TokenNamecase : case TerminalTokens . TokenNamecatch : case TerminalTokens . TokenNamechar : case TerminalTokens . TokenNameclass : case TerminalTokens . TokenNamecontinue : case TerminalTokens . TokenNamedefault : case TerminalTokens . TokenNamedo : case TerminalTokens . TokenNamedouble : case TerminalTokens . TokenNameelse : case TerminalTokens . TokenNameextends : case TerminalTokens . TokenNamefalse : case TerminalTokens . TokenNamefinal : case TerminalTokens . TokenNamefinally : case TerminalTokens . TokenNamefloat : case TerminalTokens . TokenNamefor : case TerminalTokens . TokenNameif : case TerminalTokens . TokenNameimplements : case TerminalTokens . TokenNameimport : case TerminalTokens . TokenNameinstanceof : case TerminalTokens . TokenNameint : case TerminalTokens . TokenNameinterface : case TerminalTokens . TokenNamelong : case TerminalTokens . TokenNamenative : case TerminalTokens . TokenNamenew : case TerminalTokens . TokenNamenull : case TerminalTokens . TokenNamepackage : case TerminalTokens . TokenNameprivate : case TerminalTokens . TokenNameprotected : case TerminalTokens . TokenNamepublic : case TerminalTokens . TokenNameshort : case TerminalTokens . TokenNamestatic : case TerminalTokens . TokenNamestrictfp : case TerminalTokens . TokenNamesuper : case TerminalTokens . TokenNameswitch : case TerminalTokens . TokenNamesynchronized : case TerminalTokens . TokenNamethis : case TerminalTokens . TokenNamethrow : case TerminalTokens . TokenNametransient : case TerminalTokens . TokenNametrue : case TerminalTokens . TokenNametry : case TerminalTokens . TokenNamevoid : case TerminalTokens . TokenNamevolatile : case TerminalTokens . TokenNamewhile : if ( iToken == 0 ) { pushIdentifier ( true , true ) ; primitiveToken = token ; consumeToken ( ) ; break nextToken ; } default : if ( iToken == 0 ) { if ( this . identifierPtr >= 0 ) { this . lastIdentifierEndPosition = ( int ) this . identifierPositionStack [ this . identifierPtr ] ; } return null ; } if ( ( iToken & 1 ) == 0 ) { switch ( parserKind ) { case COMPLETION_PARSER : if ( this . identifierPtr >= 0 ) { this . lastIdentifierEndPosition = ( int ) this . identifierPositionStack [ this . identifierPtr ] ; } return syntaxRecoverQualifiedName ( primitiveToken ) ; case DOM_PARSER : if ( this . currentTokenType != - 1 ) { this . index = this . tokenPreviousPosition ; this . scanner . currentPosition = this . tokenPreviousPosition ; this . currentTokenType = - 1 ; } default : throw new InvalidInputException ( ) ; } } break nextToken ; } } if ( parserKind != COMPLETION_PARSER && this . currentTokenType != - 1 ) { this . index = this . tokenPreviousPosition ; this . scanner . currentPosition = this . tokenPreviousPosition ; this . currentTokenType = - 1 ; } if ( this . identifierPtr >= 0 ) { this . lastIdentifierEndPosition = ( int ) this . identifierPositionStack [ this . identifierPtr ] ; } return createTypeReference ( primitiveToken ) ; } protected boolean parseReference ( ) throws InvalidInputException { int currentPosition = this . scanner . currentPosition ; try { Object typeRef = null ; Object reference = null ; int previousPosition = - 1 ; int typeRefStartPosition = - 1 ; nextToken : while ( this . index < this . scanner . eofPosition ) { previousPosition = this . index ; int token = readTokenSafely ( ) ; switch ( token ) { case TerminalTokens . TokenNameStringLiteral : if ( typeRef != null ) break nextToken ; consumeToken ( ) ; int start = this . scanner . getCurrentTokenStartPosition ( ) ; if ( this . tagValue == TAG_VALUE_VALUE ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidValueReference ( start , getTokenEndPosition ( ) , this . sourceParser . modifiers ) ; return false ; } if ( verifyEndLine ( previousPosition ) ) { return createFakeReference ( start ) ; } if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocUnexpectedText ( this . scanner . currentPosition , this . lineEnd ) ; return false ; case TerminalTokens . TokenNameLESS : if ( typeRef != null ) break nextToken ; consumeToken ( ) ; start = this . scanner . getCurrentTokenStartPosition ( ) ; if ( parseHref ( ) ) { consumeToken ( ) ; if ( this . tagValue == TAG_VALUE_VALUE ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidValueReference ( start , getIndexPosition ( ) , this . sourceParser . modifiers ) ; return false ; } if ( verifyEndLine ( previousPosition ) ) { return createFakeReference ( start ) ; } if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocUnexpectedText ( this . scanner . currentPosition , this . lineEnd ) ; } else if ( this . tagValue == TAG_VALUE_VALUE ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidValueReference ( start , getIndexPosition ( ) , this . sourceParser . modifiers ) ; } return false ; case TerminalTokens . TokenNameERROR : consumeToken ( ) ; if ( this . scanner . currentCharacter == '#' ) { reference = parseMember ( typeRef ) ; if ( reference != null ) { return pushSeeRef ( reference ) ; } return false ; } char [ ] currentError = this . scanner . getCurrentIdentifierSource ( ) ; if ( currentError . length > 0 && currentError [ 0 ] == '"' ) { if ( this . reportProblems ) { boolean isUrlRef = false ; if ( this . tagValue == TAG_SEE_VALUE ) { int length = currentError . length , i = 1 ; while ( i < length && ScannerHelper . isLetter ( currentError [ i ] ) ) { i ++ ; } if ( i < ( length - 2 ) && currentError [ i ] == ':' && currentError [ i + 1 ] == '/' && currentError [ i + 2 ] == '/' ) { isUrlRef = true ; } } if ( isUrlRef ) { this . sourceParser . problemReporter ( ) . javadocInvalidSeeUrlReference ( this . scanner . getCurrentTokenStartPosition ( ) , getTokenEndPosition ( ) ) ; } else { this . sourceParser . problemReporter ( ) . javadocInvalidReference ( this . scanner . getCurrentTokenStartPosition ( ) , getTokenEndPosition ( ) ) ; } } return false ; } break nextToken ; case TerminalTokens . TokenNameIdentifier : if ( typeRef == null ) { typeRefStartPosition = this . scanner . getCurrentTokenStartPosition ( ) ; typeRef = parseQualifiedName ( true ) ; if ( this . abort ) return false ; break ; } break nextToken ; default : break nextToken ; } } if ( reference == null ) reference = typeRef ; if ( reference == null ) { this . index = this . tokenPreviousPosition ; this . scanner . currentPosition = this . tokenPreviousPosition ; this . currentTokenType = - 1 ; if ( this . tagValue == TAG_VALUE_VALUE ) { if ( ( this . kind & DOM_PARSER ) != 0 ) createTag ( ) ; return true ; } if ( this . reportProblems ) { this . sourceParser . problemReporter ( ) . javadocMissingReference ( this . tagSourceStart , this . tagSourceEnd , this . sourceParser . modifiers ) ; } return false ; } if ( this . lastIdentifierEndPosition > this . javadocStart ) { this . index = this . lastIdentifierEndPosition + 1 ; this . scanner . currentPosition = this . index ; } this . currentTokenType = - 1 ; if ( this . tagValue == TAG_VALUE_VALUE ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidReference ( typeRefStartPosition , this . lineEnd ) ; return false ; } int currentIndex = this . index ; char ch = readChar ( ) ; switch ( ch ) { case '(' : if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocMissingHashCharacter ( typeRefStartPosition , this . lineEnd , String . valueOf ( this . source , typeRefStartPosition , this . lineEnd - typeRefStartPosition + 1 ) ) ; return false ; case ':' : ch = readChar ( ) ; if ( ch == '/' && ch == readChar ( ) ) { if ( this . reportProblems ) { this . sourceParser . problemReporter ( ) . javadocInvalidSeeUrlReference ( typeRefStartPosition , this . lineEnd ) ; return false ; } } } this . index = currentIndex ; 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 . reportProblems ) this . sourceParser . problemReporter ( ) . javadocMalformedSeeReference ( typeRefStartPosition , end ) ; return false ; } return pushSeeRef ( reference ) ; } catch ( InvalidInputException ex ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidReference ( currentPosition , getTokenEndPosition ( ) ) ; } this . index = this . tokenPreviousPosition ; this . scanner . currentPosition = this . tokenPreviousPosition ; this . currentTokenType = - 1 ; return false ; } protected abstract boolean parseTag ( int previousPosition ) throws InvalidInputException ; protected boolean parseThrows ( ) { int start = this . scanner . currentPosition ; try { Object typeRef = parseQualifiedName ( true ) ; if ( this . abort ) return false ; if ( typeRef == null ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocMissingThrowsClassName ( this . tagSourceStart , this . tagSourceEnd , this . sourceParser . modifiers ) ; } else { return pushThrowName ( typeRef ) ; } } catch ( InvalidInputException ex ) { if ( this . reportProblems ) this . sourceParser . problemReporter ( ) . javadocInvalidThrowsClass ( start , getTokenEndPosition ( ) ) ; } return false ; } protected 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 = ScannerHelper . getNumericValue ( this . source [ idx ++ ] ) ) > 15 || c1 < 0 ) || ( ( c2 = ScannerHelper . getNumericValue ( this . source [ idx ++ ] ) ) > 15 || c2 < 0 ) || ( ( c3 = ScannerHelper . getNumericValue ( this . source [ idx ++ ] ) ) > 15 || c3 < 0 ) || ( ( c4 = ScannerHelper . getNumericValue ( this . source [ idx ++ ] ) ) > 15 || c4 < 0 ) ) ) { c = ( char ) ( ( ( c1 * 16 + c2 ) * 16 + c3 ) * 16 + c4 ) ; } } return c ; } protected void pushIdentifier ( boolean newLength , boolean isToken ) { 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 ] = isToken ? this . scanner . getCurrentTokenSource ( ) : 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 ] ++ ; } } protected void pushOnAstStack ( Object node , boolean newLength ) { if ( node == null ) { int stackLength = this . astLengthStack . length ; if ( ++ this . astLengthPtr >= stackLength ) { System . arraycopy ( this . astLengthStack , 0 , this . astLengthStack = new int [ stackLength + AST_STACK_INCREMENT ] , 0 , stackLength ) ; } 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 + AST_STACK_INCREMENT ] , 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 + AST_STACK_INCREMENT ] , 0 , stackLength ) ; } this . astLengthStack [ this . astLengthPtr ] = 1 ; } else { this . astLengthStack [ this . astLengthPtr ] ++ ; } } protected abstract boolean pushParamName ( boolean isTypeParam ) ; protected abstract boolean pushSeeRef ( Object statement ) ; protected void pushText ( int start , int end ) { } protected abstract boolean pushThrowName ( Object typeRef ) ; 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 = ScannerHelper . getNumericValue ( this . source [ this . index ++ ] ) ) > 15 || c1 < 0 ) || ( ( c2 = ScannerHelper . getNumericValue ( this . source [ this . index ++ ] ) ) > 15 || c2 < 0 ) || ( ( c3 = ScannerHelper . getNumericValue ( this . source [ this . index ++ ] ) ) > 15 || c3 < 0 ) || ( ( c4 = ScannerHelper . getNumericValue ( this . source [ this . index ++ ] ) ) > 15 || c4 < 0 ) ) ) { c = ( char ) ( ( ( c1 * 16 + c2 ) * 16 + c3 ) * 16 + c4 ) ; } else { this . index = pos ; } } return c ; } protected 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 ) ) { this . lineStarted = false ; while ( this . currentTokenType == TerminalTokens . TokenNameMULTIPLY ) { this . currentTokenType = this . scanner . getNextToken ( ) ; } } this . index = this . scanner . currentPosition ; this . lineStarted = true ; } return this . currentTokenType ; } protected int readTokenAndConsume ( ) throws InvalidInputException { int token = readToken ( ) ; consumeToken ( ) ; return token ; } protected int readTokenSafely ( ) { int token = TerminalTokens . TokenNameERROR ; try { token = readToken ( ) ; } catch ( InvalidInputException iie ) { } return token ; } protected void recordInheritedPosition ( long position ) { if ( this . inheritedPositions == null ) { this . inheritedPositions = new long [ INHERITED_POSITIONS_ARRAY_INCREMENT ] ; this . inheritedPositionsPtr = 0 ; } else { if ( this . inheritedPositionsPtr == this . inheritedPositions . length ) { System . arraycopy ( this . inheritedPositions , 0 , this . inheritedPositions = new long [ this . inheritedPositionsPtr + INHERITED_POSITIONS_ARRAY_INCREMENT ] , 0 , this . inheritedPositionsPtr ) ; } } this . inheritedPositions [ this . inheritedPositionsPtr ++ ] = position ; } protected void refreshInlineTagPosition ( int previousPosition ) { } protected void refreshReturnStatement ( ) { } protected void setInlineTagStarted ( boolean started ) { this . inlineTagStarted = started ; } protected Object syntaxRecoverQualifiedName ( int primitiveToken ) throws InvalidInputException { return null ; } public String toString ( ) { StringBuffer buffer = new StringBuffer ( ) ; int startPos = this . scanner . currentPosition < this . index ? this . scanner . currentPosition : this . index ; int endPos = this . scanner . currentPosition < this . index ? this . index : this . scanner . currentPosition ; if ( startPos == this . source . length ) return "EOFnn" + new String ( this . source ) ; if ( endPos > this . source . length ) return "" + new String ( this . source ) ; 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 < this . index ) { buffer . append ( "" ) ; } else { buffer . append ( "" ) ; } buffer . append ( middle ) ; if ( this . scanner . currentPosition < this . index ) { buffer . append ( "" ) ; } else { buffer . append ( "" ) ; } buffer . append ( end ) ; return buffer . toString ( ) ; } protected abstract void updateDocComment ( ) ; protected void updateLineEnd ( ) { while ( this . index > ( this . lineEnd + 1 ) ) { if ( this . linePtr < this . lastLinePtr ) { this . lineEnd = this . scanner . getLineEnd ( ++ this . linePtr ) - 1 ; } else { this . lineEnd = this . javadocEnd ; return ; } } } protected boolean verifyEndLine ( int textPosition ) { boolean domParser = ( this . kind & DOM_PARSER ) != 0 ; if ( this . inlineTagStarted ) { if ( peekChar ( ) == '}' ) { if ( domParser ) { createTag ( ) ; pushText ( textPosition , this . starPosition ) ; } return true ; } return false ; } int startPosition = this . index ; int previousPosition = this . index ; this . starPosition = - 1 ; char ch = readChar ( ) ; nextChar : while ( true ) { switch ( ch ) { case '\r' : case '\n' : if ( domParser ) { createTag ( ) ; pushText ( textPosition , previousPosition ) ; } this . index = previousPosition ; return true ; case ' ' : case ' ' : case '\t' : if ( this . starPosition >= 0 ) break nextChar ; break ; case '*' : this . starPosition = previousPosition ; break ; case '/' : if ( this . starPosition >= textPosition ) { if ( domParser ) { createTag ( ) ; pushText ( textPosition , this . starPosition ) ; } return true ; } break nextChar ; default : break nextChar ; } previousPosition = this . index ; ch = readChar ( ) ; } this . index = startPosition ; return false ; } protected boolean verifySpaceOrEndComment ( ) { this . starPosition = - 1 ; int startPosition = this . index ; char ch = peekChar ( ) ; switch ( ch ) { case '}' : return this . inlineTagStarted ; default : if ( ScannerHelper . isWhitespace ( ch ) ) { return true ; } } int previousPosition = this . index ; ch = readChar ( ) ; while ( this . index < this . source . length ) { switch ( ch ) { case '*' : this . starPosition = previousPosition ; break ; case '/' : if ( this . starPosition >= startPosition ) { return true ; } default : this . index = startPosition ; return false ; } previousPosition = this . index ; ch = readChar ( ) ; } this . index = startPosition ; return false ; } } </s>