Prune constructor and method signatures after removing unused fields
Removing an unused field sometimes means removing constructor code that used to initialize that field. Removing that initialization code sometimes leaves whole constructor arguments unused. Removing those unused arguments can leave us with unused code to compute those arguments in constructors' callers, and so on. This commit tries to clean all of this up, working backward from the unused fields that an earlier commit already removed. Hopefully I have avoided removing upstream code that had other important side effects, but it wouldn't hurt for a WALA expert to review this change carefully.
This commit is contained in:
parent
b4e5d078dd
commit
42c7866dfd
|
@ -288,7 +288,7 @@ public abstract class JDTJava2CAstTranslator<T extends Position> {
|
|||
private final T fSourcePosition;
|
||||
|
||||
public ClassEntity(ITypeBinding jdtType, String name, Collection<CAstQualifier> quals, Collection<CAstEntity> entities,
|
||||
T pos, Set<CAstAnnotation> annotations) {
|
||||
T pos) {
|
||||
fName = name;
|
||||
fQuals = quals;
|
||||
fEntities = entities;
|
||||
|
@ -531,9 +531,7 @@ public abstract class JDTJava2CAstTranslator<T extends Position> {
|
|||
|
||||
Collection<CAstQualifier> quals = JDT2CAstUtils.mapModifiersToQualifiers(modifiers, isInterface, isAnnotation);
|
||||
|
||||
Set<CAstAnnotation> annotations = handleAnnotations(typeBinding);
|
||||
|
||||
return new ClassEntity(typeBinding, name, quals, memberEntities, makePosition(n), annotations);
|
||||
return new ClassEntity(typeBinding, name, quals, memberEntities, makePosition(n));
|
||||
}
|
||||
|
||||
private CAstEntity visit(AnonymousClassDeclaration n, WalkContext context) {
|
||||
|
|
|
@ -91,7 +91,7 @@ public abstract class FieldBasedCallGraphBuilder {
|
|||
private MethodTargetSelector setupMethodTargetSelector(IClassHierarchy cha, JavaScriptConstructorFunctions constructors2, AnalysisOptions options) {
|
||||
MethodTargetSelector result = new JavaScriptConstructTargetSelector(constructors2, options.getMethodTargetSelector());
|
||||
if (options instanceof JSAnalysisOptions && ((JSAnalysisOptions)options).handleCallApply()) {
|
||||
result = new JavaScriptFunctionApplyTargetSelector(new JavaScriptFunctionDotCallTargetSelector(result, cache));
|
||||
result = new JavaScriptFunctionApplyTargetSelector(new JavaScriptFunctionDotCallTargetSelector(result));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder {
|
|||
|
||||
SSAContextInterpreter contextInterpreter = setupSSAContextInterpreter(cha, options, cache, appContextInterpreter);
|
||||
|
||||
setupMethodTargetSelector(cha, options, cache);
|
||||
setupMethodTargetSelector(cha, options);
|
||||
|
||||
setupContextSelector(options, appContextSelector, doOneCFA);
|
||||
|
||||
|
@ -71,11 +71,11 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder {
|
|||
}
|
||||
|
||||
|
||||
private void setupMethodTargetSelector(IClassHierarchy cha, JSAnalysisOptions options, IAnalysisCacheView cache) {
|
||||
private void setupMethodTargetSelector(IClassHierarchy cha, JSAnalysisOptions options) {
|
||||
MethodTargetSelector targetSelector = new JavaScriptConstructTargetSelector(cha, options
|
||||
.getMethodTargetSelector());
|
||||
if (options.handleCallApply()) {
|
||||
targetSelector = new JavaScriptFunctionApplyTargetSelector(new JavaScriptFunctionDotCallTargetSelector(targetSelector, cache));
|
||||
targetSelector = new JavaScriptFunctionApplyTargetSelector(new JavaScriptFunctionDotCallTargetSelector(targetSelector));
|
||||
}
|
||||
if (options.useLoadFileTargetSelector()) {
|
||||
targetSelector = new LoadFileTargetSelector(targetSelector, this);
|
||||
|
|
|
@ -62,7 +62,7 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele
|
|||
private static final TypeName CALL_TYPE_NAME = TypeName.findOrCreate("Lprologue.js/Function_prototype_call");
|
||||
private final MethodTargetSelector base;
|
||||
|
||||
public JavaScriptFunctionDotCallTargetSelector(MethodTargetSelector base, IAnalysisCacheView cache2) {
|
||||
public JavaScriptFunctionDotCallTargetSelector(MethodTargetSelector base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,7 +161,7 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
return (o instanceof CopyPropagationRecord) && instructionIndex == ((CopyPropagationRecord) o).instructionIndex;
|
||||
}
|
||||
|
||||
private CopyPropagationRecord(int instructionIndex, int lhs, int rhs) {
|
||||
private CopyPropagationRecord(int instructionIndex, int rhs) {
|
||||
if (DEBUG_UNDO)
|
||||
System.err.println(("new copy record for instruction #" + instructionIndex + ", rhs value is " + rhs));
|
||||
this.rhs = rhs;
|
||||
|
@ -442,7 +442,7 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
|
||||
assignments.put(rhs, lhs);
|
||||
|
||||
CopyPropagationRecord rec = new CopyPropagationRecord(index, lhs, newRhs);
|
||||
CopyPropagationRecord rec = new CopyPropagationRecord(index, newRhs);
|
||||
push(R[lhs], rec);
|
||||
if (topR(rhs) != null) {
|
||||
topR(rhs).addChild(rec);
|
||||
|
|
|
@ -63,10 +63,10 @@ public class ContextSensitiveReachingDefs {
|
|||
*/
|
||||
private final ReachingDefsDomain domain = new ReachingDefsDomain();
|
||||
|
||||
public ContextSensitiveReachingDefs(CallGraph cg, IAnalysisCacheView cache) {
|
||||
public ContextSensitiveReachingDefs(CallGraph cg) {
|
||||
this.cha = cg.getClassHierarchy();
|
||||
// we use an ICFGSupergraph, which basically adapts ExplodedInterproceduralCFG to the ISupergraph interface
|
||||
this.supergraph = ICFGSupergraph.make(cg, cache);
|
||||
this.supergraph = ICFGSupergraph.make(cg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -184,8 +184,7 @@ public class DataflowTest extends WalaTestCase {
|
|||
|
||||
CallGraphBuilder builder = Util.makeZeroOneCFABuilder(options, new AnalysisCacheImpl(), cha, scope);
|
||||
CallGraph cg = builder.makeCallGraph(options, null);
|
||||
IAnalysisCacheView cache = new AnalysisCacheImpl();
|
||||
ContextSensitiveReachingDefs reachingDefs = new ContextSensitiveReachingDefs(cg, cache);
|
||||
ContextSensitiveReachingDefs reachingDefs = new ContextSensitiveReachingDefs(cg);
|
||||
TabulationResult<BasicBlockInContext<IExplodedBasicBlock>, CGNode, Pair<CGNode, Integer>> result = reachingDefs.analyze();
|
||||
ISupergraph<BasicBlockInContext<IExplodedBasicBlock>, CGNode> supergraph = reachingDefs.getSupergraph();
|
||||
for (BasicBlockInContext<IExplodedBasicBlock> bb : supergraph) {
|
||||
|
|
|
@ -83,8 +83,7 @@ public class InitializerTest {
|
|||
|
||||
System.out.println("Start");
|
||||
|
||||
IAnalysisCacheView cache = new AnalysisCacheImpl();
|
||||
StaticInitializer reachingDefs = new StaticInitializer(cg, cache);
|
||||
StaticInitializer reachingDefs = new StaticInitializer(cg);
|
||||
TabulationResult<BasicBlockInContext<IExplodedBasicBlock>, CGNode, IClass> result = reachingDefs.analyze();
|
||||
ISupergraph<BasicBlockInContext<IExplodedBasicBlock>, CGNode> supergraph = reachingDefs.getSupergraph();
|
||||
for (BasicBlockInContext<IExplodedBasicBlock> bb : supergraph) {
|
||||
|
|
|
@ -68,9 +68,9 @@ public class StaticInitializer {
|
|||
return initialized;
|
||||
}
|
||||
|
||||
public StaticInitializer(CallGraph cg, IAnalysisCacheView cache) {
|
||||
public StaticInitializer(CallGraph cg) {
|
||||
cha = cg.getClassHierarchy();
|
||||
supergraph = ICFGSupergraph.make(cg, cache);
|
||||
supergraph = ICFGSupergraph.make(cg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -141,7 +141,7 @@ public class IntraprocNullPointerAnalysis<T extends ISSABasicBlock> {
|
|||
|
||||
solver.solve(progress);
|
||||
|
||||
final Graph<T> deleted = createDeletedGraph(solver);
|
||||
final Graph<T> deleted = createDeletedGraph();
|
||||
|
||||
for (final T ch : catched) {
|
||||
deleted.addNode(ch);
|
||||
|
@ -161,8 +161,8 @@ public class IntraprocNullPointerAnalysis<T extends ISSABasicBlock> {
|
|||
}
|
||||
}
|
||||
|
||||
private Graph<T> createDeletedGraph(NullPointerSolver<T> solver) {
|
||||
NegativeCFGBuilderVisitor nCFGbuilder = new NegativeCFGBuilderVisitor(solver);
|
||||
private Graph<T> createDeletedGraph() {
|
||||
NegativeCFGBuilderVisitor nCFGbuilder = new NegativeCFGBuilderVisitor();
|
||||
for (T bb : cfg) {
|
||||
nCFGbuilder.work(bb);
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ public class IntraprocNullPointerAnalysis<T extends ISSABasicBlock> {
|
|||
private class NegativeCFGBuilderVisitor implements IVisitor {
|
||||
|
||||
private final Graph<T> deleted;
|
||||
private NegativeCFGBuilderVisitor(NullPointerSolver<T> solver) {
|
||||
private NegativeCFGBuilderVisitor() {
|
||||
this.deleted = new SparseNumberedGraph<T>(2);
|
||||
for (T bb : cfg) {
|
||||
deleted.addNode(bb);
|
||||
|
|
|
@ -52,12 +52,12 @@ public class ICFGSupergraph implements ISupergraph<BasicBlockInContext<IExploded
|
|||
|
||||
private final ExplodedInterproceduralCFG icfg;
|
||||
|
||||
protected ICFGSupergraph(ExplodedInterproceduralCFG icfg, IAnalysisCacheView cache) {
|
||||
protected ICFGSupergraph(ExplodedInterproceduralCFG icfg) {
|
||||
this.icfg = icfg;
|
||||
}
|
||||
|
||||
public static ICFGSupergraph make(CallGraph cg, IAnalysisCacheView cache) {
|
||||
ICFGSupergraph w = new ICFGSupergraph(ExplodedInterproceduralCFG.make(cg), cache);
|
||||
public static ICFGSupergraph make(CallGraph cg) {
|
||||
ICFGSupergraph w = new ICFGSupergraph(ExplodedInterproceduralCFG.make(cg));
|
||||
return w;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ public class IFDSExplorerExample {
|
|||
CallGraph cg = builder.makeCallGraph(options, null);
|
||||
System.out.println("done with CG");
|
||||
System.out.println("computing reaching defs");
|
||||
ContextSensitiveReachingDefs reachingDefs = new ContextSensitiveReachingDefs(cg, cache);
|
||||
ContextSensitiveReachingDefs reachingDefs = new ContextSensitiveReachingDefs(cg);
|
||||
TabulationResult<BasicBlockInContext<IExplodedBasicBlock>, CGNode, Pair<CGNode, Integer>> result = reachingDefs.analyze();
|
||||
System.out.println("done with reaching defs");
|
||||
IFDSExplorer.setDotExe(p.getProperty("dotExe"));
|
||||
|
|
|
@ -48,8 +48,6 @@
|
|||
*/
|
||||
package org.scandroid.flow.functions;
|
||||
|
||||
import org.scandroid.domain.IFDSTaintDomain;
|
||||
|
||||
import com.ibm.wala.dataflow.IFDS.IUnaryFlowFunction;
|
||||
import com.ibm.wala.ssa.ISSABasicBlock;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
|
@ -58,7 +56,7 @@ import com.ibm.wala.util.intset.IntSetAction;
|
|||
public class TracingFlowFunction<E extends ISSABasicBlock> implements IUnaryFlowFunction {
|
||||
private final IUnaryFlowFunction function;
|
||||
|
||||
public TracingFlowFunction(IFDSTaintDomain<E> domain, IUnaryFlowFunction function) {
|
||||
public TracingFlowFunction(IUnaryFlowFunction function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ public class CGAnalysisContext<E extends ISSABasicBlock> {
|
|||
}
|
||||
});
|
||||
if (options.includeLibrary()) {
|
||||
graph = (ISupergraph) ICFGSupergraph.make(cg, cache);
|
||||
graph = (ISupergraph) ICFGSupergraph.make(cg);
|
||||
} else {
|
||||
|
||||
Collection<CGNode> nodes = HashSetFactory.make();
|
||||
|
@ -213,7 +213,7 @@ public class CGAnalysisContext<E extends ISSABasicBlock> {
|
|||
nodes.add(nIter.next());
|
||||
}
|
||||
CallGraph pcg = PartialCallGraph.make(cg, cg.getEntrypointNodes(), nodes);
|
||||
graph = (ISupergraph) ICFGSupergraph.make(pcg, cache);
|
||||
graph = (ISupergraph) ICFGSupergraph.make(pcg);
|
||||
}
|
||||
|
||||
oneLevelGraph = GraphSlicer.prune(cg, new Predicate<CGNode>() {
|
||||
|
|
|
@ -42,7 +42,7 @@ public class AddBytecodeDebug {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
for (int i = 0; i < 1; i++) {
|
||||
instrumenter = new OfflineInstrumenter(true);
|
||||
instrumenter = new OfflineInstrumenter();
|
||||
|
||||
try (final Writer w = new BufferedWriter(new FileWriter("report", false))) {
|
||||
args = instrumenter.parseStandardArgs(args);
|
||||
|
|
|
@ -73,7 +73,7 @@ public class Bench {
|
|||
doException = true;
|
||||
}
|
||||
}
|
||||
instrumenter = new OfflineInstrumenter(!doException);
|
||||
instrumenter = new OfflineInstrumenter();
|
||||
instrumenter.setPassUnmodifiedClasses(true);
|
||||
instrumenter.beginTraversal();
|
||||
ClassInstrumenter ci;
|
||||
|
|
|
@ -41,7 +41,7 @@ public class InterfaceAnalyzer {
|
|||
final static HashMap<String, TypeStats> typeStats = new HashMap<>();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OfflineInstrumenter instrumenter = new OfflineInstrumenter(true);
|
||||
OfflineInstrumenter instrumenter = new OfflineInstrumenter();
|
||||
|
||||
try (final Writer w = new BufferedWriter(new OutputStreamWriter(System.out))) {
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ public class Mangler {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
for (int i = 0; i < 1; i++) {
|
||||
instrumenter = new OfflineInstrumenter(true);
|
||||
instrumenter = new OfflineInstrumenter();
|
||||
|
||||
try (final Writer w = new BufferedWriter(new FileWriter("report", false))) {
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ public class Statistics {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
for (int i = 0; i < 1; i++) {
|
||||
instrumenter = new OfflineInstrumenter(true);
|
||||
instrumenter = new OfflineInstrumenter();
|
||||
|
||||
try (Writer w = new BufferedWriter(new FileWriter("report", false))) {
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ public class OfflineDynamicCallGraph {
|
|||
patchCalls = true;
|
||||
} else if ("--rt-jar".equals(args[i])) {
|
||||
System.err.println("using " + args[i+1] + " as stdlib");
|
||||
OfflineInstrumenter libReader = new OfflineInstrumenter(true);
|
||||
OfflineInstrumenter libReader = new OfflineInstrumenter();
|
||||
libReader.addInputJar(new File(args[i+1]));
|
||||
while ((ci = libReader.nextClass()) != null) {
|
||||
CTUtils.addClassToHierarchy(cha, ci.getReader());
|
||||
|
@ -94,7 +94,7 @@ public class OfflineDynamicCallGraph {
|
|||
}
|
||||
}
|
||||
|
||||
instrumenter = new OfflineInstrumenter(true);
|
||||
instrumenter = new OfflineInstrumenter();
|
||||
args = instrumenter.parseStandardArgs(args);
|
||||
|
||||
instrumenter.setPassUnmodifiedClasses(true);
|
||||
|
|
|
@ -23,7 +23,7 @@ public class OnlineDynamicCallGraph implements ClassFileTransformer {
|
|||
private Writer out = new PrintWriter(System.err);
|
||||
|
||||
public OnlineDynamicCallGraph() throws IllegalArgumentException, IOException, InvalidClassFileException {
|
||||
OfflineInstrumenter libReader = new OfflineInstrumenter(true);
|
||||
OfflineInstrumenter libReader = new OfflineInstrumenter();
|
||||
for (String cps : new String[]{ System.getProperty("java.class.path"), System.getProperty("sun.boot.class.path") }) {
|
||||
for (String cp : cps.split(File.pathSeparator)) {
|
||||
File x = new File(cp);
|
||||
|
@ -50,7 +50,7 @@ public class OnlineDynamicCallGraph implements ClassFileTransformer {
|
|||
if (className.contains("com/ibm/wala") || className.contains("java/lang") || (className.contains("java/") && !className.matches("java/util/[A-Z]")) || className.contains("sun/")) {
|
||||
return classfileBuffer;
|
||||
} else {
|
||||
ClassInstrumenter ci = new ClassInstrumenter(className, classfileBuffer, cha, false);
|
||||
ClassInstrumenter ci = new ClassInstrumenter(className, classfileBuffer, cha);
|
||||
return OfflineDynamicCallGraph.doClass(ci, out).makeBytes();
|
||||
}
|
||||
} catch (InvalidClassFileException | IOException | FailureException e) {
|
||||
|
|
|
@ -93,7 +93,7 @@ public class CopyWriter {
|
|||
|
||||
final ArrayList<ZipEntry> entries = new ArrayList<>();
|
||||
|
||||
instrumenter = new OfflineInstrumenter(true);
|
||||
instrumenter = new OfflineInstrumenter();
|
||||
instrumenter.setManifestBuilder(new OfflineInstrumenter.ManifestBuilder() {
|
||||
@Override
|
||||
public void addEntry(ZipEntry ze) {
|
||||
|
|
|
@ -66,8 +66,8 @@ final public class ClassInstrumenter {
|
|||
/**
|
||||
* Create a class instrumenter from raw bytes.
|
||||
*/
|
||||
public ClassInstrumenter(String inputName, byte[] bytes, ClassHierarchyProvider cha, boolean reuseStackMaps) throws InvalidClassFileException {
|
||||
this(inputName, new ClassReader(bytes), cha, reuseStackMaps);
|
||||
public ClassInstrumenter(String inputName, byte[] bytes, ClassHierarchyProvider cha) throws InvalidClassFileException {
|
||||
this(inputName, new ClassReader(bytes), cha);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,7 +91,7 @@ final public class ClassInstrumenter {
|
|||
*
|
||||
* @throws IllegalArgumentException if cr is null
|
||||
*/
|
||||
public ClassInstrumenter(String inputName, ClassReader cr, ClassHierarchyProvider cha, boolean reuseStackMaps) throws InvalidClassFileException {
|
||||
public ClassInstrumenter(String inputName, ClassReader cr, ClassHierarchyProvider cha) throws InvalidClassFileException {
|
||||
if (cr == null) {
|
||||
throw new IllegalArgumentException("cr is null");
|
||||
}
|
||||
|
|
|
@ -24,20 +24,13 @@ import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
|||
* specialization of OfflineInstrumenterBase to use the shrikeCT functionality.
|
||||
*/
|
||||
final public class OfflineInstrumenter extends OfflineInstrumenterBase {
|
||||
private final boolean reuseStackMaps;
|
||||
/**
|
||||
* Create an empty collection of classes to instrument.
|
||||
*/
|
||||
public OfflineInstrumenter(boolean reuseStackMaps) {
|
||||
this.reuseStackMaps = reuseStackMaps;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object makeClassFromStream(String inputName, BufferedInputStream s) throws IOException {
|
||||
byte[] bytes = new byte[s.available()];
|
||||
Util.readFully(s, bytes);
|
||||
try {
|
||||
return new ClassInstrumenter(inputName, bytes, cha, reuseStackMaps);
|
||||
return new ClassInstrumenter(inputName, bytes, cha);
|
||||
} catch (InvalidClassFileException e) {
|
||||
throw new IOException("Class is invalid: " + e.getMessage());
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public class BatchVerifier {
|
|||
private static int errors = 0;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OfflineInstrumenter oi = new OfflineInstrumenter(true);
|
||||
OfflineInstrumenter oi = new OfflineInstrumenter();
|
||||
args = oi.parseStandardArgs(args);
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
|
|
|
@ -41,7 +41,7 @@ public class BootstrapDumper {
|
|||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OfflineInstrumenter oi = new OfflineInstrumenter(true);
|
||||
OfflineInstrumenter oi = new OfflineInstrumenter();
|
||||
String[] classpathEntries = oi.parseStandardArgs(args);
|
||||
|
||||
PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
|
||||
|
|
|
@ -57,7 +57,7 @@ public class BootstrapInstrumentor {
|
|||
}
|
||||
|
||||
public void doit(String[] args) throws Exception {
|
||||
OfflineInstrumenter oi = new OfflineInstrumenter(true);
|
||||
OfflineInstrumenter oi = new OfflineInstrumenter();
|
||||
oi.parseStandardArgs(args);
|
||||
|
||||
oi.setPassUnmodifiedClasses(true);
|
||||
|
|
|
@ -72,7 +72,7 @@ public class ClassPrinter {
|
|||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OfflineInstrumenter oi = new OfflineInstrumenter(true);
|
||||
OfflineInstrumenter oi = new OfflineInstrumenter();
|
||||
args = oi.parseStandardArgs(args);
|
||||
|
||||
PrintWriter w = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
|
||||
|
|
|
@ -36,7 +36,7 @@ public class ClassSearcher {
|
|||
private static int scanned = 0;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
instrumenter = new OfflineInstrumenter(true);
|
||||
instrumenter = new OfflineInstrumenter();
|
||||
|
||||
try (final Writer w = new BufferedWriter(new FileWriter("report", true))) {
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ public class MethodTracer {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
for (int i = 0; i < 1; i++) {
|
||||
instrumenter = new OfflineInstrumenter(true);
|
||||
instrumenter = new OfflineInstrumenter();
|
||||
|
||||
try (final Writer w = new BufferedWriter(new FileWriter("report", false))) {
|
||||
|
||||
|
|
Loading…
Reference in New Issue