<s> package org . eclipse . jdt . internal . core . search . indexing ; import org . eclipse . core . runtime . IStatus ; import org . eclipse . jdt . core . Signature ; import org . eclipse . jdt . core . compiler . CharOperation ; import org . eclipse . jdt . core . search . SearchDocument ; import org . eclipse . jdt . internal . compiler . ExtraFlags ; import org . eclipse . jdt . internal . compiler . ast . TypeDeclaration ; import org . eclipse . jdt . internal . compiler . classfmt . ClassFileConstants ; import org . eclipse . jdt . internal . compiler . classfmt . ClassFileReader ; import org . eclipse . jdt . internal . compiler . classfmt . ClassFormatException ; import org . eclipse . jdt . internal . compiler . classfmt . FieldInfo ; import org . eclipse . jdt . internal . compiler . classfmt . MethodInfo ; import org . eclipse . jdt . internal . compiler . env . ClassSignature ; import org . eclipse . jdt . internal . compiler . env . EnumConstantSignature ; import org . eclipse . jdt . internal . compiler . env . IBinaryAnnotation ; import org . eclipse . jdt . internal . compiler . env . IBinaryElementValuePair ; import org . eclipse . jdt . internal . compiler . lookup . TagBits ; import org . eclipse . jdt . internal . compiler . lookup . TypeConstants ; import org . eclipse . jdt . internal . compiler . util . SuffixConstants ; import org . eclipse . jdt . internal . core . util . Util ; public class BinaryIndexer extends AbstractIndexer implements SuffixConstants { private static final char [ ] BYTE = "byte" . toCharArray ( ) ; private static final char [ ] CHAR = "char" . toCharArray ( ) ; private static final char [ ] DOUBLE = "double" . toCharArray ( ) ; private static final char [ ] FLOAT = "float" . toCharArray ( ) ; private static final char [ ] INT = "int" . toCharArray ( ) ; private static final char [ ] LONG = "long" . toCharArray ( ) ; private static final char [ ] SHORT = "short" . toCharArray ( ) ; private static final char [ ] BOOLEAN = "boolean" . toCharArray ( ) ; private static final char [ ] VOID = "void" . toCharArray ( ) ; private static final char [ ] INIT = "<init>" . toCharArray ( ) ; public BinaryIndexer ( SearchDocument document ) { super ( document ) ; } private void addBinaryStandardAnnotations ( long annotationTagBits ) { if ( ( annotationTagBits & TagBits . AnnotationTargetMASK ) != 0 ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_ANNOTATION_TARGET ; addAnnotationTypeReference ( compoundName [ compoundName . length - 1 ] ) ; addBinaryTargetAnnotation ( annotationTagBits ) ; } if ( ( annotationTagBits & TagBits . AnnotationRetentionMASK ) != 0 ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_ANNOTATION_RETENTION ; addAnnotationTypeReference ( compoundName [ compoundName . length - 1 ] ) ; addBinaryRetentionAnnotation ( annotationTagBits ) ; } if ( ( annotationTagBits & TagBits . AnnotationDeprecated ) != 0 ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_DEPRECATED ; addAnnotationTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } if ( ( annotationTagBits & TagBits . AnnotationDocumented ) != 0 ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_ANNOTATION_DOCUMENTED ; addAnnotationTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } if ( ( annotationTagBits & TagBits . AnnotationInherited ) != 0 ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_ANNOTATION_INHERITED ; addAnnotationTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } if ( ( annotationTagBits & TagBits . AnnotationOverride ) != 0 ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_OVERRIDE ; addAnnotationTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } if ( ( annotationTagBits & TagBits . AnnotationSuppressWarnings ) != 0 ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_SUPPRESSWARNINGS ; addAnnotationTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } if ( ( annotationTagBits & TagBits . AnnotationSafeVarargs ) != 0 ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_SAFEVARARGS ; addAnnotationTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } if ( ( annotationTagBits & TagBits . AnnotationPolymorphicSignature ) != 0 ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_INVOKE_METHODHANDLE_$_POLYMORPHICSIGNATURE ; addAnnotationTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } } private void addBinaryTargetAnnotation ( long bits ) { char [ ] [ ] compoundName = null ; if ( ( bits & TagBits . AnnotationForAnnotationType ) != 0 ) { compoundName = TypeConstants . JAVA_LANG_ANNOTATION_ELEMENTTYPE ; addTypeReference ( compoundName [ compoundName . length - 1 ] ) ; addFieldReference ( TypeConstants . UPPER_ANNOTATION_TYPE ) ; } if ( ( bits & TagBits . AnnotationForConstructor ) != 0 ) { if ( compoundName == null ) { compoundName = TypeConstants . JAVA_LANG_ANNOTATION_ELEMENTTYPE ; addTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } addFieldReference ( TypeConstants . UPPER_CONSTRUCTOR ) ; } if ( ( bits & TagBits . AnnotationForField ) != 0 ) { if ( compoundName == null ) { compoundName = TypeConstants . JAVA_LANG_ANNOTATION_ELEMENTTYPE ; addTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } addFieldReference ( TypeConstants . UPPER_FIELD ) ; } if ( ( bits & TagBits . AnnotationForLocalVariable ) != 0 ) { if ( compoundName == null ) { compoundName = TypeConstants . JAVA_LANG_ANNOTATION_ELEMENTTYPE ; addTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } addFieldReference ( TypeConstants . UPPER_LOCAL_VARIABLE ) ; } if ( ( bits & TagBits . AnnotationForMethod ) != 0 ) { if ( compoundName == null ) { compoundName = TypeConstants . JAVA_LANG_ANNOTATION_ELEMENTTYPE ; addTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } addFieldReference ( TypeConstants . UPPER_METHOD ) ; } if ( ( bits & TagBits . AnnotationForPackage ) != 0 ) { if ( compoundName == null ) { compoundName = TypeConstants . JAVA_LANG_ANNOTATION_ELEMENTTYPE ; addTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } addFieldReference ( TypeConstants . UPPER_PACKAGE ) ; } if ( ( bits & TagBits . AnnotationForParameter ) != 0 ) { if ( compoundName == null ) { compoundName = TypeConstants . JAVA_LANG_ANNOTATION_ELEMENTTYPE ; addTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } addFieldReference ( TypeConstants . UPPER_PARAMETER ) ; } if ( ( bits & TagBits . AnnotationForType ) != 0 ) { if ( compoundName == null ) { compoundName = TypeConstants . JAVA_LANG_ANNOTATION_ELEMENTTYPE ; addTypeReference ( compoundName [ compoundName . length - 1 ] ) ; } addFieldReference ( TypeConstants . TYPE ) ; } } private void addBinaryRetentionAnnotation ( long bits ) { char [ ] [ ] compoundName = TypeConstants . JAVA_LANG_ANNOTATION_RETENTIONPOLICY ; addTypeReference ( compoundName [ compoundName . length - 1 ] ) ; if ( ( bits & TagBits . AnnotationRuntimeRetention ) == TagBits . AnnotationRuntimeRetention ) { addFieldReference ( TypeConstants . UPPER_RUNTIME ) ; } else if ( ( bits & TagBits . AnnotationClassRetention ) != 0 ) { addFieldReference ( TypeConstants . UPPER_CLASS ) ; } else if ( ( bits & TagBits . AnnotationSourceRetention ) != 0 ) { addFieldReference ( TypeConstants . UPPER_SOURCE ) ; } } private void addBinaryAnnotation ( IBinaryAnnotation annotation ) { addAnnotationTypeReference ( replace ( '/' , '.' , Signature . toCharArray ( annotation . getTypeName ( ) ) ) ) ; IBinaryElementValuePair [ ] valuePairs = annotation . getElementValuePairs ( ) ; if ( valuePairs != null ) { for ( int j = 0 , vpLength = valuePairs . length ; j < vpLength ; j ++ ) { IBinaryElementValuePair valuePair = valuePairs [ j ] ; addMethodReference ( valuePair . getName ( ) , 0 ) ; Object pairValue = valuePair . getValue ( ) ; addPairValue ( pairValue ) ; } } } private void addPairValue ( Object pairValue ) { if ( pairValue instanceof EnumConstantSignature ) { EnumConstantSignature enumConstant = ( EnumConstantSignature ) pairValue ; addTypeReference ( replace ( '/' , '.' , Signature . toCharArray ( enumConstant . getTypeName ( ) ) ) ) ; addNameReference ( enumConstant . getEnumConstantName ( ) ) ; } else if ( pairValue instanceof ClassSignature ) { ClassSignature classConstant = ( ClassSignature ) pairValue ; addTypeReference ( replace ( '/' , '.' , Signature . toCharArray ( classConstant . getTypeName ( ) ) ) ) ; } else if ( pairValue instanceof IBinaryAnnotation ) { addBinaryAnnotation ( ( IBinaryAnnotation ) pairValue ) ; } else if ( pairValue instanceof Object [ ] ) { Object [ ] objects = ( Object [ ] ) pairValue ; for ( int i = 0 , l = objects . length ; i < l ; i ++ ) { addPairValue ( objects [ i ] ) ; } } } public void addTypeReference ( char [ ] typeName ) { int length = typeName . length ; if ( length > 2 && typeName [ length - 2 ] == '$' ) { switch ( typeName [ length - 1 ] ) { case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : return ; } } typeName = CharOperation . replaceOnCopy ( typeName , '$' , '.' ) ; super . addTypeReference ( typeName ) ; } private void convertToArrayType ( char [ ] [ ] parameterTypes , int counter , int arrayDim ) { int length = parameterTypes [ counter ] . length ; char [ ] arrayType = new char [ length + arrayDim * 2 ] ; System . arraycopy ( parameterTypes [ counter ] , 0 , arrayType , 0 , length ) ; for ( int i = 0 ; i < arrayDim ; i ++ ) { arrayType [ length + ( i * 2 ) ] = '[' ; arrayType [ length + ( i * 2 ) + 1 ] = ']' ; } parameterTypes [ counter ] = arrayType ; } private char [ ] convertToArrayType ( char [ ] typeName , int arrayDim ) { int length = typeName . length ; char [ ] arrayType = new char [ length + arrayDim * 2 ] ; System . arraycopy ( typeName , 0 , arrayType , 0 , length ) ; for ( int i = 0 ; i < arrayDim ; i ++ ) { arrayType [ length + ( i * 2 ) ] = '[' ; arrayType [ length + ( i * 2 ) + 1 ] = ']' ; } return arrayType ; } private char [ ] decodeFieldType ( char [ ] signature ) throws ClassFormatException { if ( signature == null ) return null ; int arrayDim = 0 ; for ( int i = 0 , max = signature . length ; i < max ; i ++ ) { switch ( signature [ i ] ) { case 'B' : if ( arrayDim > 0 ) return convertToArrayType ( BYTE , arrayDim ) ; return BYTE ; case 'C' : if ( arrayDim > 0 ) return convertToArrayType ( CHAR , arrayDim ) ; return CHAR ; case 'D' : if ( arrayDim > 0 ) return convertToArrayType ( DOUBLE , arrayDim ) ; return DOUBLE ; case 'F' : if ( arrayDim > 0 ) return convertToArrayType ( FLOAT , arrayDim ) ; return FLOAT ; case 'I' : if ( arrayDim > 0 ) return convertToArrayType ( INT , arrayDim ) ; return INT ; case 'J' : if ( arrayDim > 0 ) return convertToArrayType ( LONG , arrayDim ) ; return LONG ; case 'L' : int indexOfSemiColon = CharOperation . indexOf ( ';' , signature , i + 1 ) ; if ( indexOfSemiColon == - 1 ) throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; if ( arrayDim > 0 ) { return convertToArrayType ( replace ( '/' , '.' , CharOperation . subarray ( signature , i + 1 , indexOfSemiColon ) ) , arrayDim ) ; } return replace ( '/' , '.' , CharOperation . subarray ( signature , i + 1 , indexOfSemiColon ) ) ; case 'S' : if ( arrayDim > 0 ) return convertToArrayType ( SHORT , arrayDim ) ; return SHORT ; case 'Z' : if ( arrayDim > 0 ) return convertToArrayType ( BOOLEAN , arrayDim ) ; return BOOLEAN ; case 'V' : return VOID ; case '[' : arrayDim ++ ; break ; default : throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; } } return null ; } private char [ ] [ ] decodeParameterTypes ( char [ ] signature , boolean firstIsSynthetic ) throws ClassFormatException { if ( signature == null ) return null ; int indexOfClosingParen = CharOperation . lastIndexOf ( ')' , signature ) ; if ( indexOfClosingParen == 1 ) { return null ; } if ( indexOfClosingParen == - 1 ) { throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; } char [ ] [ ] parameterTypes = new char [ 3 ] [ ] ; int parameterTypesCounter = 0 ; int arrayDim = 0 ; for ( int i = 1 ; i < indexOfClosingParen ; i ++ ) { if ( parameterTypesCounter == parameterTypes . length ) { System . arraycopy ( parameterTypes , 0 , ( parameterTypes = new char [ parameterTypesCounter * 2 ] [ ] ) , 0 , parameterTypesCounter ) ; } switch ( signature [ i ] ) { case 'B' : parameterTypes [ parameterTypesCounter ++ ] = BYTE ; if ( arrayDim > 0 ) convertToArrayType ( parameterTypes , parameterTypesCounter - 1 , arrayDim ) ; arrayDim = 0 ; break ; case 'C' : parameterTypes [ parameterTypesCounter ++ ] = CHAR ; if ( arrayDim > 0 ) convertToArrayType ( parameterTypes , parameterTypesCounter - 1 , arrayDim ) ; arrayDim = 0 ; break ; case 'D' : parameterTypes [ parameterTypesCounter ++ ] = DOUBLE ; if ( arrayDim > 0 ) convertToArrayType ( parameterTypes , parameterTypesCounter - 1 , arrayDim ) ; arrayDim = 0 ; break ; case 'F' : parameterTypes [ parameterTypesCounter ++ ] = FLOAT ; if ( arrayDim > 0 ) convertToArrayType ( parameterTypes , parameterTypesCounter - 1 , arrayDim ) ; arrayDim = 0 ; break ; case 'I' : parameterTypes [ parameterTypesCounter ++ ] = INT ; if ( arrayDim > 0 ) convertToArrayType ( parameterTypes , parameterTypesCounter - 1 , arrayDim ) ; arrayDim = 0 ; break ; case 'J' : parameterTypes [ parameterTypesCounter ++ ] = LONG ; if ( arrayDim > 0 ) convertToArrayType ( parameterTypes , parameterTypesCounter - 1 , arrayDim ) ; arrayDim = 0 ; break ; case 'L' : int indexOfSemiColon = CharOperation . indexOf ( ';' , signature , i + 1 ) ; if ( indexOfSemiColon == - 1 ) throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; if ( firstIsSynthetic && parameterTypesCounter == 0 ) { firstIsSynthetic = false ; } else { parameterTypes [ parameterTypesCounter ++ ] = replace ( '/' , '.' , CharOperation . subarray ( signature , i + 1 , indexOfSemiColon ) ) ; if ( arrayDim > 0 ) convertToArrayType ( parameterTypes , parameterTypesCounter - 1 , arrayDim ) ; } i = indexOfSemiColon ; arrayDim = 0 ; break ; case 'S' : parameterTypes [ parameterTypesCounter ++ ] = SHORT ; if ( arrayDim > 0 ) convertToArrayType ( parameterTypes , parameterTypesCounter - 1 , arrayDim ) ; arrayDim = 0 ; break ; case 'Z' : parameterTypes [ parameterTypesCounter ++ ] = BOOLEAN ; if ( arrayDim > 0 ) convertToArrayType ( parameterTypes , parameterTypesCounter - 1 , arrayDim ) ; arrayDim = 0 ; break ; case '[' : arrayDim ++ ; break ; default : throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; } } if ( parameterTypes . length != parameterTypesCounter ) { System . arraycopy ( parameterTypes , 0 , parameterTypes = new char [ parameterTypesCounter ] [ ] , 0 , parameterTypesCounter ) ; } return parameterTypes ; } private char [ ] decodeReturnType ( char [ ] signature ) throws ClassFormatException { if ( signature == null ) return null ; int indexOfClosingParen = CharOperation . lastIndexOf ( ')' , signature ) ; if ( indexOfClosingParen == - 1 ) throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; int arrayDim = 0 ; for ( int i = indexOfClosingParen + 1 , max = signature . length ; i < max ; i ++ ) { switch ( signature [ i ] ) { case 'B' : if ( arrayDim > 0 ) return convertToArrayType ( BYTE , arrayDim ) ; return BYTE ; case 'C' : if ( arrayDim > 0 ) return convertToArrayType ( CHAR , arrayDim ) ; return CHAR ; case 'D' : if ( arrayDim > 0 ) return convertToArrayType ( DOUBLE , arrayDim ) ; return DOUBLE ; case 'F' : if ( arrayDim > 0 ) return convertToArrayType ( FLOAT , arrayDim ) ; return FLOAT ; case 'I' : if ( arrayDim > 0 ) return convertToArrayType ( INT , arrayDim ) ; return INT ; case 'J' : if ( arrayDim > 0 ) return convertToArrayType ( LONG , arrayDim ) ; return LONG ; case 'L' : int indexOfSemiColon = CharOperation . indexOf ( ';' , signature , i + 1 ) ; if ( indexOfSemiColon == - 1 ) throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; if ( arrayDim > 0 ) { return convertToArrayType ( replace ( '/' , '.' , CharOperation . subarray ( signature , i + 1 , indexOfSemiColon ) ) , arrayDim ) ; } return replace ( '/' , '.' , CharOperation . subarray ( signature , i + 1 , indexOfSemiColon ) ) ; case 'S' : if ( arrayDim > 0 ) return convertToArrayType ( SHORT , arrayDim ) ; return SHORT ; case 'Z' : if ( arrayDim > 0 ) return convertToArrayType ( BOOLEAN , arrayDim ) ; return BOOLEAN ; case 'V' : return VOID ; case '[' : arrayDim ++ ; break ; default : throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; } } return null ; } private int extractArgCount ( char [ ] signature , char [ ] className ) throws ClassFormatException { int indexOfClosingParen = CharOperation . lastIndexOf ( ')' , signature ) ; if ( indexOfClosingParen == 1 ) { return 0 ; } if ( indexOfClosingParen == - 1 ) { throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; } int parameterTypesCounter = 0 ; for ( int i = 1 ; i < indexOfClosingParen ; i ++ ) { switch ( signature [ i ] ) { case 'B' : case 'C' : case 'D' : case 'F' : case 'I' : case 'J' : case 'S' : case 'Z' : parameterTypesCounter ++ ; break ; case 'L' : int indexOfSemiColon = CharOperation . indexOf ( ';' , signature , i + 1 ) ; if ( indexOfSemiColon == - 1 ) throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; if ( className != null && parameterTypesCounter == 0 ) { char [ ] classSignature = Signature . createCharArrayTypeSignature ( className , true ) ; int length = indexOfSemiColon - i + 1 ; if ( classSignature . length > ( length + 1 ) ) { for ( int j = i , k = 0 ; j < indexOfSemiColon ; j ++ , k ++ ) { if ( ! ( signature [ j ] == classSignature [ k ] || ( signature [ j ] == '/' && classSignature [ k ] == '.' ) ) ) { parameterTypesCounter ++ ; break ; } } } else { parameterTypesCounter ++ ; } className = null ; } else { parameterTypesCounter ++ ; } i = indexOfSemiColon ; break ; case '[' : break ; default : throw new ClassFormatException ( ClassFormatException . ErrInvalidMethodSignature ) ; } } return parameterTypesCounter ; } private char [ ] extractClassName ( int [ ] constantPoolOffsets , ClassFileReader reader , int index ) { int class_index = reader . u2At ( constantPoolOffsets [ index ] + 1 ) ; int utf8Offset = constantPoolOffsets [ reader . u2At ( constantPoolOffsets [ class_index ] + 1 ) ] ; return reader . utf8At ( utf8Offset + 3 , reader . u2At ( utf8Offset + 1 ) ) ; } private char [ ] extractName ( int [ ] constantPoolOffsets , ClassFileReader reader , int index ) { int nameAndTypeIndex = reader . u2At ( constantPoolOffsets [ index ] + 3 ) ; int utf8Offset = constantPoolOffsets [ reader . u2At ( constantPoolOffsets [ nameAndTypeIndex ] + 1 ) ] ; return reader . utf8At ( utf8Offset + 3 , reader . u2At ( utf8Offset + 1 ) ) ; } private char [ ] extractClassReference ( int [ ] constantPoolOffsets , ClassFileReader reader , int index ) { int utf8Offset = constantPoolOffsets [ reader . u2At ( constantPoolOffsets [ index ] + 1 ) ] ; return reader . utf8At ( utf8Offset + 3 , reader . u2At ( utf8Offset + 1 ) ) ; } private void extractReferenceFromConstantPool ( byte [ ] contents , ClassFileReader reader ) throws ClassFormatException { int [ ] constantPoolOffsets = reader . getConstantPoolOffsets ( ) ; int constantPoolCount = constantPoolOffsets . length ; for ( int i = 1 ; i < constantPoolCount ; i ++ ) { int tag = reader . u1At ( constantPoolOffsets [ i ] ) ; char [ ] name = null ; char [ ] type = null ; switch ( tag ) { case ClassFileConstants . FieldRefTag : name = extractName ( constantPoolOffsets , reader , i ) ; addFieldReference ( name ) ; break ; case ClassFileConstants . MethodRefTag : case ClassFileConstants . InterfaceMethodRefTag : name = extractName ( constantPoolOffsets , reader , i ) ; type = extractType ( constantPoolOffsets , reader , i ) ; if ( CharOperation . equals ( INIT , name ) ) { char [ ] className = extractClassName ( constantPoolOffsets , reader , i ) ; boolean localType = false ; if ( className != null ) { for ( int c = 0 , max = className . length ; c < max ; c ++ ) { switch ( className [ c ] ) { case '/' : className [ c ] = '.' ; break ; case '$' : localType = true ; break ; } } } addConstructorReference ( className , extractArgCount ( type , localType ? className : null ) ) ; } else { addMethodReference ( name , extractArgCount ( type , null ) ) ; } break ; case ClassFileConstants . ClassTag : name = extractClassReference ( constantPoolOffsets , reader , i ) ; if ( name . length > 0 && name [ 0 ] == '[' ) break ; name = replace ( '/' , '.' , name ) ; addTypeReference ( name ) ; char [ ] [ ] qualification = CharOperation . splitOn ( '.' , name ) ; for ( int j = 0 , length = qualification . length ; j < length ; j ++ ) { addNameReference ( qualification [ j ] ) ; } break ; } } } private char [ ] extractType ( int [ ] constantPoolOffsets , ClassFileReader reader , int index ) { int constantPoolIndex = reader . u2At ( constantPoolOffsets [ index ] + 3 ) ; int utf8Offset = constantPoolOffsets [ reader . u2At ( constantPoolOffsets [ constantPoolIndex ] + 3 ) ] ; return reader . utf8At ( utf8Offset + 3 , reader . u2At ( utf8Offset + 1 ) ) ; } public void indexDocument ( ) { try { final byte [ ] contents = this . document . getByteContents ( ) ; if ( contents == null ) return ; final String path = this . document . getPath ( ) ; ClassFileReader reader = new ClassFileReader ( contents , path == null ? null : path . toCharArray ( ) ) ; char [ ] className = replace ( '/' , '.' , reader . getName ( ) ) ; int packageNameIndex = CharOperation . lastIndexOf ( '.' , className ) ; char [ ] packageName = null ; char [ ] name = null ; if ( packageNameIndex >= 0 ) { packageName = CharOperation . subarray ( className , 0 , packageNameIndex ) ; name = CharOperation . subarray ( className , packageNameIndex + 1 , className . length ) ; } else { packageName = CharOperation . NO_CHAR ; name = className ; } char [ ] enclosingTypeName = null ; boolean isNestedType = reader . isNestedType ( ) ; if ( isNestedType ) { if ( reader . isAnonymous ( ) ) { name = CharOperation . NO_CHAR ; } else { name = reader . getInnerSourceName ( ) ; } if ( reader . isLocal ( ) || reader . isAnonymous ( ) ) { enclosingTypeName = ONE_ZERO ; } else { char [ ] fullEnclosingName = reader . getEnclosingTypeName ( ) ; int nameLength = fullEnclosingName . length - packageNameIndex - 1 ; if ( nameLength <= 0 ) { return ; } enclosingTypeName = new char [ nameLength ] ; System . arraycopy ( fullEnclosingName , packageNameIndex + 1 , enclosingTypeName , 0 , nameLength ) ; } } char [ ] [ ] typeParameterSignatures = null ; char [ ] genericSignature = reader . getGenericSignature ( ) ; if ( genericSignature != null ) { CharOperation . replace ( genericSignature , '/' , '.' ) ; typeParameterSignatures = Signature . getTypeParameters ( genericSignature ) ; } if ( name == null ) return ; char [ ] [ ] superinterfaces = replace ( '/' , '.' , reader . getInterfaceNames ( ) ) ; char [ ] [ ] enclosingTypeNames = enclosingTypeName == null ? null : new char [ ] [ ] { enclosingTypeName } ; int modifiers = reader . getModifiers ( ) ; switch ( TypeDeclaration . kind ( modifiers ) ) { case TypeDeclaration . CLASS_DECL : char [ ] superclass = replace ( '/' , '.' , reader . getSuperclassName ( ) ) ; addClassDeclaration ( modifiers , packageName , name , enclosingTypeNames , superclass , superinterfaces , typeParameterSignatures , false ) ; break ; case TypeDeclaration . INTERFACE_DECL : addInterfaceDeclaration ( modifiers , packageName , name , enclosingTypeNames , superinterfaces , typeParameterSignatures , false ) ; break ; case TypeDeclaration . ENUM_DECL : superclass = replace ( '/' , '.' , reader . getSuperclassName ( ) ) ; addEnumDeclaration ( modifiers , packageName , name , enclosingTypeNames , superclass , superinterfaces , false ) ; break ; case TypeDeclaration . ANNOTATION_TYPE_DECL : addAnnotationTypeDeclaration ( modifiers , packageName , name , enclosingTypeNames , false ) ; break ; } IBinaryAnnotation [ ] annotations = reader . getAnnotations ( ) ; if ( annotations != null ) { for ( int a = 0 , length = annotations . length ; a < length ; a ++ ) { IBinaryAnnotation annotation = annotations [ a ] ; addBinaryAnnotation ( annotation ) ; } } long tagBits = reader . getTagBits ( ) & TagBits . AllStandardAnnotationsMask ; if ( tagBits != 0 ) { addBinaryStandardAnnotations ( tagBits ) ; } int extraFlags = ExtraFlags . getExtraFlags ( reader ) ; MethodInfo [ ] methods = ( MethodInfo [ ] ) reader . getMethods ( ) ; boolean noConstructor = true ; if ( methods != null ) { for ( int i = 0 , max = methods . length ; i < max ; i ++ ) { MethodInfo method = methods [ i ] ; boolean isConstructor = method . isConstructor ( ) ; char [ ] descriptor = method . getMethodDescriptor ( ) ; char [ ] [ ] parameterTypes = decodeParameterTypes ( descriptor , isConstructor && isNestedType ) ; char [ ] returnType = decodeReturnType ( descriptor ) ; char [ ] [ ] exceptionTypes = replace ( '/' , '.' , method . getExceptionTypeNames ( ) ) ; if ( isConstructor ) { noConstructor = false ; char [ ] signature = method . getGenericSignature ( ) ; if ( signature == null ) { if ( reader . isNestedType ( ) && ( ( modifiers & ClassFileConstants . AccStatic ) == 0 ) ) { signature = removeFirstSyntheticParameter ( descriptor ) ; } else { signature = descriptor ; } } addConstructorDeclaration ( name , parameterTypes == null ? 0 : parameterTypes . length , signature , parameterTypes , method . getArgumentNames ( ) , method . getModifiers ( ) , packageName , modifiers , exceptionTypes , extraFlags ) ; } else { if ( ! method . isClinit ( ) ) { addMethodDeclaration ( method . getSelector ( ) , parameterTypes , returnType , exceptionTypes ) ; } } annotations = method . getAnnotations ( ) ; if ( annotations != null ) { for ( int a = 0 , length = annotations . length ; a < length ; a ++ ) { IBinaryAnnotation annotation = annotations [ a ] ; addBinaryAnnotation ( annotation ) ; } } tagBits = method . getTagBits ( ) & TagBits . AllStandardAnnotationsMask ; if ( tagBits != 0 ) { addBinaryStandardAnnotations ( tagBits ) ; } } } if ( noConstructor ) { addDefaultConstructorDeclaration ( className , packageName , modifiers , extraFlags ) ; } FieldInfo [ ] fields = ( FieldInfo [ ] ) reader . getFields ( ) ; if ( fields != null ) { for ( int i = 0 , max = fields . length ; i < max ; i ++ ) { FieldInfo field = fields [ i ] ; char [ ] fieldName = field . getName ( ) ; char [ ] fieldType = decodeFieldType ( replace ( '/' , '.' , field . getTypeName ( ) ) ) ; addFieldDeclaration ( fieldType , fieldName ) ; annotations = field . getAnnotations ( ) ; if ( annotations != null ) { for ( int a = 0 , length = annotations . length ; a < length ; a ++ ) { IBinaryAnnotation annotation = annotations [ a ] ; addBinaryAnnotation ( annotation ) ; } } tagBits = field . getTagBits ( ) & TagBits . AllStandardAnnotationsMask ; if ( tagBits != 0 ) { addBinaryStandardAnnotations ( tagBits ) ; } } } extractReferenceFromConstantPool ( contents , reader ) ; } catch ( ClassFormatException e ) { this . document . removeAllIndexEntries ( ) ; Util . log ( IStatus . WARNING , "" + this . document . getPath ( ) + "" ) ; } catch ( RuntimeException e ) { this . document . removeAllIndexEntries ( ) ; Util . log ( IStatus . WARNING , "" + this . document . getPath ( ) + "" ) ; } } private char [ ] removeFirstSyntheticParameter ( char [ ] descriptor ) { if ( descriptor == null ) return null ; if ( descriptor . length < 3 ) return descriptor ; if ( descriptor [ 0 ] != '(' ) return descriptor ; if ( descriptor [ 1 ] != ')' ) { int start = org . eclipse . jdt . internal . compiler . util . Util . scanTypeSignature ( descriptor , 1 ) + 1 ; int length = descriptor . length - start ; char [ ] signature = new char [ length + 1 ] ; signature [ 0 ] = descriptor [ 0 ] ; System . arraycopy ( descriptor , start , signature , 1 , length ) ; return signature ; } else { return descriptor ; } } private char [ ] [ ] replace ( char toBeReplaced , char newChar , char [ ] [ ] array ) { if ( array == null ) return null ; for ( int i = 0 , max = array . length ; i < max ; i ++ ) { replace ( toBeReplaced , newChar , array [ i ] ) ; } return array ; } private char [ ] replace ( char toBeReplaced , char newChar , char [ ] array ) { if ( array == null ) return null ; for ( int i = 0 , max = array . length ; i < max ; i ++ ) { if ( array [ i ] == toBeReplaced ) { array [ i ] = newChar ; } } return array ; } } </s>