1
2
3
4 package net.sourceforge.pmd.lang.java.rule.design;
5
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.Comparator;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13 import java.util.TreeMap;
14
15 import net.sourceforge.pmd.lang.ast.Node;
16 import net.sourceforge.pmd.lang.java.ast.ASTArgumentList;
17 import net.sourceforge.pmd.lang.java.ast.ASTArguments;
18 import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral;
19 import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
20 import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
21 import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
22 import net.sourceforge.pmd.lang.java.ast.ASTEnumDeclaration;
23 import net.sourceforge.pmd.lang.java.ast.ASTExplicitConstructorInvocation;
24 import net.sourceforge.pmd.lang.java.ast.ASTFormalParameter;
25 import net.sourceforge.pmd.lang.java.ast.ASTLiteral;
26 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
27 import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclarator;
28 import net.sourceforge.pmd.lang.java.ast.ASTName;
29 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryExpression;
30 import net.sourceforge.pmd.lang.java.ast.ASTPrimaryPrefix;
31 import net.sourceforge.pmd.lang.java.ast.ASTPrimarySuffix;
32 import net.sourceforge.pmd.lang.java.ast.ASTPrimitiveType;
33 import net.sourceforge.pmd.lang.java.ast.ASTReferenceType;
34 import net.sourceforge.pmd.lang.java.ast.ASTType;
35 import net.sourceforge.pmd.lang.java.ast.AccessNode;
36 import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public final class ConstructorCallsOverridableMethodRule extends AbstractJavaRule {
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 private static class MethodInvocation {
163 private String name;
164 private ASTPrimaryExpression ape;
165 private List<String> referenceNames;
166 private List<String> qualifierNames;
167 private int argumentSize;
168 private List<String> argumentTypes;
169 private boolean superCall;
170
171 private MethodInvocation(ASTPrimaryExpression ape, List<String> qualifierNames, List<String> referenceNames, String name, int argumentSize, List<String> argumentTypes, boolean superCall) {
172 this.ape = ape;
173 this.qualifierNames = qualifierNames;
174 this.referenceNames = referenceNames;
175 this.name = name;
176 this.argumentSize = argumentSize;
177 this.argumentTypes = argumentTypes;
178 this.superCall = superCall;
179 }
180
181 public boolean isSuper() {
182 return superCall;
183 }
184
185 public String getName() {
186 return name;
187 }
188
189 public int getArgumentCount() {
190 return argumentSize;
191 }
192
193 public List<String> getArgumentTypes() {
194 return argumentTypes;
195 }
196
197 public List<String> getReferenceNames() {
198 return referenceNames;
199 }
200
201 public List<String> getQualifierNames() {
202 return qualifierNames;
203 }
204
205 public ASTPrimaryExpression getASTPrimaryExpression() {
206 return ape;
207 }
208
209 public static MethodInvocation getMethod(ASTPrimaryExpression node) {
210 MethodInvocation meth = null;
211 int i = node.jjtGetNumChildren();
212 if (i > 1) {
213
214 Node lastNode = node.jjtGetChild(i - 1);
215 if (lastNode.jjtGetNumChildren() == 1 && lastNode.jjtGetChild(0) instanceof ASTArguments) {
216
217
218 List<String> varNames = new ArrayList<String>();
219 List<String> packagesAndClasses = new ArrayList<String>();
220 String methodName = null;
221 ASTArguments args = (ASTArguments) lastNode.jjtGetChild(0);
222 int numOfArguments = args.getArgumentCount();
223 List<String> argumentTypes = ConstructorCallsOverridableMethodRule.getArgumentTypes(args);
224 boolean superFirst = false;
225 int thisIndex = -1;
226
227 FIND_SUPER_OR_THIS: {
228
229
230
231
232
233 for (int x = 0; x < i - 1; x++) {
234 Node child = node.jjtGetChild(x);
235 if (child instanceof ASTPrimarySuffix) {
236 ASTPrimarySuffix child2 = (ASTPrimarySuffix) child;
237
238
239 if (child2.getImage() == null && child2.jjtGetNumChildren() == 0) {
240 thisIndex = x;
241 break;
242 }
243
244
245
246 } else if (child instanceof ASTPrimaryPrefix) {
247 ASTPrimaryPrefix child2 = (ASTPrimaryPrefix) child;
248 if (getNameFromPrefix(child2) == null) {
249 if (child2.getImage() == null) {
250 thisIndex = x;
251 break;
252 } else {
253 superFirst = true;
254 thisIndex = x;
255
256
257 break;
258 }
259 }
260 }
261
262
263
264 }
265 }
266
267 if (thisIndex != -1) {
268
269
270 if (superFirst) {
271
272 FIRSTNODE:{
273 ASTPrimaryPrefix child = (ASTPrimaryPrefix) node.jjtGetChild(0);
274 String name = child.getImage();
275 if (i == 2) {
276 methodName = name;
277 } else {
278 varNames.add(name);
279 }
280 }
281 OTHERNODES:{
282 for (int x = 1; x < i - 1; x++) {
283 Node child = node.jjtGetChild(x);
284 ASTPrimarySuffix ps = (ASTPrimarySuffix) child;
285 if (!ps.isArguments()) {
286 String name = ((ASTPrimarySuffix) child).getImage();
287 if (x == i - 2) {
288 methodName = name;
289 } else {
290 varNames.add(name);
291 }
292 }
293 }
294 }
295 } else {
296 FIRSTNODE:{
297 if (thisIndex == 1) {
298 ASTPrimaryPrefix child = (ASTPrimaryPrefix) node.jjtGetChild(0);
299 String toParse = getNameFromPrefix(child);
300
301 java.util.StringTokenizer st = new java.util.StringTokenizer(toParse, ".");
302 while (st.hasMoreTokens()) {
303 packagesAndClasses.add(st.nextToken());
304 }
305 }
306 }
307 OTHERNODES:{
308
309
310 for (int x = thisIndex + 1; x < i - 1; x++) {
311 ASTPrimarySuffix child = (ASTPrimarySuffix) node.jjtGetChild(x);
312 if (!child.isArguments()) {
313 String name = child.getImage();
314
315 if (x == i - 2) {
316 methodName = name;
317 } else {
318 varNames.add(name);
319 }
320 }
321 }
322 }
323 }
324 } else {
325
326 FIRSTNODE:{
327 ASTPrimaryPrefix child = (ASTPrimaryPrefix) node.jjtGetChild(0);
328 String toParse = getNameFromPrefix(child);
329
330 java.util.StringTokenizer st = new java.util.StringTokenizer(toParse, ".");
331 while (st.hasMoreTokens()) {
332 String value = st.nextToken();
333 if (!st.hasMoreTokens()) {
334 if (i == 2) {
335 methodName = value;
336 } else {
337 varNames.add(value);
338 }
339 } else {
340 varNames.add(value);
341 }
342 }
343 }
344 OTHERNODES:{
345 for (int x = 1; x < i - 1; x++) {
346 ASTPrimarySuffix child = (ASTPrimarySuffix) node.jjtGetChild(x);
347 if (!child.isArguments()) {
348 String name = child.getImage();
349 if (x == i - 2) {
350 methodName = name;
351 } else {
352 varNames.add(name);
353 }
354 }
355 }
356 }
357 }
358 meth = new MethodInvocation(node, packagesAndClasses, varNames, methodName, numOfArguments, argumentTypes, superFirst);
359
360 }
361 }
362 return meth;
363 }
364
365 public void show() {
366 System.out.println("<MethodInvocation>");
367 System.out.println(" <Qualifiers>");
368 for (String name: getQualifierNames()) {
369 System.out.println(" " + name);
370 }
371 System.out.println(" </Qualifiers>");
372 System.out.println(" <Super>" + isSuper() + "</Super>");
373 System.out.println(" <References>");
374 for (String name: getReferenceNames()) {
375 System.out.println(" " + name);
376 }
377 System.out.println(" </References>");
378 System.out.println(" <Name>" + getName() + "</Name>");
379 System.out.println(" <ArgumentCount>" + getArgumentCount() + "</ArgumentCount>");
380 System.out.println(" <ArgumentTypes>" + getArgumentTypes() + "</ArgumentTypes>");
381 System.out.println("</MethodInvocation>");
382 }
383 }
384
385 private static final class ConstructorInvocation {
386 private ASTExplicitConstructorInvocation eci;
387 private String name;
388 private int count = 0;
389 private List<String> argumentTypes = new ArrayList<String>();
390
391 public ConstructorInvocation(ASTExplicitConstructorInvocation eci) {
392 this.eci = eci;
393 List<ASTArguments> l = eci.findChildrenOfType(ASTArguments.class);
394 if (!l.isEmpty()) {
395 ASTArguments aa = l.get(0);
396 count = aa.getArgumentCount();
397 argumentTypes = ConstructorCallsOverridableMethodRule.getArgumentTypes(aa);
398 }
399 name = eci.getImage();
400 }
401
402 public ASTExplicitConstructorInvocation getASTExplicitConstructorInvocation() {
403 return eci;
404 }
405
406 public int getArgumentCount() {
407 return count;
408 }
409
410 public List<String> getArgumentTypes() {
411 return argumentTypes;
412 }
413
414 public String getName() {
415 return name;
416 }
417 }
418
419 private static final class MethodHolder {
420 private ASTMethodDeclarator amd;
421 private boolean dangerous;
422 private String called;
423
424 public MethodHolder(ASTMethodDeclarator amd) {
425 this.amd = amd;
426 }
427
428 public void setCalledMethod(String name) {
429 this.called = name;
430 }
431
432 public String getCalled() {
433 return this.called;
434 }
435
436 public ASTMethodDeclarator getASTMethodDeclarator() {
437 return amd;
438 }
439
440 public boolean isDangerous() {
441 return dangerous;
442 }
443
444 public void setDangerous() {
445 dangerous = true;
446 }
447 }
448
449 private static final class ConstructorHolder {
450 private ASTConstructorDeclaration cd;
451 private boolean dangerous;
452 private ConstructorInvocation ci;
453 private boolean ciInitialized;
454
455 public ConstructorHolder(ASTConstructorDeclaration cd) {
456 this.cd = cd;
457 }
458
459 public ASTConstructorDeclaration getASTConstructorDeclaration() {
460 return cd;
461 }
462
463 public ConstructorInvocation getCalledConstructor() {
464 if (!ciInitialized) {
465 initCI();
466 }
467 return ci;
468 }
469
470 public ASTExplicitConstructorInvocation getASTExplicitConstructorInvocation() {
471 ASTExplicitConstructorInvocation eci = null;
472 if (!ciInitialized) {
473 initCI();
474 }
475 if (ci != null) {
476 eci = ci.getASTExplicitConstructorInvocation();
477 }
478 return eci;
479 }
480
481 private void initCI() {
482 List<ASTExplicitConstructorInvocation> expressions = cd.findChildrenOfType(ASTExplicitConstructorInvocation.class);
483 if (!expressions.isEmpty()) {
484 ASTExplicitConstructorInvocation eci = expressions.get(0);
485 ci = new ConstructorInvocation(eci);
486
487 }
488 ciInitialized = true;
489 }
490
491 public boolean isDangerous() {
492 return dangerous;
493 }
494
495 public void setDangerous(boolean dangerous) {
496 this.dangerous = dangerous;
497 }
498 }
499
500 private static int compareNodes(Node n1, Node n2) {
501 int l1 = n1.getBeginLine();
502 int l2 = n2.getBeginLine();
503 if (l1 == l2) {
504 return n1.getBeginColumn() - n2.getBeginColumn();
505 }
506 return l1 - l2;
507 }
508
509 private static class MethodHolderComparator implements Comparator<MethodHolder> {
510 public int compare(MethodHolder o1, MethodHolder o2) {
511 return compareNodes(o1.getASTMethodDeclarator(), o2.getASTMethodDeclarator());
512 }
513 }
514
515 private static class ConstructorHolderComparator implements Comparator<ConstructorHolder> {
516 public int compare(ConstructorHolder o1, ConstructorHolder o2) {
517 return compareNodes(o1.getASTConstructorDeclaration(), o2.getASTConstructorDeclaration());
518 }
519 }
520
521
522
523
524 private static class EvalPackage {
525 public EvalPackage() {
526 }
527
528 public EvalPackage(String className) {
529 this.className = className;
530 this.calledMethods = new ArrayList<MethodInvocation>();
531 this.allMethodsOfClass = new TreeMap<MethodHolder, List<MethodInvocation>>(new MethodHolderComparator());
532 this.calledConstructors = new ArrayList<ConstructorInvocation>();
533 this.allPrivateConstructorsOfClass = new TreeMap<ConstructorHolder, List<MethodInvocation>>(new ConstructorHolderComparator());
534 }
535
536 public String className;
537 public List<MethodInvocation> calledMethods;
538 public Map<MethodHolder, List<MethodInvocation>> allMethodsOfClass;
539
540 public List<ConstructorInvocation> calledConstructors;
541 public Map<ConstructorHolder, List<MethodInvocation>> allPrivateConstructorsOfClass;
542 }
543
544 private static final class NullEvalPackage extends EvalPackage {
545 public NullEvalPackage() {
546 className = "";
547 calledMethods = Collections.emptyList();
548 allMethodsOfClass = Collections.emptyMap();
549 calledConstructors = Collections.emptyList();
550 allPrivateConstructorsOfClass = Collections.emptyMap();
551 }
552 }
553
554 private static final NullEvalPackage NULL_EVAL_PACKAGE = new NullEvalPackage();
555
556
557
558
559
560 private final List<EvalPackage> evalPackages = new ArrayList<EvalPackage>();
561
562 private EvalPackage getCurrentEvalPackage() {
563 return evalPackages.get(evalPackages.size() - 1);
564 }
565
566
567
568
569 private void putEvalPackage(EvalPackage ep) {
570 evalPackages.add(ep);
571 }
572
573 private void removeCurrentEvalPackage() {
574 evalPackages.remove(evalPackages.size() - 1);
575 }
576
577 private void clearEvalPackages() {
578 evalPackages.clear();
579 }
580
581
582
583
584
585 private Object visitClassDec(ASTClassOrInterfaceDeclaration node, Object data) {
586 String className = node.getImage();
587 if (!node.isFinal()) {
588 putEvalPackage(new EvalPackage(className));
589 } else {
590 putEvalPackage(NULL_EVAL_PACKAGE);
591 }
592
593 super.visit(node, data);
594
595
596 if (!(getCurrentEvalPackage() instanceof NullEvalPackage)) {
597
598 while (evaluateDangerOfMethods(getCurrentEvalPackage().allMethodsOfClass)) { }
599
600 evaluateDangerOfConstructors1(getCurrentEvalPackage().allPrivateConstructorsOfClass, getCurrentEvalPackage().allMethodsOfClass.keySet());
601 while (evaluateDangerOfConstructors2(getCurrentEvalPackage().allPrivateConstructorsOfClass)) { }
602
603
604 for (MethodInvocation meth: getCurrentEvalPackage().calledMethods) {
605
606 for (MethodHolder h: getCurrentEvalPackage().allMethodsOfClass.keySet()) {
607 if (h.isDangerous()) {
608 String methName = h.getASTMethodDeclarator().getImage();
609 int count = h.getASTMethodDeclarator().getParameterCount();
610 List<String> parameterTypes = getMethodDeclaratorParameterTypes(h.getASTMethodDeclarator());
611 if (methName.equals(meth.getName()) && meth.getArgumentCount() == count
612 && parameterTypes.equals(meth.getArgumentTypes())) {
613 addViolation(data, meth.getASTPrimaryExpression(), "method '" + h.getCalled() + "'");
614 }
615 }
616 }
617 }
618
619 for (ConstructorHolder ch: getCurrentEvalPackage().allPrivateConstructorsOfClass.keySet()) {
620 if (ch.isDangerous()) {
621
622 int paramCount = ch.getASTConstructorDeclaration().getParameterCount();
623 for (ConstructorInvocation ci: getCurrentEvalPackage().calledConstructors) {
624 if (ci.getArgumentCount() == paramCount) {
625
626 addViolation(data, ci.getASTExplicitConstructorInvocation(), "constructor");
627 }
628 }
629 }
630 }
631 }
632
633 removeCurrentEvalPackage();
634 return data;
635 }
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651 private boolean evaluateDangerOfMethods(Map<MethodHolder, List<MethodInvocation>> classMethodMap) {
652
653 boolean found = false;
654 for (Map.Entry<MethodHolder, List<MethodInvocation>> entry: classMethodMap.entrySet()) {
655 MethodHolder h = entry.getKey();
656 List<MethodInvocation> calledMeths = entry.getValue();
657 for (Iterator<MethodInvocation> calledMethsIter = calledMeths.iterator(); calledMethsIter.hasNext() && !h.isDangerous();) {
658
659 MethodInvocation meth = calledMethsIter.next();
660
661 for (MethodHolder h3: classMethodMap.keySet()) {
662 if (h3.isDangerous()) {
663 String matchMethodName = h3.getASTMethodDeclarator().getImage();
664 int matchMethodParamCount = h3.getASTMethodDeclarator().getParameterCount();
665 List<String> parameterTypes = getMethodDeclaratorParameterTypes(h3.getASTMethodDeclarator());
666
667 if (matchMethodName.equals(meth.getName()) && matchMethodParamCount == meth.getArgumentCount()
668 && parameterTypes.equals(meth.getArgumentTypes())) {
669 h.setDangerous();
670 h.setCalledMethod(matchMethodName);
671 found = true;
672 break;
673 }
674 }
675 }
676 }
677 }
678 return found;
679 }
680
681
682
683
684
685
686
687 private void evaluateDangerOfConstructors1(Map<ConstructorHolder, List<MethodInvocation>> classConstructorMap, Set<MethodHolder> evaluatedMethods) {
688
689 for (Map.Entry<ConstructorHolder, List<MethodInvocation>> entry: classConstructorMap.entrySet()) {
690 ConstructorHolder ch = entry.getKey();
691 if (!ch.isDangerous()) {
692
693 List<MethodInvocation> calledMeths = entry.getValue();
694
695 for (Iterator<MethodInvocation> calledMethsIter = calledMeths.iterator(); calledMethsIter.hasNext() && !ch.isDangerous();) {
696 MethodInvocation meth = calledMethsIter.next();
697 String methName = meth.getName();
698 int methArgCount = meth.getArgumentCount();
699
700 for (MethodHolder h: evaluatedMethods) {
701 if (h.isDangerous()) {
702 String matchName = h.getASTMethodDeclarator().getImage();
703 int matchParamCount = h.getASTMethodDeclarator().getParameterCount();
704 List<String> parameterTypes = getMethodDeclaratorParameterTypes(h.getASTMethodDeclarator());
705 if (methName.equals(matchName) && methArgCount == matchParamCount
706 && parameterTypes.equals(meth.getArgumentTypes())) {
707 ch.setDangerous(true);
708
709 break;
710 }
711 }
712 }
713 }
714 }
715 }
716 }
717
718
719
720
721
722
723
724
725
726
727 private boolean evaluateDangerOfConstructors2(Map<ConstructorHolder, List<MethodInvocation>> classConstructorMap) {
728 boolean found = false;
729
730 for (ConstructorHolder ch: classConstructorMap.keySet()) {
731 ConstructorInvocation calledC = ch.getCalledConstructor();
732 if (calledC == null || ch.isDangerous()) {
733 continue;
734 }
735
736
737 int cCount = calledC.getArgumentCount();
738 for (Iterator<ConstructorHolder> innerConstIter = classConstructorMap.keySet().iterator(); innerConstIter.hasNext() && !ch.isDangerous();) {
739 ConstructorHolder h2 = innerConstIter.next();
740 if (h2.isDangerous()) {
741 int matchConstArgCount = h2.getASTConstructorDeclaration().getParameterCount();
742 List<String> parameterTypes = getMethodDeclaratorParameterTypes(h2.getASTConstructorDeclaration());
743 if (matchConstArgCount == cCount && parameterTypes.equals(calledC.getArgumentTypes())) {
744 ch.setDangerous(true);
745 found = true;
746
747 }
748 }
749 }
750 }
751 return found;
752 }
753
754 @Override
755 public Object visit(ASTCompilationUnit node, Object data) {
756 clearEvalPackages();
757 return super.visit(node, data);
758 }
759
760 @Override
761 public Object visit(ASTEnumDeclaration node, Object data) {
762
763 return data;
764 }
765
766
767
768
769
770 @Override
771 public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
772 if (!node.isInterface()) {
773 return visitClassDec(node, data);
774 } else {
775 putEvalPackage(NULL_EVAL_PACKAGE);
776 Object o = super.visit(node, data);
777 removeCurrentEvalPackage();
778 return o;
779 }
780 }
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797 @Override
798 public Object visit(ASTConstructorDeclaration node, Object data) {
799 if (!(getCurrentEvalPackage() instanceof NullEvalPackage)) {
800 List<MethodInvocation> calledMethodsOfConstructor = new ArrayList<MethodInvocation>();
801 ConstructorHolder ch = new ConstructorHolder(node);
802 addCalledMethodsOfNode(node, calledMethodsOfConstructor, getCurrentEvalPackage().className);
803 if (!node.isPrivate()) {
804
805 getCurrentEvalPackage().calledMethods.addAll(calledMethodsOfConstructor);
806
807
808
809 ASTExplicitConstructorInvocation eci = ch.getASTExplicitConstructorInvocation();
810 if (eci != null && eci.isThis()) {
811 getCurrentEvalPackage().calledConstructors.add(ch.getCalledConstructor());
812 }
813 } else {
814
815
816 getCurrentEvalPackage().allPrivateConstructorsOfClass.put(ch, calledMethodsOfConstructor);
817 }
818 }
819 return super.visit(node, data);
820 }
821
822
823
824
825
826
827 @Override
828 public Object visit(ASTMethodDeclarator node, Object data) {
829 if (!(getCurrentEvalPackage() instanceof NullEvalPackage)) {
830 AccessNode parent = (AccessNode) node.jjtGetParent();
831 MethodHolder h = new MethodHolder(node);
832 if (!parent.isAbstract() && !parent.isPrivate() && !parent.isStatic() && !parent.isFinal()) {
833 h.setDangerous();
834 ASTMethodDeclaration decl = node.getFirstParentOfType(ASTMethodDeclaration.class);
835 h.setCalledMethod(decl.getMethodName());
836 }
837 List<MethodInvocation> l = new ArrayList<MethodInvocation>();
838 addCalledMethodsOfNode((Node)parent, l, getCurrentEvalPackage().className);
839 getCurrentEvalPackage().allMethodsOfClass.put(h, l);
840 }
841 return super.visit(node, data);
842 }
843
844
845
846
847
848 private static void addCalledMethodsOfNode(Node node, List<MethodInvocation> calledMethods, String className) {
849 List<ASTPrimaryExpression> expressions = new ArrayList<ASTPrimaryExpression>();
850 node.findDescendantsOfType(ASTPrimaryExpression.class, expressions, !(node instanceof AccessNode));
851 addCalledMethodsOfNodeImpl(expressions, calledMethods, className);
852 }
853
854 private static void addCalledMethodsOfNodeImpl(List<ASTPrimaryExpression> expressions, List<MethodInvocation> calledMethods, String className) {
855 for (ASTPrimaryExpression ape: expressions) {
856 MethodInvocation meth = findMethod(ape, className);
857 if (meth != null) {
858
859 calledMethods.add(meth);
860 }
861 }
862 }
863
864
865
866
867
868
869
870 private static MethodInvocation findMethod(ASTPrimaryExpression node, String className) {
871 if (node.jjtGetNumChildren() > 0
872 && node.jjtGetChild(0).jjtGetNumChildren() > 0
873 && node.jjtGetChild(0).jjtGetChild(0) instanceof ASTLiteral) {
874 return null;
875 }
876 MethodInvocation meth = MethodInvocation.getMethod(node);
877 boolean found = false;
878
879
880
881 if (meth != null) {
882
883 if (meth.getReferenceNames().isEmpty() && !meth.isSuper()) {
884
885
886 List<String> packClass = meth.getQualifierNames();
887 if (!packClass.isEmpty()) {
888 for (String name: packClass) {
889 if (name.equals(className)) {
890 found = true;
891 break;
892 }
893 }
894 } else {
895 found = true;
896 }
897 }
898 }
899
900 return found ? meth : null;
901 }
902
903
904
905
906 private static String getNameFromPrefix(ASTPrimaryPrefix node) {
907 String name = null;
908
909 if (node.jjtGetNumChildren() == 1) {
910 Node nnode = node.jjtGetChild(0);
911 if (nnode instanceof ASTName) {
912 name = ((ASTName) nnode).getImage();
913 }
914 }
915 return name;
916 }
917
918 private static List<String> getMethodDeclaratorParameterTypes(Node methodOrConstructorDeclarator) {
919 List<ASTFormalParameter> parameters = methodOrConstructorDeclarator.findChildrenOfType(ASTFormalParameter.class);
920 List<String> parameterTypes = new ArrayList<String>();
921 if (parameters != null) {
922 for (ASTFormalParameter p : parameters) {
923 ASTType type = p.getFirstChildOfType(ASTType.class);
924 if (type.jjtGetChild(0) instanceof ASTPrimitiveType) {
925 parameterTypes.add(type.jjtGetChild(0).getImage());
926 } else if (type.jjtGetChild(0) instanceof ASTReferenceType) {
927 parameterTypes.add("ref");
928 } else {
929 parameterTypes.add("<unkown>");
930 }
931 }
932 }
933 return parameterTypes;
934 }
935
936 private static List<String> getArgumentTypes(ASTArguments args) {
937 List<String> argumentTypes = new ArrayList<String>();
938 ASTArgumentList argumentList = args.getFirstChildOfType(ASTArgumentList.class);
939 if (argumentList != null) {
940 for (int a = 0; a < argumentList.jjtGetNumChildren(); a++) {
941 Node expression = argumentList.jjtGetChild(a);
942 ASTPrimaryPrefix arg = expression.getFirstDescendantOfType(ASTPrimaryPrefix.class);
943 String type = "<unknown>";
944 if (arg != null && arg.jjtGetNumChildren() > 0) {
945 if (arg.jjtGetChild(0) instanceof ASTLiteral) {
946 ASTLiteral lit = (ASTLiteral) arg.jjtGetChild(0);
947 if (lit.isCharLiteral()) {
948 type = "char";
949 } else if (lit.isFloatLiteral()) {
950 type = "float";
951 } else if (lit.isIntLiteral()) {
952 type = "int";
953 } else if (lit.isStringLiteral()) {
954 type = "String";
955 } else if (lit.jjtGetChild(0) instanceof ASTBooleanLiteral) {
956 type = "boolean";
957 }
958 } else if (arg.jjtGetChild(0) instanceof ASTName) {
959
960 type = "ref";
961 }
962 }
963 argumentTypes.add(type);
964 }
965 }
966 return argumentTypes;
967 }
968 }