KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > search > indexing > BinaryIndexer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core.search.indexing;
12
13 import org.eclipse.jdt.core.Signature;
14 import org.eclipse.jdt.core.compiler.CharOperation;
15 import org.eclipse.jdt.core.search.SearchDocument;
16 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
17 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
18 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
19 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
20 import org.eclipse.jdt.internal.compiler.classfmt.FieldInfo;
21 import org.eclipse.jdt.internal.compiler.classfmt.MethodInfo;
22 import org.eclipse.jdt.internal.compiler.env.ClassSignature;
23 import org.eclipse.jdt.internal.compiler.env.EnumConstantSignature;
24 import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
25 import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
26 import org.eclipse.jdt.internal.compiler.lookup.TagBits;
27 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
28 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
29 import org.eclipse.jdt.internal.core.util.Util;
30
31 public class BinaryIndexer extends AbstractIndexer implements SuffixConstants {
32     private static final char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
33
private static final char[] CHAR = "char".toCharArray(); //$NON-NLS-1$
34
private static final char[] DOUBLE = "double".toCharArray(); //$NON-NLS-1$
35
private static final char[] FLOAT = "float".toCharArray(); //$NON-NLS-1$
36
private static final char[] INT = "int".toCharArray(); //$NON-NLS-1$
37
private static final char[] LONG = "long".toCharArray(); //$NON-NLS-1$
38
private static final char[] SHORT = "short".toCharArray(); //$NON-NLS-1$
39
private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
40
private static final char[] VOID = "void".toCharArray(); //$NON-NLS-1$
41
private static final char[] INIT = "<init>".toCharArray(); //$NON-NLS-1$
42

43     public BinaryIndexer(SearchDocument document) {
44         super(document);
45     }
46     private void addBinaryStandardAnnotations(long annotationTagBits) {
47         if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0) {
48             char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_TARGET;
49             addTypeReference(compoundName[compoundName.length-1]);
50             addBinaryTargetAnnotation(annotationTagBits);
51         }
52         if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0) {
53             char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_RETENTION;
54             addTypeReference(compoundName[compoundName.length-1]);
55             addBinaryRetentionAnnotation(annotationTagBits);
56         }
57         if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0) {
58             char[][] compoundName = TypeConstants.JAVA_LANG_DEPRECATED;
59             addTypeReference(compoundName[compoundName.length-1]);
60         }
61         if ((annotationTagBits & TagBits.AnnotationDocumented) != 0) {
62             char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED;
63             addTypeReference(compoundName[compoundName.length-1]);
64         }
65         if ((annotationTagBits & TagBits.AnnotationInherited) != 0) {
66             char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_INHERITED;
67             addTypeReference(compoundName[compoundName.length-1]);
68         }
69         if ((annotationTagBits & TagBits.AnnotationOverride) != 0) {
70             char[][] compoundName = TypeConstants.JAVA_LANG_OVERRIDE;
71             addTypeReference(compoundName[compoundName.length-1]);
72         }
73         if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0) {
74             char[][] compoundName = TypeConstants.JAVA_LANG_SUPPRESSWARNINGS;
75             addTypeReference(compoundName[compoundName.length-1]);
76         }
77     }
78     private void addBinaryTargetAnnotation(long bits) {
79         char[][] compoundName = null;
80         if ((bits & TagBits.AnnotationForAnnotationType) != 0) {
81             compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
82             addTypeReference(compoundName[compoundName.length-1]);
83             addFieldReference(TypeConstants.UPPER_ANNOTATION_TYPE);
84         }
85         if ((bits & TagBits.AnnotationForConstructor) != 0) {
86             if (compoundName == null) {
87                 compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
88                 addTypeReference(compoundName[compoundName.length-1]);
89             }
90             addFieldReference(TypeConstants.UPPER_CONSTRUCTOR);
91         }
92         if ((bits & TagBits.AnnotationForField) != 0) {
93             if (compoundName == null) {
94                 compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
95                 addTypeReference(compoundName[compoundName.length-1]);
96             }
97             addFieldReference(TypeConstants.UPPER_FIELD);
98         }
99         if ((bits & TagBits.AnnotationForLocalVariable) != 0) {
100             if (compoundName == null) {
101                 compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
102                 addTypeReference(compoundName[compoundName.length-1]);
103             }
104             addFieldReference(TypeConstants.UPPER_LOCAL_VARIABLE);
105         }
106         if ((bits & TagBits.AnnotationForMethod) != 0) {
107             if (compoundName == null) {
108                 compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
109                 addTypeReference(compoundName[compoundName.length-1]);
110             }
111             addFieldReference(TypeConstants.UPPER_METHOD);
112         }
113         if ((bits & TagBits.AnnotationForPackage) != 0) {
114             if (compoundName == null) {
115                 compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
116                 addTypeReference(compoundName[compoundName.length-1]);
117             }
118             addFieldReference(TypeConstants.UPPER_PACKAGE);
119         }
120         if ((bits & TagBits.AnnotationForParameter) != 0) {
121             if (compoundName == null) {
122                 compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
123                 addTypeReference(compoundName[compoundName.length-1]);
124             }
125             addFieldReference(TypeConstants.UPPER_PARAMETER);
126         }
127         if ((bits & TagBits.AnnotationForType) != 0) {
128             if (compoundName == null) {
129                 compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
130                 addTypeReference(compoundName[compoundName.length-1]);
131             }
132             addFieldReference(TypeConstants.TYPE);
133         }
134     }
135     private void addBinaryRetentionAnnotation(long bits) {
136         char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY;
137         addTypeReference(compoundName[compoundName.length-1]);
138         if ((bits & TagBits.AnnotationRuntimeRetention) != 0) {
139             addFieldReference(TypeConstants.UPPER_RUNTIME);
140         }
141         else if ((bits & TagBits.AnnotationClassRetention) != 0) {
142             addFieldReference(TypeConstants.UPPER_CLASS);
143         }
144         else if ((bits & TagBits.AnnotationSourceRetention) != 0) {
145             addFieldReference(TypeConstants.UPPER_SOURCE);
146         }
147     }
148     private void addBinaryAnnotation(IBinaryAnnotation annotation) {
149         addTypeReference(replace('/', '.', Signature.toCharArray(annotation.getTypeName())));
150         IBinaryElementValuePair[] valuePairs = annotation.getElementValuePairs();
151         if (valuePairs != null) {
152             for (int j=0, vpLength=valuePairs.length; j<vpLength; j++) {
153                 IBinaryElementValuePair valuePair = valuePairs[j];
154                 addMethodReference(valuePair.getName(), 0);
155                 Object JavaDoc pairValue = valuePair.getValue();
156                 addPairValue(pairValue);
157             }
158         }
159     }
160     private void addPairValue(Object JavaDoc pairValue) {
161         if (pairValue instanceof EnumConstantSignature) {
162             EnumConstantSignature enumConstant = (EnumConstantSignature) pairValue;
163             addTypeReference(replace('/', '.', Signature.toCharArray(enumConstant.getTypeName())));
164             addNameReference(enumConstant.getEnumConstantName());
165         } else if (pairValue instanceof ClassSignature) {
166             ClassSignature classConstant = (ClassSignature) pairValue;
167             addTypeReference(replace('/', '.', Signature.toCharArray(classConstant.getTypeName())));
168         } else if (pairValue instanceof IBinaryAnnotation) {
169             addBinaryAnnotation((IBinaryAnnotation) pairValue);
170         } else if (pairValue instanceof Object JavaDoc[]) {
171             Object JavaDoc[] objects = (Object JavaDoc[]) pairValue;
172             for (int i=0,l=objects.length; i<l; i++) {
173                 addPairValue(objects[i]);
174             }
175         }
176     }
177     public void addTypeReference(char[] typeName) {
178         int length = typeName.length;
179         if (length > 2 && typeName[length - 2] == '$') {
180             switch (typeName[length - 1]) {
181                 case '0' :
182                 case '1' :
183                 case '2' :
184                 case '3' :
185                 case '4' :
186                 case '5' :
187                 case '6' :
188                 case '7' :
189                 case '8' :
190                 case '9' :
191                     return; // skip local type names
192
}
193         }
194
195         // consider that A$B is a member type: so replace '$' with '.'
196
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=40116)
197
typeName = CharOperation.replaceOnCopy(typeName, '$', '.'); // copy it so the original is not modified
198

