Package dk.brics.string.annotation

Source Code of dk.brics.string.annotation.Transformer

package dk.brics.string.annotation;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import soot.Body;
import soot.BodyTransformer;
import soot.Value;
import soot.ValueBox;
import soot.jimple.IdentityStmt;
import soot.jimple.InvokeExpr;
import soot.jimple.ParameterRef;
import soot.jimple.Stmt;
import soot.tagkit.StringTag;
import dk.brics.automaton.Automaton;
import dk.brics.string.HotspotKind;
import dk.brics.string.RuntimeHotspot;
import dk.brics.string.RuntimeResolver;
import dk.brics.string.StringAnalysis;

public class Transformer extends BodyTransformer {

  public StringAnalysis sa = null;
  public AnnotationAnalyzer analyzer = null;
  public HotspotTagger tagger = null;
  public static final String PHASE_NAME = "jsatagger";
  public static final String TAG_TYPE = "Annotation Checker";
 
  // NOTE: According to SOOT coding rules, this is not the correct way of
  // providing a singleton. Instead one should add the class name to
  // %SOOTHOME/src/singletons.list and then run:
  // %SOOTHOME/src/make_singletons > soot/src/soot/Singletons.java
  // and then provide:
  // 1. public JSATransformer(Singletons.G.global g) {}
  // 2. public static JSATransformer v() {return G.v().<singleton_name>}
  // This is so that when resetting soot by calling G.v().reset() this
  // class will also be reset.
  private static Transformer instance = new Transformer()
  private Transformer() {} 
  public static Transformer v() {return instance;}

  @SuppressWarnings("unchecked")
  @Override
  protected void internalTransform(Body body, String arg1, Map arg2) {
    //This method is called several times, but we only need to do
    //some work the first time the method is called. Therefore we
    //check if the sa field is null
    if (sa == null) {
      RuntimeResolver rr = new RuntimeResolver();
      StringAnalysis.addResolver(rr);
     
      analyzer = new AnnotationAnalyzer();
      tagger = new HotspotTagger();
     
      Set<ValueBox> hotspots = new HashSet<ValueBox>();
      hotspots.addAll(analyzer.getHotspots());
      hotspots.addAll(rr.getHotspotExps());
     
      sa = new StringAnalysis(hotspots);
     
      handleAnnotationHotspots();
      handleAnalyzeRuntimeHotspots(rr);
    }
  }
 
  private void handleAnnotationHotspots() {
    for (ValueBox box : analyzer.getHotspots()) {
      //Stmt stmt = analyzer.getStmt(box);
      Stmt stmt = tagger.getStmt(box);
      Automaton a = analyzer.getAutomaton(box);
      Automaton b = sa.getAutomaton(box);
      Automaton diff = a.complement().intersection(b);
      if (!diff.isEmpty()) {
        String from;
        if (b.isTotal()) {
          from = "anystring";
        }
        else {
          from = quoteString(diff.getShortestExample(true));
        }
        if (stmt.containsInvokeExpr()) {
          InvokeExpr invoke = stmt.getInvokeExpr();
          for (int i=0; i<invoke.getArgCount(); i++) {
            if (box == invoke.getArgBox(i)) {
              stmt.addTag(new StringTag("Type mismatch: cannot convert argument number " + (i+1) + " from " + from + " to " + analyzer.getDescription(a)));
            }
          }
        }
        else if (stmt instanceof IdentityStmt) {
          IdentityStmt iStmt = (IdentityStmt)stmt;
          Value rvalue = iStmt.getRightOp();
          if (rvalue instanceof ParameterRef) {
            ParameterRef parameter = (ParameterRef)rvalue;
            int index = parameter.getIndex();
            stmt.addTag(new StringTag("Type mismatch: cannot convert parameter number " + (index + 1) + " from " + from + " to " + analyzer.getDescription(a)));
          }
        }
        else {
          stmt.addTag(new StringTag("Type mismatch: cannot convert from " + from + " to " + analyzer.getDescription(a)));
        }
      }
    }
  }
 
  private void handleAnalyzeRuntimeHotspots(RuntimeResolver rr) {
    List<RuntimeHotspot> runtime_hotspots = rr.getHotspots();
    for (RuntimeHotspot rh : runtime_hotspots) {
      ValueBox e = rh.spot;
      String sf = sa.getSourceFile(e);
      int line = sa.getLineNumber(e);
      String kind = "";
      if (rh.kind==HotspotKind.ANALYZE)
        kind = "RegExp.analyze()";
      else if (rh.kind==HotspotKind.CHECK)
        kind = "RegExp.check()";
      else {
        System.err.println("unrecognized runtime method!");
        System.exit(1);
      }
      System.err.println("Checking "+kind+" at line "+line+" in "+sf+"...");
      Automaton a = sa.getAutomaton(e);
      Automaton expected_neg = rh.expected.complement();
      if (rh.kind==HotspotKind.ANALYZE) {
        Automaton diff = a.intersection(expected_neg);
        if (diff.isEmpty())
          if (a.equals(rh.expected))
            System.err.println("Exact match!");
          else
            System.err.println("Always satified!");
        else {
          System.err.println("Dissatisfied by:");
          System.err.println(quoteString(diff.getShortestExample(true)));
          tagger.tag(e, "Dissatisfied by: " + quoteString(diff.getShortestExample(true)));
        }
      } else if (rh.kind==HotspotKind.CHECK) {
        if (a.intersection(expected_neg).isEmpty())
          System.err.println("Always satified!");
        else if (a.intersection(rh.expected).isEmpty()) {
          System.err.println("Never satified!");
          tagger.tag(e, "Never satified!");
        }
      }
    }
  }
 
  private static String quoteString(String s) {
    StringBuilder sb = new StringBuilder();
    sb.append("\"");
    for (int i = 0 ; i < s.length() ; i++) {
      char c = s.charAt(i);
      switch (c) {
      case '\t': sb.append("\\t"); break;
      case '\n': sb.append("\\n"); break;
      case '\r': sb.append("\\r"); break;
      case '\"': sb.append("\\\""); break;
      case '\\': sb.append("\\\\"); break;
      default:
        if (c >= 32 && c <= 126)
          sb.append(c);
        else {
          String digits = Integer.toHexString(0x10000+c);
          sb.append("\\u").append(digits.substring(1));
        }
      }
    }
    sb.append("\"");
    return sb.toString();
  }
 
  public void reset() {
    sa = null;
    analyzer = null;
    tagger = null;
  }
}
TOP

Related Classes of dk.brics.string.annotation.Transformer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.