changes.
[IRC.git] / Robust / src / Analysis / SSJava / MethodAnnotationCheck.java
index 9f61ee213d1e8545b14f7dbfcecb0512384454b3..9ed0123f3bf71c9e0e6358c146fb30ab3b321fb9 100644 (file)
@@ -4,7 +4,9 @@ import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.Vector;
 
+import IR.AnnotationDescriptor;
 import IR.ClassDescriptor;
 import IR.MethodDescriptor;
 import IR.Operation;
@@ -30,6 +32,8 @@ import IR.Tree.MethodInvokeNode;
 import IR.Tree.OpNode;
 import IR.Tree.ReturnNode;
 import IR.Tree.SubBlockNode;
+import IR.Tree.SwitchBlockNode;
+import IR.Tree.SwitchStatementNode;
 import IR.Tree.TertiaryNode;
 import Util.Pair;
 
@@ -59,17 +63,22 @@ public class MethodAnnotationCheck {
       Object obj = toanalyze.iterator().next();
       ClassDescriptor cd = (ClassDescriptor) obj;
       toanalyze.remove(cd);
-      if (!cd.isInterface()) {
+
+      if (!ssjava.isSSJavaUtil(cd) && !cd.isInterface()) {
         for (Iterator method_it = cd.getMethods(); method_it.hasNext();) {
           MethodDescriptor md = (MethodDescriptor) method_it.next();
+          checkTrustworthyMethodAnnotation(md);
           checkMethodBody(cd, md);
         }
       }
+
     }
 
     for (Iterator iterator = annotatedMDSet.iterator(); iterator.hasNext();) {
       MethodDescriptor md = (MethodDescriptor) iterator.next();
-      ssjava.putHasAnnotation(md);
+      if (!ssjava.isTrustMethod(md)) {
+        ssjava.addAnnotationRequire(md);
+      }
     }
 
     Set<Pair> visited = new HashSet<Pair>();
@@ -79,6 +88,7 @@ public class MethodAnnotationCheck {
     while (!tovisit.isEmpty()) {
       MethodDescriptor callerMD = tovisit.iterator().next();
       tovisit.remove(callerMD);
+
       Set<MethodDescriptor> calleeSet = caller2calleeSet.get(callerMD);
       if (calleeSet != null) {
         for (Iterator iterator = calleeSet.iterator(); iterator.hasNext();) {
@@ -86,8 +96,25 @@ public class MethodAnnotationCheck {
           Pair p = new Pair(callerMD, calleeMD);
           if (!visited.contains(p)) {
             visited.add(p);
-            tovisit.add(calleeMD);
-            ssjava.putHasAnnotation(calleeMD);
+
+            if (!ssjava.isTrustMethod(callerMD) && !ssjava.isTrustMethod(calleeMD)) {
+              // if method is annotated as "TRUST", do not need to check for
+              // linear type & flow-down rule
+              tovisit.add(calleeMD);
+
+              Set<MethodDescriptor> possibleCalleeSet =
+                  (Set<MethodDescriptor>) ssjava.getCallGraph().getMethods(calleeMD);
+
+              for (Iterator iterator2 = possibleCalleeSet.iterator(); iterator2.hasNext();) {
+                MethodDescriptor possibleCallee = (MethodDescriptor) iterator2.next();
+
+                if (!possibleCallee.isAbstract() && !possibleCallee.getModifiers().isNative()) {
+                  ssjava.addAnnotationRequire(possibleCallee);
+                  tovisit.add(possibleCallee);
+                }
+              }
+            }
+
           }
         }
       }
@@ -95,12 +122,25 @@ public class MethodAnnotationCheck {
 
   }
 
+  private void checkTrustworthyMethodAnnotation(MethodDescriptor md) {
+    // method annotation parsing
+    Vector<AnnotationDescriptor> methodAnnotations = md.getModifiers().getAnnotations();
+    if (methodAnnotations != null) {
+      for (int i = 0; i < methodAnnotations.size(); i++) {
+        AnnotationDescriptor an = methodAnnotations.elementAt(i);
+        if (an.getMarker().equals(ssjava.TRUST)) {
+          ssjava.addTrustMethod(md);
+        }
+      }
+    }
+  }
+
   public void methodAnnoataionInheritanceCheck() {
     // check If a method is annotated, any method that overrides it should
     // be annotated.
 
     Set<MethodDescriptor> tovisit = new HashSet<MethodDescriptor>();
-    tovisit.addAll(ssjava.getMd2hasAnnotation().keySet());
+    tovisit.addAll(ssjava.getAnnotationRequireSet());
 
     while (!tovisit.isEmpty()) {
       MethodDescriptor md = tovisit.iterator().next();
@@ -117,12 +157,43 @@ public class MethodAnnotationCheck {
             MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
             if (md.matches(matchmd)) {
               if (matchmd.getClassDesc().equals(subCD)) {
-                ssjava.putHasAnnotation(matchmd);
+                ssjava.addAnnotationRequire(matchmd);
               }
             }
           }
         }
       }
+
+      // need to check super classess if the current method is inherited from
+      // them, all of ancestor method should be annotated.
+
+      ClassDescriptor curClassDesc;
+      ClassDescriptor parentClassDesc = cd;
+
+      while (!parentClassDesc.getSymbol().equals("Object")) {
+        curClassDesc = parentClassDesc;
+        parentClassDesc = tu.getSuper(curClassDesc);
+        Set possiblematches = parentClassDesc.getMethodTable().getSet(md.getSymbol());
+        for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
+          MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
+          if (md.matches(matchmd)) {
+            ssjava.addAnnotationRequire(matchmd);
+          }
+        }
+      }
+
+      Set<ClassDescriptor> superIFSet = tu.getSuperIFs(cd);
+      for (Iterator iterator = superIFSet.iterator(); iterator.hasNext();) {
+        ClassDescriptor parentInterface = (ClassDescriptor) iterator.next();
+        Set possiblematches = parentInterface.getMethodTable().getSet(md.getSymbol());
+        for (Iterator methodit = possiblematches.iterator(); methodit.hasNext();) {
+          MethodDescriptor matchmd = (MethodDescriptor) methodit.next();
+          if (md.matches(matchmd)) {
+            ssjava.addAnnotationRequire(matchmd);
+          }
+        }
+      }
+
     }
 
   }
@@ -134,20 +205,10 @@ public class MethodAnnotationCheck {
 
   private void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn, boolean flag) {
     bn.getVarTable().setParent(nametable);
-    String label = bn.getLabel();
-    boolean isSSJavaLoop = flag;
-    if (label != null && label.equals(ssjava.SSJAVA)) {
-      if (isSSJavaLoop) {
-        throw new Error("Only outermost loop can be the self-stabilizing loop.");
-      } else {
-        annotatedMDSet.add(md);
-        isSSJavaLoop = true;
-      }
-    }
 
     for (int i = 0; i < bn.size(); i++) {
       BlockStatementNode bsn = bn.get(i);
-      checkBlockStatementNode(md, bn.getVarTable(), bsn, isSSJavaLoop);
+      checkBlockStatementNode(md, bn.getVarTable(), bsn, flag);
     }
 
   }
@@ -180,9 +241,25 @@ public class MethodAnnotationCheck {
       checkReturnNode(md, nametable, (ReturnNode) bsn, flag);
       break;
 
+    case Kind.SwitchStatementNode:
+      checkSwitchStatementNode(md, nametable, (SwitchStatementNode) bsn, flag);
+      return;
+
     }
   }
 
