Package ai.codestatistics

Source Code of ai.codestatistics.AIAnalysis

package ai.codestatistics;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;

import ai.JavaAIPlugin;
import ai.actions.AnalysisErrorHandler;
import ai.actions.AnalysisErrorHandler.ErrorEntry;
import ai.actions.ExecutionUtils;
import ai.cfg.CFGVertice;
import ai.cfg.InterestingCodeFragment;
import ai.cfg.MethodCFGBuilder;
import ai.cfg.MethodControlFlowGraph;
import ai.cfg.MethodFinder;
import ai.codestatistics.DomainComparator.ComparisonResult;
import ai.codestatistics.preferences.AnalysisPreferences;
import ai.codestatistics.preferences.DomainEntry;
import ai.common.Pair;
import ai.domain.AbstractSemanticsIntf;
import ai.domain.DomainIntf;
import ai.domain.boolintv.BoolIntvSemantics;
import ai.domain.boxes.IntegerBoxesSemantics;
import codeStatistics.extension.IAnalysisFunction;
import codeStatistics.extension.IAnalysisPlugin;

import com.google.common.collect.Multimap;

public class AIAnalysis implements IAnalysisPlugin{
  private int timeoutSeconds = 60;
 
  public class AIAnalysisResult {
    public Map<String, Object> after = new HashMap<String, Object>();
    public Map<String, Object> before = new HashMap<String, Object>();
    public Map<String, Object> loops = new HashMap<String, Object>();
    void setResultBefore(String semantics, Object result) {
      if (before.containsKey(semantics))
        throw new RuntimeException("Duplicate before value!!");
      before.put(semantics, result);
    }

    void setResultAfter(String semantics, Object result) {
      if (after.containsKey(semantics))
        throw new RuntimeException("Duplicate after value!!");
      after.put(semantics, result);
    }
   
    void setLoopInvariant(String semantics, Object result) {
      if (loops.containsKey(semantics))
        throw new RuntimeException("Duplicate loop invariant!!");
      loops.put(semantics, result);
    }
  }

  private AnalysisErrorHandler aeh;
  private Map<String, AbstractSemanticsIntf<?>> semanticsToApply = null;

  @Override
  public String getName() {
    return "JavaAI analysis";
  }
 
  private AbstractSemanticsIntf<?> getSemantics(String repr) {
    if (repr.equals("intv"))
      return new BoolIntvSemantics();
    if (repr.equals("boxes"))
      return new IntegerBoxesSemantics("");
    if (repr.startsWith("boxes:"))
      return new IntegerBoxesSemantics(repr.substring("boxes:".length()));
    throw new RuntimeException("Unknown domain description");
  }
 
  private Map<String, AbstractSemanticsIntf<?>> getSemanticsToUse(){
    Map<String, AbstractSemanticsIntf<?>> result = new HashMap<String,AbstractSemanticsIntf<?>>();
    timeoutSeconds = JavaAIPlugin.getDefault().getPreferenceStore().getInt(AnalysisPreferences.ANALYSIS_TIMEOUT);
//    String domains = JavaAIPlugin.getDefault().getPreferenceStore().getString(AnalysisPreferences.DOMAINS_PREFERENCE);
    for(DomainEntry entry: AnalysisPreferences.loadDomains(JavaAIPlugin.getDefault().getPreferenceStore().getString(AnalysisPreferences.DOMAINS_PREFERENCE)))
      result.put(entry.name, getSemantics(entry.repr));
    return result;
  }
 
  private MethodControlFlowGraph buildGraph(InterestingCodeFragment codeFragment){
    //TODO: log errors!!
    try {
       return MethodCFGBuilder.buildCFG(codeFragment);
    } catch (RuntimeException e) {
      System.err.println("Error building graph for:" + codeFragment.getUniqueName());
      e.printStackTrace(System.err);
      throw e;
    }
  }
 
  private AIAnalysisResult getOrCreateResult(Map<ASTNode, AIAnalysisResult> result, ASTNode node) {
    AIAnalysisResult res = result.get(node);
    if (res != null)
      return res;
    res = new AIAnalysisResult();
    result.put(node, res);
    return res;
  }
 
