I decided to go hog wild and clean up all the type use in Presents which

required some serious bending and folding of the generic type system, but for
the most part we managed to avoid any mutilating. The gendobj task now
generates properly typed "addToXXX" and "updateXXX" DSet methods based on the
parameterized type of the DSet. This might cause unrecompiled code to break,
but I don't think there are many cases in the base toolkit where people call
DSet adders or updaters. We'll see and I'll add backwards compatibility
versions for cases where we need them to support GG games (everything else we
can just recompile).


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4245 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2006-07-05 00:55:05 +00:00
parent 94b79826d4
commit 8afd0316ec
27 changed files with 269 additions and 212 deletions
@@ -31,6 +31,8 @@ import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
@@ -109,9 +111,7 @@ public class GenDObjectTask extends Task
throw new BuildException("Can't resolve InvocationListener", e);
}
ArrayList files = new ArrayList();
for (Iterator iter = _filesets.iterator(); iter.hasNext(); ) {
FileSet fs = (FileSet)iter.next();
for (FileSet fs : _filesets) {
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
File fromDir = fs.getDir(getProject());
String[] srcFiles = ds.getIncludedFiles();
@@ -158,7 +158,7 @@ public class GenDObjectTask extends Task
}
// determine which fields we need to deal with
ArrayList flist = new ArrayList();
ArrayList<Field> flist = new ArrayList<Field>();
Field[] fields = oclass.getDeclaredFields();
for (int ii = 0; ii < fields.length; ii++) {
Field f = fields[ii];
@@ -175,12 +175,12 @@ public class GenDObjectTask extends Task
String[] lines = null;
try {
BufferedReader bin = new BufferedReader(new FileReader(source));
ArrayList llist = new ArrayList();
ArrayList<String> llist = new ArrayList<String>();
String line = null;
while ((line = bin.readLine()) != null) {
llist.add(line);
}
lines = (String[])llist.toArray(new String[llist.size()]);
lines = llist.toArray(new String[llist.size()]);
bin.close();
} catch (IOException ioe) {
System.err.println("Error reading '" + source + "': " + ioe);
@@ -249,8 +249,8 @@ public class GenDObjectTask extends Task
StringBuilder fsection = new StringBuilder();
StringBuilder msection = new StringBuilder();
for (int ii = 0; ii < flist.size(); ii++) {
Field f = (Field)flist.get(ii);
Class ftype = f.getType();
Field f = flist.get(ii);
Class<?> ftype = f.getType();
String fname = f.getName();
// create our velocity context
@@ -262,13 +262,34 @@ public class GenDObjectTask extends Task
ctx.put("clonefield", GenUtil.cloneArgument(_dsclass, f, "value"));
ctx.put("capfield", StringUtil.unStudlyName(fname).toUpperCase());
ctx.put("upfield", StringUtils.capitalize(fname));
// if this field is an array, we need its component types
if (ftype.isArray()) {
Class etype = ftype.getComponentType();
Class<?> etype = ftype.getComponentType();
ctx.put("elemtype", GenUtil.simpleName(etype));
ctx.put("wrapelem", GenUtil.boxArgument(etype, "value"));
ctx.put("wrapoelem", GenUtil.boxArgument(etype, "ovalue"));
}
// if this field is a generic DSet, we need its bound type
if (_dsclass.isAssignableFrom(ftype)) {
Type t = f.getGenericType();
// we need to walk up the heirarchy until we get to the
// parameterized DSet
while (t instanceof Class<?>) {
t = ((Class<?>)t).getGenericSuperclass();
}
if (t instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType)t;
if (pt.getActualTypeArguments().length > 0) {
ctx.put("etype", GenUtil.simpleName(
(Class<?>)pt.getActualTypeArguments()[0]));
}
} else {
ctx.put("etype", "DSet.Entry");
}
}
// now figure out which template to use
String tname = "field.tmpl";
if (_dsclass.isAssignableFrom(ftype)) {
@@ -370,7 +391,7 @@ public class GenDObjectTask extends Task
}
/** A list of filesets that contain tile images. */
protected ArrayList _filesets = new ArrayList();
protected ArrayList<FileSet> _filesets = new ArrayList<FileSet>();
/** Used to do our own classpath business. */
protected ClassLoader _cloader;
@@ -380,15 +401,15 @@ public class GenDObjectTask extends Task
/** {@link DObject} resolved with the proper classloader so that we
* can compare it to loaded derived classes. */
protected Class _doclass;
protected Class<?> _doclass;
/** {@link DSet} resolved with the proper classloader so that we can
* compare it to loaded derived classes. */
protected Class _dsclass;
protected Class<?> _dsclass;
/** {@link OidList} resolved with the proper classloader so that we
* can compare it to loaded derived classes. */
protected Class _olclass;
protected Class<?> _olclass;
/** Specifies the start of the path to our various templates. */
protected static final String BASE_TMPL =
@@ -68,8 +68,9 @@ public class GenReceiverTask extends InvocationTask
return;
}
HashMap imports = new HashMap();
ComparableArrayList methods = new ComparableArrayList();
HashMap<String,Boolean> imports = new HashMap<String,Boolean>();
ComparableArrayList<ServiceMethod> methods =
new ComparableArrayList<ServiceMethod>();
// we need to import the receiver itself
imports.put(importify(receiver.getName()), Boolean.TRUE);
@@ -94,14 +95,14 @@ public class GenReceiverTask extends InvocationTask
}
protected void generateSender (File source, String rname, String rpackage,
List methods, Iterator imports)
List methods, Iterator<String> imports)
{
String name = StringUtil.replace(rname, "Receiver", "");
String sname = StringUtil.replace(rname, "Receiver", "Sender");
String spackage = StringUtil.replace(rpackage, ".client", ".server");
// construct our imports list
ComparableArrayList implist = new ComparableArrayList();
ComparableArrayList<String> implist = new ComparableArrayList<String>();
CollectionUtil.addAll(implist, imports);
checkedAdd(implist, ClientObject.class.getName());
checkedAdd(implist, InvocationSender.class.getName());
@@ -134,13 +135,13 @@ public class GenReceiverTask extends InvocationTask
protected void generateDecoder (
File source, String rname, String rpackage, List methods,
Iterator imports)
Iterator<String> imports)
{
String name = StringUtil.replace(rname, "Receiver", "");
String dname = StringUtil.replace(rname, "Receiver", "Decoder");
// construct our imports list
ComparableArrayList implist = new ComparableArrayList();
ComparableArrayList<String> implist = new ComparableArrayList<String>();
CollectionUtil.addAll(implist, imports);
checkedAdd(implist, InvocationDecoder.class.getName());
implist.sort();
@@ -37,13 +37,15 @@ import com.threerings.presents.server.InvocationProvider;
public class GenServiceTask extends InvocationTask
{
/** Used to keep track of custom InvocationListener derivations. */
public class ServiceListener implements Comparable
public class ServiceListener implements Comparable<ServiceListener>
{
public Class listener;
public ComparableArrayList methods = new ComparableArrayList();
public ComparableArrayList<ServiceMethod> methods =
new ComparableArrayList<ServiceMethod>();
public ServiceListener (Class service, Class listener, HashMap imports)
public ServiceListener (Class service, Class listener,
HashMap<String,Boolean> imports)
{
this.listener = listener;
Method[] methdecls = listener.getDeclaredMethods();
@@ -59,9 +61,9 @@ public class GenServiceTask extends InvocationTask
methods.sort();
}
public int compareTo (Object other)
public int compareTo (ServiceListener other)
{
return getName().compareTo(((ServiceListener)other).getName());
return getName().compareTo(other.getName());
}
public boolean equals (Object other)
@@ -115,9 +117,11 @@ public class GenServiceTask extends InvocationTask
return;
}
HashMap imports = new HashMap();
ComparableArrayList methods = new ComparableArrayList();
ComparableArrayList listeners = new ComparableArrayList();
HashMap<String,Boolean> imports = new HashMap<String,Boolean>();
ComparableArrayList<ServiceMethod> methods =
new ComparableArrayList<ServiceMethod>();
ComparableArrayList<ServiceListener> listeners =
new ComparableArrayList<ServiceListener>();
// we need to import the service itself
imports.put(importify(service.getName()), Boolean.TRUE);
@@ -158,14 +162,14 @@ public class GenServiceTask extends InvocationTask
protected void generateMarshaller (
File source, String sname, String spackage, List methods,
List listeners, Iterator imports)
List listeners, Iterator<String> imports)
{
String name = StringUtil.replace(sname, "Service", "");
String mname = StringUtil.replace(sname, "Service", "Marshaller");
String mpackage = StringUtil.replace(spackage, ".client", ".data");
// construct our imports list
ComparableArrayList implist = new ComparableArrayList();
ComparableArrayList<String> implist = new ComparableArrayList<String>();
CollectionUtil.addAll(implist, imports);
checkedAdd(implist, Client.class.getName());
checkedAdd(implist, InvocationMarshaller.class.getName());
@@ -198,14 +202,14 @@ public class GenServiceTask extends InvocationTask
protected void generateDispatcher (
File source, String sname, String spackage, List methods,
Iterator imports)
Iterator<String> imports)
{
String name = StringUtil.replace(sname, "Service", "");
String dname = StringUtil.replace(sname, "Service", "Dispatcher");
String dpackage = StringUtil.replace(spackage, ".client", ".server");
// construct our imports list
ComparableArrayList implist = new ComparableArrayList();
ComparableArrayList<String> implist = new ComparableArrayList<String>();
CollectionUtil.addAll(implist, imports);
checkedAdd(implist, ClientObject.class.getName());
checkedAdd(implist, InvocationMarshaller.class.getName());
@@ -241,14 +245,14 @@ public class GenServiceTask extends InvocationTask
protected void generateProvider (
File source, String sname, String spackage, List methods,
List listeners, Iterator imports)
List listeners, Iterator<String> imports)
{
String name = StringUtil.replace(sname, "Service", "");
String mname = StringUtil.replace(sname, "Service", "Provider");
String mpackage = StringUtil.replace(spackage, ".client", ".server");
// construct our imports list
ComparableArrayList implist = new ComparableArrayList();
ComparableArrayList<String> implist = new ComparableArrayList<String>();
CollectionUtil.addAll(implist, imports);
checkedAdd(implist, ClientObject.class.getName());
checkedAdd(implist, InvocationProvider.class.getName());
@@ -280,7 +284,7 @@ public class GenServiceTask extends InvocationTask
}
/** Services for which we should not generate provider interfaces. */
protected HashSet _providerless = new HashSet();
protected HashSet<String> _providerless = new HashSet<String>();
/** Specifies the path to the marshaller template. */
protected static final String MARSHALLER_TMPL =
@@ -46,7 +46,7 @@ public abstract class InvocationTask extends Task
public Class listener;
public ListenerArgument (int index, Class listener)
public ListenerArgument (int index, Class<?> listener)
{
this.index = index+1;
this.listener = listener;
@@ -65,21 +65,23 @@ public abstract class InvocationTask extends Task
}
/** Used to keep track of invocation service methods. */
public class ServiceMethod implements Comparable
public class ServiceMethod implements Comparable<ServiceMethod>
{
public Method method;
public ArrayList listenerArgs = new ArrayList();
public ArrayList<ListenerArgument> listenerArgs =
new ArrayList<ListenerArgument>();
public ServiceMethod (Class service, Method method, HashMap imports)
public ServiceMethod (Class<?> service, Method method,
HashMap<String,Boolean> imports)
{
this.method = method;
// we need to look through our arguments and note any needed
// imports in the supplied table
Class[] args = method.getParameterTypes();
Class<?>[] args = method.getParameterTypes();
for (int ii = 0; ii < args.length; ii++) {
Class arg = args[ii];
Class<?> arg = args[ii];
while (arg.isArray()) {
arg = arg.getComponentType();
}
@@ -132,7 +134,7 @@ public abstract class InvocationTask extends Task
public String getArgList (boolean skipFirst)
{
StringBuilder buf = new StringBuilder();
Class[] args = method.getParameterTypes();
Class<?>[] args = method.getParameterTypes();
for (int ii = skipFirst ? 1 : 0; ii < args.length; ii++) {
if (buf.length() > 0) {
buf.append(", ");
@@ -146,7 +148,7 @@ public abstract class InvocationTask extends Task
public String getWrappedArgList (boolean skipFirst)
{
StringBuilder buf = new StringBuilder();
Class[] args = method.getParameterTypes();
Class<?>[] args = method.getParameterTypes();
for (int ii = (skipFirst ? 1 : 0); ii < args.length; ii++) {
if (buf.length() > 0) {
buf.append(", ");
@@ -161,15 +163,15 @@ public abstract class InvocationTask extends Task
return (method.getParameterTypes().length > (skipFirst ? 1 : 0));
}
public int compareTo (Object other)
public int compareTo (ServiceMethod other)
{
return getCode().compareTo(((ServiceMethod)other).getCode());
return getCode().compareTo(other.getCode());
}
public String getUnwrappedArgList (boolean listenerMode)
{
StringBuilder buf = new StringBuilder();
Class[] args = method.getParameterTypes();
Class<?>[] args = method.getParameterTypes();
for (int ii = (listenerMode ? 0 : 1); ii < args.length; ii++) {
if (buf.length() > 0) {
buf.append(", ");
@@ -180,7 +182,7 @@ public abstract class InvocationTask extends Task
return buf.toString();
}
protected String boxArgument (Class clazz, int index)
protected String boxArgument (Class<?> clazz, int index)
{
if (_ilistener.isAssignableFrom(clazz)) {
return GenUtil.boxArgument(clazz, "listener" + index);
@@ -190,7 +192,7 @@ public abstract class InvocationTask extends Task
}
protected String unboxArgument (
Class clazz, int index, boolean listenerMode)
Class<?> clazz, int index, boolean listenerMode)
{
if (listenerMode && _ilistener.isAssignableFrom(clazz)) {
return "listener" + index;
@@ -252,8 +254,7 @@ public abstract class InvocationTask extends Task
throw new BuildException("Can't resolve InvocationListener", e);
}
for (Iterator iter = _filesets.iterator(); iter.hasNext(); ) {
FileSet fs = (FileSet)iter.next();
for (FileSet fs : _filesets) {
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
File fromDir = fs.getDir(getProject());
String[] srcFiles = ds.getIncludedFiles();
@@ -302,7 +303,7 @@ public abstract class InvocationTask extends Task
FileUtils.writeStringToFile(new File(path), data, "UTF-8");
}
protected static void checkedAdd (List list, Object value)
protected static <T> void checkedAdd (List<T> list, T value)
{
if (!list.contains(value)) {
list.add(value);
@@ -324,7 +325,7 @@ public abstract class InvocationTask extends Task
}
/** A list of filesets that contain tile images. */
protected ArrayList _filesets = new ArrayList();
protected ArrayList<FileSet> _filesets = new ArrayList<FileSet>();
/** A header to put on all generated source files. */
protected String _header;
@@ -337,5 +338,5 @@ public abstract class InvocationTask extends Task
/** {@link InvocationListener} resolved with the proper classloader so
* that we can compare it to loaded derived classes. */
protected Class _ilistener;
protected Class<?> _ilistener;
}
@@ -3,7 +3,7 @@
* <code>$field</code> set. The set will not change until the event is
* actually propagated through the system.
*/
public void addTo$upfield (DSet.Entry elem)
public void addTo$upfield ($etype elem)
{
requestEntryAdd($capfield, $field, elem);
}
@@ -23,7 +23,7 @@
* <code>$field</code> set. The set will not change until the event is
* actually propagated through the system.
*/
public void update$upfield (DSet.Entry elem)
public void update$upfield ($etype elem)
{
requestEntryUpdate($capfield, $field, elem);
}