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

Side by Side Diff: third_party/jmake/src/org/pantsbuild/jmake/RefClassFinder.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.lang.reflect.Modifier;
10 import java.util.LinkedHashSet;
11 import java.util.Set;
12
13 /**
14 * This class implements finding classes referencing other classes and members i n various ways.
15 *
16 * @author Misha Dmitriev
17 * 12 March 2004
18 */
19 public class RefClassFinder {
20
21 private boolean failOnDependentJar; // If true, will fail if a dependency of a sourceless class
22 // (coming from a .jar) on a "normal" class is detected
23 private boolean noWarnOnDependentJar; // If true, not even a warning will be issued in the above case.
24 private String checkedClassName;
25 private PCDManager pcdm;
26 private Set<String> affectedClassNames;
27 private boolean checkedClassIsFromJar;
28
29 /** An instance of RefClassFinder is created once per session, passing it th e global options that do not change */
30 public RefClassFinder(PCDManager pcdm, boolean failOnDependentJar, boolean n oWarnOnDependentJar) {
31 this.pcdm = pcdm;
32 this.failOnDependentJar = failOnDependentJar;
33 this.noWarnOnDependentJar = noWarnOnDependentJar;
34 }
35
36 /** This method is called every time we are going to check a new class */
37 public void initialize(String checkedClassName, boolean checkedClassIsFromJa r) {
38 this.checkedClassName = checkedClassName;
39 this.checkedClassIsFromJar = checkedClassIsFromJar;
40 affectedClassNames = new LinkedHashSet<String>();
41 }
42
43 /**
44 * Returns the names of project classes that were found potentially affec
45 * by the changes to the checked class.
46 */
47 public String[] getAffectedClassNames() {
48 int size = affectedClassNames.size();
49 if (size == 0) {
50 return null;
51 } else {
52 String[] ret = new String[size];
53 int i = 0;
54 for (String className : affectedClassNames) {
55 ret[i++] = className;
56 }
57 return ret;
58 }
59 }
60
61 /**
62 * Find all project classes that can access field fieldNo of class fieldClas sInfo.
63 * Used if a compile-time constant is changed.
64 */
65 public void findAllProjectClasses(ClassInfo fieldClassInfo, int fieldNo) {
66 for (PCDEntry pcde : pcdm.entries()) {
67 if (pcde.checkResult == PCDEntry.CV_DELETED) {
68 continue;
69 }
70 if (pcde.javaFileFullPath.endsWith(".jar")) {
71 continue;
72 }
73 ClassInfo clientInfo =
74 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
75 if (clientInfo == null) {
76 continue; // New class
77 }
78 if (memberAccessibleFrom(fieldClassInfo, fieldNo, clientInfo, true)) {
79 addToAffectedClassNames(clientInfo.name);
80 }
81 }
82 }
83
84 /**
85 * Find all project classes that reference class with the given name
86 * (but not its array class) directly from the constantpool.
87 */
88 public void findReferencingClasses0(ClassInfo classInfo) {
89 findReferencingClasses(classInfo, 0, false, null);
90 }
91
92
93 /* In the following "find...ReferencingClasses1" methods, "referencing C" me ans
94 * "referencing C or its array class directly from the constant pool, as a t ype of a data
95 * field, as a type in a method signature or a thrown exception, as a direct ly implemented
96 * interface or a direct superclass".
97 */
98 /** Used for deleted classes. */
99 public void findReferencingClassesForDeletedClass(ClassInfo classInfo) {
100 String packageName = classInfo.packageName;
101 boolean isPublic = classInfo.isPublic();
102 boolean isInterface = classInfo.isInterface();
103 for (PCDEntry pcde : pcdm.entries()) {
104 ClassInfo clientInfo =
105 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
106 if (clientInfo == null) {
107 continue; // New class
108 }
109 if (!isPublic && packageName.equals(clientInfo.packageName)) {
110 continue;
111 }
112 if (clientInfo.referencesClass(classInfo.name, isInterface, 1)) {
113 addToAffectedClassNames(clientInfo.name);
114 }
115 }
116
117 }
118
119 /**
120 * For the given class p.C, find each project class X referencing C, that is not a member of
121 * package p and is not a direct or indirect subclass of C's directly enclos ing class.
122 * (public -&gt; protected transformation)
123 */
124 public void findDiffPackageAndNotSubReferencingClasses1(ClassInfo classInfo) {
125 String packageName = classInfo.packageName;
126 String directlyEnclosingClass = classInfo.directlyEnclosingClass;
127 for (PCDEntry pcde : pcdm.entries()) {
128 ClassInfo clientInfo =
129 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
130 if (clientInfo == null) {
131 continue; // New class
132 }
133 if (packageName.equals(clientInfo.packageName) ||
134 clientInfo.isSubclassOf(directlyEnclosingClass, false)) {
135 continue;
136 }
137 if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface (), 1)) {
138 addToAffectedClassNames(clientInfo.name);
139 }
140 }
141 }
142
143 /**
144 * For class p.C, find each project class X referencing C, whose top level e nclosing
145 * class is different from that of C.
146 * (public -&gt; private transformation)
147 */
148 public void findReferencingClasses1(ClassInfo classInfo) {
149 String topLevelEnclosingClass = classInfo.topLevelEnclosingClass;
150 for (PCDEntry pcde : pcdm.entries()) {
151 ClassInfo clientInfo =
152 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
153 if (clientInfo == null) {
154 continue; // New class
155 }
156 if (topLevelEnclosingClass.equals(clientInfo.topLevelEnclosingClass) ) {
157 continue;
158 }
159 if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface (), 1)) {
160 addToAffectedClassNames(clientInfo.name);
161 }
162 }
163 }
164
165 /**
166 * For class p.C, find each project class X referencing C, whose direct or i ndirect superclass
167 * is C's directly enclosing class, or which is a member of package p, whose top level enclosing
168 * class is different from that of C.
169 * (protected -&gt; private transformation)
170 */
171 public void findThisPackageOrSubReferencingClasses1(ClassInfo classInfo) {
172 String directlyEnclosingClass = classInfo.directlyEnclosingClass;
173 String topLevelEnclosingClass = classInfo.topLevelEnclosingClass;
174 String packageName = classInfo.packageName;
175 for (PCDEntry entry : pcdm.entries()) {
176 ClassInfo clientInfo =
177 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, entry);
178 if (clientInfo == null) {
179 continue; // New class
180 }
181 if ((!clientInfo.packageName.equals(packageName)) &&
182 !clientInfo.isSubclassOf(directlyEnclosingClass, false)) {
183 continue;
184 }
185 if (clientInfo.topLevelEnclosingClass.equals(topLevelEnclosingClass) ) {
186 continue;
187 }
188 if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface (), 1)) {
189 addToAffectedClassNames(clientInfo.name);
190 }
191 }
192 }
193
194 /**
195 * For class p.C, find each project class X referencing C, which is a member of package p and whose
196 * top level enclosing class is different from that of C.
197 * (default -&gt; private transformation)
198 */
199 public void findThisPackageReferencingClasses1(ClassInfo classInfo) {
200 String topLevelEnclosingClass = classInfo.topLevelEnclosingClass;
201 String packageName = classInfo.packageName;
202 for (PCDEntry entry : pcdm.entries()) {
203 ClassInfo clientInfo =
204 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD,
205 entry);
206 if (clientInfo == null) {
207 continue; // New class
208 }
209 if (!clientInfo.packageName.equals(packageName)) {
210 continue;
211 }
212 if (topLevelEnclosingClass.equals(clientInfo.topLevelEnclosingClass) ) {
213 continue;
214 }
215 if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface (), 1)) {
216 addToAffectedClassNames(clientInfo.name);
217 }
218 }
219 }
220
221 /**
222 * For class p.C, find each project class X referencing C, which is not a me mber of package p.
223 * (public -&gt; default transformation)
224 */
225 public void findDiffPackageReferencingClasses1(ClassInfo classInfo) {
226 String packageName = classInfo.packageName;
227 for (PCDEntry pcde : pcdm.entries()) {
228 ClassInfo clientInfo =
229 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
230 if (clientInfo == null) {
231 continue; // New class
232 }
233 if (clientInfo.packageName.equals(packageName)) {
234 continue;
235 }
236 if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface (), 1)) {
237 addToAffectedClassNames(clientInfo.name);
238 }
239 }
240 }
241
242 /**
243 * For class p.C, find each project class X referencing C, which is not a me mber of package p and
244 * whose direct or indirect superclass is C's directly enclosing class.
245 * (protected -&gt; default transformation)
246 */
247 public void findDiffPackageAndSubReferencingClasses1(ClassInfo classInfo) {
248 String packageName = classInfo.packageName;
249 String directlyEnclosingClass = classInfo.directlyEnclosingClass;
250 for (PCDEntry pcde : pcdm.entries()) {
251 ClassInfo clientInfo =
252 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
253 if (clientInfo == null) {
254 continue; // New class
255 }
256 if (clientInfo.packageName.equals(packageName)) {
257 continue;
258 }
259 if (!clientInfo.isSubclassOf(directlyEnclosingClass, false)) {
260 continue;
261 }
262 if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface (), 1)) {
263 addToAffectedClassNames(clientInfo.name);
264 }
265 }
266 }
267
268 /**
269 * Find all project classes that reference both of the classes with the
270 * given names (or array classes of one or both) directly or indirectly from the
271 * constantpool, as a type of a data field, as a type in a method signature or a
272 * thrown exception, as a directly/indirectly implemented interface or a
273 * direct/indirect superclass.
274 */
275 public void findReferencingClasses2(ClassInfo classInfo1, ClassInfo classInf o2) {
276 Set<String> refClazz1 = new LinkedHashSet<String>();
277 findReferencingClasses(classInfo1, 2, false, refClazz1);
278 Set<String> refClazz2 = new LinkedHashSet<String>();
279 findReferencingClasses(classInfo2, 2, false, refClazz2);
280
281 for (String className1 : refClazz1) {
282 if (refClazz2.contains(className1)) {
283 addToAffectedClassNames(className1);
284 }
285 }
286 }
287
288 /** Find all project classes which are direct subclasses of the given class */
289 public void findDirectSubclasses(ClassInfo classInfo) {
290 for (ClassInfo subclassInfo : classInfo.getDirectSubclasses()) {
291 addToAffectedClassNames(subclassInfo.name);
292 }
293 }
294
295 /**
296 * Find all non-abstract project classes that implement the given interface or any of its
297 * subclasses directly, and all non-abstract classes that are direct descend ants of abstract
298 * classes that implement the given interface directly or indirectly. Class C implements
299 * interface I indirectly, if C or some superclass of C directly implements I or some sublcass of I.
300 */
301 public void findDirectlyAndOtherwiseImplementingConcreteClasses(ClassInfo in tfInfo) {
302 for (PCDEntry entry : pcdm.entries()) {
303 ClassInfo clientInfo =
304 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, entry);
305 if (clientInfo == null) {
306 continue; // New class
307 }
308 if (clientInfo.isInterface()) {
309 continue;
310 }
311 if (clientInfo.isAbstract()) {
312 if (clientInfo.implementsInterfaceDirectlyOrIndirectly(intfInfo. name)) {
313 findAllNearestConcreteSubclasses(clientInfo);
314 }
315 } else {
316 if (clientInfo.implementsIntfOrSubintfDirectly(intfInfo.name)) {
317 addToAffectedClassNames(clientInfo.name);
318 }
319 }
320 }
321 }
322
323 private void findAllNearestConcreteSubclasses(ClassInfo classInfo) {
324 for (ClassInfo subclassInfo : classInfo.getDirectSubclasses()) {
325 if (subclassInfo.isAbstract()) {
326 findAllNearestConcreteSubclasses(subclassInfo);
327 } else {
328 addToAffectedClassNames(subclassInfo.name);
329 }
330 }
331 }
332
333 /**
334 * Find all interfaces and abstract classes that implement the given interfa ce and declare or inherit
335 * a method with the given name. For those that overload this method, find r eferencing classes.
336 */
337 public void findAbstractSubtypesWithSameNameMethod(ClassInfo intfInfo, Strin g mName, final String mSig) {
338 for (PCDEntry pcde : pcdm.entries()) {
339 ClassInfo ci =
340 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
341 if (ci == null) {
342 continue; // New class or not in project
343 }
344 if (!(ci.isInterface() || ci.isAbstract())) {
345 continue;
346 }
347 if (ci.implementsInterfaceDirectlyOrIndirectly(intfInfo.name)) {
348 addToAffectedClassNames(ci.name);
349 // Check if the new method overloads an existing (declared or in herited) method. Overloading test is rough -
350 // we just check if the number of parameters is the same.
351 ci.findExistingSameNameMethods(mName, true, true, new ClassInfo. MethodHandler() {
352
353 void handleMethod(ClassInfo classInfo, int otherMethodIdx) {
354 String otherMSig =
355 classInfo.methodSignatures[otherMethodIdx];
356 if ( (!mSig.equals(otherMSig)) &&
357 Utils.sameParamNumber(mSig, otherMSig)) {
358 findReferencingClassesForMethod(classInfo, otherMeth odIdx);
359 }
360 }
361 });
362 }
363 }
364 }
365
366 /** Find all project classes that reference the given field. */
367 public void findReferencingClassesForField(ClassInfo classInfo, int fieldNo) {
368 findReferencingClassesForMember(classInfo, fieldNo, true, false, false);
369 }
370
371 /**
372 * Find all project classes that reference the given field and which are in
373 * different packages.
374 */
375 public void findDiffPackageReferencingClassesForField(ClassInfo classInfo, i nt fieldNo) {
376 findReferencingClassesForMember(classInfo, fieldNo, true, true, false);
377 }
378
379 /**
380 * Find all project classes that reference the given field, which are in dif ferent
381 * packages and are direct or indirect subclasses of the member's declaring class
382 * (protected -&gt; default transformation).
383 */
384 public void findDiffPackageAndSubReferencingClassesForField(ClassInfo classI nfo, int fieldNo) {
385 findReferencingClassesForMember(classInfo, fieldNo, true, true, true);
386 }
387
388 /** Find all project classes that reference the given method. */
389 public void findReferencingClassesForMethod(ClassInfo classInfo, int methodN o) {
390 findReferencingClassesForMember(classInfo, methodNo, false, false, false );
391 }
392
393 /**
394 * Find all project classes that reference the given method and which are in
395 * different packages.
396 */
397 public void findDiffPackageReferencingClassesForMethod(ClassInfo classInfo, int methodNo) {
398 findReferencingClassesForMember(classInfo, methodNo, false, true, false) ;
399 }
400
401 /**
402 * Find all project classes that reference the given method, which are in di fferent
403 * packages and are direct or indirect subclasses of the member's declaring class
404 * (protected -&gt; default transformation)
405 */
406 public void findDiffPackageAndSubReferencingClassesForMethod(ClassInfo class Info, int methodNo) {
407 findReferencingClassesForMember(classInfo, methodNo, false, true, true);
408 }
409
410 /**
411 * Find all project classes that re-implement the given method and that are
412 * direct/indirect subclasses of this method's declaring class. If some subc lass C
413 * re-implements the given method, we don't have to search C's subclasses fu rther.
414 */
415 public void findSubclassesReimplementingMethod(ClassInfo classInfo, int meth odNo) {
416 findSubclassesReimplementingMethod(classInfo, classInfo, methodNo);
417 }
418
419 private void findSubclassesReimplementingMethod(ClassInfo targetClass, Class Info methodDeclaringClass, int methodNo) {
420 for (ClassInfo subclass : targetClass.getDirectSubclasses()) {
421 if (subclass.declaresMethod(methodDeclaringClass, methodNo)) {
422 addToAffectedClassNames(subclass.name);
423 } else {
424 findSubclassesReimplementingMethod(subclass, methodDeclaringClas s, methodNo);
425 }
426 }
427 }
428
429 /**
430 * For a given class C, find all concrete direct subclasses, and all direct concrente subclasses of C's direct
431 * or indirect abstract subclasses.
432 */
433 public void findConcreteSubclasses(ClassInfo targetClass) {
434 for (ClassInfo subclass : targetClass.getDirectSubclasses()) {
435 if (subclass.isAbstract()) {
436 findConcreteSubclasses(subclass);
437 } else {
438 addToAffectedClassNames(subclass.name);
439 }
440 }
441 }
442
443 /**
444 * Find any concrete subclasses of targetClass that don't override or inheri t a concrete implementation
445 * of the given method.
446 */
447 public void findConcreteSubclassesNotOverridingAbstractMethod(ClassInfo targ etClass, ClassInfo methodDeclaringClass, int methodNo) {
448 for (ClassInfo subclass : targetClass.getDirectSubclasses()) {
449 int pos =
450 subclass.getDeclaredMethodPos(methodDeclaringClass, methodNo );
451 if (pos == -1) { // This method is not overridden in this class
452 if (!subclass.isAbstract()) {
453 addToAffectedClassNames(subclass.name);
454 } else {
455 findConcreteSubclassesNotOverridingAbstractMethod(subclass, methodDeclaringClass, methodNo);
456 }
457 } else { // A chance that this method is declared abstract once agai n...
458 if (Modifier.isAbstract(subclass.methodAccessFlags[pos])) {
459 findConcreteSubclassesNotOverridingAbstractMethod(subclass, methodDeclaringClass, methodNo);
460 }
461 }
462 }
463 }
464
465 /** Find all project classes that reference any method that throws the given exception. */
466 public void findRefsToMethodsThrowingException(ClassInfo excClassInfo) {
467 for (PCDEntry pcde : pcdm.entries()) {
468 ClassInfo classInfo =
469 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
470 if (classInfo == null) {
471 continue; // New class
472 }
473 int methodIdx = -1;
474 do {
475 methodIdx =
476 classInfo.hasMethodThrowingException(excClassInfo, metho dIdx + 1);
477 if (methodIdx != -1) {
478 findReferencingClassesForMethod(classInfo, methodIdx);
479 }
480 } while (methodIdx != -1);
481 }
482 }
483
484 /**
485 * Find all project classes declaring a static field with the given name. Cu rrently used only to look up
486 * classes referencing given class X via the "X.class" construct.
487 */
488 public void findClassesDeclaringField(String name, String signature, boolean isStatic, String packageToLookIn) {
489 for (PCDEntry pcde : pcdm.entries()) {
490 ClassInfo classInfo =
491 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
492 if (classInfo == null) {
493 continue; // New class
494 }
495 if (packageToLookIn != null &&
496 !classInfo.packageName.equals(packageToLookIn)) {
497 continue;
498 }
499 if (classInfo.declaresField(name, signature, isStatic)) {
500 addToAffectedClassNames(classInfo.name);
501 }
502 }
503 }
504
505 public void addToAffectedClassNames(String className) {
506 String res = pcdm.classAlreadyRecompiledOrUncompileable(className);
507 if (res == null) {
508 affectedClassNames.add(className);
509 } else if (!"".equals(res)) { // The dependent class comes from a .jar.
510 if (checkedClassIsFromJar || noWarnOnDependentJar) {
511 return;
512 }
513 String message = "Class " + className + " is affected by a change to " + checkedClassName + ", but can't be recompiled, " +
514 "since it is located in archive " + res;
515 if (failOnDependentJar) {
516 throw new PrivateException(new PublicExceptions.JarDependsOnSour ceException(message));
517 } else {
518 Utils.printWarningMessage("Warning: " + message);
519 }
520 }
521 }
522
523 /**
524 * Find all project classes that reference the class with the given name.
525 * The second parameter controls the "thoroughness degree", and its value is passed to ClassInfo.referencesClass()
526 * method (see the comment to it). The fromDiffPackages parameter defines wh ether all such classes
527 * or only classes from different packages are required.
528 */
529 private void findReferencingClasses(ClassInfo classInfo,
530 int thorDegree, boolean fromDiffPackages,
531 Set<String> ret) {
532 String packageName = classInfo.packageName;
533 for (PCDEntry pcde : pcdm.entries()) {
534 ClassInfo clientInfo =
535 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
536 if (clientInfo == null) {
537 continue; // New class
538 }
539 if (fromDiffPackages && packageName.equals(clientInfo.packageName)) {
540 continue;
541 }
542 // If thorDegree == 2, i.e. indirect references from the constantpoo l (e.g. a reference to a method which
543 // has classInfo as one of its formal parameter types) are taken int o account, then we should check all of
544 // the classes, whether classInfo is directly accessible from them o r not.
545 if (thorDegree != 2 && (!classAccessibleFrom(classInfo, clientInfo)) ) {
546 continue;
547 }
548
549 if (clientInfo.referencesClass(classInfo.name, classInfo.isInterface (), thorDegree)) {
550 if (ret == null) {
551 addToAffectedClassNames(clientInfo.name);
552 } else {
553 ret.add(clientInfo.name);
554 }
555 }
556 }
557 }
558
559 /**
560 * Find all project classes that reference the given member. If fromDiffPack ages
561 * is true, then only classes that do not belong to the package of the membe r's
562 * declaring class should be returned. If onlySubclasses is true, then only
563 * classes that are subclasses of member's declaring class should be returne d.
564 */
565 private void findReferencingClassesForMember(ClassInfo declaringClassInfo, i nt memberNo,
566 boolean isField,
567 boolean fromDiffPackages, boolean onlySubclasses) {
568 String declaringClassName = declaringClassInfo.name;
569 String declaringClassPackage = declaringClassInfo.packageName;
570 for (PCDEntry pcde : pcdm.entries()) {
571 ClassInfo clientInfo =
572 pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, pcde);
573 if (clientInfo == null) {
574 continue; // New class
575 }
576 String className = clientInfo.name;
577 if (className.equals(declaringClassName)) {
578 continue;
579 }
580 if (!memberAccessibleFrom(declaringClassInfo, memberNo, clientInfo, isField)) {
581 continue;
582 }
583 if (fromDiffPackages &&
584 declaringClassPackage.equals(clientInfo.packageName)) {
585 continue;
586 }
587 if (onlySubclasses && !clientInfo.isSubclassOf(declaringClassName, f alse)) {
588 continue;
589 }
590
591 if (isField) {
592 if (clientInfo.referencesField(declaringClassInfo, memberNo)) {
593 addToAffectedClassNames(clientInfo.name);
594 }
595 } else {
596 if (clientInfo.referencesMethod(declaringClassInfo, memberNo)) {
597 addToAffectedClassNames(clientInfo.name);
598 }
599 }
600 }
601 }
602
603 /** Checks if class classInfo is accessible from class clientClassInfo. */
604 private boolean classAccessibleFrom(ClassInfo classInfo, ClassInfo clientCla ssInfo) {
605 char classFlags = classInfo.accessFlags;
606 String classPackage = classInfo.packageName;
607 String clientClassPackage = clientClassInfo.packageName;
608
609 if (Modifier.isPublic(classFlags)) {
610 return true;
611 } else if (Modifier.isProtected(classFlags)) {
612 if (classPackage.equals(clientClassPackage) ||
613 clientClassInfo.isSubclassOf(classInfo.directlyEnclosingClas s, false)) {
614 return true;
615 }
616 } else if (Modifier.isPrivate(classFlags)) {
617 if (classInfo.topLevelEnclosingClass.equals(clientClassInfo.topLevel EnclosingClass)) {
618 return true;
619 }
620 } else {
621 if (classPackage.equals(clientClassPackage)) {
622 return true;
623 }
624 }
625
626 return false;
627 }
628
629 /**
630 * Checks if member memberNo (which is a field if isField == true, and metho d otherwise) of class memberClassInfo is
631 * accessible from class clientClassInfo.
632 */
633 private boolean memberAccessibleFrom(ClassInfo memberClassInfo,
634 int memberNo, ClassInfo clientClassInfo, boolean isField) {
635 char memberClassFlags = memberClassInfo.accessFlags;
636 char memberFlags = isField ? memberClassInfo.fieldAccessFlags[memberNo]
637 : memberClassInfo.methodAccessFlags[memberNo];
638 String memberClassPackage = memberClassInfo.packageName;
639 String clientClassPackage = clientClassInfo.packageName;
640
641 if (Modifier.isPublic(memberClassFlags)) {
642 if (Modifier.isPublic(memberFlags)) {
643 return true;
644 } else if (Modifier.isProtected(memberFlags) &&
645 (memberClassPackage.equals(clientClassPackage) ||
646 clientClassInfo.isSubclassOf(memberClassInfo.name, false))) {
647 return true;
648 } else if (Modifier.isPrivate(memberFlags)) {
649 if (memberClassInfo.topLevelEnclosingClass.equals(
650 clientClassInfo.topLevelEnclosingClass)) {
651 return true;
652 }
653 } else if (memberClassPackage.equals(clientClassPackage)) {
654 return true;
655 }
656 } else if (Modifier.isProtected(memberClassFlags)) {
657 if (!(memberClassPackage.equals(clientClassPackage) ||
658 clientClassInfo.isSubclassOf(memberClassInfo.directlyEnclosi ngClass, false))) {
659 return true;
660 }
661 if (Modifier.isPublic(memberFlags) ||
662 Modifier.isProtected(memberFlags)) {
663 return true;
664 } else if (Modifier.isPrivate(memberFlags)) {
665 if (memberClassInfo.topLevelEnclosingClass.equals(
666 clientClassInfo.topLevelEnclosingClass)) {
667 return true;
668 }
669 } else {
670 if (memberClassPackage.equals(clientClassPackage)) {
671 return true;
672 }
673 }
674 } else if (Modifier.isPrivate(memberClassFlags)) {
675 if (memberClassInfo.topLevelEnclosingClass.equals(
676 clientClassInfo.topLevelEnclosingClass)) {
677 return true;
678 }
679 } else { // memberClassInfo is package-private
680 if (!memberClassPackage.equals(clientClassPackage)) {
681 return false;
682 }
683 if (Modifier.isPublic(memberFlags) || Modifier.isProtected(memberFla gs)) {
684 return true;
685 } else if (Modifier.isPrivate(memberFlags)) {
686 if (memberClassInfo.topLevelEnclosingClass.equals(
687 clientClassInfo.topLevelEnclosingClass)) {
688 return true;
689 }
690 } else {
691 return true;
692 }
693 }
694
695 return false;
696 }
697 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698