+  private void checkSwitchStatementNode(MethodDescriptor md, SymbolTable nametable,
+      SwitchStatementNode ssn, boolean flag) {
+
+    checkExpressionNode(md, nametable, ssn.getCondition(), flag);
+
+    BlockNode sbn = ssn.getSwitchBody();
+    for (int i = 0; i < sbn.size(); i++) {
+      checkBlockNode(md, nametable, ((SwitchBlockNode) sbn.get(i)).getSwitchBlockStatement(), flag);
+    }
+
+  }
+
   private void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn,
       boolean flag) {
     if (dn.getExpression() != null) {
@@ -200,9 +277,22 @@ public class MethodAnnotationCheck {
   }
 
   private void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln, boolean flag) {
+
+    String label = ln.getLabel();
+    boolean isSSJavaLoop = flag;
+    if (label != null && label.equals(ssjava.SSJAVA)) {
+      if (isSSJavaLoop) {
+        throw new Error("Only outermost loop can be the self-stabilizing loop.");
+      } else {
+        ssjava.setMethodContainingSSJavaLoop(md);
+        annotatedMDSet.add(md);
+        isSSJavaLoop = true;
+      }
+    }
+
     if (ln.getType() == LoopNode.WHILELOOP || ln.getType() == LoopNode.DOWHILELOOP) {
-      checkExpressionNode(md, nametable, ln.getCondition(), flag);
-      checkBlockNode(md, nametable, ln.getBody(), flag);
+      checkExpressionNode(md, nametable, ln.getCondition(), isSSJavaLoop);
+      checkBlockNode(md, nametable, ln.getBody(), isSSJavaLoop);
     } else {
       // For loop case
       /* Link in the initializer naming environment */
@@ -210,12 +300,12 @@ public class MethodAnnotationCheck {
       bn.getVarTable().setParent(nametable);
       for (int i = 0; i < bn.size(); i++) {
         BlockStatementNode bsn = bn.get(i);
-        checkBlockStatementNode(md, bn.getVarTable(), bsn, flag);
+        checkBlockStatementNode(md, bn.getVarTable(), bsn, isSSJavaLoop);
       }
       // check the condition
-      checkExpressionNode(md, bn.getVarTable(), ln.getCondition(), flag);
-      checkBlockNode(md, bn.getVarTable(), ln.getBody(), flag);
-      checkBlockNode(md, bn.getVarTable(), ln.getUpdate(), flag);
+      checkExpressionNode(md, bn.getVarTable(), ln.getCondition(), isSSJavaLoop);
+      checkBlockNode(md, bn.getVarTable(), ln.getBody(), isSSJavaLoop);
+      checkBlockNode(md, bn.getVarTable(), ln.getUpdate(), isSSJavaLoop);
     }
   }