199         super.addTypeReference(typeName);
200     }
201     /**
202      * For example:
203      * - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
204      * - void foo(int) is (I)V ==> int
205      */

206     private void convertToArrayType(char[][] parameterTypes, int counter, int arrayDim) {
207         int length = parameterTypes[counter].length;
208         char[] arrayType = new char[length + arrayDim*2];
209         System.arraycopy(parameterTypes[counter], 0, arrayType, 0, length);
210         for (int i = 0; i < arrayDim; i++) {
211             arrayType[length + (i * 2)] = '[';
212             arrayType[length + (i * 2) + 1] = ']';
213         }
214         parameterTypes[counter] = arrayType;
215     }
216     /**
217      * For example:
218      * - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
219      * - void foo(int) is (I)V ==> int
220      */

221     private char[] convertToArrayType(char[] typeName, int arrayDim) {
222         int length = typeName.length;
223         char[] arrayType = new char[length + arrayDim*2];
224         System.arraycopy(typeName, 0, arrayType, 0, length);
225         for (int i = 0; i < arrayDim; i++) {
226             arrayType[length + (i * 2)] = '[';
227             arrayType[length + (i * 2) + 1] = ']';
228         }
229         return arrayType;
230     }
231     private char[] decodeFieldType(char[] signature) throws ClassFormatException {
232         if (signature == null) return null;
233         int arrayDim = 0;
234         for (int i = 0, max = signature.length; i < max; i++) {
235             switch(signature[i]) {
236                 case 'B':
237                     if (arrayDim > 0)
238                         return convertToArrayType(BYTE, arrayDim);
239                     return BYTE;
240                     
241                 case 'C':
242                     if (arrayDim > 0)
243                         return convertToArrayType(CHAR, arrayDim);
244                     return CHAR;
245                     
246                 case 'D':
247                     if (arrayDim > 0)
248                         return convertToArrayType(DOUBLE, arrayDim);
249                     return DOUBLE;
250                     
251                 case 'F':
252                     if (arrayDim > 0)
253                         return convertToArrayType(FLOAT, arrayDim);
254                     return FLOAT;
255                     
256                 case 'I':
257                     if (arrayDim > 0)
258                     return convertToArrayType(INT, arrayDim);
259                     return INT;
260                     
261                 case 'J':
262                     if (arrayDim > 0)
263                         return convertToArrayType(LONG, arrayDim);
264                     return LONG;
265                     
266                 case 'L':
267                     int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
268                     if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
269                     if (arrayDim > 0) {
270                         return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
271                     }
272                     return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
273                     
274                 case 'S':
275                     if (arrayDim > 0)
276                         return convertToArrayType(SHORT, arrayDim);
277                     return SHORT;
278                     
279                 case 'Z':
280                     if (arrayDim > 0)
281                         return convertToArrayType(BOOLEAN, arrayDim);
282                     return BOOLEAN;
283                     
284                 case 'V':
285                     return VOID;
286                     
287                 case '[':
288                     arrayDim++;
289                     break;
290                     
291                 default:
292                     throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
293             }
294         }
295         return null;
296     }
297     /**
298      * For example:
299      * - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
300      * - void foo(int) is (I)V ==> int
301      */

