6c3dac6caa6a06d737dc3c63ac8171353cd3988c
[IRC.git] / Robust / src / Analysis / SSJava / MethodAnnotationCheck.java
1 package Analysis.SSJava;
2
3 import java.util.HashSet;
4 import java.util.Hashtable;
5 import java.util.Iterator;
6 import java.util.Set;
7
8 import IR.ClassDescriptor;
9 import IR.MethodDescriptor;
10 import IR.Operation;
11 import IR.State;
12 import IR.SymbolTable;
13 import IR.TypeUtil;
14 import IR.Tree.ArrayAccessNode;
15 import IR.Tree.ArrayInitializerNode;
16 import IR.Tree.AssignmentNode;
17 import IR.Tree.BlockExpressionNode;
18 import IR.Tree.BlockNode;
19 import IR.Tree.BlockStatementNode;
20 import IR.Tree.CastNode;
21 import IR.Tree.CreateObjectNode;
22 import IR.Tree.DeclarationNode;
23 import IR.Tree.ExpressionNode;
24 import IR.Tree.FieldAccessNode;
25 import IR.Tree.IfStatementNode;
26 import IR.Tree.InstanceOfNode;
27 import IR.Tree.Kind;
28 import IR.Tree.LoopNode;
29 import IR.Tree.MethodInvokeNode;
30 import IR.Tree.OpNode;
31 import IR.Tree.ReturnNode;
32 import IR.Tree.SubBlockNode;
33 import IR.Tree.SwitchBlockNode;
34 import IR.Tree.SwitchStatementNode;
35 import IR.Tree.TertiaryNode;
36 import Util.Pair;
37
38 public class MethodAnnotationCheck {
39
40   State state;
41   SSJavaAnalysis ssjava;
42   TypeUtil tu;
43
44   Set<MethodDescriptor> annotatedMDSet;
45   Hashtable<MethodDescriptor, Set<MethodDescriptor>> caller2calleeSet;
46
47   public MethodAnnotationCheck(SSJavaAnalysis ssjava, State state, TypeUtil tu) {
48     this.ssjava = ssjava;
49     this.state = state;
50     this.tu = tu;
51     caller2calleeSet = new Hashtable<MethodDescriptor, Set<MethodDescriptor>>();
52     annotatedMDSet = new HashSet<MethodDescriptor>();
53   }
54
55   public void methodAnnoatationCheck() {
56     SymbolTable classtable = state.getClassSymbolTable();
57     HashSet toanalyze = new HashSet();
58     toanalyze.addAll(classtable.getValueSet());
59     toanalyze.addAll(state.getTaskSymbolTable().getValueSet());
60     while (!toanalyze.isEmpty()) {
61       Object obj = toanalyze.iterator().next();
62       ClassDescriptor cd = (ClassDescriptor) obj;
63       toanalyze.remove(cd);
64
65       if (!cd.isInterface()) {
66         for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
67           MethodDescriptor md = (MethodDescriptor) method_it.next();
68           checkMethodBody(cd, md);
69         }
70       }
71
72     }
73
74     for (Iterator iterator = annotatedMDSet.iterator(); iterator.hasNext();) {
75       MethodDescriptor md = (MethodDescriptor) iterator.next();
76       ssjava.addAnnotationRequire(md);
77     }
78
79     Set<Pair> visited = new HashSet<Pair>();
80     Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
81     tovisit.addAll(annotatedMDSet);
82
83     while (!tovisit.isEmpty()) {
84       MethodDescriptor callerMD = tovisit.iterator().next();
85       tovisit.remove(callerMD);
86
87       Set<MethodDescriptor> calleeSet = caller2calleeSet.get(callerMD);
88       if (calleeSet != null) {
89         for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
90           MethodDescriptor calleeMD = (MethodDescriptor) iterator.next();
91           Pair p = new Pair(callerMD, calleeMD);
92           if (!visited.contains(p)) {
93             visited.add(p);
94
95             tovisit.add(calleeMD);
96
97             Set<MethodDescriptor> possibleCalleeSet =
98                 (Set<MethodDescriptor>) ssjava.getCallGraph().getMethods(calleeMD);
99
100             System.out.println("caller=" + callerMD + " callee=" + possibleCalleeSet);
101
102             for (Iterator iterator2 = possibleCalleeSet.iterator(); iterator2.hasNext();) {
103               MethodDescriptor possibleCallee = (MethodDescriptor) iterator2.next();
104
105               if (!possibleCallee.isAbstract()) {
106                 ssjava.addAnnotationRequire(possibleCallee);
107                 tovisit.add(possibleCallee);
108               }
109
110             }
111
112           }
113         }
114       }
115     }
116
117   }
118
119   public void methodAnnoataionInheritanceCheck() {
120     // check If a method is annotated, any method that overrides it should
121     // be annotated.
122
123     Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
124     tovisit.addAll(ssjava.getAnnotationRequireSet());
125
126     while (!tovisit.isEmpty()) {
127       MethodDescriptor md = tovisit.iterator().next();
128       tovisit.remove(md);
129
130       ClassDescriptor cd = md.getClassDesc();
131
132       Set subClassSet = tu.getSubClasses(cd);
133       if (subClassSet != null) {
134         for (Iterator iterator2 = subClassSet.iterator(); iterator2.hasNext();) {
135           ClassDescriptor subCD = (ClassDescriptor) iterator2.next();
136           Set possiblematches = subCD.getMethodTable().getSet(md.getSymbol());
137           for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
138             MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
139             if (md.matches(matchmd)) {
140               if (matchmd.getClassDesc().equals(subCD)) {
141                 ssjava.addAnnotationRequire(matchmd);
142               }
143             }
144           }
145         }
146       }
147
148       // need to check super classess if the current method is inherited from
149       // them, all of ancestor method should be annoated
150       ClassDescriptor currentCd = cd;
151       ClassDescriptor superCd = tu.getSuper(currentCd);
152       while (!superCd.getSymbol().equals("Object")) {
153         Set possiblematches = superCd.getMethodTable().getSet(md.getSymbol());
154         for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
155           MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
156           if (md.matches(matchmd)) {
157             ssjava.addAnnotationRequire(matchmd);
158           }
159         }
160         currentCd = superCd;
161         superCd = tu.getSuper(currentCd);
162       }
163
164       Set<ClassDescriptor> superIFSet = tu.getSuperIFs(cd);
165       for (Iterator iterator = superIFSet.iterator(); iterator.hasNext();) {
166         ClassDescriptor parentInterface = (ClassDescriptor) iterator.next();
167         Set possiblematches = parentInterface.getMethodTable().getSet(md.getSymbol());
168         for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
169           MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
170           if (md.matches(matchmd)) {
171             ssjava.addAnnotationRequire(matchmd);
172           }
173         }
174       }
175
176     }
177
178   }
179
180   private void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
181     BlockNode bn = state.getMethodBody(md);
182     checkBlockNode(md, md.getParameterTable(), bn, false);
183   }
184
185   private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn, boolean flag) {
186     bn.getVarTable().setParent(nametable);
187     String label = bn.getLabel();
188     boolean isSSJavaLoop = flag;
189     if (label != null && label.equals(ssjava.SSJAVA)) {
190       if (isSSJavaLoop) {
191         throw new Error("Only outermost loop can be the self-stabilizing loop.");
192       } else {
193         annotatedMDSet.add(md);
194         isSSJavaLoop = true;
195       }
196     }
197
198     for (int i = 0; i < bn.size(); i++) {
199       BlockStatementNode bsn = bn.get(i);
200       checkBlockStatementNode(md, bn.getVarTable(), bsn, isSSJavaLoop);
201     }
202
203   }
204
205   private void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable,
206       BlockStatementNode bsn, boolean flag) {
207
208     switch (bsn.kind()) {
209     case Kind.SubBlockNode:
210       checkSubBlockNode(md, nametable, (SubBlockNode) bsn, flag);
211       return;
212
213     case Kind.BlockExpressionNode:
214       checkBlockExpressionNode(md, nametable, (BlockExpressionNode) bsn, flag);
215       break;
216
217     case Kind.DeclarationNode:
218       checkDeclarationNode(md, nametable, (DeclarationNode) bsn, flag);
219       break;
220
221     case Kind.IfStatementNode:
222       checkIfStatementNode(md, nametable, (IfStatementNode) bsn, flag);
223       break;
224
225     case Kind.LoopNode:
226       checkLoopNode(md, nametable, (LoopNode) bsn, flag);
227       break;
228
229     case Kind.ReturnNode:
230       checkReturnNode(md, nametable, (ReturnNode) bsn, flag);
231       break;
232
233     case Kind.SwitchStatementNode:
234       checkSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn, flag);
235       return;
236
237     }
238   }
239
240   private void checkSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
241       SwitchStatementNode ssn, boolean flag) {
242
243     checkExpressionNode(md, nametable, ssn.getCondition(), flag);
244
245     BlockNode sbn = ssn.getSwitchBody();
246     for (int i = 0; i < sbn.size(); i++) {
247       checkBlockNode(md, nametable, ((SwitchBlockNode) sbn.get(i)).getSwitchBlockStatement(), flag);
248     }
249
250   }
251
252   private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn,
253       boolean flag) {
254     if (dn.getExpression() != null) {
255       checkExpressionNode(md, nametable, dn.getExpression(), flag);
256     }
257   }
258
259   private void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn,
260       boolean flag) {
261     if (rn.getReturnExpression() != null) {
262       if (md.getReturnType() != null) {
263         checkExpressionNode(md, nametable, rn.getReturnExpression(), flag);
264       }
265     }
266   }
267
268   private void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln, boolean flag) {
269     if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
270       checkExpressionNode(md, nametable, ln.getCondition(), flag);
271       checkBlockNode(md, nametable, ln.getBody(), flag);
272     } else {
273       // For loop case
274       /* Link in the initializer naming environment */
275       BlockNode bn = ln.getInitializer();
276       bn.getVarTable().setParent(nametable);
277       for (int i = 0; i < bn.size(); i++) {
278         BlockStatementNode bsn = bn.get(i);
279         checkBlockStatementNode(md, bn.getVarTable(), bsn, flag);
280       }
281       // check the condition
282       checkExpressionNode(md, bn.getVarTable(), ln.getCondition(), flag);
283       checkBlockNode(md, bn.getVarTable(), ln.getBody(), flag);
284       checkBlockNode(md, bn.getVarTable(), ln.getUpdate(), flag);
285     }
286   }
287
288   private void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable,
289       IfStatementNode isn, boolean flag) {
290     checkExpressionNode(md, nametable, isn.getCondition(), flag);
291     checkBlockNode(md, nametable, isn.getTrueBlock(), flag);
292     if (isn.getFalseBlock() != null) {
293       checkBlockNode(md, nametable, isn.getFalseBlock(), flag);
294     }
295   }
296
297   private void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn,
298       boolean flag) {
299     checkBlockNode(md, nametable.getParent(), sbn.getBlockNode(), flag);
300   }
301
302   private void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable,
303       BlockExpressionNode ben, boolean flag) {
304     checkExpressionNode(md, nametable, ben.getExpression(), flag);
305   }
306
307   private void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en,
308       boolean flag) {
309     switch (en.kind()) {
310     case Kind.AssignmentNode:
311       checkAssignmentNode(md, nametable, (AssignmentNode) en, flag);
312       return;
313
314     case Kind.CastNode:
315       checkCastNode(md, nametable, (CastNode) en, flag);
316       return;
317
318     case Kind.CreateObjectNode:
319       checkCreateObjectNode(md, nametable, (CreateObjectNode) en, flag);
320       return;
321
322     case Kind.FieldAccessNode:
323       checkFieldAccessNode(md, nametable, (FieldAccessNode) en, flag);
324       return;
325
326     case Kind.ArrayAccessNode:
327       checkArrayAccessNode(md, nametable, (ArrayAccessNode) en, flag);
328       return;
329
330       // case Kind.LiteralNode:
331       // checkLiteralNode(md, nametable, (LiteralNode) en, flag);
332       // return;
333
334     case Kind.MethodInvokeNode:
335       checkMethodInvokeNode(md, nametable, (MethodInvokeNode) en, flag);
336       return;
337
338       // case Kind.NameNode:
339       // checkNameNode(md, nametable, (NameNode) en, flag);
340       // return;
341
342     case Kind.OpNode:
343       checkOpNode(md, nametable, (OpNode) en, flag);
344       return;
345
346       // case Kind.OffsetNode:
347       // checkOffsetNode(md, nametable, (OffsetNode) en, flag);
348       // return;
349
350     case Kind.TertiaryNode:
351       checkTertiaryNode(md, nametable, (TertiaryNode) en, flag);
352       return;
353
354     case Kind.InstanceOfNode:
355       checkInstanceOfNode(md, nametable, (InstanceOfNode) en, flag);
356       return;
357
358     case Kind.ArrayInitializerNode:
359       checkArrayInitializerNode(md, nametable, (ArrayInitializerNode) en, flag);
360       return;
361
362       // case Kind.ClassTypeNode:
363       // checkClassTypeNode(md, nametable, (ClassTypeNode) en, flag);
364       // return;
365     }
366   }
367
368   private void checkArrayInitializerNode(MethodDescriptor md, SymbolTable nametable,
369       ArrayInitializerNode ain, boolean flag) {
370
371     for (int i = 0; i < ain.numVarInitializers(); ++i) {
372       checkExpressionNode(md, nametable, ain.getVarInitializer(i), flag);
373     }
374
375   }
376
377   private void checkInstanceOfNode(MethodDescriptor md, SymbolTable nametable, InstanceOfNode tn,
378       boolean flag) {
379     checkExpressionNode(md, nametable, tn.getExpr(), flag);
380   }
381
382   private void checkTertiaryNode(MethodDescriptor md, SymbolTable nametable, TertiaryNode tn,
383       boolean flag) {
384     checkExpressionNode(md, nametable, tn.getCond(), flag);
385     checkExpressionNode(md, nametable, tn.getTrueExpr(), flag);
386     checkExpressionNode(md, nametable, tn.getFalseExpr(), flag);
387   }
388
389   private void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on, boolean flag) {
390
391     checkExpressionNode(md, nametable, on.getLeft(), flag);
392     if (on.getRight() != null) {
393       checkExpressionNode(md, nametable, on.getRight(), flag);
394     }
395
396   }
397
398   private void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable,
399       MethodInvokeNode min, boolean flag) {
400     for (int i = 0; i < min.numArgs(); i++) {
401       ExpressionNode en = min.getArg(i);
402       checkExpressionNode(md, nametable, en, flag);
403     }
404
405     if (min.getExpression() != null) {
406       checkExpressionNode(md, nametable, min.getExpression(), flag);
407     }
408
409     if (flag) {
410       annotatedMDSet.add(min.getMethod());
411     }
412
413     Set<MethodDescriptor> mdSet = caller2calleeSet.get(md);
414     if (mdSet == null) {
415       mdSet = new HashSet<MethodDescriptor>();
416       caller2calleeSet.put(md, mdSet);
417     }
418     mdSet.add(min.getMethod());
419
420   }
421
422   private void checkArrayAccessNode(MethodDescriptor md, SymbolTable nametable,
423       ArrayAccessNode aan, boolean flag) {
424
425     ExpressionNode left = aan.getExpression();
426     checkExpressionNode(md, nametable, left, flag);
427     checkExpressionNode(md, nametable, aan.getIndex(), flag);
428
429   }
430
431   private void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable,
432       FieldAccessNode fan, boolean flag) {
433     ExpressionNode left = fan.getExpression();
434     checkExpressionNode(md, nametable, left, flag);
435   }
436
437   private void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable,
438       CreateObjectNode con, boolean flag) {
439
440     for (int i = 0; i < con.numArgs(); i++) {
441       ExpressionNode en = con.getArg(i);
442       checkExpressionNode(md, nametable, en, flag);
443     }
444
445   }
446
447   private void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, boolean flag) {
448     ExpressionNode en = cn.getExpression();
449     checkExpressionNode(md, nametable, en, flag);
450   }
451
452   private void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an,
453       boolean flag) {
454     boolean postinc = true;
455
456     if (an.getOperation().getBaseOp() == null
457         || (an.getOperation().getBaseOp().getOp() != Operation.POSTINC && an.getOperation()
458             .getBaseOp().getOp() != Operation.POSTDEC))
459       postinc = false;
460
461     if (!postinc) {
462       checkExpressionNode(md, nametable, an.getSrc(), flag);
463     }
464
465     checkExpressionNode(md, nametable, an.getDest(), flag);
466
467   }
468
469 }