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

Side by Side Diff: third_party/jmake/src/org/pantsbuild/jmake/CompatibilityChecker.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.List;
11 import java.util.Set;
12
13 /**
14 * This class implements checking of source compatibility of classes and support ing operations
15 *
16 * @author Misha Dmitriev
17 * 12 March 2004
18 */
19 public class CompatibilityChecker {
20
21 private PCDManager pcdm;
22 private RefClassFinder rf;
23 ClassInfo oldClassInfo = null;
24 ClassInfo newClassInfo = null;
25 private boolean versionsCompatible;
26 private boolean publicConstantChanged;
27
28 public CompatibilityChecker(PCDManager pcdm, boolean failOnDependentJar, boo lean noWarnOnDependentJar) {
29 this.pcdm = pcdm;
30 publicConstantChanged = false;
31 rf = new RefClassFinder(pcdm, failOnDependentJar, noWarnOnDependentJar);
32 }
33
34 /**
35 * Compares the two class versions for the given PCDEntry. Returns true if a ll changes are source
36 * compatible, and false otherwise.
37 */
38 public boolean compareClassVersions(PCDEntry entry) {
39 // I once had the following optimization here with the comment "No sense to make any further checks if
40 // everything is recompiled anyway", but now I believe it's wrong. For e ach class that was found changed
41 // we need to know whether the new version is compatible with the old or not, since this may determine
42 // whether the new version of this class is promoted into the pdb or not (see PCDManager.updateClassInfoInPCD()).
43 // So, all changed classes should be checked just to correctly determine version compatibility.
44 // if (publicConstantChanged) return false;
45
46 oldClassInfo = pcdm.getClassInfoForPCDEntry(ClassInfo.VER_OLD, entry);
47 newClassInfo = pcdm.getClassInfoForPCDEntry(ClassInfo.VER_NEW, entry);
48
49 rf.initialize(oldClassInfo.name, entry.javaFileFullPath.endsWith(".jar") );
50 versionsCompatible = true;
51
52 checkAccessFlags();
53 checkSuperclasses();
54 checkImplementedInterfaces();
55 checkFields();
56 checkMethodsAndConstructors();
57
58 return versionsCompatible;
59 }
60
61 /** Find all dependent classes for a deleted class. */
62 public void checkDeletedClass(PCDEntry entry) {
63 oldClassInfo = entry.oldClassInfo;
64 rf.initialize(oldClassInfo.name, entry.javaFileFullPath.endsWith(".jar") );
65 rf.findReferencingClassesForDeletedClass(oldClassInfo);
66 // It may happen that the only reference to deleted class X is via "X.cl ass" construct
67 String packageToLookIn =
68 oldClassInfo.isPublic() ? null : oldClassInfo.packageName;
69 rf.findClassesDeclaringField(("class$" + oldClassInfo.name).intern(), "j ava/lang/Class", true, packageToLookIn);
70 checkForFinalFields();
71 }
72
73 /** Returns the names of classes affected by source incompatible changes to the new version of the checked class. */
74 public String[] getAffectedClasses() {
75 return rf.getAffectedClassNames();
76 }
77
78 /** All of the following methods return true if no source incompatible chang es found, and false otherwise */
79 private void checkAccessFlags() {
80 char oldClassFlags = oldClassInfo.accessFlags;
81 char newClassFlags = newClassInfo.accessFlags;
82 if (oldClassFlags == newClassFlags) {
83 return;
84 }
85
86 if (!Modifier.isFinal(oldClassFlags) && Modifier.isFinal(newClassFlags)) {
87 versionsCompatible = false;
88 rf.findDirectSubclasses(oldClassInfo);
89 }
90
91 if (!Modifier.isAbstract(oldClassFlags) && Modifier.isAbstract(newClassF lags)) {
92 versionsCompatible = false;
93 rf.findReferencingClasses0(oldClassInfo);
94 }
95
96 // Now to accessibility modifiers checking...
97 if (Modifier.isPublic(newClassFlags)) {
98 return;
99 }
100
101 if (Modifier.isProtected(newClassFlags)) {
102 if (Modifier.isPublic(oldClassFlags)) {
103 versionsCompatible = false;
104 rf.findDiffPackageAndNotSubReferencingClasses1(oldClassInfo);
105 }
106 } else if (Modifier.isPrivate(newClassFlags)) {
107 if (!Modifier.isPrivate(oldClassFlags)) {
108 versionsCompatible = false;
109 } else {
110 return; // private -> private, nothing more to check
111 }
112 if (Modifier.isPublic(oldClassFlags)) {
113 rf.findReferencingClasses1(oldClassInfo);
114 } else if (Modifier.isProtected(oldClassFlags)) {
115 rf.findThisPackageOrSubReferencingClasses1(oldClassInfo);
116 } else {
117 rf.findThisPackageReferencingClasses1(oldClassInfo);
118 }
119 } else { // newClassFlags has default access, since public has already been excluded
120 if (Modifier.isPublic(oldClassFlags)) {
121 versionsCompatible = false;
122 rf.findDiffPackageReferencingClasses1(oldClassInfo);
123 } else if (Modifier.isProtected(oldClassFlags)) {
124 versionsCompatible = false;
125 rf.findDiffPackageAndSubReferencingClasses1(oldClassInfo);
126 }
127 }
128 }
129
130 private void checkSuperclasses() {
131 List<String> oldSuperNames = oldClassInfo.getAllSuperclassNames();
132 List<String> newSuperNames = newClassInfo.getAllSuperclassNames();
133
134 int oldNamesSizeMinusOne = oldSuperNames.size() - 1;
135 for (int i = 0; i <= oldNamesSizeMinusOne; i++) {
136 String oldSuperName = oldSuperNames.get(i);
137 if (!newSuperNames.contains(oldSuperName)) {
138 versionsCompatible = false;
139 ClassInfo missingSuperClass =
140 pcdm.getClassInfoForName(ClassInfo.VER_OLD, oldSuperName );
141 if (missingSuperClass == null) { // This class is not in project
142 missingSuperClass =
143 ClassPath.getClassInfoForName(oldSuperName, pcdm);
144 if (missingSuperClass == null) {
145 missingSuperClass = new ClassInfo(oldSuperName, pcdm);
146 }
147 }
148 rf.findReferencingClasses2(missingSuperClass, oldClassInfo);
149 }
150 }
151
152 // Now check if the class is an exception, and its kind has changed from unchecked to checked
153 if (oldClassInfo.isInterface() || oldSuperNames.size() == 0) {
154 return;
155 }
156 if (!(oldSuperNames.contains("java/lang/RuntimeException") || oldSuperNa mes.contains("java/lang/Error"))) {
157 return;
158 }
159 if (!(newSuperNames.contains("java/lang/RuntimeException") || newSuperNa mes.contains("java/lang/Error"))) {
160 if (!newSuperNames.contains("java/lang/Throwable")) {
161 return;
162 }
163 // Ok, exception kind has changed from unchecked to checked.
164 versionsCompatible = false;
165 rf.findReferencingClasses0(oldClassInfo);
166 rf.findRefsToMethodsThrowingException(oldClassInfo);
167 }
168 }
169
170 private void checkImplementedInterfaces() {
171 Set<String> oldIntfNames = oldClassInfo.getAllImplementedIntfNames();
172 Set<String> newIntfNames = newClassInfo.getAllImplementedIntfNames();
173
174 for (String oldIntfName : oldIntfNames) {
175 if (!newIntfNames.contains(oldIntfName)) {
176 versionsCompatible = false;
177 ClassInfo missingSuperInterface =
178 pcdm.getClassInfoForName(ClassInfo.VER_OLD, oldIntfName) ;
179 if (missingSuperInterface == null) { // This class is not in pro ject
180 missingSuperInterface =
181 ClassPath.getClassInfoForName(oldIntfName, pcdm);
182 if (missingSuperInterface == null) {
183 missingSuperInterface = new ClassInfo(oldIntfName, pcdm) ;
184 }
185 }
186 rf.findReferencingClasses2(missingSuperInterface, oldClassInfo);
187 }
188 }
189
190 // Check if the class is abstract, and an interface has been added to it s list of implemented interfaces
191 if (newClassInfo.isAbstract()) {
192 for (String newIntfName : newIntfNames) {
193 if (!oldIntfNames.contains(newIntfName)) {
194 versionsCompatible = false;
195 rf.findConcreteSubclasses(oldClassInfo);
196 break;
197 }
198 }
199 }
200 }
201
202 private void checkFields() {
203 String oFNames[] = oldClassInfo.fieldNames;
204 String oFSignatures[] = oldClassInfo.fieldSignatures;
205 char oFFlags[] = oldClassInfo.fieldAccessFlags;
206 String nFNames[] = newClassInfo.fieldNames;
207 String nFSignatures[] = newClassInfo.fieldSignatures;
208 char nFFlags[] = newClassInfo.fieldAccessFlags;
209 int oFLen = oFNames != null ? oFNames.length : 0;
210 int nFLen = nFNames != null ? nFNames.length : 0;
211
212 int oFMod, nFMod;
213 String oFName, oFSig, nFName;
214 int i, j, k, endIdx;
215 int nonMatchingNewFields = nFLen;
216
217 for (i = 0; i < oFLen; i++) {
218 oFMod = oFFlags[i];
219 if (Modifier.isPrivate(oFMod)) {
220 continue; // Changes to private fields don't affect compatibili ty
221 }
222 oFName = oFNames[i];
223 oFSig = oFSignatures[i];
224 boolean found = false;
225
226 // Look for the same field in the new version considering name and t ype
227 endIdx = nFLen - 1;
228 k = i < nFLen ? i : endIdx;
229 for (j = 0; j < nFLen; j++) {
230 if (oFName.equals(nFNames[k]) &&
231 oFSig.equals(nFSignatures[k])) {
232 found = true;
233 break;
234 }
235 if (k < endIdx) {
236 k++;
237 } else {
238 k = 0;
239 }
240 }
241
242 if (found) {
243 nonMatchingNewFields--;
244 nFMod = nFFlags[k];
245 checkFieldModifiers(oFMod, nFMod, i, k);
246 if (publicConstantChanged) {
247 return;
248 }
249 } else { // Matching field not found
250 if (Modifier.isStatic(oFMod) && Modifier.isFinal(oFMod) &&
251 oldClassInfo.primitiveConstantInitValues != null &&
252 oldClassInfo.primitiveConstantInitValues[i] != null) {
253 // Compile-time constant deleted
254 versionsCompatible = false;
255 rf.findAllProjectClasses(oldClassInfo, i);
256 if (Modifier.isPublic(oFMod)) {
257 publicConstantChanged = true;
258 return;
259 }
260 } else {
261 versionsCompatible = false;
262 rf.findReferencingClassesForField(oldClassInfo, i);
263 }
264 }
265 }
266
267 if (nonMatchingNewFields > 0) { // There are some fields declared in the new version which don't exist in the old one
268 // Look for fields hiding same-named fields in superclasses
269 for (i = 0; i < nFLen; i++) {
270 nFName = nFNames[i];
271
272 boolean found = false;
273 for (j = 0; j < oFLen; j++) {
274 if (nFName.equals(oFNames[j])) {
275 found = true;
276 break;
277 }
278 }
279 if (found) {
280 continue; // nFName is not an added field
281 }
282 String superName = oldClassInfo.superName;
283 ClassInfo superInfo;
284 while (superName != null) {
285 superInfo =
286 pcdm.getClassInfoForName(ClassInfo.VER_OLD, superNam e);
287 if (superInfo == null) {
288 break;
289 }
290 String[] superOFNames = superInfo.fieldNames;
291 int superOFNamesLen = superOFNames != null ? superOFNames.le ngth
292 : 0;
293 for (j = 0; j < superOFNamesLen; j++) {
294 if (nFName == superOFNames[j]) {
295 versionsCompatible = false;
296 rf.findReferencingClassesForField(superInfo, j);
297 }
298 }
299 superName = superInfo.superName;
300 }
301 }
302 }
303 }
304
305 /** It is already known that old field is not private */
306 private void checkFieldModifiers(int oFMod, int nFMod, int oldFieldIdx, int newFieldIdx) {
307 if (oFMod == nFMod) {
308 if (Modifier.isFinal(oFMod) &&
309 (!ClassInfo.constFieldInitValuesEqual(oldClassInfo, oldField Idx, newClassInfo, newFieldIdx))) {
310 versionsCompatible = false;
311 rf.findAllProjectClasses(oldClassInfo, oldFieldIdx);
312 if (Modifier.isPublic(oFMod)) {
313 publicConstantChanged = true; // Means we will have to reco mpile ALL project classes
314 }
315 return;
316 }
317 }
318
319 // These tests are ordered such that if a previous test succeeds, there is no need to do further tests, since that
320 // former test will cause more classes to be checked than any of the fur ther tests. That is why it is possible to
321 // check properties that are in fact independent (e.g. accessibility vs. static/non-static) together. But this
322 // optimization only works since all kinds of tests result in the same k ind of find..ReferencingClassesForField()
323 // outcome. For methods this is not true, and so there we have to check independent properties separately.
324 if (Modifier.isStatic(oFMod) && Modifier.isFinal(oFMod) && // oFMod is k nown to be non-private
325 (!Modifier.isFinal(nFMod) || !ClassInfo.constFieldInitValuesEqua l(oldClassInfo, oldFieldIdx, newClassInfo, newFieldIdx))) {
326 versionsCompatible = false;
327 rf.findAllProjectClasses(oldClassInfo, oldFieldIdx);
328 if (Modifier.isPublic(oFMod)) {
329 publicConstantChanged = true;
330 }
331 } else if (Modifier.isPrivate(nFMod) || // oFMod is known to be non-priv ate
332 (!Modifier.isFinal(oFMod) && Modifier.isFinal(nFMod)) ||
333 (Modifier.isStatic(oFMod) != Modifier.isStatic(nFMod)) ||
334 (Modifier.isVolatile(oFMod) != Modifier.isVolatile(nFMod))) {
335 versionsCompatible = false;
336 rf.findReferencingClassesForField(oldClassInfo, oldFieldIdx);
337 } else if (Modifier.isPublic(oFMod) && Modifier.isProtected(nFMod)) {
338 versionsCompatible = false;
339 rf.findDiffPackageReferencingClassesForField(oldClassInfo, oldFieldI dx);
340 } else if ((Modifier.isPublic(oFMod) || Modifier.isProtected(oFMod)) &&
341 (!(Modifier.isPublic(nFMod) || Modifier.isProtected(nFMod) || Mo difier.isPrivate(nFMod)))) {
342 versionsCompatible = false;
343 if (Modifier.isPublic(oFMod)) {
344 rf.findDiffPackageReferencingClassesForField(oldClassInfo, oldFi eldIdx);
345 } else {
346 rf.findDiffPackageAndSubReferencingClassesForField(oldClassInfo, oldFieldIdx);
347 }
348 }
349 }
350
351 private void checkForFinalFields() {
352 char oFFlags[] = oldClassInfo.fieldAccessFlags;
353 int oFLen = oldClassInfo.fieldNames != null ? oldClassInfo.fieldNames.le ngth
354 : 0;
355 int oFMod;
356
357 for (int i = 0; i < oFLen; i++) {
358 oFMod = oFFlags[i];
359 if (Modifier.isPrivate(oFMod)) {
360 continue; // Changes to private fields don't affect compatibili ty
361 }
362 if (Modifier.isStatic(oFMod) && Modifier.isFinal(oFMod)) {
363 rf.findAllProjectClasses(oldClassInfo, i);
364 if (Modifier.isPublic(oFMod)) {
365 publicConstantChanged = true;
366 return;
367 }
368 }
369 }
370 }
371
372 private void checkMethodsAndConstructors() {
373 String oMNames[] = oldClassInfo.methodNames;
374 String oMSignatures[] = oldClassInfo.methodSignatures;
375 char oMFlags[] = oldClassInfo.methodAccessFlags;
376 String nMNames[] = newClassInfo.methodNames;
377 String nMSignatures[] = newClassInfo.methodSignatures;
378 char nMFlags[] = newClassInfo.methodAccessFlags;
379 int oMLen = oMNames != null ? oMNames.length : 0;
380 int nMLen = nMNames != null ? nMNames.length : 0;
381
382 int oMMod, nMMod;
383 String oMName, oMSig, nMName, nMSig;
384 int i, j, k, endIdx;
385 int nonMatchingNewMethods = nMLen;
386
387 for (i = 0; i < oMLen; i++) {
388 oMMod = oMFlags[i];
389 if (Modifier.isPrivate(oMMod)) {
390 continue; // Changes to private methods don't affect compatibil ity
391 }
392 oMName = oMNames[i];
393 oMSig = oMSignatures[i];
394 boolean found = false;
395
396 // Look for the same method in the new version considering name and signature
397 endIdx = nMLen - 1;
398 k = i < nMLen ? i : endIdx;
399 for (j = 0; j < nMLen; j++) {
400 if (oMName == nMNames[k] && oMSig == nMSignatures[k]) {
401 found = true;
402 break;
403 }
404 if (k < endIdx) {
405 k++;
406 } else {
407 k = 0;
408 }
409 }
410
411 if (found) {
412 nonMatchingNewMethods--;
413 nMMod = nMFlags[k];
414 if (oMMod != nMMod) {
415 checkMethodModifiers(oMMod, nMMod, i);
416 }
417
418 // Check if the new method throws more exceptions than the old o ne
419 if (newClassInfo.checkedExceptions != null && newClassInfo.check edExceptions[k] != null) {
420 if (oldClassInfo.checkedExceptions == null) {
421 versionsCompatible = false;
422 rf.findReferencingClassesForMethod(oldClassInfo, i);
423 } else if (oldClassInfo.checkedExceptions[i] == null) {
424 versionsCompatible = false;
425 rf.findReferencingClassesForMethod(oldClassInfo, i);
426 } else {
427 String oldExceptions[] =
428 oldClassInfo.checkedExceptions[i];
429 String newExceptions[] =
430 newClassInfo.checkedExceptions[k];
431 for (int ei = 0; ei < newExceptions.length; ei++) {
432 String newEx = newExceptions[ei];
433 found = false;
434 for (int ej = 0; ej < oldExceptions.length; ej++) {
435 if (newEx.equals(oldExceptions[ej])) {
436 found = true;
437 break;
438 }
439 }
440 if (!found) {
441 versionsCompatible = false;
442 rf.findReferencingClassesForMethod(oldClassInfo, i);
443 break;
444 }
445 }
446 }
447 }
448 } else { // Matching method not found
449 versionsCompatible = false;
450 rf.findReferencingClassesForMethod(oldClassInfo, i);
451 // Deleting a concrete method from an abstract class is a specia l case
452 if (oldClassInfo.isAbstract() && !Modifier.isAbstract(oMMod)) {
453 rf.findConcreteSubclassesNotOverridingAbstractMethod(oldClas sInfo, oldClassInfo, i);
454 }
455 }
456 }
457
458 if (nonMatchingNewMethods > 0) { // There are some methods/constructors declared in the new version which don't exist in the old one
459 if (!oldClassInfo.isInterface()) {
460 for (i = 0; i < nMLen; i++) {
461 nMMod = nMFlags[i];
462 if (Modifier.isPrivate(nMMod)) {
463 continue;
464 }
465 String newMName = nMNames[i];
466 final String newMSig = nMSignatures[i];
467 final boolean isStatic = Modifier.isStatic(nMMod);
468
469 boolean found = false;
470 for (j = 0; j < oMLen; j++) {
471 if (newMName.equals(oMNames[j]) &&
472 newMSig.equals(oMSignatures[j])) {
473 found = true;
474 break;
475 }
476 }
477 if (found) {
478 continue; // nMName is not an added method
479 }
480 // Check if the new method is a static one that hides an inh erited static method
481 // Check if the new method overloads an existing (declared o r inherited) method. Overloading test is rough -
482 // we just check if the number of parameters is the same. No te that if a new constructor has been added, it
483 // can be treated in the same way, except that we shouldn't look up "same name methods" for it in superclasses.
484 oldClassInfo.findExistingSameNameMethods(newMName,
485 !newMName.equals("<init>"), false,
486 new ClassInfo.MethodHandler() {
487
488 void handleMethod(ClassInfo classInfo, int methodIdx) {
489 String otherMSig =
490 classInfo.methodSignatures[methodIdx];
491 if ((newMSig.equals(otherMSig) && isStatic &&
492 classInfo != oldClassInfo) ||
493 (newMSig != otherMSig &&
494 Utils.sameParamNumber(newMSig, otherMSig))) {
495 versionsCompatible = false;
496 rf.findReferencingClassesForMethod(classInfo, me thodIdx);
497 }
498 }
499 });
500
501 if (Modifier.isAbstract(nMMod)) {
502 // An abstract method added to the class. Find any concr ete subclasses that don't override
503 // or inherit a concrete implementation of this method.
504 versionsCompatible = false;
505 rf.findConcreteSubclassesNotOverridingAbstractMethod(old ClassInfo, newClassInfo, i);
506 }
507 // Check if there is a method with the same name in some sub class, such that it now overrides
508 // or overloads the added method.
509 if (subclassesDeclareSameNameMethod(oldClassInfo, newMName)) {
510 versionsCompatible = false;
511 }
512 }
513 } else { // We are checking an interface.
514 for (i = 0; i < nMLen; i++) {
515 String newMName = nMNames[i];
516 final String newMSig = nMSignatures[i];
517
518 boolean found = false;
519 for (j = 0; j < oMLen; j++) {
520 if (newMName == oMNames[j] && newMSig == oMSignatures[j] ) {
521 found = true;
522 break;
523 }
524 }
525
526 if (!found) {
527 versionsCompatible = false;
528
529 // Check if the new method overloads an existing (declar ed or inherited) method. Overloading test is rough -
530 // we just check if the number of parameters is the same .
531 oldClassInfo.findExistingSameNameMethods(newMName, true, true, new ClassInfo.MethodHandler() {
532
533 void handleMethod(ClassInfo classInfo, int methodIdx ) {
534 String otherMSig =
535 classInfo.methodSignatures[methodIdx];
536 if (newMSig != otherMSig &&
537 Utils.sameParamNumber(newMSig, otherMSig )) {
538 rf.findReferencingClassesForMethod(classInfo , methodIdx);
539 }
540 }
541 });
542
543 rf.findDirectlyAndOtherwiseImplementingConcreteClasses(o ldClassInfo);
544 rf.findAbstractSubtypesWithSameNameMethod(oldClassInfo, newMName, newMSig);
545 break;
546 }
547 }
548 }
549 }
550 }
551
552 private void checkMethodModifiers(int oMMod, int nMMod, int oldMethodIdx) {
553 if (Modifier.isPrivate(nMMod)) {
554 versionsCompatible = false;
555 rf.findReferencingClassesForMethod(oldClassInfo, oldMethodIdx);
556 } else if (Modifier.isPublic(oMMod) && Modifier.isProtected(nMMod)) {
557 versionsCompatible = false;
558 rf.findDiffPackageReferencingClassesForMethod(oldClassInfo, oldMetho dIdx);
559 } else if ((Modifier.isPublic(oMMod) || Modifier.isProtected(oMMod)) &&
560 (!(Modifier.isPublic(nMMod) || Modifier.isProtected(nMMod) || Mo difier.isPrivate(nMMod)))) {
561 versionsCompatible = false;
562 if (Modifier.isPublic(oMMod)) {
563 rf.findDiffPackageReferencingClassesForMethod(oldClassInfo, oldM ethodIdx);
564 } else {
565 rf.findDiffPackageAndSubReferencingClassesForMethod(oldClassInfo , oldMethodIdx);
566 }
567 } else if ((Modifier.isPrivate(oMMod) && !Modifier.isPrivate(nMMod)) ||
568 (Modifier.isProtected(oMMod) && Modifier.isPublic(nMMod)) ||
569 (!(Modifier.isPublic(oMMod) || Modifier.isProtected(oMMod) || Mo difier.isPrivate(oMMod)) &&
570 (Modifier.isPublic(nMMod) || Modifier.isProtected(nMMod)))) {
571 versionsCompatible = false;
572 rf.findSubclassesReimplementingMethod(oldClassInfo, oldMethodIdx);
573 }
574
575 if ((!Modifier.isAbstract(oMMod) && Modifier.isAbstract(nMMod)) ||
576 (Modifier.isStatic(oMMod) != Modifier.isStatic(nMMod))) {
577 versionsCompatible = false;
578 rf.findReferencingClassesForMethod(oldClassInfo, oldMethodIdx);
579 if (!Modifier.isAbstract(oMMod) && Modifier.isAbstract(nMMod)) {
580 rf.findConcreteSubclassesNotOverridingAbstractMethod(oldClassInf o, newClassInfo, oldMethodIdx);
581 }
582 }
583 if (!Modifier.isFinal(oMMod) && Modifier.isFinal(nMMod)) {
584 versionsCompatible = false;
585 rf.findSubclassesReimplementingMethod(oldClassInfo, oldMethodIdx);
586 }
587 }
588
589 /**
590 * Returns true if any subclass(es), direct or indirect, declare a method wi th name methodName.
591 * For each such occurence, referencing classes are looked up and added to t he list of affected classes.
592 */
593 private boolean subclassesDeclareSameNameMethod(ClassInfo oldClassInfo, Stri ng methodName) {
594 boolean res = false;
595 ClassInfo[] directSubclasses = oldClassInfo.getDirectSubclasses();
596 for (int i = 0; i < directSubclasses.length; i++) {
597 ClassInfo subclass = directSubclasses[i];
598 int methNo = subclass.declaresSameNameMethod(methodName);
599 if (methNo >= 0) {
600 rf.addToAffectedClassNames(subclass.name);
601 rf.findReferencingClassesForMethod(subclass, methNo);
602 res = true;
603 }
604 if (subclassesDeclareSameNameMethod(subclass, methodName)) {
605 res = true;
606 }
607 }
608 return res;
609 }
610 }
OLDNEW
« no previous file with comments | « third_party/jmake/src/org/pantsbuild/jmake/ClassPath.java ('k') | third_party/jmake/src/org/pantsbuild/jmake/Main.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698