提交 1fc9520f 编写于 作者: J jjg

7021650: fix Context issues

Reviewed-by: mcimadamore
上级 58c54719
/* /*
* 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 { ...@@ -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);
} }
}); });
} }
......
/* /*
* 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 { ...@@ -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);
} }
} }
}); });
......
...@@ -44,13 +44,13 @@ import com.sun.tools.javac.util.Context; ...@@ -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;
} }
}); });
......
...@@ -129,10 +129,10 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil ...@@ -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);
} }
}); });
} }
......
...@@ -312,7 +312,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { ...@@ -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);
......
...@@ -1045,7 +1045,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea ...@@ -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);
......
...@@ -108,7 +108,7 @@ public class Context { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) {
......
/* /*
* 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 { ...@@ -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);
} }
}); });
} }
......
/* /*
* 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 { ...@@ -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);
} }
}); });
} }
......
/* /*
* 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 { ...@@ -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);
} }
}); });
} }
......
/* /*
* 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.*; ...@@ -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);
} }
}); });
} }
......
/* /*
* 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 { ...@@ -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,
......
...@@ -34,6 +34,7 @@ import com.sun.tools.javac.code.Kinds.KindName; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) {
......
...@@ -522,10 +522,10 @@ class Example implements Comparable<Example> { ...@@ -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) {
......
/*
* 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());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册