302     private char[][] decodeParameterTypes(char[] signature, boolean firstIsSynthetic) throws ClassFormatException {
303         if (signature == null) return null;
304         int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
305         if (indexOfClosingParen == 1) {
306             // there is no parameter
307
return null;
308         }
309         if (indexOfClosingParen == -1) {
310             throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
311         }
312         char[][] parameterTypes = new char[3][];
313         int parameterTypesCounter = 0;
314         int arrayDim = 0;
315         for (int i = 1; i < indexOfClosingParen; i++) {
316             if (parameterTypesCounter == parameterTypes.length) {
317                 // resize
318
System.arraycopy(parameterTypes, 0, (parameterTypes = new char[parameterTypesCounter * 2][]), 0, parameterTypesCounter);
319             }
320             switch(signature[i]) {
321                 case 'B':
322                     parameterTypes[parameterTypesCounter++] = BYTE;
323                     if (arrayDim > 0)
324                         convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
325                     arrayDim = 0;
326                     break;
327                     
328                 case 'C':
329                     parameterTypes[parameterTypesCounter++] = CHAR;
330                     if (arrayDim > 0)
331                         convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
332                     arrayDim = 0;
333                     break;
334
335                 case 'D':
336                     parameterTypes[parameterTypesCounter++] = DOUBLE;
337                     if (arrayDim > 0)
338                         convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
339                     arrayDim = 0;
340                     break;
341
342                 case 'F':
343                     parameterTypes[parameterTypesCounter++] = FLOAT;
344                     if (arrayDim > 0)
345                         convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
346                     arrayDim = 0;
347                     break;
348                     
349                 case 'I':
350                     parameterTypes[parameterTypesCounter++] = INT;
351                     if (arrayDim > 0)
352                         convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
353                     arrayDim = 0;
354                     break;
355                     
356                 case 'J':
357                     parameterTypes[parameterTypesCounter++] = LONG;
358                     if (arrayDim > 0)
359                         convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
360                     arrayDim = 0;
361                     break;
362
363                 case 'L':
364                     int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
365                     if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
366                     if (firstIsSynthetic && parameterTypesCounter == 0) {
367                         // skip first synthetic parameter
368
firstIsSynthetic = false;
369                     } else {
370                         parameterTypes[parameterTypesCounter++] = replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
371                         if (arrayDim > 0)
372                             convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
373                     }
374                     i = indexOfSemiColon;
375                     arrayDim = 0;
376                     break;
377
378                 case 'S':
379                     parameterTypes[parameterTypesCounter++] = SHORT;
380                     if (arrayDim > 0)
381                         convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
382                     arrayDim = 0;
383                     break;
384
385                 case 'Z':
386                     parameterTypes[parameterTypesCounter++] = BOOLEAN;
387                     if (arrayDim > 0)
388                         convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
389                     arrayDim = 0;
390                     break;
391
392                 case '[':
393                     arrayDim++;
394                     break;
395                     
396                 default:
397                     throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
398             }
399         }
400         if (parameterTypes.length != parameterTypesCounter) {
401             System.arraycopy(parameterTypes, 0, parameterTypes = new char[parameterTypesCounter][], 0, parameterTypesCounter);
402         }
403         return parameterTypes;
404     }
405     private char[] decodeReturnType(char[] signature) throws ClassFormatException {
406         if (signature == null) return null;
407         int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
408         if (indexOfClosingParen == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
409         int arrayDim = 0;
410         for (int i = indexOfClosingParen + 1, max = signature.length; i < max; i++) {
411             switch(signature[i]) {
412                 case 'B':
413                     if (arrayDim > 0)
414                         return convertToArrayType(BYTE, arrayDim);
415                     return BYTE;
416                     
417                 case 'C':
418                     if (arrayDim > 0)
419                         return convertToArrayType(CHAR, arrayDim);
420                     return CHAR;
421                     
422                 case 'D':
423                     if (arrayDim > 0)
424                         return convertToArrayType(DOUBLE, arrayDim);
425                     return DOUBLE;
426
427                 case 'F':
428                     if (arrayDim > 0)
429                         return convertToArrayType(FLOAT, arrayDim);
430                     return FLOAT;
431
432                 case 'I':
433                     if (arrayDim > 0)
434                         return convertToArrayType(INT, arrayDim);
435                     return INT;
436
437                 case 'J':
438                     if (arrayDim > 0)
439                         return convertToArrayType(LONG, arrayDim);
440                     return LONG;
441
442                 case 'L':
443                     int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
444                     if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
445                     if (arrayDim > 0) {
446                         return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
447                     }
448                     return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
449
450                 case 'S':
451                     if (arrayDim > 0)
452                         return convertToArrayType(SHORT, arrayDim);
453                     return SHORT;
454
455                 case 'Z':
456                     if (arrayDim > 0)
457                         return convertToArrayType(BOOLEAN, arrayDim);
458                     return BOOLEAN;
459
460                 case 'V':
461                     return VOID;
462
463                 case '[':
464                     arrayDim++;
465                     break;
466                     
467                 default:
468                     throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
469             }
470         }
471         return null;
472     }
473     private int extractArgCount(char[] signature, char[] className) throws ClassFormatException {
474         int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
475         if (indexOfClosingParen == 1) {
476             // there is no parameter
477
return 0;
478         }
479         if (indexOfClosingParen == -1) {
480             throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
481         }
482         int parameterTypesCounter = 0;
483         for (int i = 1; i < indexOfClosingParen; i++) {
484             switch(signature[i]) {
485                 case 'B':
486                 case 'C':
487                 case 'D':
488                 case 'F':
489                 case 'I':
490                 case 'J':
491                 case 'S':
492                 case 'Z':
493                     parameterTypesCounter++;
494                     break;
495                 case 'L':
496                     int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
497                     if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
498                     // verify if first parameter is synthetic
499
if (className != null && parameterTypesCounter == 0) {
500                         char[] classSignature = Signature.createCharArrayTypeSignature(className, true);
501                         int length = indexOfSemiColon-i+1;
502                         if (classSignature.length > (length+1)) {
503                             // synthetic means that parameter type has same signature than given class
504
for (int j=i, k=0; j<indexOfSemiColon; j++, k++) {
505                                 if (!(signature[j] == classSignature[k] || (signature[j] == '/' && classSignature[k] == '.' ))) {
506                                     parameterTypesCounter++;
507                                     break;
508                                 }
509                             }
510                         } else {
511                             parameterTypesCounter++;
512                         }
513                         className = null; // do not verify following parameters
514
} else {
515                         parameterTypesCounter++;
516                     }
517                     i = indexOfSemiColon;
518                     break;
519                 case '[':
520                     break;
521                 default:
522                     throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
523             }
524         }
525         return parameterTypesCounter;
526     }
527     private char[] extractClassName(int[] constantPoolOffsets, ClassFileReader reader, int index) {
528         // the entry at i has to be a field ref or a method/interface method ref.
529
int class_index = reader.u2At(constantPoolOffsets[index] + 1);
530         int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[class_index] + 1)];
531         return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
532     }
533     private char[] extractName(int[] constantPoolOffsets, ClassFileReader reader, int index) {
534         int nameAndTypeIndex = reader.u2At(constantPoolOffsets[index] + 3);
535         int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[nameAndTypeIndex] + 1)];
536         return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
537     }
538     private char[] extractClassReference(int[] constantPoolOffsets, ClassFileReader reader, int index) {
539         // the entry at i has to be a class ref.
540
int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[index] + 1)];
541         return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
542     }
543     /**
544      * Extract all type, method, field and interface method references from the constant pool
545      */

