From bf501313f15b70ecf0ef706bb9fc5416312927a8 Mon Sep 17 00:00:00 2001 From: Jamie Doornbos Date: Mon, 5 May 2008 22:53:31 +0000 Subject: [PATCH] Narya.abc work - get rid of unused imports in generated service targets: * ServiceMethod import options: - Made argument type imports ignore first N args (0 for old behavior) - Made marshaller listener imports optional * Added InvocationTask._verbose and several dumps of current imports to help track down future superfluous imports * Made the import of ServiceListener method arguments' types optional * Wrapped up most of processService code into protected inner class ServiceDescription and made configurable: - Optional import of the types of the first arguments of the service methods - Optinoal import of the types of listener method arguments * Changed generate methods to take the service class and construct their own local ServiceDescription configured for their target * Removed global import of service class and do it explicitly where required (via method addServiceImport) * Made some imports conditional - InvocationResponseEvent for mashallers only if service has some listeners - InvocationException for providers only if service has some methods with listener arguments * Removed unused variables and imports git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5036 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../presents/tools/GenReceiverTask.java | 5 +- .../presents/tools/GenServiceTask.java | 249 +++++++++++------- .../presents/tools/InvocationTask.java | 26 +- 3 files changed, 177 insertions(+), 103 deletions(-) diff --git a/src/java/com/threerings/presents/tools/GenReceiverTask.java b/src/java/com/threerings/presents/tools/GenReceiverTask.java index d133df309..59ac679ee 100644 --- a/src/java/com/threerings/presents/tools/GenReceiverTask.java +++ b/src/java/com/threerings/presents/tools/GenReceiverTask.java @@ -27,7 +27,6 @@ import java.io.StringWriter; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -84,7 +83,7 @@ public class GenReceiverTask extends InvocationTask !Modifier.isAbstract(m.getModifiers())) { continue; } - methods.add(new ServiceMethod(receiver, m, imports, null)); + methods.add(new ServiceMethod(receiver, m, imports, null, 0, true)); } methods.sort(); @@ -98,7 +97,6 @@ public class GenReceiverTask extends InvocationTask List methods, Iterator 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 @@ -138,7 +136,6 @@ public class GenReceiverTask extends InvocationTask Iterator imports) { String name = StringUtil.replace(rname, "Receiver", ""); - String dname = StringUtil.replace(rname, "Receiver", "Decoder"); // construct our imports list ComparableArrayList implist = new ComparableArrayList(); diff --git a/src/java/com/threerings/presents/tools/GenServiceTask.java b/src/java/com/threerings/presents/tools/GenServiceTask.java index 68e2f0a5a..8742594fa 100644 --- a/src/java/com/threerings/presents/tools/GenServiceTask.java +++ b/src/java/com/threerings/presents/tools/GenServiceTask.java @@ -31,8 +31,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; -import java.util.List; import org.apache.velocity.VelocityContext; @@ -64,7 +62,8 @@ public class GenServiceTask extends InvocationTask public ServiceListener (Class service, Class listener, HashMap imports, - HashMap rawimports) + HashMap rawimports, + boolean importArguments) { this.listener = listener; Method[] methdecls = listener.getDeclaredMethods(); @@ -75,7 +74,17 @@ public class GenServiceTask extends InvocationTask !Modifier.isAbstract(m.getModifiers())) { continue; } - methods.add(new ServiceMethod(service, m, imports, rawimports)); + if (_verbose) { + System.out.println("Adding " + m + ", imports are " + + StringUtil.toString(imports.keySet())); + } + methods.add(new ServiceMethod( + service, m, imports, rawimports, importArguments ? 0 : 999, + true)); + if (_verbose) { + System.out.println("Added " + m + ", imports are " + + StringUtil.toString(imports.keySet())); + } } methods.sort(); } @@ -128,90 +137,54 @@ public class GenServiceTask extends InvocationTask protected void processService (File source, Class service) { System.out.println("Processing " + service.getName() + "..."); - String sname = service.getName(); - String spackage = ""; - int didx = sname.lastIndexOf("."); - if (didx != -1) { - spackage = sname.substring(0, didx); - sname = sname.substring(didx+1); - } - + // verify that the service class name is as we expect it to be - if (!sname.endsWith("Service")) { - System.err.println("Cannot process '" + sname + "':"); + if (!service.getName().endsWith("Service")) { + System.err.println("Cannot process '" + service.getName() + "':"); System.err.println( "Service classes must be named SomethingService."); return; } - HashMap imports = new HashMap(); - HashMap rawimports = new HashMap(); - ComparableArrayList methods = - new ComparableArrayList(); - ComparableArrayList listeners = - new ComparableArrayList(); - - // we need to import the service itself - imports.put(importify(service.getName()), Boolean.TRUE); - rawimports.put(service.getName(), Boolean.TRUE); - - // look through and locate our service methods, also locating any - // custom InvocationListener derivations along the way - Method[] methdecls = service.getDeclaredMethods(); - for (int ii = 0; ii < methdecls.length; ii++) { - Method m = methdecls[ii]; - // service interface methods must be public and abstract - if (!Modifier.isPublic(m.getModifiers()) && - !Modifier.isAbstract(m.getModifiers())) { - continue; - } - // check this method for custom listener declarations - Class[] args = m.getParameterTypes(); - for (int aa = 0; aa < args.length; aa++) { - if (_ilistener.isAssignableFrom(args[aa]) && - GenUtil.simpleName( - args[aa], null).startsWith(sname + ".")) { - checkedAdd(listeners, new ServiceListener( - service, args[aa], imports, rawimports)); - } - } - methods.add(new ServiceMethod(service, m, imports, rawimports)); - } - listeners.sort(); - methods.sort(); - - generateMarshaller(source, sname, spackage, methods, listeners, - imports.keySet(), rawimports.keySet()); - generateDispatcher(source, sname, spackage, methods, - imports.keySet()); - if (!_providerless.contains(sname)) { - generateProvider(source, sname, spackage, methods, listeners, - imports.keySet()); + generateMarshaller(source, service); + generateDispatcher(source, service); + if (!_providerless.contains(service.getSimpleName())) { + generateProvider(source, service); } } - protected void generateMarshaller ( - File source, String sname, String spackage, List methods, - List listeners, Collection imports, - Collection rawimports) + protected void generateMarshaller (File source, Class service) { + if (_verbose) { + System.out.println("Generating marshaller"); + } + + ServiceDescription sdesc = new ServiceDescription(service, true, true); + + // Marshallers always require the service + sdesc.addServiceImport(); + + String sname = sdesc.sname; String name = StringUtil.replace(sname, "Service", ""); String mname = StringUtil.replace(sname, "Service", "Marshaller"); - String mpackage = StringUtil.replace(spackage, ".client", ".data"); + String mpackage = StringUtil.replace( + sdesc.spackage, ".client", ".data"); // construct our imports list ComparableArrayList implist = new ComparableArrayList(); - implist.addAll(imports); + implist.addAll(sdesc.imports.keySet()); checkedAdd(implist, Client.class.getName()); checkedAdd(implist, InvocationMarshaller.class.getName()); - checkedAdd(implist, InvocationResponseEvent.class.getName()); + if (sdesc.listeners.size() > 0) { + checkedAdd(implist, InvocationResponseEvent.class.getName()); + } implist.sort(); VelocityContext ctx = new VelocityContext(); ctx.put("name", name); ctx.put("package", mpackage); - ctx.put("methods", methods); - ctx.put("listeners", listeners); + ctx.put("methods", sdesc.methods); + ctx.put("listeners", sdesc.listeners); ctx.put("imports", implist); // determine the path to our marshaller file @@ -238,7 +211,7 @@ public class GenServiceTask extends InvocationTask // convert the raw imports into ActionScript versions (inner-classes // become Foo_Bar) Collection asimports = new ArrayList(); - for (String impy : rawimports) { + for (String impy : sdesc.rawimports.keySet()) { asimports.add(impy.replace("$", "_")); } @@ -267,10 +240,10 @@ public class GenServiceTask extends InvocationTask // now generate ActionScript versions of our listener marshallers // because those have to be in separate files - for (ServiceListener listener : listeners) { + for (ServiceListener listener : sdesc.listeners) { // recreate our imports with just what we need here implist = new ComparableArrayList(); - implist.addAll(imports); + implist.addAll(sdesc.imports.keySet()); checkedAdd(implist, imlm.getName().replace("$", "_")); String lname = listener.listener.getName(); checkedAdd(implist, lname.replace("$", "_")); @@ -302,11 +275,11 @@ public class GenServiceTask extends InvocationTask checkedAdd(implist, isil.getName().replace("$", "_")); implist.sort(); ctx.put("imports", implist); - ctx.put("package", spackage); + ctx.put("package", sdesc.spackage); try { // make sure our service directory exists - String sppath = spackage.replace('.', File.separatorChar); + String sppath = sdesc.spackage.replace('.', File.separatorChar); new File(_asroot + File.separator + sppath).mkdirs(); // generate an ActionScript version of our service @@ -318,7 +291,7 @@ public class GenServiceTask extends InvocationTask // also generate ActionScript versions of any inner listener // interfaces because those have to be in separate files - for (ServiceListener listener : listeners) { + for (ServiceListener listener : sdesc.listeners) { // recreate our imports with just what we need here implist = new ComparableArrayList(); implist.addAll(asimports); @@ -344,30 +317,40 @@ public class GenServiceTask extends InvocationTask } } - protected void generateDispatcher ( - File source, String sname, String spackage, List methods, - Collection imports) + protected void generateDispatcher (File source, Class service) { - String name = StringUtil.replace(sname, "Service", ""); - String dname = StringUtil.replace(sname, "Service", "Dispatcher"); - String dpackage = StringUtil.replace(spackage, ".client", ".server"); + if (_verbose) { + System.out.println("Generating dispatcher"); + } + + ServiceDescription sdesc = new ServiceDescription(service, false, false); + + // If any listeners are to be used in dispatches, we need to import the service + if (sdesc.listeners.size() > 0) { + sdesc.addServiceImport(); + } + + String name = StringUtil.replace(sdesc.sname, "Service", ""); + String dpackage = StringUtil.replace( + sdesc.spackage, ".client", ".server"); // construct our imports list ComparableArrayList implist = new ComparableArrayList(); - implist.addAll(imports); + implist.addAll(sdesc.imports.keySet()); checkedAdd(implist, ClientObject.class.getName()); checkedAdd(implist, InvocationMarshaller.class.getName()); checkedAdd(implist, InvocationDispatcher.class.getName()); checkedAdd(implist, InvocationException.class.getName()); - String mname = StringUtil.replace(sname, "Service", "Marshaller"); - String mpackage = StringUtil.replace(spackage, ".client", ".data"); + String mname = StringUtil.replace(sdesc.sname, "Service", "Marshaller"); + String mpackage = StringUtil.replace( + sdesc.spackage, ".client", ".data"); checkedAdd(implist, mpackage + "." + mname); implist.sort(); VelocityContext ctx = new VelocityContext(); ctx.put("name", name); ctx.put("package", dpackage); - ctx.put("methods", methods); + ctx.put("methods", sdesc.methods); ctx.put("imports", implist); try { @@ -387,27 +370,33 @@ public class GenServiceTask extends InvocationTask } } - protected void generateProvider ( - File source, String sname, String spackage, List methods, - List listeners, Collection imports) + protected void generateProvider (File source, Class service) { - String name = StringUtil.replace(sname, "Service", ""); - String mname = StringUtil.replace(sname, "Service", "Provider"); - String mpackage = StringUtil.replace(spackage, ".client", ".server"); + if (_verbose) { + System.out.println("Generating provider"); + } + + ServiceDescription sdesc = new ServiceDescription(service, false, false); + + String name = StringUtil.replace(sdesc.sname, "Service", ""); + String mpackage = StringUtil.replace( + sdesc.spackage, ".client", ".server"); // construct our imports list ComparableArrayList implist = new ComparableArrayList(); - implist.addAll(imports); + implist.addAll(sdesc.imports.keySet()); checkedAdd(implist, ClientObject.class.getName()); checkedAdd(implist, InvocationProvider.class.getName()); - checkedAdd(implist, InvocationException.class.getName()); + if (sdesc.hasAnyListenerArgs()) { + checkedAdd(implist, InvocationException.class.getName()); + } implist.sort(); VelocityContext ctx = new VelocityContext(); ctx.put("name", name); ctx.put("package", mpackage); - ctx.put("methods", methods); - ctx.put("listeners", listeners); + ctx.put("methods", sdesc.methods); + ctx.put("listeners", sdesc.listeners); ctx.put("imports", implist); try { @@ -427,6 +416,82 @@ public class GenServiceTask extends InvocationTask } } + // rolls up everything needed for the generate* methods + protected class ServiceDescription + { + ServiceDescription ( + Class service, + boolean importServiceMethodsFirstArgument, + boolean importListenerArguments) + { + this.service = service; + sname = service.getSimpleName(); + spackage = service.getPackage().getName(); + + // look through and locate our service methods, also locating any + // custom InvocationListener derivations along the way + Method[] methdecls = service.getDeclaredMethods(); + for (int ii = 0; ii < methdecls.length; ii++) { + Method m = methdecls[ii]; + // service interface methods must be public and abstract + if (!Modifier.isPublic(m.getModifiers()) && + !Modifier.isAbstract(m.getModifiers())) { + continue; + } + // check this method for custom listener declarations + Class[] args = m.getParameterTypes(); + for (int aa = 0; aa < args.length; aa++) { + if (_ilistener.isAssignableFrom(args[aa]) && + GenUtil.simpleName( + args[aa], null).startsWith(sname + ".")) { + checkedAdd(listeners, new ServiceListener( + service, args[aa], imports, rawimports, + importListenerArguments)); + } + } + if (_verbose) { + System.out.println("Adding " + m + ", imports are " + + StringUtil.toString(imports.keySet())); + } + methods.add(new ServiceMethod(service, m, imports, rawimports, + importServiceMethodsFirstArgument ? 0 : 1, + importListenerArguments)); + if (_verbose) { + System.out.println("Added " + m + ", imports are " + + StringUtil.toString(imports.keySet())); + } + } + listeners.sort(); + methods.sort(); + } + + boolean hasAnyListenerArgs () + { + for (ServiceMethod sm : methods) { + if (!sm.listenerArgs.isEmpty()) { + return true; + } + } + return false; + } + + void addServiceImport () + { + imports.put(importify(service.getName()), Boolean.TRUE); + rawimports.put(service.getName(), Boolean.TRUE); + } + + Class service; + String sname; + String spackage; + HashMap imports = new HashMap(); + HashMap rawimports = new HashMap(); + ComparableArrayList methods = + new ComparableArrayList(); + ComparableArrayList listeners = + new ComparableArrayList(); + } + /** The path to our ActionScript source files. */ protected File _asroot; diff --git a/src/java/com/threerings/presents/tools/InvocationTask.java b/src/java/com/threerings/presents/tools/InvocationTask.java index 58980d177..6e6d2a707 100644 --- a/src/java/com/threerings/presents/tools/InvocationTask.java +++ b/src/java/com/threerings/presents/tools/InvocationTask.java @@ -30,7 +30,6 @@ import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import org.apache.commons.io.FileUtils; @@ -46,7 +45,6 @@ import org.apache.tools.ant.util.ClasspathUtils; import org.apache.velocity.app.VelocityEngine; import com.samskivert.util.ObjectUtil; -import com.samskivert.util.SortableArrayList; import com.samskivert.util.StringUtil; import com.samskivert.velocity.VelocityUtil; @@ -94,7 +92,8 @@ public abstract class InvocationTask extends Task } } - /** Used to keep track of invocation service methods. */ + /** Used to keep track of invocation service methods (or listener + * methods). */ public class ServiceMethod implements Comparable { public Method method; @@ -104,14 +103,16 @@ public abstract class InvocationTask extends Task public ServiceMethod (Class service, Method method, HashMap imports, - HashMap rawimports) + HashMap rawimports, + int ignoreArguments, + boolean importMarshallerListeners) { this.method = method; // we need to look through our arguments and note any needed // imports in the supplied table Class[] args = method.getParameterTypes(); - for (int ii = 0; ii < args.length; ii++) { + for (int ii = ignoreArguments; ii < args.length; ii++) { Class arg = args[ii]; while (arg.isArray()) { arg = arg.getComponentType(); @@ -144,7 +145,8 @@ public abstract class InvocationTask extends Task // InvocationService listeners, we need to import its // marshaller as well String sname = GenUtil.simpleName(arg, null); - if (_ilistener.isAssignableFrom(arg)) { + if (importMarshallerListeners && + _ilistener.isAssignableFrom(arg)) { String mname = arg.getName(); mname = StringUtil.replace(mname, "Service", "Marshaller"); mname = StringUtil.replace(mname, "Listener", "Marshaller"); @@ -265,7 +267,6 @@ public abstract class InvocationTask extends Task { StringBuilder buf = new StringBuilder(); Class[] args = method.getParameterTypes(); - Type[] ptypes = method.getGenericParameterTypes(); for (int ii = (listenerMode ? 0 : 1); ii < args.length; ii++) { if (buf.length() > 0) { buf.append(", "); @@ -327,6 +328,14 @@ public abstract class InvocationTask extends Task } } + /** + * Configures to output extra information when generating code. + */ + public void setVerbose (boolean verbose) + { + _verbose = verbose; + } + /** Configures our classpath which we'll use to load service classes. */ public void setClasspathref (Reference pathref) { @@ -432,6 +441,9 @@ public abstract class InvocationTask extends Task /** A header to put on all generated source files. */ protected String _header; + /** Show extra output if set. */ + protected boolean _verbose; + /** Used to do our own classpath business. */ protected ClassLoader _cloader;