You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pivot.apache.org by tv...@apache.org on 2009/05/07 01:33:59 UTC
svn commit: r772466 - in /incubator/pivot/trunk: build.xml
wtk/src/pivot/wtkx/BindProcessor.java wtk/src/pivot/wtkx/Bindable.java
Author: tvolkert
Date: Wed May 6 23:33:59 2009
New Revision: 772466
URL: http://svn.apache.org/viewvc?rev=772466&view=rev
Log:
Made the bind processor generate code that works with inheritance chains
Modified:
incubator/pivot/trunk/build.xml
incubator/pivot/trunk/wtk/src/pivot/wtkx/BindProcessor.java
incubator/pivot/trunk/wtk/src/pivot/wtkx/Bindable.java
Modified: incubator/pivot/trunk/build.xml
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/build.xml?rev=772466&r1=772465&r2=772466&view=diff
==============================================================================
--- incubator/pivot/trunk/build.xml (original)
+++ incubator/pivot/trunk/build.xml Wed May 6 23:33:59 2009
@@ -374,7 +374,7 @@
target="${compiler.target}"
encoding="${compiler.encoding}"
failonerror="true">
- <compilerarg value="-Xlint"/>
+ <compilerarg line="-Xlint -processor pivot.wtkx.BindProcessor"/>
<classpath>
<pathelement location="core/${folder.bin}"/>
<fileset dir="wtk/lib" includes="**/*.jar"/>
Modified: incubator/pivot/trunk/wtk/src/pivot/wtkx/BindProcessor.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/pivot/wtkx/BindProcessor.java?rev=772466&r1=772465&r2=772466&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/pivot/wtkx/BindProcessor.java (original)
+++ incubator/pivot/trunk/wtk/src/pivot/wtkx/BindProcessor.java Wed May 6 23:33:59 2009
@@ -52,9 +52,6 @@
* Annotation processor that injects <tt>bind()</tt> overrides into classes
* that use the <tt>@Load</tt> and <tt>@Bind</tt> annotations to perform WTKX
* loading and binding.
- * <p>
- * TODO Make base bind() final, and strip out that flag at compilation time
- * to allow us to extend it.
*
* @author tvolkert
*/
@@ -62,6 +59,11 @@
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class BindProcessor extends AbstractProcessor {
/**
+ * Holds pertinent information about a class' member variables that use
+ * the <tt>@Load</tt> and <tt>@Bind</tt> annotations. A bind scope object
+ * is pushed onto a stack before visiting a class and popped off the
+ * stack after visiting it, allowing us to know if any members variables
+ * contained in the class need bind processing as we're exiting the class.
*
* @author tvolkert
*/
@@ -80,13 +82,21 @@
}
/**
- * This actually does the work of instance initializer injection.
+ * This actually does the work of bind method override injection.
*
* @author tvolkert
*/
private class BindInjector extends TreeTranslator {
private ArrayStack<BindScope> bindScopeStack = new ArrayStack<BindScope>();
+ /**
+ * Injects an override implementation of the <tt>bind()</tt> method
+ * into the specified class if any member variables are found to be
+ * annotated with the <tt>@Load</tt> or <tt>@Bind</tt> annotations.
+ *
+ * @param tree
+ * The AST class declaration node
+ */
@Override
public void visitClassDef(JCTree.JCClassDecl tree) {
BindScope bindScope = new BindScope();
@@ -98,8 +108,11 @@
if (bindScope.loadGroups != null) {
StringBuilder sourceCode = new StringBuilder("{");
- // TODO Call super.bind() once impl stripping is being done
- // on the base class' implementation
+ sourceCode.append("try {");
+ sourceCode.append("super.bind();");
+ sourceCode.append("} catch (Exception ex) {");
+ sourceCode.append("throw new pivot.wtkx.BindException(ex);");
+ sourceCode.append("}");
sourceCode.append("pivot.wtkx.WTKXSerializer wtkxSerializer;");
sourceCode.append("Object value;");
@@ -166,6 +179,8 @@
JCTree.JCBlock methodBody = parser.block();
// Create the bind() override AST method declaration
+ // TODO Declare it to throw IOException, then remove the
+ // try/catch from super.bind()
Type.MethodType methodType = new Type.MethodType(
List.<Type>nil(), // Argument types
symbolTable.voidType, // Return type
@@ -188,6 +203,44 @@
}
}
+ /**
+ * Checks for the <tt>@BindMethod</tt> annotation on a method
+ * (signalling the base class' implementation). When found, this strips
+ * the method of its body and the <tt>final</tt> keyword, thus clearing
+ * the way for us to override <tt>bind()</tt> in bindable subclasses
+ * with inline implementations that can safely call
+ * <tt>super.bind()</tt> without running the runtime bind
+ * implementation.
+ *
+ * @param tree
+ * The AST method declaration node
+ */
+ @Override
+ public void visitMethodDef(JCTree.JCMethodDecl tree) {
+ super.visitMethodDef(tree);
+
+ Element methodElement = tree.sym;
+ Bindable.BindMethod bindMethod = methodElement.getAnnotation(Bindable.BindMethod.class);
+
+ if (bindMethod != null) {
+ // Remove the 'final' flag so that we may extend the method
+ tree.sym.flags_field &= ~Flags.FINAL;
+ tree.mods.flags &= ~Flags.FINAL;
+
+ // Clear the method body so that it becomes a no-op
+ tree.body.stats = List.<JCTree.JCStatement>nil();
+ }
+ }
+
+ /**
+ * Looks for the <tt>@Load</tt> and <tt>@Bind</tt> annotations on
+ * member variable declarations. When found, it records pertinent
+ * information in the current bind scope, to be used before we exit
+ * the containing class.
+ *
+ * @param tree
+ * The AST variable declaration node
+ */
@Override
public void visitVarDef(JCTree.JCVariableDecl tree) {
super.visitVarDef(tree);
@@ -269,7 +322,7 @@
if (!roundEnvironment.processingOver()) {
for (Element rootElement : roundEnvironment.getRootElements()) {
if (rootElement.getKind() == ElementKind.CLASS) {
- // Visit each Class tree with our bindInjector visitor
+ // Visit each AST class node with our BindInjector visitor
JCTree tree = (JCTree)trees.getTree(rootElement);
tree.accept(bindInjector);
}
Modified: incubator/pivot/trunk/wtk/src/pivot/wtkx/Bindable.java
URL: http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/pivot/wtkx/Bindable.java?rev=772466&r1=772465&r2=772466&view=diff
==============================================================================
--- incubator/pivot/trunk/wtk/src/pivot/wtkx/Bindable.java (original)
+++ incubator/pivot/trunk/wtk/src/pivot/wtkx/Bindable.java Wed May 6 23:33:59 2009
@@ -64,9 +64,24 @@
}
/**
+ * Flags the base implementation of the bind method. This cues the
+ * annotation processor to remove the <tt>final</tt> flag from the method
+ * so that it may be extended by the compiler and to remove the body of the
+ * method, making it a no-op at runtime (since the annotation processor
+ * inlines all WTKX binding).
+ *
+ * @author tvolkert
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @Target(ElementType.METHOD)
+ static @interface BindMethod {
+ }
+
+ /**
* Applies WTKX binding annotations to this bindable object.
*/
- protected void bind() throws IOException, BindException {
+ @BindMethod
+ protected final void bind() throws IOException, BindException {
// Walk fields and resolve annotations
ArrayList<Class<?>> typeHierarchy = new ArrayList<Class<?>>();
Class<?> type = getClass();