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