Save This Page
Home » groovy-src-1.6.3 » org.codehaus » groovy » vmplugin » v5 » [javadoc | source]
    1   /*
    2    * Copyright 2003-2007 the original author or authors.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   
   17   package org.codehaus.groovy.vmplugin.v5;
   18   
   19   import java.lang.reflect;
   20   import java.lang.annotation;
   21   import java.util.Iterator;
   22   import java.util.List;
   23   
   24   import org.codehaus.groovy.GroovyBugError;
   25   import org.codehaus.groovy.vmplugin.VMPlugin;
   26   import org.codehaus.groovy.ast;
   27   import org.codehaus.groovy.ast.expr;
   28   import org.codehaus.groovy.ast.stmt.ReturnStatement;
   29   import org.codehaus.groovy.ast.ClassHelper;
   30   
   31   /**
   32    * java 5 based functions
   33    * @author Jochen Theodorou
   34    *
   35    */
   36   public class Java5 implements VMPlugin {
   37       private static Class[] PLUGIN_DGM={PluginDefaultGroovyMethods.class};
   38   
   39       public void setAdditionalClassInformation(ClassNode cn) {
   40           setGenericsTypes(cn);
   41       }
   42   
   43       private void setGenericsTypes(ClassNode cn) {
   44           TypeVariable[] tvs = cn.getTypeClass().getTypeParameters();
   45           GenericsType[] gts = configureTypeVariable(tvs);
   46           cn.setGenericsTypes(gts);
   47       }
   48   
   49       private GenericsType[] configureTypeVariable(TypeVariable[] tvs) {
   50           if (tvs.length==0) return null;
   51           GenericsType[] gts = new GenericsType[tvs.length];
   52           for (int i = 0; i < tvs.length; i++) {
   53               gts[i] = configureTypeVariableDefintion(tvs[i]);
   54           }
   55           return gts;
   56       }
   57   
   58       private GenericsType configureTypeVariableDefintion(TypeVariable tv) {
   59          ClassNode base = configureTypeVariableReference(tv);
   60          ClassNode redirect = base.redirect();
   61          base.setRedirect(null);
   62          Type[] tBounds = tv.getBounds();
   63          GenericsType gt;
   64          if (tBounds.length==0) {
   65              gt = new GenericsType(base);
   66          } else {
   67              ClassNode[] cBounds = configureTypes(tBounds);
   68              gt = new GenericsType(base,cBounds,null);
   69              gt.setName(base.getName());
   70              gt.setPlaceholder(true);
   71          }
   72          base.setRedirect(redirect);
   73          return gt;
   74       }
   75   
   76       private ClassNode[] configureTypes(Type[] types){
   77           if (types.length==0) return null;
   78           ClassNode[] nodes = new ClassNode[types.length];
   79           for (int i=0; i<types.length; i++){
   80               nodes[i] = configureType(types[i]);
   81           }
   82           return nodes;
   83       }
   84   
   85       private ClassNode configureType(Type type) {
   86           if (type instanceof WildcardType) {
   87               return configureWildcardType((WildcardType) type);
   88           } else if (type instanceof ParameterizedType) {
   89               return configureParameterizedType((ParameterizedType) type);
   90           } else if (type instanceof GenericArrayType) {
   91               return configureGenericArray((GenericArrayType) type);
   92           } else if (type instanceof TypeVariable) {
   93               return configureTypeVariableReference((TypeVariable) type);
   94           } else if (type instanceof Class) {
   95               return configureClass((Class) type);
   96           } else {
   97               throw new GroovyBugError("unknown type: " + type + " := " + type.getClass());
   98           }
   99       }
  100   
  101       private ClassNode configureClass(Class c){
  102           if (c.isPrimitive()) {
  103               return ClassHelper.make(c);
  104           } else {
  105               return ClassHelper.makeWithoutCaching(c, false);
  106           }
  107       }
  108   
  109       private ClassNode configureGenericArray(GenericArrayType genericArrayType) {
  110           Type component = genericArrayType.getGenericComponentType();
  111           ClassNode node = configureType(component);
  112           return node.makeArray();
  113       }
  114   
  115       private ClassNode configureWildcardType(WildcardType wildcardType) {
  116           ClassNode base = ClassHelper.makeWithoutCaching("?");
  117           //TODO: more than one lower bound for wildcards?
  118           ClassNode[] lowers = configureTypes(wildcardType.getLowerBounds());
  119           ClassNode lower=null;
  120           if (lower!=null) lower = lowers[0];
  121   
  122           ClassNode[] upper = configureTypes(wildcardType.getUpperBounds());
  123           GenericsType t = new GenericsType(base,upper,lower);
  124           t.setWildcard(true);
  125   
  126           ClassNode ref = ClassHelper.makeWithoutCaching(Object.class,false);
  127           ref.setGenericsTypes(new GenericsType[]{t});
  128   
  129           return ref;
  130       }
  131   
  132       private ClassNode configureParameterizedType(ParameterizedType parameterizedType) {
  133           ClassNode base = configureType(parameterizedType.getRawType());
  134           GenericsType[] gts = configureTypeArguments(parameterizedType.getActualTypeArguments());
  135           base.setGenericsTypes(gts);
  136           return base;
  137       }
  138   
  139       private ClassNode configureTypeVariableReference(TypeVariable tv) {
  140           ClassNode cn = ClassHelper.makeWithoutCaching(tv.getName());
  141           cn.setGenericsPlaceHolder(true);
  142           ClassNode cn2 = ClassHelper.makeWithoutCaching(tv.getName());
  143           GenericsType[] gts = new GenericsType[]{new GenericsType(cn2)};
  144           cn.setGenericsTypes(gts);
  145           cn.setRedirect(ClassHelper.OBJECT_TYPE);
  146           return cn;
  147       }
  148   
  149       private GenericsType[] configureTypeArguments(Type[] ta) {
  150           if (ta.length==0) return null;
  151           GenericsType[] gts = new GenericsType[ta.length];
  152           for (int i = 0; i < ta.length; i++) {
  153               gts[i] = new GenericsType(configureType(ta[i]));
  154           }
  155           return gts;
  156       }
  157   
  158       public Class[] getPluginDefaultGroovyMethods() {
  159           return PLUGIN_DGM;
  160       }
  161   
  162       private void setAnnotationMetaData(ClassNode cn) {
  163           Annotation[] annotations =  cn.getTypeClass().getAnnotations();
  164           for (int i=0; i<annotations.length; i++) {
  165               Annotation annotation = annotations[i];
  166               AnnotationNode node = new AnnotationNode(ClassHelper.make(annotation.annotationType()));
  167               configureAnnotation(node,annotation);
  168               cn.addAnnotation(node);
  169           }
  170       }
  171   
  172       private void configureAnnotationFromDefinition(AnnotationNode definition, AnnotationNode root) {
  173           ClassNode type = definition.getClassNode();
  174           if (!type.isResolved()) return;
  175           Class clazz = type.getTypeClass();
  176           if (clazz==Retention.class) {
  177               Expression exp = definition.getMember("value");
  178               if (!(exp instanceof PropertyExpression)) return;
  179               PropertyExpression pe = (PropertyExpression) exp;
  180               String name = pe.getPropertyAsString();
  181               RetentionPolicy policy = RetentionPolicy.valueOf(name);
  182               setRetentionPolicy(policy,root);
  183           } else if (clazz==Target.class) {
  184               Expression exp = definition.getMember("value");
  185               if (!(exp instanceof ListExpression)) return;
  186               ListExpression le = (ListExpression) exp;
  187               int bitmap = 0;
  188               for (Iterator it=le.getExpressions().iterator(); it.hasNext();) {
  189                   PropertyExpression element = (PropertyExpression) it.next();
  190                   String name = element.getPropertyAsString();
  191                   ElementType value = ElementType.valueOf(name);
  192                   bitmap |= getElementCode(value);
  193               }
  194               root.setAllowedTargets(bitmap);
  195           }
  196       }
  197   
  198       public void configureAnnotation(AnnotationNode node) {
  199           ClassNode type = node.getClassNode();
  200           List annotations = type.getAnnotations();
  201           for (Iterator it=annotations.iterator(); it.hasNext();) {
  202               AnnotationNode an = (AnnotationNode) it.next();
  203               configureAnnotationFromDefinition(an,node);
  204           }
  205   
  206           configureAnnotationFromDefinition(node,node);
  207       }
  208   
  209       private void configureAnnotation(AnnotationNode node, Annotation annotation) {
  210           Class type = annotation.annotationType();
  211           if (type == Retention.class) {
  212               Retention r = (Retention) annotation;
  213               RetentionPolicy value = r.value();
  214               setRetentionPolicy(value,node);
  215               node.setMember("value",new PropertyExpression(
  216                       new ClassExpression(ClassHelper.makeWithoutCaching(RetentionPolicy.class,false)),
  217                       value.toString()));
  218           } else if (type == Target.class) {
  219               Target t = (Target) annotation;
  220               ElementType[] elements = t.value();
  221               int bitmap = 0;
  222               for (int i=0; i<elements.length; i++) {
  223                   bitmap |= getElementCode(elements[i]);
  224               }
  225               node.setAllowedTargets(bitmap);
  226           }
  227       }
  228   
  229       private void setRetentionPolicy(RetentionPolicy value,  AnnotationNode node) {
  230           switch (value) {
  231             case RUNTIME: node.setRuntimeRetention(true); break;
  232             case SOURCE:  node.setSourceRetention(true); break;
  233             case CLASS:   node.setClassRetention(true); break;
  234             default: throw new GroovyBugError("unsupported Retention "+value);
  235           }
  236       }
  237   
  238       private int getElementCode(ElementType value) {
  239           switch (value) {
  240               case TYPE:            return AnnotationNode.TYPE_TARGET;
  241               case CONSTRUCTOR:     return AnnotationNode.CONSTRUCTOR_TARGET;
  242               case METHOD:          return AnnotationNode.METHOD_TARGET;
  243               case FIELD:           return AnnotationNode.FIELD_TARGET;
  244               case PARAMETER:       return AnnotationNode.PARAMETER_TARGET;
  245               case LOCAL_VARIABLE:  return AnnotationNode.LOCAL_VARIABLE_TARGET;
  246               case ANNOTATION_TYPE: return AnnotationNode.ANNOTATION_TARGET;
  247               case PACKAGE:         return AnnotationNode.PACKAGE_TARGET;
  248               default: throw new GroovyBugError("unsupported Target " + value);
  249           }
  250       }
  251   
  252       private void setMethodDefaultValue(MethodNode mn, Method m) {
  253           Object defaultValue = m.getDefaultValue();
  254           mn.setCode(new ReturnStatement(new ConstantExpression(defaultValue)));
  255           mn.setAnnotationDefault(true);
  256       }
  257   
  258       public void configureClassNode(CompileUnit compileUnit, ClassNode classNode) {
  259           Class clazz = classNode.getTypeClass();
  260           Field[] fields = clazz.getDeclaredFields();
  261           for (int i = 0; i < fields.length; i++) {
  262               Field f = fields[i];
  263               ClassNode ret = makeClassNode(compileUnit,f.getGenericType(),f.getType());
  264               classNode.addField(fields[i].getName(), fields[i].getModifiers(), ret, null);
  265           }
  266           Method[] methods = clazz.getDeclaredMethods();
  267           for (int i = 0; i < methods.length; i++) {
  268               Method m = methods[i];
  269               ClassNode ret = makeClassNode(compileUnit,m.getGenericReturnType(),m.getReturnType());
  270               Parameter[] params = makeParameters(compileUnit,m.getGenericParameterTypes(),m.getParameterTypes());
  271               ClassNode[] exceptions = makeClassNodes(compileUnit,m.getGenericExceptionTypes(),m.getExceptionTypes());
  272               MethodNode mn = new MethodNode(m.getName(), m.getModifiers(), ret, params, exceptions, null);
  273               setMethodDefaultValue(mn,m);
  274               classNode.addMethod(mn);
  275           }
  276           Constructor[] constructors = clazz.getDeclaredConstructors();
  277           for (int i = 0; i < constructors.length; i++) {
  278               Constructor ctor = constructors[i];
  279               Parameter[] params = makeParameters(compileUnit,ctor.getGenericParameterTypes(), ctor.getParameterTypes());
  280               ClassNode[] exceptions = makeClassNodes(compileUnit,ctor.getGenericExceptionTypes(),ctor.getExceptionTypes());
  281               classNode.addConstructor(ctor.getModifiers(), params, exceptions, null);
  282           }
  283   
  284           Class sc = clazz.getSuperclass();
  285           if (sc != null) classNode.setUnresolvedSuperClass(makeClassNode(compileUnit,clazz.getGenericSuperclass(),sc));
  286           makeInterfaceTypes(compileUnit,classNode,clazz);
  287           setAnnotationMetaData(classNode);
  288   
  289       }
  290   
  291       private void makeInterfaceTypes(CompileUnit cu, ClassNode classNode, Class clazz) {
  292           Type[] interfaceTypes = clazz.getGenericInterfaces();
  293           if (interfaceTypes.length==0) {
  294               classNode.setInterfaces(ClassNode.EMPTY_ARRAY);
  295           } else {
  296               Class[] interfaceClasses = clazz.getInterfaces();
  297               ClassNode[] ret = new ClassNode[interfaceTypes.length];
  298               for (int i=0;i<interfaceTypes.length;i++){
  299                   ret[i] = makeClassNode(cu, interfaceTypes[i], interfaceClasses[i]);
  300               }
  301               classNode.setInterfaces(ret);
  302           }
  303       }
  304   
  305       private ClassNode[] makeClassNodes(CompileUnit cu, Type[] types, Class[] cls) {
  306           ClassNode[] nodes = new ClassNode[types.length];
  307           for (int i=0;i<nodes.length;i++) {
  308               nodes[i] = makeClassNode(cu, types[i],cls[i]);
  309           }
  310           return nodes;
  311       }
  312   
  313       private ClassNode makeClassNode(CompileUnit cu, Type t, Class c) {
  314           ClassNode back = null;
  315           if (cu!=null)   back = cu.getClass(c.getName());
  316           if (back==null) back = ClassHelper.make(c);
  317           if (!(t instanceof Class)) {
  318               ClassNode front = configureType(t);
  319               front.setRedirect(back);
  320               return front;
  321           }
  322           return back;
  323       }
  324   
  325       private Parameter[] makeParameters(CompileUnit cu, Type[] types, Class[] cls) {
  326           Parameter[] params = Parameter.EMPTY_ARRAY;
  327           if (types.length>0) {
  328               params = new Parameter[types.length];
  329               for (int i=0;i<params.length;i++) {
  330                   params[i] = makeParameter(cu,types[i],cls[i],i);
  331               }
  332           }
  333           return params;
  334       }
  335   
  336       private Parameter makeParameter(CompileUnit cu, Type type, Class cl,int idx) {
  337           ClassNode cn = makeClassNode(cu,type,cl);
  338           return new Parameter(cn, "param" + idx);
  339       }
  340   }
  341   

Save This Page
Home » groovy-src-1.6.3 » org.codehaus » groovy » vmplugin » v5 » [javadoc | source]