BindingAutomatonProvider bindings = new BindingAutomatonProvider();
RuntimeResolver rr = new RuntimeResolver(bindings);
List<RuntimeHotspot> runtimeHotspots = rr.getHotspots();
AnnotationAnalyzer aa = new AnnotationAnalyzer(bindings);
Set<ValueBox> annotationHotspots = aa.getHotspots();
// if there were static type errors in the @Type annotations then report those and abort
if (aa.getErrors().size() > 0) {
log.error("STATIC TYPE ERRORS");
for (StaticTypeError error : aa.getErrors()) {
log.error(error.getMessage());
}
return;
}
int numHotspots = runtimeHotspots.size() + annotationHotspots.size();
log.info("HOTSPOTS");
log.info("From runtime system: " + runtimeHotspots.size());
log.info("From annotations: " + annotationHotspots.size());
log.info("Total: " + numHotspots);
List<ValueBox> allHotspots = new ArrayList<ValueBox>();
allHotspots.addAll(rr.getHotspotExps());
allHotspots.addAll(annotationHotspots);
// add resolvers
StringAnalysis.addResolver(rr);
// add custom resolvers
for (Class<?> clazz : customResolvers) {
Object o = clazz.newInstance();
if (!(o instanceof Resolver)) {
throw new RuntimeException(clazz.getCanonicalName() + " does not implement " + Resolver.class.getCanonicalName());
}
Resolver resolver = (Resolver)o;
StringAnalysis.addResolver(resolver);
}
// create external visibility
ExternalVisibility ext = null;
if (external != null) {
Object o = external.newInstance();
if (!(o instanceof ExternalVisibility)) {
throw new RuntimeException(external.getCanonicalName() + " does not implement " + ExternalVisibility.class.getCanonicalName());
}
ext = (ExternalVisibility) o;
}
StringAnalysis sa = new StringAnalysis(allHotspots, ext);
long time2 = System.currentTimeMillis();
// report results for runtime hotspots
for (RuntimeHotspot rh : runtimeHotspots) {
ValueBox e = rh.spot;
String sf = sa.getSourceFile(e);
int line = sa.getLineNumber(e);
String kind = "";
if (rh.kind == HotspotKind.ANALYZE) {
kind = "Strings.analyze()";
} else if (rh.kind == HotspotKind.CHECK) {
kind = "Strings.check()";
} else {
log.fatal("unrecognized runtime method!");
System.exit(1);
}
log.info("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)) {
log.info("Exact match!");
} else {
log.info("Always satisfied!");
}
} else {
log.info("Dissatisfied by:");
log.info("\"" + Misc.escape(diff.getShortestExample(true)) + "\"");
}
} else if (rh.kind == HotspotKind.CHECK) {
if (a.intersection(expected_neg).isEmpty()) {
log.info("Always satisfied!");
} else if (a.intersection(rh.expected).isEmpty()) {
log.info("Never satisfied!");
}
}
}
// report results for annotation hotspots
for (ValueBox box : annotationHotspots) {
String sf = sa.getSourceFile(box);
int line = sa.getLineNumber(box);
Automaton auto = sa.getAutomaton(box);
Automaton expected = aa.getAutomaton(box);
System.out.print(sf + ":" + line + " ");
if (!auto.subsetOf(expected)) {
Automaton violating = auto.minus(expected);
String example = Misc.escape(violating.getShortestExample(true));
String type = aa.getDescription(expected);
if (type.length() > 25) // 25 is completely arbitrary
type = type.substring(0, 21) + "...";
log.info("ERROR: The type \"" + type + "\" is violated by:");
log.info(" \"" + example + "\"");
} else {