Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: third_party/jmake/src/org/pantsbuild/jmake/ClassInfo.java

Issue 1373723003: Fix javac --incremental by using jmake for dependency analysis (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@aidl
Patch Set: fix license check Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /* Copyright (c) 2002-2008 Sun Microsystems, Inc. All rights reserved
2 *
3 * This program is distributed under the terms of
4 * the GNU General Public License Version 2. See the LICENSE file
5 * at the top of the source tree.
6 */
7 package org.pantsbuild.jmake;
8
9 import java.io.Serializable;
10 import java.lang.reflect.Modifier;
11 import java.util.ArrayList;
12 import java.util.LinkedHashSet;
13 import java.util.List;
14 import java.util.Set;
15
16 /**
17 * A reflection of a class, in the form that allows fast checks and information obtaining.
18 *
19 * @author Misha Dmitriev
20 * 5 April 2004
21 */
22 @SuppressWarnings("serial")
23 public class ClassInfo implements Serializable {
24
25 public static final int VER_OLD = 0; // Old version
26 public static final int VER_NEW = 1; // New version
27 public static final int NO_VERSIONS = 2; // Non-project class, no change tr acking
28 private transient PCDManager pcdm;
29 transient int verCode; // Version code for this Cla ssInfo - one of the above.
30 String name = null;
31 transient String packageName; // Package name; restored wh en database is reloaded
32 int javacTargetRelease = Utils.JAVAC_TARGET_RELEASE_OLDEST; // Can have valu es from Utils.JAVAC_TARGET_RELEASE_xxx
33 String cpoolRefsToClasses[]; // Directly referenced class names tri mmed of array and 'L' prefixes and ';' suffixes
34 boolean isRefClassArray[]; // Indicates if a directly referenced class is actually an array class
35 // In all signatures we replace the 'L' and ';' symbols that enclose non-pri mitive type names with '@' and '#' respectively,
36 // so that class names inside signatures can be located fast and unambiguous ly.
37 String cpoolRefsToFieldClasses[]; // Defining classes of referenced fiel ds, trimmed of enclosing 'L' and ';' symbols
38 String cpoolRefsToFieldNames[]; // Names of referenced fields
39 String cpoolRefsToFieldSignatures[]; // Signatures of referenced fields
40 String cpoolRefsToMethodClasses[]; // Defining classes of referenced meth ods, trimmed of enclosing 'L' and ';' symbols
41 String cpoolRefsToMethodNames[]; // Names of referenced methods
42 String cpoolRefsToMethodSignatures[]; // Signatures of referenced methods
43 char accessFlags; // isInterface flag included
44 boolean isNonMemberNestedClass = false; // True if this is a non-member nest ed class
45 String superName;
46 String interfaces[];
47 String fieldNames[];
48 String fieldSignatures[];
49 char fieldAccessFlags[];
50 Object primitiveConstantInitValues[];
51 String methodNames[];
52 String methodSignatures[];
53 char methodAccessFlags[];
54 String checkedExceptions[][];
55 transient ClassInfo directSubclasses[]; // Direct subclasses. Created lazily and not preserved on disk.
56 transient String directlyEnclosingClass; // Directly enclosing class na me; restored when database is reloaded
57 transient String topLevelEnclosingClass; // Top-level enclosing class n ame; restored when database is reloaded
58 String nestedClasses[]; // Names of all nested classes. Don't ma ke transient - it's used to check
59 // if nested classes for this class were added/deleted in new version
60 transient char nestedClassAccessFlags[]; // No need to store this infor mation permanently
61 transient boolean nestedClassNonMember[]; // Ditto
62
63 /** Creates new ClassInfo out of a class file. The last parameter is needed only to produce sensible error reports.*/
64 public ClassInfo(byte[] classFileBytes, int verCode, PCDManager pcdm, String classFileFullPath) {
65 this.pcdm = pcdm;
66 this.verCode = verCode;
67 pcdm.getClassFileReader().readClassFile(classFileBytes, this, classFileF ullPath, true);
68 packageName = Utils.getPackageName(name);
69 directlyEnclosingClass =
70 Utils.getDirectlyEnclosingClass(name, this.javacTargetRelease);
71 topLevelEnclosingClass = Utils.getTopLevelEnclosingClass(name);
72 }
73
74 /**
75 * Create a "lightweight" ClassInfo, that contains just the class name, supe r name, interfaces, flags and verCode.
76 * Used for non-project classes, that don't change themselves, for which we are only interested in type hierarchy structure.
77 */
78 public ClassInfo(byte[] classFileBytes, PCDManager pcdm, String classFileFul lPath) {
79 this.pcdm = pcdm;
80 this.verCode = NO_VERSIONS;
81 pcdm.getClassFileReader().readClassFile(classFileBytes, this, classFileF ullPath, false);
82 packageName = Utils.getPackageName(name);
83 directlyEnclosingClass =
84 Utils.getDirectlyEnclosingClass(name, this.javacTargetRelease);
85 topLevelEnclosingClass = Utils.getTopLevelEnclosingClass(name);
86 }
87
88 /** Even more lightweight variant - created for a deleted non-project class, to enable minimum possible checks. */
89 public ClassInfo(String name, PCDManager pcdm) {
90 this.pcdm = pcdm;
91 this.verCode = NO_VERSIONS;
92 this.name = name;
93 packageName = Utils.getPackageName(name);
94 directlyEnclosingClass = Utils.getDirectlyEnclosingClass(name, 0);
95 topLevelEnclosingClass = Utils.getTopLevelEnclosingClass(name);
96 }
97
98 public ClassInfo() {
99 }
100
101 /** Initialize transient data that can be initialized immediately after this ClassInfo is read from the project database */
102 public void initializeImmediateTransientFields() {
103 verCode = VER_OLD;
104
105 packageName = Utils.getPackageName(name);
106
107 directlyEnclosingClass =
108 Utils.getDirectlyEnclosingClass(name, this.javacTargetRelease);
109 topLevelEnclosingClass = Utils.getTopLevelEnclosingClass(name);
110 }
111
112 /**
113 * Called to restore the pointer to the current PCDManager after this ClassI nfo is brought back
114 * from the store.
115 */
116 public void restorePCDM(PCDManager pcdm) {
117 this.pcdm = pcdm;
118 }
119
120 public boolean isInterface() {
121 return Modifier.isInterface(accessFlags);
122 }
123
124 public boolean isAbstract() {
125 return Modifier.isAbstract(accessFlags);
126 }
127
128 public boolean isPublic() {
129 return Modifier.isPublic(accessFlags);
130 }
131
132 /**
133 * Returns the names of the superclasses of the given class (transitively), that belong
134 * to the same project, plus those of the superclasses that can be found on the class path
135 * supplied to jmake, and on the boot class path.
136 */
137 public List<String> getAllSuperclassNames() {
138 List<String> res = new ArrayList<String>();
139 String superName = this.superName;
140 while (superName != null && !"java/lang/Object".equals(superName)) {
141 res.add(superName);
142 ClassInfo classInfo = pcdm.getClassInfoForName(verCode, superName);
143 if (classInfo == null) { // Class not in project (or deleted?). Try to find it and further superclasses in non-project classes
144 ClassPath.getSuperclasses(superName, res, pcdm);
145 break;
146 }
147 superName = classInfo.superName;
148 }
149 return res;
150 }
151
152 /**
153 * Returns the set of names of the interfaces transitively implemented by th e given
154 * class, that belong to the same project.
155 */
156 public Set<String> getAllImplementedIntfNames() {
157 Set<String> res = new LinkedHashSet<String>();
158 addImplementedInterfaceNames(false, res);
159 return res;
160 }
161
162 /** Add to the given set the names of direct/all interfaces implemented by t he given class. */
163 private void addImplementedInterfaceNames(boolean directOnly,
164 Set<String> intfSet) {
165 if (interfaces != null) {
166 for (int i = 0; i < interfaces.length; i++) {
167 String superIntfName = interfaces[i];
168 intfSet.add(superIntfName);
169 if (directOnly) {
170 continue;
171 }
172 ClassInfo superIntfInfo =
173 pcdm.getClassInfoForName(verCode, superIntfName);
174 if (superIntfInfo == null) { // Class not in project
175 ClassPath.addAllImplementedInterfaceNames(superIntfName, int fSet, pcdm);
176 } else {
177 superIntfInfo.addImplementedInterfaceNames(false, intfSet);
178 }
179 }
180 }
181
182 if (directOnly || superName == null ||
183 "java/lang/Object".equals(superName)) {
184 return;
185 }
186 ClassInfo superInfo = pcdm.getClassInfoForName(verCode, superName);
187 if (superInfo == null) { // Class not in project
188 ClassPath.addAllImplementedInterfaceNames(superName, intfSet, pcdm);
189 } else {
190 superInfo.addImplementedInterfaceNames(false, intfSet);
191 }
192 }
193
194 /** Returns the array of all direct subclasses of this class (array of zero length if there are none). */
195 public ClassInfo[] getDirectSubclasses() {
196 if (directSubclasses != null) {
197 return directSubclasses;
198 }
199
200 List<ClassInfo> listRes = new ArrayList<ClassInfo>();
201
202 for (PCDEntry entry : pcdm.entries()) {
203 ClassInfo classInfo = pcdm.getClassInfoForPCDEntry(verCode, entry);
204 if (classInfo == null) {
205 continue; // New or deleted class, depending on verCode
206 }
207 if (classInfo.superName.equals(name)) {
208 listRes.add(classInfo);
209 }
210 }
211
212 directSubclasses = listRes.toArray(new ClassInfo[listRes.size()]);
213 return directSubclasses;
214 }
215
216 /** Check if the initial values for the given primitive constatnts in two cl asses are the same. */
217 public static boolean constFieldInitValuesEqual(ClassInfo oldClassInfo, int oldFieldNo,
218 ClassInfo newClassInfo, int newFieldNo) {
219 Object oldInitValue = oldClassInfo.primitiveConstantInitValues == null ? null
220 : oldClassInfo.primitiveConstantInitValues[oldFieldNo];
221 Object newInitValue = newClassInfo.primitiveConstantInitValues == null ? null
222 : newClassInfo.primitiveConstantInitValues[newFieldNo];
223 if (oldInitValue == newInitValue) {
224 return true;
225 }
226 if (oldInitValue == null || newInitValue == null) {
227 return false;
228 }
229
230 if (oldInitValue instanceof Integer) {
231 if (((Integer) oldInitValue).intValue() == ((Integer) newInitValue). intValue()) {
232 return true;
233 } else {
234 return false;
235 }
236 } else if (oldInitValue instanceof String) {
237 if ( ((String) oldInitValue).equals((String) newInitValue) ) {
238 return true;
239 } else {
240 return false;
241 }
242 } else if (oldInitValue instanceof Long) {
243 if (((Long) oldInitValue).longValue() == ((Long) newInitValue).longV alue()) {
244 return true;
245 } else {
246 return false;
247 }
248 } else if (oldInitValue instanceof Float) {
249 if (((Float) oldInitValue).floatValue() == ((Float) newInitValue).fl oatValue()) {
250 return true;
251 } else {
252 return false;
253 }
254 } else if (oldInitValue instanceof Double) {
255 if (((Double) oldInitValue).doubleValue() == ((Double) newInitValue) .doubleValue()) {
256 return true;
257 } else {
258 return false;
259 }
260 }
261
262 return true;
263 }
264
265 public boolean implementsInterfaceDirectly(String intfName) {
266 if (interfaces == null) {
267 return false;
268 }
269 for (int i = 0; i < interfaces.length; i++) {
270 if (intfName.equals(interfaces[i])) {
271 return true;
272 }
273 }
274 return false;
275 }
276
277 /** Check if this class implements interface I or any subinterface of I dire ctly */
278 public boolean implementsIntfOrSubintfDirectly(String intfName) {
279 if (interfaces == null) {
280 return false;
281 }
282 for (int i = 0; i < interfaces.length; i++) {
283 if (intfName.equals(interfaces[i])) {
284 return true;
285 }
286 // An interface can have multiple superinterfaces, all of which are listed in its "interfaces" array
287 // (although in the .java source it "extends" them all).
288 ClassInfo superIntfInfo =
289 pcdm.getClassInfoForName(verCode, interfaces[i]);
290 if (superIntfInfo == null) {
291 continue; // Class not in project
292 }
293 if (superIntfInfo.implementsIntfOrSubintfDirectly(intfName)) {
294 return true;
295 }
296 }
297 return false;
298 }
299
300 /**
301 * Class C implements interface I indirectly, if C or some superclass of C d irectly implements I
302 * or some subinterface of I.
303 */
304 public boolean implementsInterfaceDirectlyOrIndirectly(String intfName) {
305 if (interfaces == null) {
306 return false;
307 }
308
309 if (implementsIntfOrSubintfDirectly(intfName)) {
310 return true;
311 }
312
313 if (superName != null) {
314 ClassInfo superInfo = pcdm.getClassInfoForName(verCode, superName);
315 if (superInfo == null) {
316 return false; // Class not in project
317 }
318 return superInfo.implementsInterfaceDirectlyOrIndirectly(intfName);
319 }
320
321 return false;
322 }
323
324 /**
325 * Returns true if this class declares a field with the same name and type a s
326 * the field number fieldNo in class classInfo.
327 */
328 public boolean declaresField(ClassInfo classInfo, int fieldNo) {
329 if (fieldNames == null) {
330 return false;
331 }
332 String fieldName = classInfo.fieldNames[fieldNo];
333 String fieldSignature = classInfo.fieldSignatures[fieldNo];
334
335 for (int i = 0; i < fieldNames.length; i++) {
336 if (fieldName.equals(fieldNames[i]) &&
337 fieldSignature.equals(fieldSignatures[i])) {
338 return true;
339 }
340 }
341 return false;
342 }
343
344 /** Returns true if this class declares a field with the given name, signatu re and access */
345 public boolean declaresField(String name, String signature, boolean isStatic ) {
346 if (fieldNames == null) {
347 return false;
348 }
349 signature = ("@" + signature + "#").intern();
350 for (int i = 0; i < fieldNames.length; i++) {
351 if (name.equals(fieldNames[i]) &&
352 signature.equals(fieldSignatures[i]) &&
353 Modifier.isStatic(fieldAccessFlags[i]) == isStatic) {
354 return true;
355 }
356 }
357 return false;
358 }
359
360 /**
361 * Returns true if this class declares a method with the same name and signa ture as
362 * the method number methodNo in class classInfo.
363 */
364 public boolean declaresMethod(ClassInfo classInfo, int methodNo) {
365 if (methodNames == null) {
366 return false;
367 }
368 String methodName = classInfo.methodNames[methodNo];
369 String methodSignature = classInfo.methodSignatures[methodNo];
370
371 for (int i = 0; i < methodNames.length; i++) {
372 if (methodName.equals(methodNames[i]) &&
373 methodSignature.equals(methodSignatures[i])) {
374 return true;
375 }
376 }
377 return false;
378 }
379
380 /**
381 * If this class declares a method with the same name and signature as the g iven method,
382 * return its position. Otherwise, return -1.
383 */
384 public int getDeclaredMethodPos(ClassInfo classInfo, int methodNo) {
385 if (methodNames == null) {
386 return -1;
387 }
388 String methodName = classInfo.methodNames[methodNo];
389 String methodSignature = classInfo.methodSignatures[methodNo];
390
391 for (int i = 0; i < methodNames.length; i++) {
392 if (methodName.equals(methodNames[i]) &&
393 methodSignature.equals(methodSignatures[i])) {
394 return i;
395 }
396 }
397 return -1;
398 }
399
400 /**
401 * Returns a nonnegative number (position in the method array) if this class declares a method with the
402 * name methodName, and -1 otherwise.
403 */
404 public int declaresSameNameMethod(String methodName) {
405 if (methodNames == null) {
406 return -1;
407 }
408 for (int j = 0; j < methodNames.length; j++) {
409 if (methodName.equals(methodNames[j])) {
410 return j;
411 }
412 }
413 return -1;
414 }
415
416 /**
417 * Check if this class references the given class in different ways, dependi ng on thorDegree parameter.
418 * thorDegree = 0: the given class (but not its array class) directly from t he constantpool.
419 *
420 * thorDegree = 1: the given class or its array class directly from the cons tantpool, as a
421 * type of a data field, as a type in a method signature or a thrown excepti on, as a directly
422 * implemented interface or a direct superclass
423 *
424 * thorDegree = 2: the given class or its array class directly or indirectly from the
425 * constantpool, as a type of a data field, as a type in a method signature or a thrown exception,
426 * as a directly/indirectly implemented interface or a direct/indirect super class.
427 *
428 * isRefTypeInterface indicates whether className is an interface.
429 */
430 public boolean referencesClass(String className, boolean isRefTypeInterface, int thorDegree) {
431 int i;
432
433 if (thorDegree == 0) {
434 if (cpoolRefsToClasses == null) {
435 return false;
436 }
437 for (i = 0; i < cpoolRefsToClasses.length; i++) {
438 if (!isRefClassArray[i] &&
439 className.equals(cpoolRefsToClasses[i])) {
440 return true;
441 }
442 }
443 } else {
444 if (isSubclassOf(className, (thorDegree == 1))) {
445 return true;
446 }
447 if (isRefTypeInterface) {
448 if (thorDegree == 1) {
449 if (implementsInterfaceDirectly(className)) {
450 return true;
451 }
452 } else {
453 // Check for indirectly implemented interfaces
454 if (implementsInterfaceDirectlyOrIndirectly(className)) {
455 return true;
456 }
457 }
458 }
459
460 if (cpoolRefsToClasses != null) {
461 for (i = 0; i < cpoolRefsToClasses.length; i++) {
462 if (className.equals(cpoolRefsToClasses[i])) {
463 return true;
464 }
465 }
466 }
467 if (thorDegree == 2) {
468 // Check for indirect references from the constantpool
469 if (cpoolRefsToFieldSignatures != null) {
470 for (i = 0; i < cpoolRefsToFieldSignatures.length; i++) {
471 if (signatureIncludesClassName(cpoolRefsToFieldSignature s[i], className)) {
472 return true;
473 }
474 }
475 }
476 if (cpoolRefsToMethodNames != null) {
477 for (i = 0; i < cpoolRefsToMethodSignatures.length; i++) {
478 if (signatureIncludesClassName(cpoolRefsToMethodSignatur es[i], className)) {
479 return true;
480 }
481 }
482 }
483 }
484
485 if (fieldSignatures != null) {
486 for (i = 0; i < fieldSignatures.length; i++) {
487 if (signatureIncludesClassName(fieldSignatures[i], className )) {
488 return true;
489 }
490 }
491 }
492 if (methodSignatures != null) {
493 for (i = 0; i < methodSignatures.length; i++) {
494 if (signatureIncludesClassName(methodSignatures[i], classNam e)) {
495 return true;
496 }
497 }
498 }
499 if (checkedExceptions != null) {
500 for (i = 0; i < checkedExceptions.length; i++) {
501 if (checkedExceptions[i] != null) {
502 String excArray[] = checkedExceptions[i];
503 for (int j = 0; j < excArray.length; j++) {
504 if (className.equals(excArray[j])) {
505 return true;
506 }
507 }
508 }
509 }
510 }
511 }
512
513 return false;
514 }
515
516 private static boolean signatureIncludesClassName(String signature, String c lassName) {
517 int stIndex = signature.indexOf(className);
518 if (stIndex == -1) {
519 return false;
520 }
521 return ((stIndex != 0 && signature.charAt(stIndex - 1) == '@' && signatu re.charAt(stIndex + className.length()) == '#') ||
522 (stIndex == 0 && signature.length() == className.length()));
523 }
524
525 public boolean isSubclassOf(String className, boolean directOnly) {
526 if (className.equals(superName)) {
527 return true;
528 }
529 if (directOnly) {
530 return false;
531 }
532 String superName = this.superName;
533 while (superName != null) {
534 if (className.equals(superName)) {
535 return true;
536 }
537 ClassInfo classInfo = pcdm.getClassInfoForName(verCode, superName);
538 if (classInfo == null) {
539 break; // Class not in project
540 }
541 superName = classInfo.superName;
542 }
543 return false;
544 }
545
546 /**
547 * Check if this class references field number fieldNo of class fieldDefClas sInfo. Let us call
548 * this field C.f. Actual reference contained in the constant pool may be no t to C.f itself,
549 * but to Csub.f, where Csub is some subclass of C such that neither Csub no r any other class
550 * located between C and Csub in the class hierarchy redeclares f. We look u p both "real"
551 * references C.f and "fake" references such as Csub.f.
552 */
553 public boolean referencesField(ClassInfo fieldDefClassInfo, int fieldNo) {
554 if (cpoolRefsToFieldNames == null) {
555 return false;
556 }
557 String fieldDefClassName = fieldDefClassInfo.name;
558 String fieldName = fieldDefClassInfo.fieldNames[fieldNo];
559 String fieldSig = fieldDefClassInfo.fieldSignatures[fieldNo];
560 for (int i = 0; i < cpoolRefsToFieldNames.length; i++) {
561 if (fieldName.equals(cpoolRefsToFieldNames[i]) &&
562 fieldSig.equals(cpoolRefsToFieldSignatures[i]) ) {
563 if (fieldDefClassName.equals(cpoolRefsToFieldClasses[i]) ) {
564 return true; // "real" reference
565 } else { // Check if this is a "fake" reference that resolves t o the above "real" reference
566 ClassInfo classInThisCpool =
567 pcdm.getClassInfoForName(verCode, cpoolRefsToFieldCl asses[i]);
568 if (classInThisCpool == null) {
569 continue; // Class not in project
570 }
571 if (!classInThisCpool.isSubclassOf(fieldDefClassInfo.name, f alse)) {
572 continue;
573 }
574
575 // Ok, now check that this field is not actually redeclared in fieldDefClassInfo or
576 // somewhere in between it and classInThisCpool
577 boolean redeclared = false;
578 ClassInfo curClass = classInThisCpool;
579 do {
580 if (curClass.declaresField(fieldDefClassInfo, fieldNo)) {
581 redeclared = true;
582 break;
583 }
584 String superName = curClass.superName;
585 curClass = pcdm.getClassInfoForName(verCode, superName);
586 if (curClass == null) {
587 break;
588 }
589 } while (curClass != fieldDefClassInfo);
590 if (!redeclared) {
591 return true;
592 }
593 }
594 }
595 }
596 return false;
597 }
598
599 /**
600 * Check if this class references method number methodNo of class methodDefC lassInfo. Let us
601 * call this method C.m. Actual reference contained in the constant pool may be not to C.m
602 * itself, but to Csub.m, where Csub is some subclass of C such that neither Csub nor any
603 * other class located between C and Csub in the class hierarchy redeclares m. We look up
604 * both "real" references C.m and "fake" references such as Csub.m.
605 */
606 public boolean referencesMethod(ClassInfo methodDefClassInfo, int methodNo) {
607 if (cpoolRefsToMethodNames == null) {
608 return false;
609 }
610 String methodDefClassName = methodDefClassInfo.name;
611 String methodName = methodDefClassInfo.methodNames[methodNo];
612 String methodSig = methodDefClassInfo.methodSignatures[methodNo];
613 for (int i = 0; i < cpoolRefsToMethodNames.length; i++) {
614 if (methodName.equals(cpoolRefsToMethodNames[i]) &&
615 methodSig.equals(cpoolRefsToMethodSignatures[i])) {
616 if (methodDefClassName.equals(cpoolRefsToMethodClasses[i])) {
617 return true; // "real" reference
618 } else { // Check if this is a "fake" reference that resolves t o the above "real" reference
619 // Be careful - class in the cpool may be not a project clas s (e.g. a core class).
620 ClassInfo classInThisCpool =
621 pcdm.getClassInfoForName(verCode, cpoolRefsToMethodC lasses[i]);
622 if (classInThisCpool == null) {
623 continue; // Class not in project
624 }
625 if (classInThisCpool.isSubclassOf(methodDefClassInfo.name, f alse)) {
626 // Ok, now check that this method is not actually redecl ared in classInThisCpool (which is
627 // lower in the hierarchy) or somewhere in between it an d classInThisCpool
628 boolean redeclared = false;
629 ClassInfo curClass = classInThisCpool;
630 do {
631 if (curClass.declaresMethod(methodDefClassInfo, meth odNo)) {
632 redeclared = true;
633 break;
634 }
635 String superName = curClass.superName;
636 curClass =
637 pcdm.getClassInfoForName(verCode, superName) ;
638 if (curClass == null) {
639 break;
640 }
641 } while (curClass != methodDefClassInfo);
642 if (!redeclared) {
643 return true;
644 }
645 } else if (methodDefClassInfo.isInterface() && classInThisCp ool.implementsIntfOrSubintfDirectly(methodDefClassName)) {
646 return true;
647 }
648 }
649 }
650 }
651 return false;
652 }
653
654 /**
655 * If this class has a method that throws the given exception, return its in dex. Otherwise return -1.
656 * The search starts from method with index startMethodIdx.
657 */
658 public int hasMethodThrowingException(ClassInfo excClassInfo, int startMetho dIdx) {
659 if (checkedExceptions == null) {
660 return -1;
661 }
662 if (startMethodIdx >= checkedExceptions.length) {
663 return -1;
664 }
665 String excName = excClassInfo.name;
666 for (int i = startMethodIdx; i < checkedExceptions.length; i++) {
667 if (checkedExceptions[i] == null) {
668 continue;
669 }
670 String[] exc = checkedExceptions[i];
671 for (int j = 0; j < exc.length; j++) {
672 if (exc[j].equals(excName)) {
673 return i;
674 }
675 }
676 }
677 return -1;
678 }
679
680 public static abstract class MethodHandler {
681
682 abstract void handleMethod(ClassInfo ci, int methodIdx);
683 }
684
685 /**
686 * Check this class and all its superclasses (if includeSuperclasses == true ) and superinterfaces (if includeInterfaces == true)
687 * for a method with the given name. If such a method is found, call h.handl eMethod(classInfo, methodIdx).
688 */
689 public void findExistingSameNameMethods(String methodName, boolean includeSu perclasses, boolean includeInterfaces, MethodHandler h) {
690 String className = name;
691 ClassInfo classInfo;
692 while (className != null) {
693 classInfo = pcdm.getClassInfoForName(verCode, className);
694 if (classInfo == null) {
695 break; // Class not in project
696 }
697 String mNames[] = classInfo.methodNames;
698 int mNamesLen = mNames != null ? mNames.length : 0;
699 for (int i = 0; i < mNamesLen; i++) {
700 if (methodName.equals(mNames[i])) {
701 h.handleMethod(classInfo, i);
702 }
703 }
704 if (includeInterfaces && classInfo.interfaces != null) {
705 String intfNames[] = classInfo.interfaces;
706 for (int i = 0; i < intfNames.length; i++) {
707 ClassInfo superIntfInfo =
708 pcdm.getClassInfoForName(verCode, intfNames[i]);
709 if (superIntfInfo == null) {
710 continue; // Class not in project
711 }
712 superIntfInfo.findExistingSameNameMethods(methodName, true, includeInterfaces, h);
713 }
714 }
715 if (includeSuperclasses) {
716 className = classInfo.superName;
717 } else {
718 return;
719 }
720 }
721 }
722
723 public static boolean isPrimitiveFieldSig(String fieldSig) {
724 return fieldSig.indexOf('@') == -1;
725 }
726
727 /**
728 * Check if the given signature is of a class type, and that class does not belong to the project.
729 * It used to be a check for just a core type name, but sometimes people use JDK sources as e.g. a test
730 * case - so better perform a universal (and entirely correct, unlike just a core type name) test here.
731 */
732 public boolean isNonProjectClassTypeFieldSig(String fieldSig) {
733 int stPos = fieldSig.indexOf('@');
734 if (stPos == -1) {
735 return false;
736 }
737 int endPos = fieldSig.indexOf('#');
738 String className = fieldSig.substring(stPos + 1, endPos);
739 return (!pcdm.isProjectClass(verCode, className));
740 }
741
742 /** For debugging. */
743 public String toString() {
744 return name + (verCode == VER_OLD ? " OLD" : " NEW");
745 }
746 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698