7021650: fix Context issues

Reviewed-by: mcimadamore
This commit is contained in:
Jonathan Gibbons 2011-02-25 12:09:33 -08:00
parent 6d172a6a63
commit a51962066d
15 changed files with 310 additions and 65 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -48,15 +48,15 @@ public class Bark extends Log {
* Preregisters factories to create and use a Bark object for use as * Preregisters factories to create and use a Bark object for use as
* both a Log and a Bark. * both a Log and a Bark.
*/ */
public static void preRegister(final Context context) { public static void preRegister(Context context) {
context.put(barkKey, new Context.Factory<Bark>() { context.put(barkKey, new Context.Factory<Bark>() {
public Bark make() { public Bark make(Context c) {
return new Bark(context); return new Bark(c);
} }
}); });
context.put(Log.logKey, new Context.Factory<Log>() { context.put(Log.logKey, new Context.Factory<Log>() {
public Log make() { public Log make(Context c) {
return Bark.instance(context); return Bark.instance(c);
} }
}); });
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -157,19 +157,19 @@ public final class JavacTool implements JavaCompiler {
/** /**
* Register that a compilation is about to start. * Register that a compilation is about to start.
*/ */
void beginContext(final Context context) { void beginContext(Context context) {
if (compilationInProgress) if (compilationInProgress)
throw new IllegalStateException("Compilation in progress"); throw new IllegalStateException("Compilation in progress");
compilationInProgress = true; compilationInProgress = true;
final JavaFileManager givenFileManager = context.get(JavaFileManager.class); final JavaFileManager givenFileManager = context.get(JavaFileManager.class);
context.put(JavaFileManager.class, (JavaFileManager)null); context.put(JavaFileManager.class, (JavaFileManager)null);
context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() { context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
public JavaFileManager make() { public JavaFileManager make(Context c) {
if (givenFileManager != null) { if (givenFileManager != null) {
context.put(JavaFileManager.class, givenFileManager); c.put(JavaFileManager.class, givenFileManager);
return givenFileManager; return givenFileManager;
} else { } else {
return new JavacFileManager(context, true, null); return new JavacFileManager(c, true, null);
} }
} }
}); });

View file

@ -44,13 +44,13 @@ import com.sun.tools.javac.util.Context;
public class CacheFSInfo extends FSInfo { public class CacheFSInfo extends FSInfo {
/** /**
* Register a Context.Factory to create a singleton CacheFSInfo. * Register a Context.Factory to create a CacheFSInfo.
*/ */
public static void preRegister(final Context context) { public static void preRegister(Context context) {
context.put(FSInfo.class, new Context.Factory<FSInfo>() { context.put(FSInfo.class, new Context.Factory<FSInfo>() {
public FSInfo make() { public FSInfo make(Context c) {
FSInfo instance = new CacheFSInfo(); FSInfo instance = new CacheFSInfo();
context.put(FSInfo.class, instance); c.put(FSInfo.class, instance);
return instance; return instance;
} }
}); });

View file

@ -129,10 +129,10 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil
/** /**
* Register a Context.Factory to create a JavacFileManager. * Register a Context.Factory to create a JavacFileManager.
*/ */
public static void preRegister(final Context context) { public static void preRegister(Context context) {
context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() { context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
public JavaFileManager make() { public JavaFileManager make(Context c) {
return new JavacFileManager(context, true, null); return new JavacFileManager(c, true, null);
} }
}); });
} }

View file

@ -312,7 +312,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
/** Construct a new compiler using a shared context. /** Construct a new compiler using a shared context.
*/ */
public JavaCompiler(final Context context) { public JavaCompiler(Context context) {
this.context = context; this.context = context;
context.put(compilerKey, this); context.put(compilerKey, this);

View file

@ -1045,7 +1045,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
* other values are implicitly reset. * other values are implicitly reset.
*/ */
private Context nextContext() { private Context nextContext() {
Context next = new Context(); Context next = new Context(context);
Options options = Options.instance(context); Options options = Options.instance(context);
Assert.checkNonNull(options); Assert.checkNonNull(options);

View file

@ -108,7 +108,7 @@ public class Context {
* instance. * instance.
*/ */
public static interface Factory<T> { public static interface Factory<T> {
T make(); T make(Context c);
}; };
/** /**
@ -124,6 +124,8 @@ public class Context {
Object old = ht.put(key, fac); Object old = ht.put(key, fac);
if (old != null) if (old != null)
throw new AssertionError("duplicate context value"); throw new AssertionError("duplicate context value");
checkState(ft);
ft.put(key, fac); // cannot be duplicate if unique in ht
} }
/** Set the value for the key in this context. */ /** Set the value for the key in this context. */
@ -142,7 +144,7 @@ public class Context {
Object o = ht.get(key); Object o = ht.get(key);
if (o instanceof Factory<?>) { if (o instanceof Factory<?>) {
Factory<?> fac = (Factory<?>)o; Factory<?> fac = (Factory<?>)o;
o = fac.make(); o = fac.make(this);
if (o instanceof Factory<?>) if (o instanceof Factory<?>)
throw new AssertionError("T extends Context.Factory"); throw new AssertionError("T extends Context.Factory");
Assert.check(ht.get(key) == o); Assert.check(ht.get(key) == o);
@ -158,6 +160,20 @@ public class Context {
public Context() {} public Context() {}
/**
* The table of preregistered factories.
*/
private Map<Key<?>,Factory<?>> ft = new HashMap<Key<?>,Factory<?>>();
public Context(Context prev) {
kt.putAll(prev.kt); // retain all implicit keys
ft.putAll(prev.ft); // retain all factory objects
ht.putAll(prev.ft); // init main table with factories
}
/*
* The key table, providing a unique Key<T> for each Class<T>.
*/
private Map<Class<?>, Key<?>> kt = new HashMap<Class<?>, Key<?>>(); private Map<Class<?>, Key<?>> kt = new HashMap<Class<?>, Key<?>>();
private <T> Key<T> key(Class<T> clss) { private <T> Key<T> key(Class<T> clss) {
@ -198,6 +214,7 @@ public class Context {
public void clear() { public void clear() {
ht = null; ht = null;
kt = null; kt = null;
ft = null;
} }
private static void checkState(Map<?,?> t) { private static void checkState(Map<?,?> t) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -44,10 +44,10 @@ class JavadocClassReader extends ClassReader {
return (JavadocClassReader)instance; return (JavadocClassReader)instance;
} }
public static void preRegister(final Context context) { public static void preRegister(Context context) {
context.put(classReaderKey, new Context.Factory<ClassReader>() { context.put(classReaderKey, new Context.Factory<ClassReader>() {
public ClassReader make() { public ClassReader make(Context c) {
return new JavadocClassReader(context); return new JavadocClassReader(c);
} }
}); });
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -48,10 +48,10 @@ public class JavadocEnter extends Enter {
return (JavadocEnter)instance; return (JavadocEnter)instance;
} }
public static void preRegister(final Context context) { public static void preRegister(Context context) {
context.put(enterKey, new Context.Factory<Enter>() { context.put(enterKey, new Context.Factory<Enter>() {
public Enter make() { public Enter make(Context c) {
return new JavadocEnter(context); return new JavadocEnter(c);
} }
}); });
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -46,10 +46,10 @@ class JavadocMemberEnter extends MemberEnter {
return (JavadocMemberEnter)instance; return (JavadocMemberEnter)instance;
} }
public static void preRegister(final Context context) { public static void preRegister(Context context) {
context.put(memberEnterKey, new Context.Factory<MemberEnter>() { context.put(memberEnterKey, new Context.Factory<MemberEnter>() {
public MemberEnter make() { public MemberEnter make(Context c) {
return new JavadocMemberEnter(context); return new JavadocMemberEnter(c);
} }
}); });
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -34,10 +34,10 @@ import com.sun.tools.javac.util.*;
* @author Neal Gafter * @author Neal Gafter
*/ */
public class JavadocTodo extends Todo { public class JavadocTodo extends Todo {
public static void preRegister(final Context context) { public static void preRegister(Context context) {
context.put(todoKey, new Context.Factory<Todo>() { context.put(todoKey, new Context.Factory<Todo>() {
public Todo make() { public Todo make(Context c) {
return new JavadocTodo(context); return new JavadocTodo(c);
} }
}); });
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -57,23 +57,23 @@ public class Messager extends Log implements DocErrorReporter {
return (Messager)instance; return (Messager)instance;
} }
public static void preRegister(final Context context, public static void preRegister(Context context,
final String programName) { final String programName) {
context.put(logKey, new Context.Factory<Log>() { context.put(logKey, new Context.Factory<Log>() {
public Log make() { public Log make(Context c) {
return new Messager(context, return new Messager(c,
programName); programName);
} }
}); });
} }
public static void preRegister(final Context context, public static void preRegister(Context context,
final String programName, final String programName,
final PrintWriter errWriter, final PrintWriter errWriter,
final PrintWriter warnWriter, final PrintWriter warnWriter,
final PrintWriter noticeWriter) { final PrintWriter noticeWriter) {
context.put(logKey, new Context.Factory<Log>() { context.put(logKey, new Context.Factory<Log>() {
public Log make() { public Log make(Context c) {
return new Messager(context, return new Messager(c,
programName, programName,
errWriter, errWriter,
warnWriter, warnWriter,

View file

@ -34,6 +34,7 @@ import com.sun.tools.javac.code.Kinds.KindName;
import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.*;
import com.sun.tools.javac.file.*; import com.sun.tools.javac.file.*;
import com.sun.tools.javac.main.Main; import com.sun.tools.javac.main.Main;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.parser.Token; import com.sun.tools.javac.parser.Token;
import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration; import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
@ -107,8 +108,7 @@ class ArgTypeCompilerFactory implements Example.Compiler.Factory {
JavacTaskImpl t = (JavacTaskImpl) tool.getTask(out, fm, null, opts, null, fos); JavacTaskImpl t = (JavacTaskImpl) tool.getTask(out, fm, null, opts, null, fos);
Context c = t.getContext(); Context c = t.getContext();
ArgTypeMessages.preRegister(c); ArgTypeMessages.preRegister(c);
Options options = Options.instance(c); ArgTypeJavaCompiler.preRegister(c);
Log.instance(c).setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options));
Boolean ok = t.call(); Boolean ok = t.call();
return ok; return ok;
@ -144,7 +144,7 @@ class ArgTypeCompilerFactory implements Example.Compiler.Factory {
} }
}; };
JavacFileManager.preRegister(c); // can't create it until Log has been set up JavacFileManager.preRegister(c); // can't create it until Log has been set up
ArgTypeDiagnosticFormatter.preRegister(c); ArgTypeJavaCompiler.preRegister(c);
ArgTypeMessages.preRegister(c); ArgTypeMessages.preRegister(c);
int result = main.compile(args.toArray(new String[args.size()]), c); int result = main.compile(args.toArray(new String[args.size()]), c);
@ -170,7 +170,7 @@ class ArgTypeCompilerFactory implements Example.Compiler.Factory {
Context c = new Context(); Context c = new Context();
JavacFileManager.preRegister(c); // can't create it until Log has been set up JavacFileManager.preRegister(c); // can't create it until Log has been set up
ArgTypeDiagnosticFormatter.preRegister(c); ArgTypeJavaCompiler.preRegister(c);
ArgTypeMessages.preRegister(c); ArgTypeMessages.preRegister(c);
com.sun.tools.javac.main.Main m = new com.sun.tools.javac.main.Main("javac", out); com.sun.tools.javac.main.Main m = new com.sun.tools.javac.main.Main("javac", out);
int rc = m.compile(args.toArray(new String[args.size()]), c); int rc = m.compile(args.toArray(new String[args.size()]), c);
@ -189,17 +189,6 @@ class ArgTypeCompilerFactory implements Example.Compiler.Factory {
* arg types. * arg types.
*/ */
static class ArgTypeDiagnosticFormatter extends AbstractDiagnosticFormatter { static class ArgTypeDiagnosticFormatter extends AbstractDiagnosticFormatter {
static void preRegister(final Context context) {
context.put(Log.logKey, new Context.Factory<Log>() {
public Log make() {
Log log = new Log(context) { };
Options options = Options.instance(context);
log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options));
return log;
}
});
}
ArgTypeDiagnosticFormatter(Options options) { ArgTypeDiagnosticFormatter(Options options) {
super(null, new SimpleConfiguration(options, super(null, new SimpleConfiguration(options,
@ -245,15 +234,38 @@ class ArgTypeCompilerFactory implements Example.Compiler.Factory {
} }
} }
/**
* Trivial subtype of JavaCompiler to get access to the protected compilerKey field.
* The factory is used to ensure that the log is initialized with an instance of
* ArgTypeDiagnosticFormatter before we create the required JavaCompiler.
*/
static class ArgTypeJavaCompiler extends JavaCompiler {
static void preRegister(Context context) {
context.put(compilerKey, new Context.Factory<JavaCompiler>() {
public JavaCompiler make(Context c) {
Log log = Log.instance(c);
Options options = Options.instance(c);
log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options));
return new JavaCompiler(c);
}
});
}
// not used
private ArgTypeJavaCompiler() {
super(null);
}
}
/** /**
* Diagnostic formatter which "localizes" a message as a line * Diagnostic formatter which "localizes" a message as a line
* containing a key, and a possibly empty set of descriptive strings for the * containing a key, and a possibly empty set of descriptive strings for the
* arg types. * arg types.
*/ */
static class ArgTypeMessages extends JavacMessages { static class ArgTypeMessages extends JavacMessages {
static void preRegister(final Context c) { static void preRegister(Context context) {
c.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() { context.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() {
public JavacMessages make() { public JavacMessages make(Context c) {
return new ArgTypeMessages(c) { return new ArgTypeMessages(c) {
@Override @Override
public String getLocalizedString(Locale l, String key, Object... args) { public String getLocalizedString(Locale l, String key, Object... args) {

View file

@ -522,10 +522,10 @@ class Example implements Comparable<Example> {
super(context); super(context);
} }
static void preRegister(final Context c, final Set<String> keys) { static void preRegister(Context c, final Set<String> keys) {
if (keys != null) { if (keys != null) {
c.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() { c.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() {
public JavacMessages make() { public JavacMessages make(Context c) {
return new MessageTracker(c) { return new MessageTracker(c) {
@Override @Override
public String getLocalizedString(Locale l, String key, Object... args) { public String getLocalizedString(Locale l, String key, Object... args) {

View file

@ -0,0 +1,216 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 7021650
* @summary Fix Context issues
* @library ../../lib
* @build JavacTestingAbstractProcessor T7021650
* @run main T7021650
*/
import java.io.*;
import java.net.*;
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.tools.*;
import com.sun.tools.javac.comp.Attr;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.Main;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.util.Context;
public class T7021650 extends JavacTestingAbstractProcessor {
public static void main(String... args) throws Exception {
new T7021650().run();
}
static File testSrc = new File(System.getProperty("test.src"));
static final int MAX_ROUNDS = 3;
/**
* Perform a compilation with custom factories registered in the context,
* and verify that corresponding objects are created in each round.
*/
void run() throws Exception {
Counter demoCounter = new Counter();
Counter myAttrCounter = new Counter();
Context context = new Context();
// Use a custom file manager which creates classloaders for annotation
// processors with a sensible delegation parent, so that all instances
// of test classes come from the same class loader. This is important
// because the test performs class checks on the instances of classes
// found in the context for each round or processing.
context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() {
public JavaFileManager make(Context c) {
return new JavacFileManager(c, true, null) {
@Override
protected ClassLoader getClassLoader(URL[] urls) {
return new URLClassLoader(urls, T7021650.class.getClassLoader());
}
};
}
});
Demo.preRegister(context, demoCounter);
MyAttr.preRegister(context, myAttrCounter);
String[] args = {
"-d", ".",
"-processor", T7021650.class.getName(),
"-XprintRounds",
new File(testSrc, T7021650.class.getName() + ".java").getPath()
};
compile(context, args);
// Expect to create Demo for initial round, then MAX_ROUNDS in which
// GenX files are generated, then standard final round of processing.
checkEqual("demoCounter", demoCounter.count, MAX_ROUNDS + 2);
// Expect to create MyAttr for same processing rounds as for Demo,
// plus additional context for final compilation.
checkEqual("myAttrCounter", myAttrCounter.count, MAX_ROUNDS + 3);
}
void compile(Context context, String... args) throws Exception {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
Main m = new Main("javac", pw);
int rc = m.compile(args, context);
pw.close();
String out = sw.toString();
if (!out.isEmpty())
System.err.println(out);
if (rc != 0)
throw new Exception("compilation failed unexpectedly: rc=" + rc);
}
void checkEqual(String label, int found, int expect) throws Exception {
if (found != expect)
throw new Exception("unexpected value for " + label
+ ": expected " + expect
+ ": found " + found);
}
//---------------
/*
* A custom class unknown to javac but nonetheless registered in the context.
*/
static class Demo {
static void preRegister(Context context, final Counter counter) {
context.put(Demo.class, new Context.Factory<Demo>() {
public Demo make(Context c) {
counter.count++;
return new Demo(c);
}
});
}
Demo(Context c) {
c.put(Demo.class, this);
}
static Demo instance(Context context) {
return context.get(Demo.class);
}
}
/**
* A custom version of a standard javac component.
*/
static class MyAttr extends Attr {
static void preRegister(Context context, final Counter counter) {
context.put(attrKey, new Context.Factory<Attr>() {
public Attr make(Context c) {
counter.count++;
return new MyAttr(c);
}
});
}
MyAttr(Context c) {
super(c);
}
}
static class Counter {
int count;
}
//---------------
int round = 0;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
round++;
Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
// verify items in context as expected
check("Demo", Demo.instance(context), Demo.class);
check("Attr", Attr.instance(context), MyAttr.class);
// For a few rounds, generate new source files, so that we can check whether
// values in the context are correctly handled in subsequent processing rounds
if (round <= MAX_ROUNDS) {
String pkg = "p";
String currClass = "Gen" + round;
String curr = pkg + "." + currClass;
String next = (pkg + ".Gen" + (round + 1));
StringBuilder text = new StringBuilder();
text.append("package ").append(pkg).append(";\n");
text.append("public class ").append(currClass).append(" {\n");
if (round < MAX_ROUNDS)
text.append(" ").append(next).append(" x;\n");
text.append("}\n");
try {
JavaFileObject fo = filer.createSourceFile(curr);
Writer out = fo.openWriter();
try {
out.write(text.toString());
} finally {
out.close();
}
} catch (IOException e) {
throw new Error(e);
}
}
return true;
}
void check(String label, Object o, Class<?> clazz) {
if (o == null)
throw new IllegalStateException(label + ": no item found");
if (!clazz.isAssignableFrom(o.getClass()))
throw new IllegalStateException(label + ": unexpected class: " + o.getClass());
}
}