<s> package org . eclipse . jdt . internal . core . util ; import org . eclipse . jdt . core . compiler . CharOperation ; import org . eclipse . jdt . internal . compiler . ast . Wildcard ; public class BindingKeyParser { int keyStart ; static final char C_THROWN = '|' ; static class Scanner { static final int PACKAGE = 0 ; static final int TYPE = 1 ; static final int FIELD = 2 ; static final int METHOD = 3 ; static final int ARRAY = 4 ; static final int LOCAL_VAR = 5 ; static final int FLAGS = 6 ; static final int WILDCARD = 7 ; static final int CAPTURE = 8 ; static final int BASE_TYPE = 9 ; static final int END = 10 ; static final int START = - 1 ; int index = 0 , start ; char [ ] source ; int token = START ; Scanner ( char [ ] source ) { this . source = source ; } char [ ] getTokenSource ( ) { int length = this . index - this . start ; char [ ] result = new char [ length ] ; System . arraycopy ( this . source , this . start , result , 0 , length ) ; return result ; } boolean isAtAnnotationStart ( ) { return this . index < this . source . length && this . source [ this . index ] == '@' ; } boolean isAtCaptureStart ( ) { return this . index < this . source . length && this . source [ this . index ] == '!' ; } boolean isAtFieldOrMethodStart ( ) { return this . index < this . source . length && this . source [ this . index ] == '.' ; } boolean isAtLocalVariableStart ( ) { return this . index < this . source . length && this . source [ this . index ] == '#' ; } boolean isAtMemberTypeStart ( ) { return this . index < this . source . length && ( this . source [ this . index ] == '$' || ( this . source [ this . index ] == '.' && this . source [ this . index - 1 ] == '>' ) ) ; } boolean isAtParametersEnd ( ) { return this . index < this . source . length && this . source [ this . index ] == '>' ; } boolean isAtParametersStart ( ) { char currentChar ; return this . index > 0 && this . index < this . source . length && ( ( currentChar = this . source [ this . index ] ) == '<' || currentChar == '%' ) ; } boolean isAtRawTypeEnd ( ) { return this . index > 0 && this . index < this . source . length && this . source [ this . index ] == '>' ; } boolean isAtSecondaryTypeStart ( ) { return this . index < this . source . length && this . source [ this . index ] == '~' ; } boolean isAtWildcardStart ( ) { return this . index < this . source . length && this . source [ this . index ] == '{' ; } boolean isAtTypeParameterStart ( ) { return this . index < this . source . length && this . source [ this . index ] == 'T' ; } boolean isAtTypeArgumentStart ( ) { return this . index < this . source . length && "LIZVCDBFJS[!" . indexOf ( this . source [ this . index ] ) != - 1 ; } boolean isAtThrownStart ( ) { return this . index < this . source . length && this . source [ this . index ] == C_THROWN ; } boolean isAtTypeVariableStart ( ) { return this . index < this . source . length && this . source [ this . index ] == ':' ; } boolean isAtTypeWithCaptureStart ( ) { return this . index < this . source . length && this . source [ this . index ] == '&' ; } int nextToken ( ) { int previousTokenEnd = this . index ; this . start = this . index ; int dollarIndex = - 1 ; int length = this . source . length ; while ( this . index <= length ) { char currentChar = this . index == length ? Character . MIN_VALUE : this . source [ this . index ] ; switch ( currentChar ) { case 'B' : case 'C' : case 'D' : case 'F' : case 'I' : case 'J' : case 'N' : case 'S' : case 'V' : case 'Z' : if ( this . index == previousTokenEnd && ( this . index == 0 || this . source [ this . index - 1 ] != '.' ) ) { this . index ++ ; this . token = BASE_TYPE ; return this . token ; } break ; case 'L' : case 'T' : if ( this . index == previousTokenEnd && ( this . index == 0 || this . source [ this . index - 1 ] != '.' ) ) { this . start = this . index + 1 ; dollarIndex = - 1 ; } break ; case ';' : if ( this . index == previousTokenEnd ) { this . start = this . index + 1 ; dollarIndex = - 1 ; previousTokenEnd = this . start ; } else { if ( dollarIndex != - 1 ) this . index = dollarIndex ; this . token = TYPE ; return this . token ; } break ; case '$' : if ( this . index == previousTokenEnd ) { this . start = this . index + 1 ; dollarIndex = - 1 ; } else { if ( dollarIndex == - 1 ) { dollarIndex = this . index ; break ; } this . index = dollarIndex ; this . token = TYPE ; return this . token ; } break ; case '~' : if ( this . index == previousTokenEnd ) { this . start = this . index + 1 ; dollarIndex = - 1 ; } else { this . token = TYPE ; return this . token ; } break ; case '.' : case '%' : case ':' : case '>' : case '@' : this . start = this . index + 1 ; dollarIndex = - 1 ; previousTokenEnd = this . start ; break ; case '[' : while ( this . index < length && this . source [ this . index ] == '[' ) this . index ++ ; this . token = ARRAY ; return this . token ; case '<' : if ( this . start > 0 ) { switch ( this . source [ this . start - 1 ] ) { case '.' : if ( this . source [ this . start - 2 ] == '>' ) { if ( dollarIndex != - 1 ) this . index = dollarIndex ; this . token = TYPE ; } else { this . token = METHOD ; } return this . token ; default : if ( this . index == previousTokenEnd ) { this . start = this . index + 1 ; dollarIndex = - 1 ; previousTokenEnd = this . start ; } else { if ( dollarIndex != - 1 ) this . index = dollarIndex ; this . token = TYPE ; return this . token ; } } } break ; case '(' : this . token = METHOD ; return this . token ; case ')' : if ( this . token == TYPE ) { this . token = FIELD ; return this . token ; } this . start = this . index + 1 ; dollarIndex = - 1 ; previousTokenEnd = this . start ; break ; case '#' : if ( this . index == previousTokenEnd ) { this . start = this . index + 1 ; dollarIndex = - 1 ; previousTokenEnd = this . start ; } else { this . token = LOCAL_VAR ; return this . token ; } break ; case Character . MIN_VALUE : switch ( this . token ) { case START : this . token = PACKAGE ; break ; case METHOD : case LOCAL_VAR : this . token = LOCAL_VAR ; break ; case TYPE : if ( this . index > this . start && this . source [ this . start - 1 ] == '.' ) this . token = FIELD ; else this . token = END ; break ; case WILDCARD : this . token = TYPE ; break ; default : this . token = END ; break ; } return this . token ; case '*' : case '+' : case '-' : this . index ++ ; this . token = WILDCARD ; return this . token ; case '!' : case '&' : this . index ++ ; this . token = CAPTURE ; return this . token ; } this . index ++ ; } this . token = END ; return this . token ; } void skipMethodSignature ( ) { this . start = this . index ; int braket = 0 ; while ( this . index < this . source . length ) { switch ( this . source [ this . index ] ) { case '#' : case '%' : case '@' : case C_THROWN : return ; case ':' : if ( braket == 0 ) return ; break ; case '<' : case '(' : braket ++ ; break ; case '>' : case ')' : braket -- ; break ; } this . index ++ ; } } void skipRank ( ) { this . start = this . index ; while ( this . index < this . source . length && "0123456789" . indexOf ( this . source [ this . index ] ) != - 1 ) this . index ++ ; } void skipThrownStart ( ) { while ( this . index < this . source . length && this . source [ this . index ] == C_THROWN ) this . index ++ ; } void skipParametersStart ( ) { while ( this . index < this . source . length && ( this . source [ this . index ] == '<' || this . source [ this . index ] == '%' ) ) this . index ++ ; } void skipParametersEnd ( ) { while ( this . index < this . source . length && this . source [ this . index ] != '>' ) this . index ++ ; this . index ++ ; } void skipTypeEnd ( ) { if ( this . index < this . source . length && this . source [ this . index ] == ';' ) this . index ++ ; } void skipRankStart ( ) { if ( this . index < this . source . length && this . source [ this . index ] == '{' ) this . index ++ ; } void skipRankEnd ( ) { if ( this . index < this . source . length && this . source [ this . index ] == '}' ) this . index ++ ; this . start = this . index ; } public String toString ( ) { StringBuffer buffer = new StringBuffer ( ) ; switch ( this . token ) { case START : buffer . append ( "START: " ) ; break ; case PACKAGE : buffer . append ( "PACKAGE: " ) ; break ; case TYPE : buffer . append ( "TYPE: " ) ; break ; case FIELD : buffer . append ( "FIELD: " ) ; break ; case METHOD : buffer . append ( "METHOD: " ) ; break ; case ARRAY : buffer . append ( "ARRAY: " ) ; break ; case LOCAL_VAR : buffer . append ( "LOCAL VAR: " ) ; break ; case FLAGS : buffer . append ( "MODIFIERS: " ) ; break ; case WILDCARD : buffer . append ( "WILDCARD: " ) ; break ; case CAPTURE : buffer . append ( "CAPTURE: " ) ; break ; case BASE_TYPE : buffer . append ( "BASE TYPE: " ) ; break ; case END : buffer . append ( "END: " ) ; break ; } if ( this . index < 0 ) { buffer . append ( "**" ) ; buffer . append ( this . source ) ; } else if ( this . index <= this . source . length ) { buffer . append ( this . source , 0 , this . start ) ; buffer . append ( '*' ) ; if ( this . start <= this . index ) { buffer . append ( this . source , this . start , this . index - this . start ) ; buffer . append ( '*' ) ; buffer . append ( this . source , this . index , this . source . length - this . index ) ; } else { buffer . append ( '*' ) ; buffer . append ( this . source , this . start , this . source . length - this . start ) ; } } else { buffer . append ( this . source ) ; buffer . append ( "**" ) ; } return buffer . toString ( ) ; } } private boolean parsingPaused ; private Scanner scanner ; private boolean hasTypeName = true ; private boolean isMalformed ; public BindingKeyParser ( BindingKeyParser parser ) { this ( "" ) ; this . scanner = parser . scanner ; } public BindingKeyParser ( String key ) { this . scanner = new Scanner ( key . toCharArray ( ) ) ; } public void consumeAnnotation ( ) { } public void consumeArrayDimension ( char [ ] brakets ) { } public void consumeBaseType ( char [ ] baseTypeSig ) { } public void consumeCapture ( int position ) { } public void consumeException ( ) { } public void consumeField ( char [ ] fieldName ) { } public void consumeParameterizedGenericMethod ( ) { } public void consumeLocalType ( char [ ] uniqueKey ) { } public void consumeLocalVar ( char [ ] varName , int occurrenceCount ) { } public void consumeMethod ( char [ ] selector , char [ ] signature ) { } public void consumeModifiers ( char [ ] modifiers ) { } public void consumeNonGenericType ( ) { } public void consumeMemberType ( char [ ] simpleTypeName ) { } public void consumePackage ( char [ ] pkgName ) { } public void consumeParameterizedType ( char [ ] simpleTypeName , boolean isRaw ) { } public void consumeParser ( BindingKeyParser parser ) { } public void consumeRawType ( ) { } public void consumeScope ( int scopeNumber ) { } public void consumeSecondaryType ( char [ ] simpleTypeName ) { } public void consumeFullyQualifiedName ( char [ ] fullyQualifiedName ) { } public void consumeKey ( ) { } public void consumeTopLevelType ( ) { } public void consumeType ( ) { } public void consumeTypeParameter ( char [ ] typeParameterName ) { } public void consumeTypeVariable ( char [ ] position , char [ ] typeVariableName ) { } public void consumeTypeWithCapture ( ) { } public void consumeWildCard ( int kind ) { } public void consumeWildcardRank ( int rank ) { } public String getKey ( ) { return new String ( this . scanner . source ) ; } public boolean hasTypeName ( ) { return this . hasTypeName ; } public void malformedKey ( ) { this . isMalformed = true ; } public BindingKeyParser newParser ( ) { return new BindingKeyParser ( this ) ; } public void parse ( ) { parse ( false ) ; } public void parse ( boolean pauseAfterFullyQualifiedName ) { if ( ! this . parsingPaused ) { parseFullyQualifiedName ( ) ; parseSecondaryType ( ) ; if ( pauseAfterFullyQualifiedName ) { this . parsingPaused = true ; return ; } } if ( ! hasTypeName ( ) ) { consumeKey ( ) ; return ; } consumeTopLevelType ( ) ; parseInnerType ( ) ; if ( this . scanner . isAtParametersStart ( ) ) { this . scanner . skipParametersStart ( ) ; if ( this . scanner . isAtTypeParameterStart ( ) ) { parseGenericType ( ) ; this . scanner . skipParametersEnd ( ) ; parseInnerType ( ) ; } else if ( this . scanner . isAtTypeArgumentStart ( ) ) parseParameterizedType ( null , false ) ; else if ( this . scanner . isAtRawTypeEnd ( ) ) parseRawType ( ) ; } else { consumeNonGenericType ( ) ; } consumeType ( ) ; this . scanner . skipTypeEnd ( ) ; if ( this . scanner . isAtFieldOrMethodStart ( ) ) { switch ( this . scanner . nextToken ( ) ) { case Scanner . FIELD : parseField ( ) ; if ( this . scanner . isAtAnnotationStart ( ) ) { parseAnnotation ( ) ; } return ; case Scanner . METHOD : parseMethod ( ) ; if ( this . scanner . isAtLocalVariableStart ( ) ) { parseLocalVariable ( ) ; } else if ( this . scanner . isAtTypeVariableStart ( ) ) { parseTypeVariable ( ) ; } else if ( this . scanner . isAtAnnotationStart ( ) ) { parseAnnotation ( ) ; } break ; default : malformedKey ( ) ; return ; } } else if ( this . scanner . isAtTypeVariableStart ( ) ) { parseTypeVariable ( ) ; } else if ( this . scanner . isAtWildcardStart ( ) ) { parseWildcard ( ) ; } else if ( this . scanner . isAtTypeWithCaptureStart ( ) ) { parseTypeWithCapture ( ) ; } else if ( this . scanner . isAtAnnotationStart ( ) ) { parseAnnotation ( ) ; } consumeKey ( ) ; } private void parseFullyQualifiedName ( ) { if ( this . scanner . isAtCaptureStart ( ) ) { parseCapture ( ) ; this . hasTypeName = false ; return ; } switch ( this . scanner . nextToken ( ) ) { case Scanner . PACKAGE : this . keyStart = 0 ; consumePackage ( this . scanner . getTokenSource ( ) ) ; this . hasTypeName = false ; return ; case Scanner . TYPE : this . keyStart = this . scanner . start - 1 ; consumeFullyQualifiedName ( this . scanner . getTokenSource ( ) ) ; break ; case Scanner . BASE_TYPE : this . keyStart = this . scanner . start - 1 ; consumeBaseType ( this . scanner . getTokenSource ( ) ) ; this . hasTypeName = false ; break ; case Scanner . ARRAY : this . keyStart = this . scanner . start ; consumeArrayDimension ( this . scanner . getTokenSource ( ) ) ; switch ( this . scanner . nextToken ( ) ) { case Scanner . TYPE : consumeFullyQualifiedName ( this . scanner . getTokenSource ( ) ) ; break ; case Scanner . BASE_TYPE : consumeBaseType ( this . scanner . getTokenSource ( ) ) ; this . hasTypeName = false ; break ; default : malformedKey ( ) ; return ; } break ; default : malformedKey ( ) ; return ; } } private void parseParameterizedMethod ( ) { this . scanner . skipParametersStart ( ) ; while ( ! this . scanner . isAtParametersEnd ( ) && ! this . isMalformed ) { parseTypeArgument ( ) ; } consumeParameterizedGenericMethod ( ) ; } private void parseGenericType ( ) { while ( ! this . scanner . isAtParametersEnd ( ) && ! this . isMalformed ) { if ( this . scanner . nextToken ( ) != Scanner . TYPE ) { malformedKey ( ) ; return ; } consumeTypeParameter ( this . scanner . getTokenSource ( ) ) ; this . scanner . skipTypeEnd ( ) ; } } private void parseInnerType ( ) { if ( ! this . scanner . isAtMemberTypeStart ( ) || this . scanner . nextToken ( ) != Scanner . TYPE ) return ; char [ ] typeName = this . scanner . getTokenSource ( ) ; if ( Character . isDigit ( typeName [ 0 ] ) ) { int nextToken = Scanner . TYPE ; while ( this . scanner . isAtMemberTypeStart ( ) && ! this . isMalformed ) nextToken = this . scanner . nextToken ( ) ; typeName = nextToken == Scanner . END ? this . scanner . source : CharOperation . subarray ( this . scanner . source , this . keyStart , this . scanner . index + 1 ) ; consumeLocalType ( typeName ) ; } else { consumeMemberType ( typeName ) ; parseInnerType ( ) ; } } private void parseLocalVariable ( ) { if ( this . scanner . nextToken ( ) != Scanner . LOCAL_VAR ) { malformedKey ( ) ; return ; } char [ ] varName = this . scanner . getTokenSource ( ) ; if ( Character . isDigit ( varName [ 0 ] ) ) { int index = Integer . parseInt ( new String ( varName ) ) ; consumeScope ( index ) ; if ( ! this . scanner . isAtLocalVariableStart ( ) ) { malformedKey ( ) ; return ; } parseLocalVariable ( ) ; } else { int occurrenceCount = 0 ; if ( this . scanner . isAtLocalVariableStart ( ) ) { if ( this . scanner . nextToken ( ) != Scanner . LOCAL_VAR ) { malformedKey ( ) ; return ; } char [ ] occurrence = this . scanner . getTokenSource ( ) ; occurrenceCount = Integer . parseInt ( new String ( occurrence ) ) ; } consumeLocalVar ( varName , occurrenceCount ) ; } } private void parseMethod ( ) { char [ ] selector = this . scanner . getTokenSource ( ) ; this . scanner . skipMethodSignature ( ) ; char [ ] signature = this . scanner . getTokenSource ( ) ; consumeMethod ( selector , signature ) ; if ( this . scanner . isAtThrownStart ( ) ) { parseThrownExceptions ( ) ; } if ( this . scanner . isAtParametersStart ( ) ) parseParameterizedMethod ( ) ; } private void parseAnnotation ( ) { int token = this . scanner . token ; BindingKeyParser parser = newParser ( ) ; parser . parse ( ) ; consumeParser ( parser ) ; consumeAnnotation ( ) ; this . isMalformed = parser . isMalformed ; this . scanner . token = token ; } private void parseCapture ( ) { if ( this . scanner . nextToken ( ) != Scanner . CAPTURE ) return ; parseCaptureWildcard ( ) ; if ( this . scanner . nextToken ( ) != Scanner . TYPE ) { malformedKey ( ) ; return ; } char [ ] positionChars = this . scanner . getTokenSource ( ) ; int position = Integer . parseInt ( new String ( positionChars ) ) ; consumeCapture ( position ) ; this . scanner . skipTypeEnd ( ) ; } private void parseCaptureWildcard ( ) { int token = this . scanner . token ; BindingKeyParser parser = newParser ( ) ; parser . parse ( ) ; consumeParser ( parser ) ; this . isMalformed = parser . isMalformed ; this . scanner . token = token ; } private void parseField ( ) { char [ ] fieldName = this . scanner . getTokenSource ( ) ; parseReturnType ( ) ; consumeField ( fieldName ) ; } private void parseThrownExceptions ( ) { int token = this . scanner . token ; while ( this . scanner . isAtThrownStart ( ) && ! this . isMalformed ) { this . scanner . skipThrownStart ( ) ; BindingKeyParser parser = newParser ( ) ; parser . parse ( ) ; consumeParser ( parser ) ; consumeException ( ) ; this . isMalformed = parser . isMalformed ; } this . scanner . token = token ; } private void parseParameterizedType ( char [ ] typeName , boolean isRaw ) { if ( ! isRaw ) { while ( ! this . scanner . isAtParametersEnd ( ) && ! this . isMalformed ) { parseTypeArgument ( ) ; } } this . scanner . skipParametersEnd ( ) ; consumeParameterizedType ( typeName , isRaw ) ; this . scanner . skipTypeEnd ( ) ; if ( this . scanner . isAtMemberTypeStart ( ) && this . scanner . nextToken ( ) == Scanner . TYPE ) { typeName = this . scanner . getTokenSource ( ) ; if ( this . scanner . isAtParametersStart ( ) ) { this . scanner . skipParametersStart ( ) ; parseParameterizedType ( typeName , this . scanner . isAtRawTypeEnd ( ) ) ; } else consumeParameterizedType ( typeName , true ) ; } } private void parseRawType ( ) { this . scanner . skipParametersEnd ( ) ; consumeRawType ( ) ; this . scanner . skipTypeEnd ( ) ; if ( this . scanner . isAtMemberTypeStart ( ) && this . scanner . nextToken ( ) == Scanner . TYPE ) { char [ ] typeName = this . scanner . getTokenSource ( ) ; if ( this . scanner . isAtParametersStart ( ) ) { this . scanner . skipParametersStart ( ) ; parseParameterizedType ( typeName , this . scanner . isAtRawTypeEnd ( ) ) ; } else consumeParameterizedType ( typeName , true ) ; } } private void parseReturnType ( ) { this . scanner . index ++ ; int token = this . scanner . token ; BindingKeyParser parser = newParser ( ) ; parser . parse ( ) ; consumeParser ( parser ) ; this . isMalformed = parser . isMalformed ; this . scanner . token = token ; } private void parseSecondaryType ( ) { if ( ! this . scanner . isAtSecondaryTypeStart ( ) || this . scanner . nextToken ( ) != Scanner . TYPE ) return ; consumeSecondaryType ( this . scanner . getTokenSource ( ) ) ; } private void parseTypeArgument ( ) { int token = this . scanner . token ; BindingKeyParser parser = newParser ( ) ; parser . parse ( ) ; consumeParser ( parser ) ; this . isMalformed = parser . isMalformed ; this . scanner . token = token ; } private void parseTypeWithCapture ( ) { if ( this . scanner . nextToken ( ) != Scanner . CAPTURE ) return ; int token = this . scanner . token ; BindingKeyParser parser = newParser ( ) ; parser . parse ( ) ; consumeParser ( parser ) ; consumeTypeWithCapture ( ) ; this . isMalformed = parser . isMalformed ; this . scanner . token = token ; } private void parseTypeVariable ( ) { if ( this . scanner . nextToken ( ) != Scanner . TYPE ) { malformedKey ( ) ; return ; } char [ ] typeVariableName = this . scanner . getTokenSource ( ) ; char [ ] position ; int length = typeVariableName . length ; if ( length > 0 && Character . isDigit ( typeVariableName [ 0 ] ) ) { int firstT = CharOperation . indexOf ( 'T' , typeVariableName ) ; position = CharOperation . subarray ( typeVariableName , 0 , firstT ) ; typeVariableName = CharOperation . subarray ( typeVariableName , firstT + 1 , typeVariableName . length ) ; } else { position = CharOperation . NO_CHAR ; } consumeTypeVariable ( position , typeVariableName ) ; this . scanner . skipTypeEnd ( ) ; } private void parseWildcard ( ) { parseWildcardRank ( ) ; if ( this . scanner . nextToken ( ) != Scanner . WILDCARD ) return ; char [ ] source = this . scanner . getTokenSource ( ) ; if ( source . length == 0 ) { malformedKey ( ) ; return ; } int kind = - 1 ; switch ( source [ 0 ] ) { case '*' : kind = Wildcard . UNBOUND ; break ; case '+' : kind = Wildcard . EXTENDS ; break ; case '-' : kind = Wildcard . SUPER ; break ; } if ( kind == - 1 ) { malformedKey ( ) ; return ; } if ( kind != Wildcard . UNBOUND ) parseWildcardBound ( ) ; consumeWildCard ( kind ) ; } private void parseWildcardRank ( ) { this . scanner . skipRankStart ( ) ; this . scanner . skipRank ( ) ; char [ ] source = this . scanner . getTokenSource ( ) ; consumeWildcardRank ( Integer . parseInt ( new String ( source ) ) ) ; this . scanner . skipRankEnd ( ) ; } private void parseWildcardBound ( ) { int token = this . scanner . token ; BindingKeyParser parser = newParser ( ) ; parser . parse ( ) ; consumeParser ( parser ) ; this . isMalformed = parser . isMalformed ; this . scanner . token = token ; } } </s>