diff --git a/.gitignore b/.gitignore index f5f547c..ed0737b 100644 --- a/.gitignore +++ b/.gitignore @@ -243,3 +243,7 @@ /trunk/codemodel/codemodel-annotation-compiler/target /trunk/codemodel/codemodel-annotation-compiler/velocity.log /trunk/codemodel/codemodel-annotation-compiler/*.iml + +.gradle/ +codemodel/build/ +codemodel/target/ diff --git a/build.gradle b/build.gradle index 3f428a3..e95ad98 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ allprojects { apply plugin: 'maven' group = 'com.unquietcode.tools.jcodemodel' - version = '1.0.2' + version = '1.0.2-SNAPSHOT' } subprojects { diff --git a/codemodel-annotation-compiler/pom.xml b/codemodel-annotation-compiler/pom.xml index 38588cd..28b1378 100644 --- a/codemodel-annotation-compiler/pom.xml +++ b/codemodel-annotation-compiler/pom.xml @@ -44,20 +44,20 @@ 4.0.0 unquietcode.tools.jcodemodel codemodel-annotation-compiler - 1.0.2 + 1.0.2-SNAPSHOT Codemodel Annotation Compiler The annotation compiler ant task for the CodeModel java source code generation library unquietcode.tools.jcodemodel codemodel-project - 1.0.2 + 1.0.2-SNAPSHOT ../pom.xml unquietcode.tools.jcodemodel codemodel - 1.0.2 + 1.0.2-SNAPSHOT com.sun.istack diff --git a/codemodel/build.gradle b/codemodel/build.gradle index a460734..238e630 100644 --- a/codemodel/build.gradle +++ b/codemodel/build.gradle @@ -28,14 +28,14 @@ artifacts { uploadArchives { repositories { mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + //beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) + authentication(userName: hasProperty('ossrhUsername')?ossrhUsername:'', password: hasProperty('ossrhPassword')?ossrhPassword:'') } snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) + authentication(userName: hasProperty('ossrhUsername')?ossrhUsername:'', password: hasProperty('ossrhPassword')?ossrhPassword:'') } pom.project { @@ -70,6 +70,6 @@ uploadArchives { } } -signing { - sign configurations.archives -} \ No newline at end of file +//signing { +// sign configurations.archives +//} \ No newline at end of file diff --git a/codemodel/pom.xml b/codemodel/pom.xml index ffa326a..18bba66 100644 --- a/codemodel/pom.xml +++ b/codemodel/pom.xml @@ -45,7 +45,7 @@ unquietcode.tools.jcodemodel codemodel-project - 1.0.2 + 1.0.2-SNAPSHOT ../pom.xml diff --git a/codemodel/src/main/java/com/sun/codemodel/JAnnotationUse.java b/codemodel/src/main/java/com/sun/codemodel/JAnnotationUse.java index bccd8b6..0665c82 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JAnnotationUse.java +++ b/codemodel/src/main/java/com/sun/codemodel/JAnnotationUse.java @@ -306,10 +306,10 @@ public JAnnotationUse param(String name, JEnumConstant value){ * This can be used for e.g to specify *
       *        @XmlCollectionItem(type=Integer.class);
-      * 
-      * For adding a value of Class
-      * @link
-      * #annotationParam(java.lang.String, java.lang.Class)
+      * 
+ * For adding a value of {@code Class} + * {@link + * #annotationParam(java.lang.String, java.lang.Class)} * @param name * The simple name for this annotation param * diff --git a/codemodel/src/main/java/com/sun/codemodel/JArray.java b/codemodel/src/main/java/com/sun/codemodel/JArray.java index abb2a43..c75fb19 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JArray.java +++ b/codemodel/src/main/java/com/sun/codemodel/JArray.java @@ -37,66 +37,84 @@ * only if the new code is made subject to such option by the copyright * holder. */ - package com.sun.codemodel; import java.util.ArrayList; import java.util.List; - /** * array creation and initialization. */ public final class JArray extends JExpressionImpl { private final JType type; - private final JExpression size; + private final List sizes = new ArrayList(); private List exprs = null; /** * Add an element to the array initializer + * @param e + * @return */ public JArray add(JExpression e) { - if (exprs == null) + if (exprs == null) { exprs = new ArrayList(); + } exprs.add(e); return this; } + public JArray addSize(JExpression e) { + if (e != null) { + sizes.add(e); + } + return this; + } + JArray(JType type, JExpression size) { this.type = type; - this.size = size; + if (size != null) { + sizes.add(size); + } } public void generate(JFormatter f) { - + // generally we produce new T[x], but when T is an array type (T=T'[]) // then new T'[][x] is wrong. It has to be new T'[x][]. int arrayCount = 0; JType t = type; - - while( t.isArray() ) { + + while (t.isArray()) { t = t.elementType(); arrayCount++; } - f.p("new").g(t).p('['); - if (size != null) - f.g(size); - f.p(']'); - - for( int i=0; i bindings) { return new JArrayClass(owner(),c); } + @Override + public JClass inner(String name) { + return null; + } + } diff --git a/codemodel/src/main/java/com/sun/codemodel/JBlock.java b/codemodel/src/main/java/com/sun/codemodel/JBlock.java index 2ac9b27..a0ea793 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JBlock.java +++ b/codemodel/src/main/java/com/sun/codemodel/JBlock.java @@ -41,8 +41,8 @@ package com.sun.codemodel; import java.util.ArrayList; -import java.util.List; import java.util.Collections; +import java.util.List; /** * A block of Java code, which may contain statements and local declarations. @@ -66,6 +66,7 @@ public final class JBlock implements JGenerable, JStatement { */ private boolean bracesRequired = true; private boolean indentRequired = true; + private boolean newlineRequired = true; /** * Current position. @@ -73,12 +74,21 @@ public final class JBlock implements JGenerable, JStatement { private int pos; public JBlock() { - this(true,true); + this(true, true, true); } public JBlock(boolean bracesRequired, boolean indentRequired) { + this(bracesRequired, indentRequired, true); + } + + public JBlock(boolean bracesRequired, boolean indentRequired, boolean newlineRequired) { this.bracesRequired = bracesRequired; this.indentRequired = indentRequired; + this.newlineRequired = newlineRequired; + } + + public void setNewlineRequired(boolean val) { + this.newlineRequired = val; } /** @@ -402,10 +412,17 @@ public void _continue() { */ public JBlock block() { JBlock b = new JBlock(); - b.bracesRequired = false; - b.indentRequired = false; + // why false? of course they are both required +// b.bracesRequired = false; +// b.indentRequired = false; return insert(b); } + + public JSynchronized _synchronized(JExpression lock) { + JSynchronized syn = new JSynchronized(lock); + insert(syn); + return syn; + } /** * Creates a "literal" statement directly. @@ -462,7 +479,7 @@ public JForEach forEach(JType varType, String name, JExpression collection) { } public void state(JFormatter f) { f.g(this); - if (bracesRequired) + if (newlineRequired) f.nl(); } diff --git a/codemodel/src/main/java/com/sun/codemodel/JCatchBlock.java b/codemodel/src/main/java/com/sun/codemodel/JCatchBlock.java index 8053e11..62be8a8 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JCatchBlock.java +++ b/codemodel/src/main/java/com/sun/codemodel/JCatchBlock.java @@ -45,15 +45,18 @@ * Catch block for a try/catch/finally statement */ -public class JCatchBlock implements JGenerable { +public class JCatchBlock implements JTryBlock.CatchBlock { JClass exception; private JVar var = null; private JBlock body = new JBlock(); + private boolean isMulti = false; JCatchBlock(JClass exception) { this.exception = exception; } + + public JVar param(String name) { if (var != null) throw new IllegalStateException(); diff --git a/codemodel/src/main/java/com/sun/codemodel/JClass.java b/codemodel/src/main/java/com/sun/codemodel/JClass.java index 954a9ef..54b0f1f 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JClass.java +++ b/codemodel/src/main/java/com/sun/codemodel/JClass.java @@ -37,7 +37,6 @@ * only if the new code is made subject to such option by the copyright * holder. */ - package com.sun.codemodel; import java.util.ArrayList; @@ -49,14 +48,15 @@ /** * Represents a Java reference type, such as a class, an interface, * an enum, an array type, a parameterized type. - * + *

*

* To be exact, this object represents an "use" of a reference type, - * not necessarily a declaration of it, which is modeled as {@link JDefinedClass}. + * not necessarily a declaration of it, which is modeled as + * {@link JDefinedClass}. */ -public abstract class JClass extends JType -{ - protected JClass( JCodeModel _owner ) { +public abstract class JClass extends JType { + + protected JClass(JCodeModel _owner) { this._owner = _owner; } @@ -64,13 +64,13 @@ protected JClass( JCodeModel _owner ) { * Gets the name of this class. * * @return - * name of this class, without any qualification. - * For example, this method returns "String" for - * java.lang.String. + * name of this class, without any qualification. + * For example, this method returns "String" for + * java.lang.String. */ abstract public String name(); - - /** + + /** * Gets the package to which this class belongs. * TODO: shall we move move this down? */ @@ -83,41 +83,48 @@ protected JClass( JCodeModel _owner ) { public JClass outer() { return null; } - - private final JCodeModel _owner; - /** Gets the JCodeModel object to which this object belongs. */ - public final JCodeModel owner() { return _owner; } + public abstract JClass inner(String name); + + private final JCodeModel _owner; + + /** + * Gets the JCodeModel object to which this object belongs. + */ + public final JCodeModel owner() { + return _owner; + } + /** * Gets the super class of this class. - * + *

* @return - * Returns the JClass representing the superclass of the - * entity (class or interface) represented by this {@link JClass}. - * Even if no super class is given explicitly or this {@link JClass} - * is not a class, this method still returns - * {@link JClass} for {@link Object}. - * If this JClass represents {@link Object}, return null. + * Returns the JClass representing the superclass of the + * entity (class or interface) represented by this {@link JClass}. + * Even if no super class is given explicitly or this {@link JClass} + * is not a class, this method still returns + * {@link JClass} for {@link Object}. + * If this JClass represents {@link Object}, return null. */ abstract public JClass _extends(); - + /** * Iterates all super interfaces directly implemented by * this class/interface. - * + *

* @return - * A non-null valid iterator that iterates all - * {@link JClass} objects that represents those interfaces - * implemented by this object. + * A non-null valid iterator that iterates all + * {@link JClass} objects that represents those interfaces + * implemented by this object. */ abstract public Iterator _implements(); - + /** * Iterates all the type parameters of this class/interface. - * *

- * For example, if this {@link JClass} represents - * Set<T>, this method returns an array + *

+ * For example, if this {@link JClass} represents + * Set<T>, this method returns an array * that contains single {@link JTypeVar} for 'T'. */ public JTypeVar[] typeParams() { @@ -144,18 +151,22 @@ public JTypeVar[] typeParams() { * defined in the java.lang package, return the corresponding * primitive type. Otherwise null. */ - public JPrimitiveType getPrimitiveType() { return null; } + public JPrimitiveType getPrimitiveType() { + return null; + } /** * @deprecated calling this method from {@link JClass} * would be meaningless, since it's always guaranteed to * return this. */ - public JClass boxify() { return this; } + public JClass boxify() { + return this; + } public JType unboxify() { JPrimitiveType pt = getPrimitiveType(); - return pt==null ? (JType)this : pt; + return pt == null ? (JType) this : pt; } public JClass erasure() { @@ -165,32 +176,42 @@ public JClass erasure() { /** * Checks the relationship between two classes. *

- * This method works in the same way as {@link Class#isAssignableFrom(Class)} + * This method works in the same way as + * {@link Class#isAssignableFrom(Class)} * works. For example, baseClass.isAssignableFrom(derivedClass)==true. */ - public final boolean isAssignableFrom( JClass derived ) { + public final boolean isAssignableFrom(JClass derived) { // to avoid the confusion, always use "this" explicitly in this method. - + // null can be assigned to any type. - if( derived instanceof JNullType ) return true; - - if( this==derived ) return true; - + if (derived instanceof JNullType) { + return true; + } + + if (this == derived) { + return true; + } + // the only class that is assignable from an interface is // java.lang.Object - if( this==_package().owner().ref(Object.class) ) return true; - + if (this == _package().owner().ref(Object.class)) { + return true; + } + JClass b = derived._extends(); - if( b!=null && this.isAssignableFrom(b) ) + if (b != null && this.isAssignableFrom(b)) { return true; - - if( this.isInterface() ) { + } + + if (this.isInterface()) { Iterator itfs = derived._implements(); - while( itfs.hasNext() ) - if( this.isAssignableFrom(itfs.next()) ) + while (itfs.hasNext()) { + if (this.isAssignableFrom(itfs.next())) { return true; + } + } } - + return false; } @@ -199,101 +220,114 @@ public final boolean isAssignableFrom( JClass derived ) { * *

* For example, given the following - *


+     * <pre>{@code
      * interface Foo<T> extends List<List<T>> {}
      * interface Bar extends Foo<String> {}
-     * 
+ * }
* This method works like this: - *

+     * <pre>
+     * {@code
      * getBaseClass( Bar, List ) = List<List<String>
      * getBaseClass( Bar, Foo  ) = Foo<String>
      * getBaseClass( Foo<? extends Number>, Collection ) = Collection<List<? extends Number>>
      * getBaseClass( ArrayList<? extends BigInteger>, List ) = List<? extends BigInteger>
-     * 
+ * } * * @param baseType - * The class whose parameterization we are interested in. + * The class whose parameterization we are interested in. * @return - * The use of {@code baseType} in {@code this} type. - * or null if the type is not assignable to the base type. + * The use of {@code baseType} in {@code this} type. + * or null if the type is not assignable to the base type. */ - public final JClass getBaseClass( JClass baseType ) { + public final JClass getBaseClass(JClass baseType) { - if( this.erasure().equals(baseType) ) + if (this.erasure().equals(baseType)) { return this; + } JClass b = _extends(); - if( b!=null ) { + if (b != null) { JClass bc = b.getBaseClass(baseType); - if(bc!=null) + if (bc != null) { return bc; + } } Iterator itfs = _implements(); - while( itfs.hasNext() ) { + while (itfs.hasNext()) { JClass bc = itfs.next().getBaseClass(baseType); - if(bc!=null) + if (bc != null) { return bc; + } } return null; } - public final JClass getBaseClass( Class baseType ) { + public final JClass getBaseClass(Class baseType) { return getBaseClass(owner().ref(baseType)); } - private JClass arrayClass; + public JClass array() { - if(arrayClass==null) - arrayClass = new JArrayClass(owner(),this); + if (arrayClass == null) { + arrayClass = new JArrayClass(owner(), this); + } return arrayClass; } /** * "Narrows" a generic class to a concrete class by specifying * a type argument. - * *

- * .narrow(X) builds Set<X> from Set. + *

+ * .narrow(X) builds Set<X> from + * Set. */ - public JClass narrow( Class clazz ) { + public JClass narrow(Class clazz) { return narrow(owner().ref(clazz)); } - public JClass narrow( Class... clazz ) { + public JClass narrow(Class... clazz) { JClass[] r = new JClass[clazz.length]; - for( int i=0; i - * .narrow(X) builds Set<X> from Set. + *

+ * .narrow(X) builds Set<X> from + * Set. */ - public JClass narrow( JClass clazz ) { - return new JNarrowedClass(this,clazz); + public JClass narrow(JClass clazz) { + return new JNarrowedClass(this, clazz); } - public JClass narrow( JType type ) { + public JClass narrow(JType type) { return narrow(type.boxify()); } - public JClass narrow( JClass... clazz ) { - return new JNarrowedClass(this,Arrays.asList(clazz.clone())); + public JClass narrow(JClass... clazz) { + return new JNarrowedClass(this, Arrays.asList(clazz.clone())); } - public JClass narrow( List clazz ) { - return new JNarrowedClass(this,new ArrayList(clazz)); + public JClass narrow(List clazz) { + return new JNarrowedClass(this, new ArrayList(clazz)); + } + + public JClass narrowDiamond() { + return new JNarrowedClass(this); } /** - * If this class is parameterized, return the type parameter of the given index. + * If this class is parameterized, return the type parameter of the given + * index. */ public List getTypeParameters() { return Collections.emptyList(); @@ -303,7 +337,7 @@ public List getTypeParameters() { * Returns true if this class is a parameterized class. */ public final boolean isParameterized() { - return erasure()!=this; + return erasure() != this; } /** @@ -315,45 +349,61 @@ public final JClass wildcard() { return new JTypeWildcard(this); } + /** + * Create "? super T" from T + * + * @return never null + */ + public final JClass superWildcard() { + return new JTypeWildcard(this, true); + } + /** * Substitutes the type variables with their actual arguments. - * *

- * For example, when this class is Map<String,Map<V>>, + *

+ * For example, when this class is {@code Map>}, * (where V then doing * substituteParams( V, Integer ) returns a {@link JClass} - * for Map<String,Map<Integer>>. - * + * for {@code Map>}. + *

*

* This method needs to work recursively. */ - protected abstract JClass substituteParams( JTypeVar[] variables, List bindings ); - + protected abstract JClass substituteParams(JTypeVar[] variables, List bindings); + public String toString() { return this.getClass().getName() + '(' + name() + ')'; } - public final JExpression dotclass() { return JExpr.dotclass(this); } - /** Generates a static method invocation. */ + /** + * Generates a static method invocation. + */ public final JInvocation staticInvoke(JMethod method) { - return new JInvocation(this,method); + return new JInvocation(this, method); } - - /** Generates a static method invocation. */ + + /** + * Generates a static method invocation. + */ public final JInvocation staticInvoke(String method) { - return new JInvocation(this,method); + return new JInvocation(this, method); } - - /** Static field reference. */ + + /** + * Static field reference. + */ public final JFieldRef staticRef(String field) { return new JFieldRef(this, field); } - /** Static field reference. */ + /** + * Static field reference. + */ public final JFieldRef staticRef(JVar field) { return new JFieldRef(this, field); } diff --git a/codemodel/src/main/java/com/sun/codemodel/JClassProxy.java b/codemodel/src/main/java/com/sun/codemodel/JClassProxy.java new file mode 100644 index 0000000..53ec28b --- /dev/null +++ b/codemodel/src/main/java/com/sun/codemodel/JClassProxy.java @@ -0,0 +1,253 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.sun.codemodel; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * + * @author lkroll + */ +public class JClassProxy extends JClass { + + private JClass proxee = null; + private final Map innerProxies = new HashMap(); + private final String shortName; + private final ClassResolver resolver; + + public JClassProxy(JCodeModel _owner, String shortName, ClassResolver resolver) { + super(_owner); + this.shortName = shortName; + this.resolver = resolver; + } + + public boolean isResolved() { + return proxee != null; + } + + public void assertResolved() { + if (proxee == null) { + proxee = resolver.resolveClass(shortName); + } + if (proxee == null) { + throw new RuntimeException("Class " + shortName + " could not be resolved using resolver " + resolver); + } + } + + public void setProxee(JClass clazz) { + if (clazz instanceof JClassProxy) { + throw new RuntimeException("Building endless proxy hierarchies is not a good idea!"); + } + this.proxee = clazz; + } + + @Override + public String name() { + if (isResolved()) { + return proxee.name(); + } else { + return shortName; + //throw new UnresolvedClassException(shortName); + } + } + + @Override + public JPackage _package() { + assertResolved(); + if (isResolved()) { + return proxee._package(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public JClass inner(String name) { + if (isResolved()) { + return proxee.inner(name); + } else { + return new JClassProxy(this.owner(), name, new InnerClassResolver(this)); + } + } + + @Override + public JClass outer() { + assertResolved(); + if (isResolved()) { + return proxee.outer(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public JClass _extends() { + assertResolved(); + if (isResolved()) { + return proxee._extends(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public Iterator _implements() { + assertResolved(); + if (isResolved()) { + return proxee._implements(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public JTypeVar[] typeParams() { + assertResolved(); + if (isResolved()) { + return proxee.typeParams(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public boolean isInterface() { + assertResolved(); + if (isResolved()) { + return proxee.isInterface(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public boolean isAbstract() { + assertResolved(); + if (isResolved()) { + return proxee.isAbstract(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public JPrimitiveType getPrimitiveType() { + assertResolved(); + if (isResolved()) { + return proxee.getPrimitiveType(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public JClass erasure() { + assertResolved(); + if (isResolved()) { + return proxee.erasure(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + protected JClass substituteParams(JTypeVar[] variables, List bindings) { + assertResolved(); + if (isResolved()) { + return proxee.substituteParams(variables, bindings); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public String fullName() { + assertResolved(); + if (isResolved()) { + return proxee.fullName(); + } else { + throw new UnresolvedClassException(shortName); + } + } + + @Override + public void generate(JFormatter f) { + assertResolved(); + if (isResolved()) { + f.t(proxee); + } else { + throw new UnresolvedClassException(shortName); + } + } + + /** + * Prints the class name in javadoc @link format. + */ + @Override + void printLink(JFormatter f) { + assertResolved(); + if (isResolved()) { + f.p("{@link ").g(proxee).p('}'); + } else { + throw new UnresolvedClassException(shortName); + } + + } + + public static class UnresolvedClassException extends RuntimeException { + + private final String shortName; + + private UnresolvedClassException(String shortName) { + this.shortName = shortName; + } + + @Override + public String getMessage() { + return "Proxied class " + shortName + " has not been resolved, yet"; + } + + } + + public static interface ClassResolver { + + public JClass resolveClass(String name); + } + + private static class InnerClassResolver implements ClassResolver { + + private final JClassProxy outer; + + InnerClassResolver(JClassProxy outer) { + this.outer = outer; + } + + public JClass resolveClass(String name) { + if (!outer.isResolved()) { + outer.assertResolved(); + } + System.out.println("Proxee type is: " + outer.proxee); + if (outer.proxee instanceof JDefinedClass) { + JDefinedClass jdc = (JDefinedClass) outer.proxee; + for (Entry e : jdc.getClasses().entrySet()) { + JDefinedClass jdcInner = e.getValue(); + System.out.println(" " + e.getKey() + " --> " + jdcInner.fullName()); + } + } + return outer.proxee.inner(name); + + } + + @Override + public String toString() { + return "InnerClassResolver(" + outer + ")"; + } + } +} diff --git a/codemodel/src/main/java/com/sun/codemodel/JCodeModel.java b/codemodel/src/main/java/com/sun/codemodel/JCodeModel.java index b993858..cf79c60 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JCodeModel.java +++ b/codemodel/src/main/java/com/sun/codemodel/JCodeModel.java @@ -37,9 +37,11 @@ * only if the new code is made subject to such option by the copyright * holder. */ - package com.sun.codemodel; +import com.sun.codemodel.util.NameUtilities; +import com.sun.codemodel.writer.FileCodeWriter; +import com.sun.codemodel.writer.ProgressCodeWriter; import java.io.File; import java.io.IOException; import java.io.PrintStream; @@ -51,11 +53,6 @@ import java.util.List; import java.util.Map; -import com.sun.codemodel.util.NameUtilities; -import com.sun.codemodel.writer.FileCodeWriter; -import com.sun.codemodel.writer.ProgressCodeWriter; - - /** * Root of the code DOM. * @@ -75,74 +72,89 @@ * *

* Every CodeModel node is always owned by one {@link JCodeModel} object - * at any given time (which can be often accesesd by the owner() method.) + * at any given time (which can be often accesesd by the owner() + * method.) * * As such, when you generate Java code, most of the operation works - * in a top-down fashion. For example, you create a class from {@link JCodeModel}, + * in a top-down fashion. For example, you create a class from + * {@link JCodeModel}, * which gives you a {@link JDefinedClass}. Then you invoke a method on it * to generate a new method, which gives you {@link JMethod}, and so on. * - * There are a few exceptions to this, most notably building {@link JExpression}s, + * There are a few exceptions to this, most notably building + * {@link JExpression}s, * but generally you work with CodeModel in a top-down fashion. * - * Because of this design, most of the CodeModel classes aren't directly instanciable. + * Because of this design, most of the CodeModel classes aren't directly + * instanciable. * * *

Where to go from here?

*

- * Most of the time you'd want to populate new type definitions in a {@link JCodeModel}. + * Most of the time you'd want to populate new type definitions in a + * {@link JCodeModel}. * See {@link #_class(String, ClassType)}. */ public final class JCodeModel { - - /** The packages that this JCodeWriter contains. */ - private HashMap packages = new HashMap(); - - /** All JReferencedClasses are pooled here. */ - private final HashMap,JReferencedClass> refClasses = new HashMap,JReferencedClass>(); - /** All JDirectClass are pooled here. */ - private final Map refDirectClasses = new HashMap(); + /** + * The packages that this JCodeWriter contains. + */ + private HashMap packages = new HashMap(); + + /** + * All JReferencedClasses are pooled here. + */ + private final HashMap, JReferencedClass> refClasses = new HashMap, JReferencedClass>(); - /** Obtains a reference to the special "null" type. */ - public final JNullType NULL = new JNullType(this); - // primitive types - public final JPrimitiveType VOID = new JPrimitiveType(this,"void", Void.class); - public final JPrimitiveType BOOLEAN = new JPrimitiveType(this,"boolean",Boolean.class); - public final JPrimitiveType BYTE = new JPrimitiveType(this,"byte", Byte.class); - public final JPrimitiveType SHORT = new JPrimitiveType(this,"short", Short.class); - public final JPrimitiveType CHAR = new JPrimitiveType(this,"char", Character.class); - public final JPrimitiveType INT = new JPrimitiveType(this,"int", Integer.class); - public final JPrimitiveType FLOAT = new JPrimitiveType(this,"float", Float.class); - public final JPrimitiveType LONG = new JPrimitiveType(this,"long", Long.class); - public final JPrimitiveType DOUBLE = new JPrimitiveType(this,"double", Double.class); - /** - * If the flag is true, we will consider two classes "Foo" and "foo" - * as a collision. + * All JDirectClass are pooled here. */ - protected static final boolean isCaseSensitiveFileSystem = getFileSystemCaseSensitivity(); - - private static boolean getFileSystemCaseSensitivity() { - try { - // let the system property override, in case the user really - // wants to override. - if( System.getProperty("com.sun.codemodel.FileSystemCaseSensitive")!=null ) - return true; - } catch( Exception e ) {} - - // on Unix, it's case sensitive. - return (File.separatorChar == '/'); - } + private final Map refDirectClasses = new HashMap(); + /** + * Obtains a reference to the special "null" type. + */ + public final JNullType NULL = new JNullType(this); + // primitive types + public final JPrimitiveType VOID = new JPrimitiveType(this, "void", Void.class); + public final JPrimitiveType BOOLEAN = new JPrimitiveType(this, "boolean", Boolean.class); + public final JPrimitiveType BYTE = new JPrimitiveType(this, "byte", Byte.class); + public final JPrimitiveType SHORT = new JPrimitiveType(this, "short", Short.class); + public final JPrimitiveType CHAR = new JPrimitiveType(this, "char", Character.class); + public final JPrimitiveType INT = new JPrimitiveType(this, "int", Integer.class); + public final JPrimitiveType FLOAT = new JPrimitiveType(this, "float", Float.class); + public final JPrimitiveType LONG = new JPrimitiveType(this, "long", Long.class); + public final JPrimitiveType DOUBLE = new JPrimitiveType(this, "double", Double.class); +// +// /** +// * If the flag is true, we will consider two classes "Foo" and "foo" +// * as a collision. +// */ +// protected static final boolean isCaseSensitiveFileSystem = getFileSystemCaseSensitivity(); + +// private static boolean getFileSystemCaseSensitivity() { +// try { +// // let the system property override, in case the user really +// // wants to override. +// if (System.getProperty("com.sun.codemodel.FileSystemCaseSensitive") != null) { +// return true; +// } +// } catch (Exception e) { +// } +// +// // on Unix, it's case sensitive. +// return (File.separatorChar == '/'); +// } + + public JCodeModel() { + } - public JCodeModel() {} - /** * Add a package to the list of packages to be generated * * @param name - * Name of the package. Use "" to indicate the root package. + * Name of the package. Use "" to indicate the root package. * * @return Newly generated package */ @@ -154,7 +166,7 @@ public JPackage _package(String name) { } return p; } - + public final JPackage rootPackage() { return _package(""); } @@ -166,73 +178,79 @@ public final JPackage rootPackage() { public Iterator packages() { return packages.values().iterator(); } - + /** * Creates a new generated class. - * + *

* @exception JClassAlreadyExistsException - * When the specified class/interface was already created. + * When the specified class/interface was already created. */ public JDefinedClass _class(String fullyqualifiedName) throws JClassAlreadyExistsException { - return _class(fullyqualifiedName,ClassType.CLASS); + return _class(fullyqualifiedName, ClassType.CLASS); } /** * Creates a dummy, unknown {@link JClass} that represents a given name. * *

- * This method is useful when the code generation needs to include the user-specified - * class that may or may not exist, and only thing known about it is a class name. + * This method is useful when the code generation needs to include the + * user-specified + * class that may or may not exist, and only thing known about it is a class + * name. */ public JClass directClass(String name) { - return new JDirectClass(this,name); + return new JDirectClass(this, name); } /** * Creates a new generated class. * * @exception JClassAlreadyExistsException - * When the specified class/interface was already created. + * When the specified class/interface was already created. */ - public JDefinedClass _class(int mods, String fullyqualifiedName,ClassType t) throws JClassAlreadyExistsException { + public JDefinedClass _class(int mods, String fullyqualifiedName, ClassType t) throws JClassAlreadyExistsException { int idx = fullyqualifiedName.lastIndexOf('.'); - if( idx<0 ) return rootPackage()._class(fullyqualifiedName); - else - return _package(fullyqualifiedName.substring(0,idx)) - ._class(mods, fullyqualifiedName.substring(idx+1), t ); + if (idx < 0) { + return rootPackage()._class(fullyqualifiedName); + } else { + return _package(fullyqualifiedName.substring(0, idx)) + ._class(mods, fullyqualifiedName.substring(idx + 1), t); + } } /** * Creates a new generated class. * * @exception JClassAlreadyExistsException - * When the specified class/interface was already created. + * When the specified class/interface was already created. */ - public JDefinedClass _class(String fullyqualifiedName,ClassType t) throws JClassAlreadyExistsException { - return _class( JMod.PUBLIC, fullyqualifiedName, t ); + public JDefinedClass _class(String fullyqualifiedName, ClassType t) throws JClassAlreadyExistsException { + return _class(JMod.PUBLIC, fullyqualifiedName, t); } /** * Gets a reference to the already created generated class. - * + *

* @return null - * If the class is not yet created. + * If the class is not yet created. * @see JPackage#_getClass(String) */ public JDefinedClass _getClass(String fullyQualifiedName) { int idx = fullyQualifiedName.lastIndexOf('.'); - if( idx<0 ) return rootPackage()._getClass(fullyQualifiedName); - else - return _package(fullyQualifiedName.substring(0,idx)) - ._getClass( fullyQualifiedName.substring(idx+1) ); + if (idx < 0) { + return rootPackage()._getClass(fullyQualifiedName); + } else { + return _package(fullyQualifiedName.substring(0, idx)) + ._getClass(fullyQualifiedName.substring(idx + 1)); + } } /** * Creates a new anonymous class. - * + *

* @deprecated - * The naming convention doesn't match the rest of the CodeModel. - * Use {@link #anonymousClass(JClass)} instead. + * The naming convention doesn't match the rest of the CodeModel. + * Use {@link #anonymousClass(JClass)} instead. */ public JDefinedClass newAnonymousClass(JClass baseType) { return new JAnonymousClass(baseType); @@ -248,18 +266,18 @@ public JDefinedClass anonymousClass(JClass baseType) { public JDefinedClass anonymousClass(Class baseType) { return anonymousClass(ref(baseType)); } - + /** * Generates Java source code. * A convenience method for build(destDir,destDir,System.out). - * + *

* @param destDir - * source files are generated into this directory. - * @param status - * if non-null, progress indication will be sent to this stream. + * source files are generated into this directory. + * @param status + * if non-null, progress indication will be sent to this stream. */ - public void build( File destDir, PrintStream status ) throws IOException { - build(destDir,destDir,status); + public void build(File destDir, PrintStream status) throws IOException { + build(destDir, destDir, status); } /** @@ -267,51 +285,53 @@ public void build( File destDir, PrintStream status ) throws IOException { * A convenience method that calls {@link #build(CodeWriter,CodeWriter)}. * * @param srcDir - * Java source files are generated into this directory. + * Java source files are generated into this directory. * @param resourceDir - * Other resource files are generated into this directory. - * @param status - * if non-null, progress indication will be sent to this stream. + * Other resource files are generated into this directory. + * @param status + * if non-null, progress indication will be sent to this stream. */ - public void build( File srcDir, File resourceDir, PrintStream status ) throws IOException { + public void build(File srcDir, File resourceDir, PrintStream status) throws IOException { CodeWriter src = new FileCodeWriter(srcDir); CodeWriter res = new FileCodeWriter(resourceDir); - if(status!=null) { - src = new ProgressCodeWriter(src, status ); - res = new ProgressCodeWriter(res, status ); + if (status != null) { + src = new ProgressCodeWriter(src, status); + res = new ProgressCodeWriter(res, status); } - build(src,res); + build(src, res); } /** * A convenience method for build(destDir,System.out). */ - public void build( File destDir ) throws IOException { - build(destDir,System.out); + public void build(File destDir) throws IOException { + build(destDir, System.out); } /** - * A convenience method for build(srcDir,resourceDir,System.out). + * A convenience method for + * build(srcDir,resourceDir,System.out). */ - public void build( File srcDir, File resourceDir ) throws IOException { - build(srcDir,resourceDir,System.out); + public void build(File srcDir, File resourceDir) throws IOException { + build(srcDir, resourceDir, System.out); } /** * A convenience method for build(out,out). */ - public void build( CodeWriter out ) throws IOException { - build(out,out); + public void build(CodeWriter out) throws IOException { + build(out, out); } - + /** * Generates Java source code. */ - public void build( CodeWriter source, CodeWriter resource ) throws IOException { + public void build(CodeWriter source, CodeWriter resource) throws IOException { JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]); // avoid concurrent modification exception - for( JPackage pkg : pkgs ) - pkg.build(source,resource); + for (JPackage pkg : pkgs) { + pkg.build(source, resource); + } source.close(); resource.close(); } @@ -324,12 +344,12 @@ public int countArtifacts() { int r = 0; JPackage[] pkgs = packages.values().toArray(new JPackage[packages.size()]); // avoid concurrent modification exception - for( JPackage pkg : pkgs ) + for (JPackage pkg : pkgs) { r += pkg.countArtifacts(); + } return r; } - /** * Obtains a reference to an existing class from its Class object. * @@ -339,10 +359,11 @@ public int countArtifacts() { * @see #_ref(Class) for the version that handles more cases. */ public JClass ref(Class clazz) { - JReferencedClass jrc = (JReferencedClass)refClasses.get(clazz); + JReferencedClass jrc = (JReferencedClass) refClasses.get(clazz); if (jrc == null) { - if (clazz.isPrimitive()) - throw new IllegalArgumentException(clazz+" is a primitive"); + if (clazz.isPrimitive()) { + throw new IllegalArgumentException(clazz + " is a primitive"); + } if (clazz.isArray()) { return new JArrayClass(this, _ref(clazz.getComponentType())); } else { @@ -354,10 +375,11 @@ public JClass ref(Class clazz) { } public JType _ref(Class c) { - if(c.isPrimitive()) - return JType.parse(this,c.getName()); - else + if (c.isPrimitive()) { + return JType.parse(this, c.getName()); + } else { return ref(c); + } } /** @@ -386,12 +408,25 @@ public JClass ref(String fullyQualifiedClassName) { // assume it's not visible to us. JDirectClass jdrc = refDirectClasses.get(fullyQualifiedClassName); if (jdrc == null) { - jdrc = new JDirectClass(this,fullyQualifiedClassName); - refDirectClasses.put(fullyQualifiedClassName, jdrc); + jdrc = new JDirectClass(this, fullyQualifiedClassName); + refDirectClasses.put(fullyQualifiedClassName, jdrc); } return jdrc; } + public JClass refNoDirect(String fullyQualifiedClassName) throws ClassNotFoundException { + try { + // try the context class loader first + return ref(SecureLoader.getContextClassLoader().loadClass(fullyQualifiedClassName)); + } catch (ClassNotFoundException e) { + // fall through + } + // then the default mechanism. + + return ref(Class.forName(fullyQualifiedClassName)); + + } + /** * Cached for {@link #wildcard()}. */ @@ -402,8 +437,9 @@ public JClass ref(String fullyQualifiedClassName) { * which is equivalent to "? extends Object". */ public JClass wildcard() { - if(wildcard==null) + if (wildcard == null) { wildcard = ref(Object.class).wildcard(); + } return wildcard; } @@ -411,19 +447,21 @@ public JClass wildcard() { * Obtains a type object from a type name. * *

- * This method handles primitive types, arrays, and existing {@link Class}es. + * This method handles primitive types, arrays, and existing + * {@link Class}es. * * @exception ClassNotFoundException - * If the specified type is not found. + * If the specified type is not found. */ public JType parseType(String name) throws ClassNotFoundException { // array - if(name.endsWith("[]")) - return parseType(name.substring(0,name.length()-2)).array(); + if (name.endsWith("[]")) { + return parseType(name.substring(0, name.length() - 2)).array(); + } // try primitive type try { - return JType.parse(this,name); + return JType.parse(this, name); } catch (IllegalArgumentException e) { ; } @@ -433,6 +471,7 @@ public JType parseType(String name) throws ClassNotFoundException { } private final class TypeNameParser { + private final String s; private int idx; @@ -441,7 +480,8 @@ public TypeNameParser(String s) { } /** - * Parses a type name token T (which can be potentially of the form Tr&ly;T1,T2,...>, + * Parses a type name token T (which can be potentially of the form + * Tr&ly;T1,T2,...>, * or "? extends/super T".) * * @return the index of the character next to T. @@ -449,35 +489,35 @@ public TypeNameParser(String s) { JClass parseTypeName() throws ClassNotFoundException { int start = idx; - if(s.charAt(idx)=='?') { + if (s.charAt(idx) == '?') { // wildcard idx++; ws(); String head = s.substring(idx); - if(head.startsWith("extends")) { - idx+=7; + if (head.startsWith("extends")) { + idx += 7; ws(); return parseTypeName().wildcard(); - } else - if(head.startsWith("super")) { + } else if (head.startsWith("super")) { throw new UnsupportedOperationException("? super T not implemented"); } else { // not supported - throw new IllegalArgumentException("only extends/super can follow ?, but found "+s.substring(idx)); + throw new IllegalArgumentException("only extends/super can follow ?, but found " + s.substring(idx)); } } - while(idx' */ private JClass parseArguments(JClass rawType) throws ClassNotFoundException { - if(s.charAt(idx)!='<') + if (s.charAt(idx) != '<') { throw new IllegalArgumentException(); + } idx++; List args = new ArrayList(); - while(true) { + while (true) { args.add(parseTypeName()); - if(idx==s.length()) - throw new IllegalArgumentException("Missing '>' in "+s); + if (idx == s.length()) { + throw new IllegalArgumentException("Missing '>' in " + s); + } char ch = s.charAt(idx); - if(ch=='>') + if (ch == '>') { return rawType.narrow(args.toArray(new JClass[args.size()])); + } - if(ch!=',') + if (ch != ',') { throw new IllegalArgumentException(s); + } idx++; } @@ -544,17 +590,18 @@ private JClass parseArguments(JClass rawType) throws ClassNotFoundException { /** * References to existing classes. - * + *

*

* JReferencedClass is kept in a pool so that they are shared. * There is one pool for each JCodeModel object. - * + *

*

* It is impossible to cache JReferencedClass globally only because * there is the _package() method, which obtains the owner JPackage * object, which is scoped to JCodeModel. */ private class JReferencedClass extends JClass implements JDeclaration { + private final Class _class; JReferencedClass(Class _clazz) { @@ -568,7 +615,7 @@ public String name() { } public String fullName() { - return NameUtilities.getFullName(_class); + return NameUtilities.getFullName(_class); } public String binaryName() { @@ -577,7 +624,9 @@ public String binaryName() { public JClass outer() { Class p = _class.getDeclaringClass(); - if(p==null) return null; + if (p == null) { + return null; + } return ref(p); } @@ -585,37 +634,44 @@ public JPackage _package() { String name = fullName(); // this type is array - if (name.indexOf('[') != -1) + if (name.indexOf('[') != -1) { return JCodeModel.this._package(""); + } // other normal case int idx = name.lastIndexOf('.'); - if (idx < 0) + if (idx < 0) { return JCodeModel.this._package(""); - else + } else { return JCodeModel.this._package(name.substring(0, idx)); + } } public JClass _extends() { Class sp = _class.getSuperclass(); if (sp == null) { - if(isInterface()) + if (isInterface()) { return owner().ref(Object.class); + } return null; - } else + } else { return ref(sp); + } } public Iterator _implements() { final Class[] interfaces = _class.getInterfaces(); return new Iterator() { private int idx = 0; + public boolean hasNext() { return idx < interfaces.length; } + public JClass next() { return JCodeModel.this.ref(interfaces[idx++]); } + public void remove() { throw new UnsupportedOperationException(); } @@ -632,10 +688,11 @@ public boolean isAbstract() { public JPrimitiveType getPrimitiveType() { Class v = boxToPrimitive.get(_class); - if(v!=null) - return JType.parse(JCodeModel.this,v.getName()); - else + if (v != null) { + return JType.parse(JCodeModel.this, v.getName()); + } else { return null; + } } public boolean isArray() { @@ -654,34 +711,41 @@ protected JClass substituteParams(JTypeVar[] variables, List bindings) { // TODO: does JDK 1.5 reflection provides these information? return this; } + + @Override + public JClass inner(String name) { + return ref(fullName() + "." + name); + } } /** - * Conversion from primitive type {@link Class} (such as {@link Integer#TYPE} + * Conversion from primitive type {@link Class} (such as + * {@link Integer#TYPE} * to its boxed type (such as Integer.class) */ - public static final Map,Class> primitiveToBox; + public static final Map, Class> primitiveToBox; /** * The reverse look up for {@link #primitiveToBox} */ - public static final Map,Class> boxToPrimitive; + public static final Map, Class> boxToPrimitive; static { - Map,Class> m1 = new HashMap,Class>(); - Map,Class> m2 = new HashMap,Class>(); - - m1.put(Boolean.class,Boolean.TYPE); - m1.put(Byte.class,Byte.TYPE); - m1.put(Character.class,Character.TYPE); - m1.put(Double.class,Double.TYPE); - m1.put(Float.class,Float.TYPE); - m1.put(Integer.class,Integer.TYPE); - m1.put(Long.class,Long.TYPE); - m1.put(Short.class,Short.TYPE); - m1.put(Void.class,Void.TYPE); - - for (Map.Entry, Class> e : m1.entrySet()) - m2.put(e.getValue(),e.getKey()); + Map, Class> m1 = new HashMap, Class>(); + Map, Class> m2 = new HashMap, Class>(); + + m1.put(Boolean.class, Boolean.TYPE); + m1.put(Byte.class, Byte.TYPE); + m1.put(Character.class, Character.TYPE); + m1.put(Double.class, Double.TYPE); + m1.put(Float.class, Float.TYPE); + m1.put(Integer.class, Integer.TYPE); + m1.put(Long.class, Long.TYPE); + m1.put(Short.class, Short.TYPE); + m1.put(Void.class, Void.TYPE); + + for (Map.Entry, Class> e : m1.entrySet()) { + m2.put(e.getValue(), e.getKey()); + } boxToPrimitive = Collections.unmodifiableMap(m1); primitiveToBox = Collections.unmodifiableMap(m2); diff --git a/codemodel/src/main/java/com/sun/codemodel/JConditional.java b/codemodel/src/main/java/com/sun/codemodel/JConditional.java index 1db8587..ff8b918 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JConditional.java +++ b/codemodel/src/main/java/com/sun/codemodel/JConditional.java @@ -54,12 +54,12 @@ public class JConditional implements JStatement { /** * JBlock of statements for "then" clause */ - private JBlock _then = new JBlock(); + private JStatement _then = null; /** * JBlock of statements for optional "else" clause */ - private JBlock _else = null; + private JStatement _else = null; /** * Constructor @@ -71,13 +71,24 @@ public class JConditional implements JStatement { this.test = test; } + public void setThen(JStatement _then) { + this._then = _then; + } + + public void setElse(JStatement _else) { + this._else = _else; + } + /** - * Return the block to be excuted by the "then" branch + * Return a block to be excuted by the "then" branch * * @return Then block */ public JBlock _then() { - return _then; + if (_then == null || !(_then instanceof JBlock)) { + _then = new JBlock(); + } + return (JBlock) _then; } /** @@ -86,35 +97,30 @@ public JBlock _then() { * @return Newly generated else block */ public JBlock _else() { - if (_else == null) _else = new JBlock(); - return _else; + if (_else == null || !(_else instanceof JBlock)) { + _else = new JBlock(); + } + return (JBlock) _else; } /** * Creates ... else if(...) ... code. */ public JConditional _elseif(JExpression boolExp) { - return _else()._if(boolExp); + _else = new JBlock(false, false); + return ((JBlock) _else)._if(boolExp); } public void state(JFormatter f) { - if(test==JExpr.TRUE) { - _then.generateBody(f); - return; - } - if(test==JExpr.FALSE) { - _else.generateBody(f); - return; - } if (JOp.hasTopOp(test)) { f.p("if ").g(test); } else { f.p("if (").g(test).p(')'); } - f.g(_then); + f.s(_then); if (_else != null) - f.p("else").g(_else); + f.p("else").s(_else); f.nl(); } } diff --git a/codemodel/src/main/java/com/sun/codemodel/JDefinedClass.java b/codemodel/src/main/java/com/sun/codemodel/JDefinedClass.java index 41859a7..93fd1fc 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JDefinedClass.java +++ b/codemodel/src/main/java/com/sun/codemodel/JDefinedClass.java @@ -143,7 +143,7 @@ public class JDefinedClass * or enum * */ - private final ClassType classType; + private ClassType classType; /** List containing the enum value declarations * @@ -668,9 +668,9 @@ public JDefinedClass _class(int mods, String name, ClassType classTypeVal) throws JClassAlreadyExistsException { String NAME; - if (JCodeModel.isCaseSensitiveFileSystem) - NAME = name.toUpperCase(); - else +// if (JCodeModel.isCaseSensitiveFileSystem) +// NAME = name.toUpperCase(); +// else NAME = name; if (getClasses().containsKey(NAME)) @@ -754,7 +754,7 @@ public final Iterator classes() { return classes.values().iterator(); } - private Map getClasses() { + public Map getClasses() { if(classes==null) classes = new TreeMap(); return classes; @@ -961,4 +961,20 @@ public Collection annotations() { public JMods mods() { return mods; } + + public void setMods(int mods) { + if (isInterface()) + this.mods = JMods.forInterface(mods); + else + this.mods = JMods.forClass(mods); + } + + public void setType(ClassType type) { + this.classType = type; + } + + @Override + public JClass inner(String name) { + return getClasses().get(name); + } } diff --git a/codemodel/src/main/java/com/sun/codemodel/JDirectClass.java b/codemodel/src/main/java/com/sun/codemodel/JDirectClass.java index 64a620f..b1b9f14 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JDirectClass.java +++ b/codemodel/src/main/java/com/sun/codemodel/JDirectClass.java @@ -40,9 +40,9 @@ package com.sun.codemodel; +import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Collections; /** * A special {@link JClass} that represents an unknown class (except its name.) @@ -57,6 +57,7 @@ final class JDirectClass extends JClass { public JDirectClass(JCodeModel _owner,String fullName) { super(_owner); this.fullName = fullName; + throw new RuntimeException("Stop using this it fucks up imports!"); } public String name() { @@ -94,4 +95,9 @@ public boolean isAbstract() { protected JClass substituteParams(JTypeVar[] variables, List bindings) { return this; } + + @Override + public JClass inner(String name) { + return new JDirectClass(owner(), fullName()+"."+name); + } } diff --git a/codemodel/src/main/java/com/sun/codemodel/JDirectRef.java b/codemodel/src/main/java/com/sun/codemodel/JDirectRef.java new file mode 100644 index 0000000..5e327f4 --- /dev/null +++ b/codemodel/src/main/java/com/sun/codemodel/JDirectRef.java @@ -0,0 +1,32 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.sun.codemodel; + +/** + * + * @author lkroll + */ +public class JDirectRef extends JExpressionImpl implements JAssignmentTarget { + + private final String ref; + + public JDirectRef(String ref) { + this.ref = ref; + } + + public void generate(JFormatter f) { + f.p(ref); + } + + public JExpression assign(JExpression rhs) { + return JExpr.assign(this, rhs); + } + + public JExpression assignPlus(JExpression rhs) { + return JExpr.assignPlus(this, rhs); + } + +} diff --git a/codemodel/src/main/java/com/sun/codemodel/JDoLoop.java b/codemodel/src/main/java/com/sun/codemodel/JDoLoop.java index bb5be4d..7b648a7 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JDoLoop.java +++ b/codemodel/src/main/java/com/sun/codemodel/JDoLoop.java @@ -55,7 +55,7 @@ public class JDoLoop implements JStatement { /** * JBlock of statements which makes up body of this Do statement */ - private JBlock body = null; + private JStatement body = null; /** * Construct a Do statment @@ -65,14 +65,20 @@ public class JDoLoop implements JStatement { } public JBlock body() { - if (body == null) body = new JBlock(); - return body; + if (body == null || !(body instanceof JBlock)) { + body = new JBlock(); + } + return (JBlock) body; + } + + public void setBody(JStatement stmt) { + this.body = stmt; } public void state(JFormatter f) { f.p("do"); if (body != null) - f.g(body); + f.s(body); else f.p("{ }"); diff --git a/codemodel/src/main/java/com/sun/codemodel/JExpr.java b/codemodel/src/main/java/com/sun/codemodel/JExpr.java index 068f1cb..1c432f1 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JExpr.java +++ b/codemodel/src/main/java/com/sun/codemodel/JExpr.java @@ -37,10 +37,8 @@ * only if the new code is made subject to such option by the copyright * holder. */ - package com.sun.codemodel; - /** * Factory methods that generate various {@link JExpression}s. */ @@ -49,7 +47,8 @@ public abstract class JExpr { /** * This class is not instanciable. */ - private JExpr() { } + private JExpr() { + } public static JExpressionStatement assign(JAssignmentTarget lhs, JExpression rhs) { return new JAssignment(lhs, rhs); @@ -59,33 +58,61 @@ public static JExpressionStatement assignPlus(JAssignmentTarget lhs, JExpression return new JAssignment(lhs, rhs, "+"); } - public static JExpressionStatement assignMinus(JAssignmentTarget lhs, JExpression rhs) { - return new JAssignment(lhs, rhs, "-"); - } + public static JExpressionStatement assignMinus(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, "-"); + } + + public static JExpressionStatement assignTimes(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, "*"); + } + + public static JExpressionStatement assignDivide(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, "/"); + } + + public static JExpressionStatement assignMod(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, "%"); + } + + public static JExpressionStatement assignShl(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, "<<"); + } + + public static JExpressionStatement assignShr(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, ">>"); + } + + public static JExpressionStatement assignUshr(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, ">>>"); + } - public static JExpressionStatement assignTimes(JAssignmentTarget lhs, JExpression rhs) { - return new JAssignment(lhs, rhs, "*"); - } + public static JExpressionStatement assignAnd(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, "&"); + } - public static JExpressionStatement assignDivide(JAssignmentTarget lhs, JExpression rhs) { - return new JAssignment(lhs, rhs, "/"); - } + public static JExpressionStatement assignOr(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, "|"); + } + + public static JExpressionStatement assignXor(JAssignmentTarget lhs, JExpression rhs) { + return new JAssignment(lhs, rhs, "^"); + } - public static JExpressionStatement incr(final JExpression expression) { - return new JExpressionStatementWrapper(JOp.incr(expression)); - } + public static JExpressionStatement incr(final JExpression expression) { + return new JExpressionStatementWrapper(JOp.incr(expression)); + } - public static JStatement preincr(final JExpression expression) { - return new JExpressionStatementWrapper(JOp.preincr(expression)); - } + public static JExpressionStatement preincr(final JExpression expression) { + return new JExpressionStatementWrapper(JOp.preincr(expression)); + } - public static JStatement decr(final JExpression expression) { - return new JExpressionStatementWrapper(JOp.decr(expression)); - } + public static JExpressionStatement decr(final JExpression expression) { + return new JExpressionStatementWrapper(JOp.decr(expression)); + } - public static JStatement predecr(final JExpression expression) { - return new JExpressionStatementWrapper(JOp.predecr(expression)); - } + public static JExpressionStatement predecr(final JExpression expression) { + return new JExpressionStatementWrapper(JOp.predecr(expression)); + } public static JInvocation _new(JClass c) { return new JInvocation(c); @@ -94,13 +121,13 @@ public static JInvocation _new(JClass c) { public static JInvocation _new(JType t) { return new JInvocation(t); } - + public static JInvocation invoke(String method) { - return new JInvocation((JExpression)null, method); + return new JInvocation((JExpression) null, method); } - + public static JInvocation invoke(JMethod method) { - return new JInvocation((JExpression)null,method); + return new JInvocation((JExpression) null, method); } public static JInvocation invoke(JExpression lhs, JMethod method) { @@ -112,11 +139,11 @@ public static JInvocation invoke(JExpression lhs, String method) { } public static JFieldRef ref(String field) { - return new JFieldRef((JExpression)null, field); + return new JFieldRef((JExpression) null, field); } public static JFieldRef ref(JExpression lhs, JVar field) { - return new JFieldRef(lhs,field); + return new JFieldRef(lhs, field); } public static JFieldRef ref(JExpression lhs, String field) { @@ -124,20 +151,49 @@ public static JFieldRef ref(JExpression lhs, String field) { } public static JFieldRef refthis(String field) { - return new JFieldRef(null, field, true); + return new JFieldRef(null, field, true); } public static JExpression dotclass(final JClass cl) { return new JExpressionImpl() { - public void generate(JFormatter f) { - JClass c; - if(cl instanceof JNarrowedClass) - c = ((JNarrowedClass)cl).basis; - else - c = cl; - f.g(c).p(".class"); + public void generate(JFormatter f) { + JClass c; + if (cl instanceof JNarrowedClass) { + c = ((JNarrowedClass) cl).basis; + } else { + c = cl; + } + f.g(c).p(".class"); + } + }; + } + + public static JExpression dotthis(final JClass cl) { + return new JExpressionImpl() { + public void generate(JFormatter f) { + JClass c; + if (cl instanceof JNarrowedClass) { + c = ((JNarrowedClass) cl).basis; + } else { + c = cl; } - }; + f.g(c).p(".this"); + } + }; + } + + public static JExpression dotsuper(final JClass cl) { + return new JExpressionImpl() { + public void generate(JFormatter f) { + JClass c; + if (cl instanceof JNarrowedClass) { + c = ((JNarrowedClass) cl).basis; + } else { + c = cl; + } + f.g(c).p(".super"); + } + }; } public static JArrayCompRef component(JExpression lhs, JExpression index) { @@ -149,14 +205,14 @@ public static JCast cast(JType type, JExpression expr) { } public static JArray newArray(JType type) { - return newArray(type,null); + return newArray(type, null); } /** * Generates {@code new T[size]}. * * @param type - * The type of the array component. 'T' or {@code new T[size]}. + * The type of the array component. 'T' or {@code new T[size]}. */ public static JArray newArray(JType type, JExpression size) { // you cannot create an array whose component type is a generic @@ -167,40 +223,44 @@ public static JArray newArray(JType type, JExpression size) { * Generates {@code new T[size]}. * * @param type - * The type of the array component. 'T' or {@code new T[size]}. + * The type of the array component. 'T' or {@code new T[size]}. */ public static JArray newArray(JType type, int size) { - return newArray(type,lit(size)); + return newArray(type, lit(size)); } - - + private static final JExpression __this = new JAtom("this"); + /** * Returns a reference to "this", an implicit reference * to the current object. */ - public static JExpression _this() { return __this; } + public static JExpression _this() { + return __this; + } private static final JExpression __super = new JAtom("super"); + /** * Returns a reference to "super", an implicit reference * to the super class. */ - public static JExpression _super() { return __super; } - - - /* -- Literals -- */ + public static JExpression _super() { + return __super; + } + /* -- Literals -- */ private static final JExpression __null = new JAtom("null"); + public static JExpression _null() { return __null; } - + /** * Boolean constant that represents true */ public static final JExpression TRUE = new JAtom("true"); - + /** * Boolean constant that represents false */ @@ -209,7 +269,7 @@ public static JExpression _null() { public static JExpression lit(boolean b) { return b ? TRUE : FALSE; } - + public static JExpression lit(int n) { return new JAtom(Integer.toString(n)); } @@ -219,49 +279,35 @@ public static JExpression lit(long n) { } public static JExpression lit(float f) { - if (f == Float.NEGATIVE_INFINITY) - { - return new JAtom("java.lang.Float.NEGATIVE_INFINITY"); - } - else if (f == Float.POSITIVE_INFINITY) - { - return new JAtom("java.lang.Float.POSITIVE_INFINITY"); - } - else if (Float.isNaN(f)) - { - return new JAtom("java.lang.Float.NaN"); - } - else - { - return new JAtom(Float.toString(f) + "F"); - } + if (f == Float.NEGATIVE_INFINITY) { + return new JAtom("java.lang.Float.NEGATIVE_INFINITY"); + } else if (f == Float.POSITIVE_INFINITY) { + return new JAtom("java.lang.Float.POSITIVE_INFINITY"); + } else if (Float.isNaN(f)) { + return new JAtom("java.lang.Float.NaN"); + } else { + return new JAtom(Float.toString(f) + "F"); + } } public static JExpression lit(double d) { - if (d == Double.NEGATIVE_INFINITY) - { - return new JAtom("java.lang.Double.NEGATIVE_INFINITY"); - } - else if (d == Double.POSITIVE_INFINITY) - { - return new JAtom("java.lang.Double.POSITIVE_INFINITY"); - } - else if (Double.isNaN(d)) - { - return new JAtom("java.lang.Double.NaN"); - } - else - { - return new JAtom(Double.toString(d) + "D"); - } + if (d == Double.NEGATIVE_INFINITY) { + return new JAtom("java.lang.Double.NEGATIVE_INFINITY"); + } else if (d == Double.POSITIVE_INFINITY) { + return new JAtom("java.lang.Double.POSITIVE_INFINITY"); + } else if (Double.isNaN(d)) { + return new JAtom("java.lang.Double.NaN"); + } else { + return new JAtom(Double.toString(d) + "D"); + } } static final String charEscape = "\b\t\n\f\r\"\'\\"; - static final String charMacro = "btnfr\"'\\"; - + static final String charMacro = "btnfr\"'\\"; + /** * Escapes the given string, then surrounds it by the specified - * quotation mark. + * quotation mark. */ public static String quotify(char quote, String s) { int n = s.length(); @@ -270,8 +316,8 @@ public static String quotify(char quote, String s) { for (int i = 0; i < n; i++) { char c = s.charAt(i); int j = charEscape.indexOf(c); - if(j>=0) { - if((quote=='"' && c=='\'') || (quote=='\'' && c=='"')) { + if (j >= 0) { + if ((quote == '"' && c == '\'') || (quote == '\'' && c == '"')) { sb.append(c); } else { sb.append('\\'); @@ -286,12 +332,13 @@ public static String quotify(char quote, String s) { // the escaping here (regardless of the actual file encoding) // // see bug - if( c<0x20 || 0x7E *

* This method can be used as a short-cut to create a JExpression. * For example, instead of _a.gt(_b), you can write - * it as: JExpr.direct("a>b"). - * + * it as: {@code JExpr.direct("a>b")}. + *

*

* Be warned that there is a danger in using this method, * as it obfuscates the object model. */ - public static JExpression direct( final String source ) { - return new JExpressionImpl(){ - public void generate( JFormatter f ) { + public static JExpression direct(final String source) { + if ((source == null) || source.isEmpty()) { + throw new RuntimeException("DUDE!"); + } + return new JExpressionImpl() { + public void generate(JFormatter f) { f.p('(').p(source).p(')'); } }; } - static class JExpressionStatementWrapper extends JExpressionImpl implements JExpressionStatement { - final JExpression expression; + static class JExpressionStatementWrapper extends JExpressionImpl implements JExpressionStatement { - JExpressionStatementWrapper(JExpression expression) { - this.expression = expression; - } + final JExpression expression; - public void generate(JFormatter f) { - expression.generate(f); - } + JExpressionStatementWrapper(JExpression expression) { + this.expression = expression; + } - public void state(JFormatter f) { - expression.generate(f); - f.p(';').nl(); - } - } -} \ No newline at end of file + public void generate(JFormatter f) { + expression.generate(f); + } + + public void state(JFormatter f) { + expression.generate(f); + f.p(';').nl(); + } + } +} diff --git a/codemodel/src/main/java/com/sun/codemodel/JExprProxy.java b/codemodel/src/main/java/com/sun/codemodel/JExprProxy.java new file mode 100644 index 0000000..05546fc --- /dev/null +++ b/codemodel/src/main/java/com/sun/codemodel/JExprProxy.java @@ -0,0 +1,29 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.sun.codemodel; + +import com.sun.codemodel.JGenProxy.Resolver; + +/** + * + * @author lkroll + */ +public class JExprProxy extends JExpressionImpl { + + private JExpression proxee = null; + private final Resolver resolver; + + public JExprProxy(Resolver resolver) { + this.resolver = resolver; + } + + public void generate(JFormatter f) { + if (proxee == null) { + proxee = resolver.resolve(); + } + f.g(proxee); + } +} diff --git a/codemodel/src/main/java/com/sun/codemodel/JExpression.java b/codemodel/src/main/java/com/sun/codemodel/JExpression.java index 57d52ac..99efc52 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JExpression.java +++ b/codemodel/src/main/java/com/sun/codemodel/JExpression.java @@ -122,12 +122,12 @@ public interface JExpression extends JGenerable { JExpression shl(JExpression right); /** - * Returns "[this]>>[right]" + * Returns "[this]<<[right]" */ JExpression shr(JExpression right); /** - * Returns "[this]>>>[right]" + * Returns "[this]<<<[right]" */ JExpression shrz(JExpression right); @@ -169,6 +169,14 @@ public interface JExpression extends JGenerable { * Arguments shall be added to the returned {@link JInvocation} object. */ JInvocation invoke(String method); + +// /** +// * Return [this].new [id] +// * +// * Arguments shall be added to the returned {@link JInvocation} object. +// */ +// JInvocation _new(String id); + JFieldRef ref(JVar field); JFieldRef ref(String field); JArrayCompRef component(JExpression index); diff --git a/codemodel/src/main/java/com/sun/codemodel/JExpressionImpl.java b/codemodel/src/main/java/com/sun/codemodel/JExpressionImpl.java index 5d50095..8a329f9 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JExpressionImpl.java +++ b/codemodel/src/main/java/com/sun/codemodel/JExpressionImpl.java @@ -37,19 +37,19 @@ * only if the new code is made subject to such option by the copyright * holder. */ - package com.sun.codemodel; /** * Provides default implementations for {@link JExpression}. */ -public abstract class JExpressionImpl implements JExpression -{ +public abstract class JExpressionImpl implements JExpression { + // // // from JOp // // + public final JExpression minus() { return JOp.minus(this); } @@ -69,17 +69,17 @@ public final JExpression incr() { return JOp.incr(this); } - public final JExpression preincr() { - return JOp.preincr(this); - } + public final JExpression preincr() { + return JOp.preincr(this); + } public final JExpression decr() { return JOp.decr(this); } - public final JExpression predecr() { - return JOp.predecr(this); - } + public final JExpression predecr() { + return JOp.predecr(this); + } public final JExpression plus(JExpression right) { return JOp.plus(this, right); diff --git a/codemodel/src/main/java/com/sun/codemodel/JField.java b/codemodel/src/main/java/com/sun/codemodel/JField.java new file mode 100644 index 0000000..41f69ea --- /dev/null +++ b/codemodel/src/main/java/com/sun/codemodel/JField.java @@ -0,0 +1,14 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.sun.codemodel; + +/** + * + * @author lkroll + */ +public interface JField extends JExpression, JAssignmentTarget { + +} diff --git a/codemodel/src/main/java/com/sun/codemodel/JFieldProxy.java b/codemodel/src/main/java/com/sun/codemodel/JFieldProxy.java new file mode 100644 index 0000000..b4bf65b --- /dev/null +++ b/codemodel/src/main/java/com/sun/codemodel/JFieldProxy.java @@ -0,0 +1,72 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.sun.codemodel; + +/** + * + * @author lkroll + */ +public class JFieldProxy extends JExpressionImpl implements JField { + + private JField proxee = null; + private final String name; + private final FieldResolver resolver; + + public JFieldProxy(String name, FieldResolver resolver) { + this.name = name; + this.resolver = resolver; + } + + public boolean isResolved() { + if (proxee == null) { + proxee = resolver.resolveField(name); + } + return proxee != null; + } + + public void setProxee(JField ref) { + if (ref instanceof JFieldProxy) { + throw new RuntimeException("Building endless proxy hierarchies is not a good idea!"); + } + this.proxee = ref; + } + + public void generate(JFormatter f) { + if (isResolved()) { + f.g(proxee); + } else { + throw new UnresolvedFieldException(name); + } + } + + public JExpression assign(JExpression rhs) { + return JExpr.assign(this, rhs); + } + + public JExpression assignPlus(JExpression rhs) { + return JExpr.assignPlus(this, rhs); + } + + public static interface FieldResolver { + + public JField resolveField(String name); + } + + public static class UnresolvedFieldException extends RuntimeException { + + private final String name; + + private UnresolvedFieldException(String name) { + this.name = name; + } + + @Override + public String getMessage() { + return "Proxied field " + name + " has not been resolved, yet"; + } + + } +} diff --git a/codemodel/src/main/java/com/sun/codemodel/JFieldRef.java b/codemodel/src/main/java/com/sun/codemodel/JFieldRef.java index eccc9ef..149c95e 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JFieldRef.java +++ b/codemodel/src/main/java/com/sun/codemodel/JFieldRef.java @@ -45,7 +45,7 @@ * Field Reference */ -public class JFieldRef extends JExpressionImpl implements JAssignmentTarget { +public class JFieldRef extends JExpressionImpl implements JField { /** * Object expression upon which this field will be accessed, or * null for the implicit 'this'. diff --git a/codemodel/src/main/java/com/sun/codemodel/JForEach.java b/codemodel/src/main/java/com/sun/codemodel/JForEach.java index 8dcdc19..7ce460e 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JForEach.java +++ b/codemodel/src/main/java/com/sun/codemodel/JForEach.java @@ -37,7 +37,6 @@ * only if the new code is made subject to such option by the copyright * holder. */ - package com.sun.codemodel; /** @@ -49,42 +48,47 @@ */ public final class JForEach implements JStatement { - private final JType type; - private final String var; - private JBlock body = null; // lazily created - private final JExpression collection; + private final JType type; + private final String var; + private JStatement body = null; // lazily created + private final JExpression collection; private final JVar loopVar; - public JForEach(JType vartype, String variable, JExpression collection) { + public JForEach(JType vartype, String variable, JExpression collection) { - this.type = vartype; - this.var = variable; - this.collection = collection; + this.type = vartype; + this.var = variable; + this.collection = collection; loopVar = new JVar(JMods.forVar(JMod.NONE), type, var, collection); } - /** * Returns a reference to the loop variable. */ - public JVar var() { - return loopVar; - } + public JVar var() { + return loopVar; + } - public JBlock body() { - if (body == null) - body = new JBlock(); - return body; - } + public JBlock body() { + if (body == null || !(body instanceof JBlock)) { + body = new JBlock(); + } + return (JBlock) body; + } + + public void setBody(JStatement stmt) { + this.body = stmt; + } - public void state(JFormatter f) { - f.p("for ("); - f.g(type).id(var).p(": ").g(collection); - f.p(')'); - if (body != null) - f.g(body).nl(); - else - f.p(';').nl(); - } + public void state(JFormatter f) { + f.p("for ("); + f.g(type).id(var).p(": ").g(collection); + f.p(')'); + if (body != null) { + f.s(body).nl(); + } else { + f.p(';').nl(); + } + } } diff --git a/codemodel/src/main/java/com/sun/codemodel/JForLoop.java b/codemodel/src/main/java/com/sun/codemodel/JForLoop.java index ec2d2c5..0f9ac52 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JForLoop.java +++ b/codemodel/src/main/java/com/sun/codemodel/JForLoop.java @@ -53,7 +53,7 @@ public class JForLoop implements JStatement { private List inits = new ArrayList(); private JExpression test = null; private List updates = new ArrayList(); - private JBlock body = null; + private JStatement body = null; public JVar init(int mods, JType type, String var, JExpression e) { JVar v = new JVar(JMods.forVar(mods), type, var, e); @@ -69,6 +69,10 @@ public void init(JVar v, JExpression e) { inits.add(JExpr.assign(v, e)); } + public void init(JExpression e) { + inits.add(e); + } + public void test(JExpression e) { this.test = e; } @@ -78,8 +82,14 @@ public void update(JExpression e) { } public JBlock body() { - if (body == null) body = new JBlock(); - return body; + if (body == null || !(body instanceof JBlock)) { + body = new JBlock(); + } + return (JBlock) body; + } + + public void setBody(JStatement stmt) { + this.body = stmt; } public void state(JFormatter f) { @@ -95,7 +105,7 @@ public void state(JFormatter f) { } f.p(';').g(test).p(';').g(updates).p(')'); if (body != null) - f.g(body).nl(); + f.s(body).nl(); else f.p(';').nl(); } diff --git a/codemodel/src/main/java/com/sun/codemodel/JFormatter.java b/codemodel/src/main/java/com/sun/codemodel/JFormatter.java index 2206e0a..0ccd268 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JFormatter.java +++ b/codemodel/src/main/java/com/sun/codemodel/JFormatter.java @@ -480,6 +480,13 @@ private boolean supressImport(JClass clazz, JClass c) { if(clazz.outer()==null) { return true; // no need to explicitly import a class into itself } + JClass curC = clazz; + while (curC.outer() != null) { // check for myself in the class hierarchy + if (curC.outer().compareTo(clazz) == 0) { + return true; // don't import my own children + } + curC = curC.outer(); + } } return false; } diff --git a/codemodel/src/main/java/com/sun/codemodel/JGenProxy.java b/codemodel/src/main/java/com/sun/codemodel/JGenProxy.java new file mode 100644 index 0000000..fc33382 --- /dev/null +++ b/codemodel/src/main/java/com/sun/codemodel/JGenProxy.java @@ -0,0 +1,33 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.sun.codemodel; + +/** + * + * @author lkroll + */ +public class JGenProxy implements JGenerable { + + private JGenerable proxee; + private final Resolver resolver; + + public JGenProxy(Resolver resolver) { + this.resolver = resolver; + } + + public void generate(JFormatter f) { + if (proxee == null) { + proxee = resolver.resolve(); + } + f.g(proxee); + } + + public static interface Resolver { + + public E resolve(); + } + +} diff --git a/codemodel/src/main/java/com/sun/codemodel/JInvocation.java b/codemodel/src/main/java/com/sun/codemodel/JInvocation.java index 4222151..97344da 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JInvocation.java +++ b/codemodel/src/main/java/com/sun/codemodel/JInvocation.java @@ -37,13 +37,11 @@ * only if the new code is made subject to such option by the copyright * holder. */ - package com.sun.codemodel; import java.util.ArrayList; import java.util.List; - /** * JMethod invocation */ @@ -57,9 +55,11 @@ public final class JInvocation extends JExpressionImpl implements JStatement { /** * Name of the method to be invoked. - * Either this field is set, or {@link #method}, or {@link #type} (in which case it's a + * Either this field is set, or {@link #method}, or {@link #type} (in which + * case it's a * constructor invocation.) - * This allows {@link JMethod#name(String) the name of the method to be changed later}. + * This allows + * {@link JMethod#name(String) the name of the method to be changed later}. */ private String name; @@ -81,53 +81,58 @@ public final class JInvocation extends JExpressionImpl implements JStatement { * Invokes a method on an object. * * @param object - * JExpression for the object upon which - * the named method will be invoked, - * or null if none + * JExpression for the object upon which + * the named method will be invoked, + * or null if none * * @param name - * Name of method to invoke + * Name of method to invoke */ JInvocation(JExpression object, String name) { - this( (JGenerable)object, name ); + this((JGenerable) object, name); } JInvocation(JExpression object, JMethod method) { - this( (JGenerable)object, method ); + this((JGenerable) object, method); } - + /** * Invokes a static method on a class. */ JInvocation(JClass type, String name) { - this( (JGenerable)type, name ); + this((JGenerable) type, name); } JInvocation(JClass type, JMethod method) { - this( (JGenerable)type, method ); + this((JGenerable) type, method); } private JInvocation(JGenerable object, String name) { this.object = object; - if (name.indexOf('.') >= 0) + if (name.indexOf('.') >= 0) { throw new IllegalArgumentException("method name contains '.': " + name); + } this.name = name; } private JInvocation(JGenerable object, JMethod method) { this.object = object; - this.method =method; + this.method = method; + } + + public static JInvocation invokeOn(JGenerable object, String name) { + return new JInvocation(object, name); } /** * Invokes a constructor of an object (i.e., creates * a new object.) - * + *

* @param c - * Type of the object to be created. If this type is - * an array type, added arguments are treated as array - * initializer. Thus you can create an expression like - * new int[]{1,2,3,4,5}. + * Type of the object to be created. If this type is + * an array type, added arguments are treated as array + * initializer. Thus you can create an expression like + * new int[]{1,2,3,4,5}. */ JInvocation(JType c) { this.isConstructor = true; @@ -135,13 +140,15 @@ private JInvocation(JGenerable object, JMethod method) { } /** - * Add an expression to this invocation's argument list + * Add an expression to this invocation's argument list * * @param arg - * Argument to add to argument list + * Argument to add to argument list */ public JInvocation arg(JExpression arg) { - if(arg==null) throw new IllegalArgumentException(); + if (arg == null) { + throw new IllegalArgumentException(); + } args.add(arg); return this; } @@ -154,43 +161,48 @@ public JInvocation arg(JExpression arg) { public JInvocation arg(String v) { return arg(JExpr.lit(v)); } - - /** - * Returns all arguments of the invocation. - * @return - * If there's no arguments, an empty array will be returned. - */ - public JExpression[] listArgs() { - return args.toArray(new JExpression[args.size()]); - } + + /** + * Returns all arguments of the invocation. + *

+ * @return + * If there's no arguments, an empty array will be returned. + */ + public JExpression[] listArgs() { + return args.toArray(new JExpression[args.size()]); + } public void generate(JFormatter f) { if (isConstructor && type.isArray()) { // [RESULT] new T[]{arg1,arg2,arg3,...}; f.p("new").g(type).p('{'); } else { - if (isConstructor) + if (isConstructor) { f.p("new").g(type).p('('); - else { + } else { String name = this.name; - if(name==null) name=this.method.name(); + if (name == null) { + name = this.method.name(); + } - if (object != null) + if (object != null) { f.g(object).p('.').p(name).p('('); - else + } else { f.id(name).p('('); + } } } - + f.g(args); - if (isConstructor && type.isArray()) + if (isConstructor && type.isArray()) { f.p('}'); - else + } else { f.p(')'); - - if( type instanceof JDefinedClass && ((JDefinedClass)type).isAnonymous() ) { - ((JAnonymousClass)type).declareBody(f); + } + + if (type instanceof JDefinedClass && ((JDefinedClass) type).isAnonymous()) { + ((JAnonymousClass) type).declareBody(f); } } diff --git a/codemodel/src/main/java/com/sun/codemodel/JJavaName.java b/codemodel/src/main/java/com/sun/codemodel/JJavaName.java index 51e2573..1073e9e 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JJavaName.java +++ b/codemodel/src/main/java/com/sun/codemodel/JJavaName.java @@ -100,8 +100,7 @@ public static boolean isJavaPackageName(String s) { * ("my_children","MyChildren","myChildren", and "MY-CHILDREN", "CODE003-children" respectively) *

* Although this method only works for English words, it handles non-English - * words gracefully (by just returning it as-is.) For example, 日本語 - * will be returned as-is without modified, not "日本語s" + * words gracefully (by just returning it as-is.) *

* This method doesn't handle suffixes very well. For example, passing * "person56" will return "person56s", not "people56". diff --git a/codemodel/src/main/java/com/sun/codemodel/JMods.java b/codemodel/src/main/java/com/sun/codemodel/JMods.java index b1e9064..d757c8c 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JMods.java +++ b/codemodel/src/main/java/com/sun/codemodel/JMods.java @@ -59,7 +59,9 @@ public class JMods implements JGenerable { private static int CLASS = (JMod.PUBLIC | JMod.PRIVATE | JMod.PROTECTED | JMod.STATIC | JMod.FINAL | JMod.ABSTRACT); private static int INTERFACE = JMod.PUBLIC; - /** bit-packed representation of modifiers. */ + /** + * bit-packed representation of modifiers. + */ private int mods; private JMods(int mods) { @@ -107,18 +109,34 @@ static JMods forInterface(int mods) { return new JMods(mods); } + /** + * @deprecated replaced by {@link #is(int)} + */ + @Deprecated public boolean isAbstract() { - return (mods & JMod.ABSTRACT) != 0; + return is(JMod.ABSTRACT); } + /** + * @deprecated replaced by {@link #is(int)} + */ + @Deprecated public boolean isNative() { return (mods & JMod.NATIVE) != 0; } + /** + * @deprecated replaced by {@link #is(int)} + */ + @Deprecated public boolean isSynchronized() { return (mods & JMod.SYNCHRONIZED) != 0; } + public boolean is(int mod) { + return (mods & mod) != 0; + } + public void setSynchronized(boolean newValue) { setFlag(JMod.SYNCHRONIZED, newValue); } @@ -150,17 +168,37 @@ private void setFlag(int bit, boolean newValue) { } public void generate(JFormatter f) { - if ((mods & JMod.PUBLIC) != 0) f.p("public"); - if ((mods & JMod.PROTECTED) != 0) f.p("protected"); - if ((mods & JMod.PRIVATE) != 0) f.p("private"); - if ((mods & JMod.FINAL) != 0) f.p("final"); - if ((mods & JMod.STATIC) != 0) f.p("static"); - if ((mods & JMod.ABSTRACT) != 0) f.p("abstract"); - if ((mods & JMod.NATIVE) != 0) f.p("native"); - if ((mods & JMod.SYNCHRONIZED) != 0) f.p("synchronized"); - if ((mods & JMod.TRANSIENT) != 0) f.p("transient"); - if ((mods & JMod.VOLATILE) != 0) f.p("volatile"); + if ((mods & JMod.PUBLIC) != 0) { + f.p("public"); } + if ((mods & JMod.PROTECTED) != 0) { + f.p("protected"); + } + if ((mods & JMod.PRIVATE) != 0) { + f.p("private"); + } + if ((mods & JMod.FINAL) != 0) { + f.p("final"); + } + if ((mods & JMod.STATIC) != 0) { + f.p("static"); + } + if ((mods & JMod.ABSTRACT) != 0) { + f.p("abstract"); + } + if ((mods & JMod.NATIVE) != 0) { + f.p("native"); + } + if ((mods & JMod.SYNCHRONIZED) != 0) { + f.p("synchronized"); + } + if ((mods & JMod.TRANSIENT) != 0) { + f.p("transient"); + } + if ((mods & JMod.VOLATILE) != 0) { + f.p("volatile"); + } + } @Override public String toString() { diff --git a/codemodel/src/main/java/com/sun/codemodel/JMultiCatchBlock.java b/codemodel/src/main/java/com/sun/codemodel/JMultiCatchBlock.java new file mode 100644 index 0000000..1e83dee --- /dev/null +++ b/codemodel/src/main/java/com/sun/codemodel/JMultiCatchBlock.java @@ -0,0 +1,49 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.sun.codemodel; + +/** + * + * @author lkroll + */ +public class JMultiCatchBlock implements JTryBlock.CatchBlock { + + private final JMods mods; + private final String var; + private final JClass[] exceptions; + private JBlock body = new JBlock(); + private JVar variable = null; + + JMultiCatchBlock(JMods mods, String name, JClass... exceptions) { + this.mods = mods; + var = name; + this.exceptions = exceptions; + } + + public JBlock body() { + return body; + } + + public JVar getVar() { + if (variable == null) { + variable = new JVar(mods, exceptions[0], var, null); + } + return variable; + } + + public void generate(JFormatter f) { + f.p("catch("); + f.g(mods); + for (int i = 0; i < exceptions.length; i++) { + f.g(exceptions[i]); + if (i != (exceptions.length -1)) { + f.p(" | "); + } + } + f.id(var).p(')').g(body); + } + +} diff --git a/codemodel/src/main/java/com/sun/codemodel/JNarrowedClass.java b/codemodel/src/main/java/com/sun/codemodel/JNarrowedClass.java index 5f8fe13..e7f1d1b 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JNarrowedClass.java +++ b/codemodel/src/main/java/com/sun/codemodel/JNarrowedClass.java @@ -37,24 +37,23 @@ * only if the new code is made subject to such option by the copyright * holder. */ - package com.sun.codemodel; -import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Collections; -import java.util.ArrayList; /** * Represents X<Y>. * * TODO: consider separating the decl and the use. - * + *

* @author - * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) + * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) */ class JNarrowedClass extends JClass { + /** * A generic class with type parameters. */ @@ -63,59 +62,70 @@ class JNarrowedClass extends JClass { * Arguments to those parameters. */ private final List args; + private final boolean isDiamond; JNarrowedClass(JClass basis, JClass arg) { - this(basis,Collections.singletonList(arg)); + this(basis, Collections.singletonList(arg)); } - + JNarrowedClass(JClass basis, List args) { super(basis.owner()); this.basis = basis; assert !(basis instanceof JNarrowedClass); this.args = args; + isDiamond = false; + } + + JNarrowedClass(JClass basis) { + super(basis.owner()); + this.basis = basis; + args = null; + isDiamond = true; } @Override - public JClass narrow( JClass clazz ) { - List newArgs = new ArrayList(args); - newArgs.add(clazz); - return new JNarrowedClass(basis,newArgs); + public JClass narrow(JClass clazz) { + throw new UnsupportedOperationException("Can't narrow an diamond class further!"); } @Override - public JClass narrow( JClass... clazz ) { - List newArgs = new ArrayList(args); - newArgs.addAll(Arrays.asList(clazz)); - return new JNarrowedClass(basis,newArgs); + public JClass narrow(JClass... clazz) { + throw new UnsupportedOperationException("Can't narrow an diamond class further!"); } public String name() { StringBuilder buf = new StringBuilder(); buf.append(basis.name()); buf.append('<'); - boolean first = true; - for (JClass c : args) { - if(first) - first = false; - else - buf.append(','); - buf.append(c.name()); + if (!isDiamond) { + boolean first = true; + for (JClass c : args) { + if (first) { + first = false; + } else { + buf.append(','); + } + buf.append(c.name()); + } } buf.append('>'); return buf.toString(); } - + public String fullName() { StringBuilder buf = new StringBuilder(); buf.append(basis.fullName()); buf.append('<'); - boolean first = true; - for (JClass c : args) { - if(first) - first = false; - else - buf.append(','); - buf.append(c.fullName()); + if (!isDiamond) { + boolean first = true; + for (JClass c : args) { + if (first) { + first = false; + } else { + buf.append(','); + } + buf.append(c.fullName()); + } } buf.append('>'); return buf.toString(); @@ -126,13 +136,16 @@ public String binaryName() { StringBuilder buf = new StringBuilder(); buf.append(basis.binaryName()); buf.append('<'); - boolean first = true; - for (JClass c : args) { - if(first) - first = false; - else - buf.append(','); - buf.append(c.binaryName()); + if (!isDiamond) { + boolean first = true; + for (JClass c : args) { + if (first) { + first = false; + } else { + buf.append(','); + } + buf.append(c.binaryName()); + } } buf.append('>'); return buf.toString(); @@ -140,7 +153,11 @@ public String binaryName() { @Override public void generate(JFormatter f) { - f.t(basis).p('<').g(args).p(JFormatter.CLOSE_TYPE_ARGS); + f.t(basis).p('<'); + if (!isDiamond) { + f.g(args); + } + f.p(JFormatter.CLOSE_TYPE_ARGS); } @Override @@ -148,12 +165,15 @@ void printLink(JFormatter f) { basis.printLink(f); f.p("{@code <}"); boolean first = true; - for( JClass c : args ) { - if(first) - first = false; - else - f.p(','); - c.printLink(f); + if (!isDiamond) { + for (JClass c : args) { + if (first) { + first = false; + } else { + f.p(','); + } + c.printLink(f); + } } f.p("{@code >}"); } @@ -164,19 +184,28 @@ public JPackage _package() { public JClass _extends() { JClass base = basis._extends(); - if(base==null) return base; - return base.substituteParams(basis.typeParams(),args); + if (base == null || isDiamond) { + return base; + } + return base.substituteParams(basis.typeParams(), args); } public Iterator _implements() { return new Iterator() { private final Iterator core = basis._implements(); + public void remove() { core.remove(); } + public JClass next() { - return core.next().substituteParams(basis.typeParams(),args); + if (isDiamond) { + return core.next(); + } else { + return core.next().substituteParams(basis.typeParams(), args); + } } + public boolean hasNext() { return core.hasNext(); } @@ -201,15 +230,15 @@ public boolean isArray() { return false; } - // // Equality is based on value // - @Override public boolean equals(Object obj) { - if(!(obj instanceof JNarrowedClass)) return false; - return fullName().equals(((JClass)obj).fullName()); + if (!(obj instanceof JNarrowedClass)) { + return false; + } + return fullName().equals(((JClass) obj).fullName()); } @Override @@ -218,24 +247,36 @@ public int hashCode() { } protected JClass substituteParams(JTypeVar[] variables, List bindings) { - JClass b = basis.substituteParams(variables,bindings); - boolean different = b!=basis; - + if (isDiamond) { + return this; + } + JClass b = basis.substituteParams(variables, bindings); + boolean different = b != basis; + List clazz = new ArrayList(args.size()); - for( int i=0; i getTypeParameters() { + if (isDiamond) { + return new ArrayList(); + } return args; } + + @Override + public JClass inner(String name) { + return owner().ref(fullName()+"."+name); + } } diff --git a/codemodel/src/main/java/com/sun/codemodel/JNullType.java b/codemodel/src/main/java/com/sun/codemodel/JNullType.java index 66dab72..b5e5996 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JNullType.java +++ b/codemodel/src/main/java/com/sun/codemodel/JNullType.java @@ -76,4 +76,9 @@ public Iterator _implements() { protected JClass substituteParams(JTypeVar[] variables, List bindings) { return this; } + + @Override + public JClass inner(String name) { + return null; // this doesn't make sense^^ + } } diff --git a/codemodel/src/main/java/com/sun/codemodel/JPackage.java b/codemodel/src/main/java/com/sun/codemodel/JPackage.java index a525eab..732d0c6 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JPackage.java +++ b/codemodel/src/main/java/com/sun/codemodel/JPackage.java @@ -49,6 +49,8 @@ import java.io.Writer; import java.lang.annotation.Annotation; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -56,8 +58,6 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; -import java.util.Collection; -import java.util.Collections; /** @@ -119,9 +119,9 @@ public final class JPackage implements JDeclaration, JGenerable, JClassContainer throw new IllegalArgumentException(msg); } - if(JCodeModel.isCaseSensitiveFileSystem) - upperCaseClassMap = null; - else +// if(JCodeModel.isCaseSensitiveFileSystem) +// upperCaseClassMap = null; +// else upperCaseClassMap = new HashMap(); this.name = name; diff --git a/codemodel/src/main/java/com/sun/codemodel/JSynchronized.java b/codemodel/src/main/java/com/sun/codemodel/JSynchronized.java new file mode 100644 index 0000000..1c826d7 --- /dev/null +++ b/codemodel/src/main/java/com/sun/codemodel/JSynchronized.java @@ -0,0 +1,34 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.sun.codemodel; + +/** + * + * @author lkroll + */ +public class JSynchronized implements JStatement { + + private final JExpression lock; + private final JBlock body = new JBlock(); + + JSynchronized(JExpression lock) { + this.lock = lock; + } + + public JBlock body() { + return this.body; + } + + public void state(JFormatter f) { + if (JOp.hasTopOp(lock)) { + f.p("synchronized").g(lock); + } else { + f.p("synchronized(").g(lock).p(')'); + } + f.g(body).nl(); + } + +} diff --git a/codemodel/src/main/java/com/sun/codemodel/JTryBlock.java b/codemodel/src/main/java/com/sun/codemodel/JTryBlock.java index 104fe14..1d0ff18 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JTryBlock.java +++ b/codemodel/src/main/java/com/sun/codemodel/JTryBlock.java @@ -50,8 +50,9 @@ public class JTryBlock implements JStatement { + private List resources = new ArrayList(); private JBlock body = new JBlock(); - private List catches = new ArrayList(); + private List catches = new ArrayList(); private JBlock _finally = null; JTryBlock() { @@ -60,12 +61,24 @@ public class JTryBlock implements JStatement { public JBlock body() { return body; } + + public JVar resource(int mods, JType type, String id, JExpression init) { + JVar var = new JVar(JMods.forVar(mods), type, id, init); + resources.add(var); + return var; + } public JCatchBlock _catch(JClass exception) { JCatchBlock cb = new JCatchBlock(exception); catches.add(cb); return cb; } + + public JMultiCatchBlock _catch(int mods, String var, JClass... exception) { + JMultiCatchBlock cb = new JMultiCatchBlock(JMods.forVar(mods), var, exception); + catches.add(cb); + return cb; + } public JBlock _finally() { if (_finally == null) _finally = new JBlock(); @@ -73,12 +86,23 @@ public JBlock _finally() { } public void state(JFormatter f) { - f.p("try").g(body); - for (JCatchBlock cb : catches) + f.p("try"); + if (!resources.isEmpty()) { + f.p("("); + for (JVar var : resources) { + f.b(var).p(";").nl(); + } + f.p(")"); + } + f.g(body); + for (CatchBlock cb : catches) f.g(cb); if (_finally != null) f.p("finally").g(_finally); f.nl(); } + + public static interface CatchBlock extends JGenerable {} + } diff --git a/codemodel/src/main/java/com/sun/codemodel/JType.java b/codemodel/src/main/java/com/sun/codemodel/JType.java index 81bfff2..bb083a2 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JType.java +++ b/codemodel/src/main/java/com/sun/codemodel/JType.java @@ -178,7 +178,7 @@ public String toString() { * Compare two JTypes by FQCN, giving sorting precedence to types * that belong to packages java and javax over all others. * - * This method is used to sort generated import statments in a + * This method is used to sort generated import statements in a * conventional way for readability. */ public int compareTo(JType o) { diff --git a/codemodel/src/main/java/com/sun/codemodel/JTypeVar.java b/codemodel/src/main/java/com/sun/codemodel/JTypeVar.java index 0758d59..4678f92 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JTypeVar.java +++ b/codemodel/src/main/java/com/sun/codemodel/JTypeVar.java @@ -133,4 +133,9 @@ protected JClass substituteParams(JTypeVar[] variables, List bindings) { public void generate(JFormatter f) { f.id(name); } + + @Override + public JClass inner(String name) { + return null; + } } diff --git a/codemodel/src/main/java/com/sun/codemodel/JTypeWildcard.java b/codemodel/src/main/java/com/sun/codemodel/JTypeWildcard.java index 56e90c2..da2fa0a 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JTypeWildcard.java +++ b/codemodel/src/main/java/com/sun/codemodel/JTypeWildcard.java @@ -44,13 +44,11 @@ import java.util.List; /** - * Represents a wildcard type like "? extends Foo". + * Represents a wildcard type like "? extends Foo" or "? super Foo". * *

* Instances of this class can be obtained from {@link JClass#wildcard()} * - * TODO: extend this to cover "? super Integer". - * *

* Our modeling of types are starting to look really ugly. * ideally it should have been done somewhat like APT, @@ -61,18 +59,24 @@ final class JTypeWildcard extends JClass { private final JClass bound; + private final boolean _super; - JTypeWildcard(JClass bound) { + JTypeWildcard(JClass bound, boolean _super) { super(bound.owner()); this.bound = bound; + this._super = _super; + } + + JTypeWildcard(JClass bound) { + this(bound, false); } public String name() { - return "? extends "+bound.name(); + return _super ? "? super " + bound.name() : "? extends " + bound.name(); } public String fullName() { - return "? extends "+bound.fullName(); + return _super ? "? super " + bound.fullName() : "? extends " + bound.fullName(); } public JPackage _package() { @@ -116,9 +120,17 @@ protected JClass substituteParams(JTypeVar[] variables, List bindings) { } public void generate(JFormatter f) { - if(bound._extends()==null) - f.p("?"); // instead of "? extends Object" - else + if (_super) { + f.p("? super").g(bound); + } else if(bound._extends()==null) { + f.p("?"); // instead of "? extends Object" + } else { f.p("? extends").g(bound); + } + } + + @Override + public JClass inner(String name) { + return null; } } diff --git a/codemodel/src/main/java/com/sun/codemodel/JVar.java b/codemodel/src/main/java/com/sun/codemodel/JVar.java index c9d23f0..9dd0a56 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JVar.java +++ b/codemodel/src/main/java/com/sun/codemodel/JVar.java @@ -42,16 +42,16 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; -import java.util.List; import java.util.Collection; import java.util.Collections; +import java.util.List; /** * Variables and fields. */ -public class JVar extends JExpressionImpl implements JDeclaration, JAssignmentTarget, JAnnotatable { +public class JVar extends JExpressionImpl implements JField, JDeclaration, JAnnotatable { /** * Modifiers. diff --git a/codemodel/src/main/java/com/sun/codemodel/JWhileLoop.java b/codemodel/src/main/java/com/sun/codemodel/JWhileLoop.java index 78a2ea5..9d821c8 100644 --- a/codemodel/src/main/java/com/sun/codemodel/JWhileLoop.java +++ b/codemodel/src/main/java/com/sun/codemodel/JWhileLoop.java @@ -55,7 +55,7 @@ public class JWhileLoop implements JStatement { /** * JBlock of statements which makes up body of this While statement */ - private JBlock body = null; + private JStatement body = null; /** * Construct a While statment @@ -69,8 +69,14 @@ public JExpression test() { } public JBlock body() { - if (body == null) body = new JBlock(); - return body; + if (body == null || !(body instanceof JBlock)) { + body = new JBlock(); + } + return (JBlock) body; + } + + public void setBody(JStatement stmt) { + this.body = stmt; } public void state(JFormatter f) { diff --git a/codemodel/src/main/java/com/sun/codemodel/fmt/JStaticJavaFile.java b/codemodel/src/main/java/com/sun/codemodel/fmt/JStaticJavaFile.java index 6f7a865..3a5046d 100644 --- a/codemodel/src/main/java/com/sun/codemodel/fmt/JStaticJavaFile.java +++ b/codemodel/src/main/java/com/sun/codemodel/fmt/JStaticJavaFile.java @@ -40,6 +40,10 @@ package com.sun.codemodel.fmt; +import com.sun.codemodel.JClass; +import com.sun.codemodel.JPackage; +import com.sun.codemodel.JResourceFile; +import com.sun.codemodel.JTypeVar; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; @@ -53,11 +57,6 @@ import java.util.Iterator; import java.util.List; -import com.sun.codemodel.JClass; -import com.sun.codemodel.JPackage; -import com.sun.codemodel.JResourceFile; -import com.sun.codemodel.JTypeVar; - /** * Statically generated Java soruce file. * @@ -250,5 +249,10 @@ public JTypeVar[] typeParams() { protected JClass substituteParams(JTypeVar[] variables, List bindings) { return this; } + + @Override + public JClass inner(String name) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } }; } diff --git a/codemodel/src/main/java/com/sun/codemodel/package-info.java b/codemodel/src/main/java/com/sun/codemodel/package-info.java index cdfcb2b..aa4218b 100644 --- a/codemodel/src/main/java/com/sun/codemodel/package-info.java +++ b/codemodel/src/main/java/com/sun/codemodel/package-info.java @@ -50,24 +50,6 @@ * then writing it out as text files that is Java source files. * The AST looks like this: * - * {@DotDiagram - digraph G { - cls1 [label="JDefinedClass"]; - cls2 [label="JDefinedClass"]; - JCodeModel -> cls1 [label="generated class"]; - JCodeModel -> cls2 [label="generated class"]; - - m1 [label="JMethod"]; - m2 [label="JMethod"]; - - cls1 -> m1; - cls1 -> m2; - cls1 -> JField; - - m1 -> JVar [label="method parameter"]; - m1 -> JBlock [label="code"]; - } - * } * *

* You bulid this tree mostly from top-down. So, you first create @@ -122,7 +104,6 @@ * pre-encoding tokens (like 'public') to the target encoding, * and consider exploting the subtree equivalence. * - * @ArchitectureDocument */ package com.sun.codemodel; diff --git a/codemodel/src/main/java/com/sun/codemodel/util/JavadocEscapeWriter.java b/codemodel/src/main/java/com/sun/codemodel/util/JavadocEscapeWriter.java index 989d1d2..ab71d2d 100644 --- a/codemodel/src/main/java/com/sun/codemodel/util/JavadocEscapeWriter.java +++ b/codemodel/src/main/java/com/sun/codemodel/util/JavadocEscapeWriter.java @@ -52,7 +52,7 @@ * *

* Note that this class doesn't escape other Unicode characters - * that are typically unsafe. For example, 愛 (A kanji + * that are typically unsafe. For example, {@code 愛} (A kanji * that means "love") can be considered as unsafe because * javac with English Windows cannot accept this character in the * source code. diff --git a/pom.xml b/pom.xml index 6252062..6a9b436 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ Codemodel Java source code generation library http://codemodel.java.net/ - 1.0.2 + 1.0.2-SNAPSHOT pom codemodel