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