  private void analyseResult(String semantics, Map<CFGVertice, ?> results,
      Pair<Multimap<CFGVertice, ASTNode>, Multimap<CFGVertice, ASTNode>> mappings,
      Map<ASTNode, AIAnalysisResult> result, Map<CFGVertice, ASTNode> loopVertices) {
    if (results == null) // something was wrong, ignore
      return;
    for(Map.Entry<CFGVertice, ?> resultEntry: results.entrySet()){
      CFGVertice vertice = resultEntry.getKey();
      for(ASTNode nodeBeforeVertice: mappings.left.get(vertice))
        getOrCreateResult(result, nodeBeforeVertice).setResultAfter(semantics, resultEntry.getValue());
      for(ASTNode nodeAfterVertice: mappings.right.get(vertice))
        getOrCreateResult(result, nodeAfterVertice).setResultBefore(semantics, resultEntry.getValue());
      ASTNode loopNode = loopVertices.get(vertice);
      if (loopNode !=null)
        getOrCreateResult(result, loopNode).setLoopInvariant(semantics, resultEntry.getValue());
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public Map<ASTNode, Object> analyse(CompilationUnit cu) {
    System.gc(); // FIXME: trying to solve memory issues
    Map<ASTNode, AIAnalysisResult> result = new HashMap<ASTNode, AIAnalysisResult>();
    for (InterestingCodeFragment codeFragment: MethodFinder.findMethods(cu)) {
      MethodControlFlowGraph graph = buildGraph(codeFragment);
      if (graph == null)
        continue;
     
      Pair<Multimap<CFGVertice, ASTNode>, Multimap<CFGVertice, ASTNode>> mappings = graph.getVerticeMappings();
      Map<CFGVertice, ASTNode> loopVerticesMap = graph.getLoopVerticesMapping();
     
      for(Map.Entry<String, AbstractSemanticsIntf<?>> entry: semanticsToApply.entrySet()) {       
        Map<CFGVertice, ?> results = ExecutionUtils.analyseOne(graph, entry.getValue(), aeh, codeFragment, timeoutSeconds);
        if (results == null) {
          results = new HashMap<CFGVertice, Object>();
          for(CFGVertice vertice: graph.getVertices())
            results.put(vertice, null);
        }
        analyseResult(entry.getKey(), results, mappings, result, loopVerticesMap);
      }
    }
    Map<ASTNode, ?> res = result;
    return (Map<ASTNode, Object>) res;
  }

  @Override
  public void initialiseAnalysis() {
    this.aeh = new AnalysisErrorHandler();
    this.semanticsToApply = getSemanticsToUse();
  }
 
  // functions
 
  private class GetDomainValue implements IAnalysisFunction {
    private final boolean beforeOrAfter;

    public GetDomainValue(boolean beforeOrAfter) {
      this.beforeOrAfter = beforeOrAfter;
    }
   
    @Override
    public String getName() {
      String suffix = beforeOrAfter ? "before" : "after";
      return "dom_"+suffix;
    }

    @Override
    public Object execute(Object[] args, Map<ASTNode, Object> analysisResult) {
      AIAnalysisResult res = (AIAnalysisResult) analysisResult.get(args[1]);
      if (beforeOrAfter)
        return res.before.get(args[0]);
      else
        return res.after.get(args[0]);
    }

    @Override
    public Class<?>[] getArgumentType() {
      return new Class<?>[]{String.class, ASTNode.class};
    }

    @Override
    public Class<?> getResultType() {
      return DomainIntf.class;
    }
  }

  private class GetLoopInvariantValue implements IAnalysisFunction {
    public GetLoopInvariantValue() {
    }
   
    @Override
    public String getName() {
      return "dom_invariant";
    }

    @Override
    public Object execute(Object[] args, Map<ASTNode, Object> analysisResult) {
      AIAnalysisResult res = (AIAnalysisResult) analysisResult.get(args[1]);
      return res.loops.get(args[0]);
    }

    @Override
    public Class<?>[] getArgumentType() {
      return new Class<?>[]{String.class, ASTNode.class};
    }

    @Override
    public Class<?> getResultType() {
      return DomainIntf.class;
    }
  }
 
  private class IsTop implements IAnalysisFunction {

    @Override
    public String getName() {
      return "isTop";
    }

    @Override
    public Object execute(Object[] object, Map<ASTNode, Object> context) {
      DomainIntf<?> di = (DomainIntf<?>) object[0];
      return di.isTop();
    }

    @Override
    public Class<?>[] getArgumentType() {
      return new Class<?>[]{DomainIntf.class};
    }

    @Override
    public Class<?> getResultType() {
      return Boolean.class;
    }
   
  }
 
  private class LtDomains implements IAnalysisFunction {

    @Override
    public String getName() {
      return "lt";
    }

    @Override
    public Object execute(Object[] args, Map<ASTNode, Object> context) {
      DomainIntf<?> left = (DomainIntf<?>) args[0];
      DomainIntf<?> right = (DomainIntf<?>) args[1];
      ComparisonResult res = DomainComparator.compare(left, right);
      return res == ComparisonResult.RIGHT;
    }

    @Override
    public Class<?>[] getArgumentType() {
      return new Class<?>[]{DomainIntf.class, DomainIntf.class};
    }

    @Override
    public Class<?> getResultType() {
      return Boolean.class;
    }
  }
 
  private class IncomparableDomains implements IAnalysisFunction {

    @Override
    public String getName() {
      return "incomparable";
    }

    @Override
    public Object execute(Object[] args, Map<ASTNode, Object> context) {
      DomainIntf<?> left = (DomainIntf<?>) args[0];
      DomainIntf<?> right = (DomainIntf<?>) args[1];
      ComparisonResult res = DomainComparator.compare(left, right);
      return res == ComparisonResult.UNCOMPARABLE;
    }

    @Override
    public Class<?>[] getArgumentType() {
      return new Class<?>[]{DomainIntf.class, DomainIntf.class};
    }

    @Override
    public Class<?> getResultType() {
      return Boolean.class;
    }
  }
 
  @Override
  public List<IAnalysisFunction> getExtensionFunctions() {
    List<IAnalysisFunction> result = new LinkedList<IAnalysisFunction>();
    result.add(new GetDomainValue(true));
    result.add(new GetDomainValue(false));
    result.add(new IsTop());
    result.add(new LtDomains());
    result.add(new IncomparableDomains());
    result.add(new GetLoopInvariantValue());
    return result;
  }

  @Override
  public String getSummary() {
    StringBuilder builder = new StringBuilder();
    for(ErrorEntry entry: aeh.errors){
      builder.append("Code fragment: " + entry.codeFragment.getUniqueName());
      builder.append("\n");
      builder.append("ERROR:" + entry.error);
      builder.append("\n");
      builder.append("Domain:" + entry.semantics);
      builder.append("\n");
      builder.append("-----------------------------------\n");
    }
    return builder.toString();
  }
}
TOP

Related Classes of ai.codestatistics.AIAnalysis

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.