546     private void extractReferenceFromConstantPool(byte[] contents, ClassFileReader reader) throws ClassFormatException {
547         int[] constantPoolOffsets = reader.getConstantPoolOffsets();
548         int constantPoolCount = constantPoolOffsets.length;
549         for (int i = 1; i < constantPoolCount; i++) {
550             int tag = reader.u1At(constantPoolOffsets[i]);
551             /**
552              * u1 tag
553              * u2 class_index
554              * u2 name_and_type_index
555              */

556             char[] name = null;
557             char[] type = null;
558             switch (tag) {
559                 case ClassFileConstants.FieldRefTag :
560                     // add reference to the class/interface and field name and type
561
name = extractName(constantPoolOffsets, reader, i);
562                     addFieldReference(name);
563                     break;
564                 case ClassFileConstants.MethodRefTag :
565                     // add reference to the class and method name and type
566
case ClassFileConstants.InterfaceMethodRefTag :
567                     // add reference to the interface and method name and type
568
name = extractName(constantPoolOffsets, reader, i);
569                     type = extractType(constantPoolOffsets, reader, i);
570                     if (CharOperation.equals(INIT, name)) {
571                         // get class name and see if it's a local type or not
572
char[] className = extractClassName(constantPoolOffsets, reader, i);
573                         boolean localType = false;
574                         if (className != null) {
575                             for (int c = 0, max = className.length; c < max; c++) {
576                                 switch (className[c]) {
577                                     case '/':
578                                         className[c] = '.';
579                                         break;
580                                     case '$':
581                                         localType = true;
582                                         break;
583                                 }
584                             }
585                         }
586                         // add a constructor reference, use class name to extract arg count if it's a local type to remove synthetic parameter
587
addConstructorReference(className, extractArgCount(type, localType?className:null));
588                     } else {
589                         // add a method reference
590
addMethodReference(name, extractArgCount(type, null));
591                     }
592                     break;
593                 case ClassFileConstants.ClassTag :
594                     // add a type reference
595
name = extractClassReference(constantPoolOffsets, reader, i);
596                     if (name.length > 0 && name[0] == '[')
597                         break; // skip over array references
598
name = replace('/', '.', name); // so that it looks like java.lang.String
599
addTypeReference(name);
600                     
601                     // also add a simple reference on each segment of the qualification (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=24741)
602
char[][] qualification = CharOperation.splitOn('.', name);
603                     for (int j = 0, length = qualification.length; j < length; j++) {
604                         addNameReference(qualification[j]);
605                     }
606                     break;
607             }
608         }
609     }
610     private char[] extractType(int[] constantPoolOffsets, ClassFileReader reader, int index) {
611         int constantPoolIndex = reader.u2At(constantPoolOffsets[index] + 3);
612         int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[constantPoolIndex] + 3)];
613         return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
614     }
615     public void indexDocument() {
616         try {
617             final byte[] contents = this.document.getByteContents();
618             // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=107124
619
// contents can potentially be null if a IOException occurs while retrieving the contents
620
if (contents == null) return;
621             final String JavaDoc path = this.document.getPath();
622             ClassFileReader reader = new ClassFileReader(contents, path == null ? null : path.toCharArray());
623     
624             // first add type references
625
char[] className = replace('/', '.', reader.getName()); // looks like java/lang/String
626
// need to extract the package name and the simple name
627
int packageNameIndex = CharOperation.lastIndexOf('.', className);
628             char[] packageName = null;
629             char[] name = null;
630             if (packageNameIndex >= 0) {
631                 packageName = CharOperation.subarray(className, 0, packageNameIndex);
632                 name = CharOperation.subarray(className, packageNameIndex + 1, className.length);
633             } else {
634                 packageName = CharOperation.NO_CHAR;
635                 name = className;
636             }
637             char[] enclosingTypeName = null;
638             boolean isNestedType = reader.isNestedType();
639             if (isNestedType) {
640                 if (reader.isAnonymous()) {
641                     name = CharOperation.NO_CHAR;
642                 } else {
643                     name = reader.getInnerSourceName();
644                 }
645                 if (reader.isLocal() || reader.isAnonymous()) {
646                     // set specific ['0'] value for local and anonymous to be able to filter them
647
enclosingTypeName = ONE_ZERO;
648                 } else {
649                     char[] fullEnclosingName = reader.getEnclosingTypeName();
650                     int nameLength = fullEnclosingName.length - packageNameIndex - 1;
651                     if (nameLength <= 0) {
652                         // See PR 1GIR345: ITPJCORE:ALL - Indexer: NegativeArraySizeException
653
return;
654                     }
655                     enclosingTypeName = new char[nameLength];
656                     System.arraycopy(fullEnclosingName, packageNameIndex + 1, enclosingTypeName, 0, nameLength);
657                 }
658             }
659             // type parameters
660
char[][] typeParameterSignatures = null;
661             char[] genericSignature = reader.getGenericSignature();
662             if (genericSignature != null) {
663                 CharOperation.replace(genericSignature, '/', '.');
664                 typeParameterSignatures = Signature.getTypeParameters(genericSignature);
665             }
666             
667             // eliminate invalid innerclasses (1G4KCF7)
668
if (name == null) return;
669             
670             char[][] superinterfaces = replace('/', '.', reader.getInterfaceNames());
671             char[][] enclosingTypeNames = enclosingTypeName == null ? null : new char[][] {enclosingTypeName};
672             int modifiers = reader.getModifiers();
673             switch (TypeDeclaration.kind(modifiers)) {
674                 case TypeDeclaration.CLASS_DECL :
675                     char[] superclass = replace('/', '.', reader.getSuperclassName());
676                     addClassDeclaration(modifiers, packageName, name, enclosingTypeNames, superclass, superinterfaces, typeParameterSignatures, false);
677                     break;
678                 case TypeDeclaration.INTERFACE_DECL :
679                     addInterfaceDeclaration(modifiers, packageName, name, enclosingTypeNames, superinterfaces, typeParameterSignatures, false);
680                     break;
681                 case TypeDeclaration.ENUM_DECL :
682                     superclass = replace('/', '.', reader.getSuperclassName());
683                     addEnumDeclaration(modifiers, packageName, name, enclosingTypeNames, superclass, superinterfaces, false);
684                     break;
685                 case TypeDeclaration.ANNOTATION_TYPE_DECL :
686                     addAnnotationTypeDeclaration(modifiers, packageName, name, enclosingTypeNames, false);
687                     break;
688             }
689
690             // Look for references in class annotations
691
IBinaryAnnotation[] annotations = reader.getAnnotations();
692             if (annotations != null) {
693                 for (int a=0, length=annotations.length; a<length; a++) {
694                     IBinaryAnnotation annotation = annotations[a];
695                     addBinaryAnnotation(annotation);
696                 }
697             }
698             long tagBits = reader.getTagBits() & TagBits.AllStandardAnnotationsMask;
699             if (tagBits != 0) {
700                 addBinaryStandardAnnotations(tagBits);
701             }
702
703             // first reference all methods declarations and field declarations
704
MethodInfo[] methods = (MethodInfo[]) reader.getMethods();
705             if (methods != null) {
706                 for (int i = 0, max = methods.length; i < max; i++) {
707                     MethodInfo method = methods[i];
708                     boolean isConstructor = method.isConstructor();
709                     char[] descriptor = method.getMethodDescriptor();
710                     char[][] parameterTypes = decodeParameterTypes(descriptor, isConstructor && isNestedType);
711                     char[] returnType = decodeReturnType(descriptor);
712                     char[][] exceptionTypes = replace('/', '.', method.getExceptionTypeNames());
713                     if (isConstructor) {
714                         addConstructorDeclaration(className, parameterTypes, exceptionTypes);
715                     } else {
716                         if (!method.isClinit()) {
717                             addMethodDeclaration(method.getSelector(), parameterTypes, returnType, exceptionTypes);
718                         }
719                     }
720                     // look for references in method annotations
721
annotations = method.getAnnotations();
722                     if (annotations != null) {
723                         for (int a=0, length=annotations.length; a<length; a++) {
724                             IBinaryAnnotation annotation = annotations[a];
725                             addBinaryAnnotation(annotation);
726                         }
727                     }
728                 }
729             }
730             FieldInfo[] fields = (FieldInfo[]) reader.getFields();
731             if (fields != null) {
732                 for (int i = 0, max = fields.length; i < max; i++) {
733                     FieldInfo field = fields[i];
734                     char[] fieldName = field.getName();
735                     char[] fieldType = decodeFieldType(replace('/', '.', field.getTypeName()));
736                     addFieldDeclaration(fieldType, fieldName);
737                     // look for references in field annotations
738
annotations = field.getAnnotations();
739                     if (annotations != null) {
740                         for (int a=0, length=annotations.length; a<length; a++) {
741                             IBinaryAnnotation annotation = annotations[a];
742                             addBinaryAnnotation(annotation);
743                         }
744                     }
745                 }
746             }
747             // record all references found inside the .class file
748
extractReferenceFromConstantPool(contents, reader);
749         } catch (ClassFormatException e) {
750             // ignore
751
this.document.removeAllIndexEntries();
752             Util.log(e, "ClassFormatException in " + this.document.getPath() + ". Please report this issue to JDT/Core including the problematic document"); //$NON-NLS-1$ //$NON-NLS-2$
753
} catch (RuntimeException JavaDoc e) {
754             // https://bugs.eclipse.org/bugs/show_bug.cgi?id=182154
755
// logging the entry that could not be indexed and continue with the next one
756
// we remove all entries relative to the boggus document
757
this.document.removeAllIndexEntries();
758             Util.log(e, "Indexer crashed on document " + this.document.getPath() + ". Please report this issue to JDT/Core including the problematic document"); //$NON-NLS-1$ //$NON-NLS-2$
759
}
760     }
761     /*
762      * Modify the array by replacing all occurences of toBeReplaced with newChar
763      */

764     private char[][] replace(char toBeReplaced, char newChar, char[][] array) {
765         if (array == null) return null;
766         for (int i = 0, max = array.length; i < max; i++) {
767             replace(toBeReplaced, newChar, array[i]);
768         }
769         return array;
770     }
771     /*
772      * Modify the array by replacing all occurences of toBeReplaced with newChar
773      */

774     private char[] replace(char toBeReplaced, char newChar, char[] array) {
775         if (array == null) return null;
776         for (int i = 0, max = array.length; i < max; i++) {
777             if (array[i] == toBeReplaced) {
778                 array[i] = newChar;
779             }
780         }
781         return array;
782     }
783 }
784
Popular Tags