Clover coverage report - groovy - 1.0-beta-6
Coverage timestamp: Thu Jul 15 2004 13:18:22 BST
file stats: LOC: 311   Methods: 13
NCLOC: 217   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
DummyClassGenerator.java 0% 0% 0% 0%
coverage
 1   
 /*
 2   
  * $Id: DummyClassGenerator.java,v 1.1 2004/07/10 03:31:39 bran Exp $
 3   
  *
 4   
  * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
 5   
  *
 6   
  * Redistribution and use of this software and associated documentation
 7   
  * ("Software"), with or without modification, are permitted provided that the
 8   
  * following conditions are met: 1. Redistributions of source code must retain
 9   
  * copyright statements and notices. Redistributions must also contain a copy
 10   
  * of this document. 2. Redistributions in binary form must reproduce the above
 11   
  * copyright notice, this list of conditions and the following disclaimer in
 12   
  * the documentation and/or other materials provided with the distribution. 3.
 13   
  * The name "groovy" must not be used to endorse or promote products derived
 14   
  * from this Software without prior written permission of The Codehaus. For
 15   
  * written permission, please contact info@codehaus.org. 4. Products derived
 16   
  * from this Software may not be called "groovy" nor may "groovy" appear in
 17   
  * their names without prior written permission of The Codehaus. "groovy" is a
 18   
  * registered trademark of The Codehaus. 5. Due credit should be given to The
 19   
  * Codehaus - http://groovy.codehaus.org/
 20   
  *
 21   
  * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
 22   
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 23   
  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 24   
  * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
 25   
  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 26   
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 27   
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 28   
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 29   
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 30   
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 31   
  * DAMAGE.
 32   
  *
 33   
  */
 34   
 package org.codehaus.groovy.classgen;
 35   
 
 36   
 import groovy.lang.GroovyRuntimeException;
 37   
 import groovy.lang.MissingClassException;
 38   
 import org.codehaus.groovy.ast.*;
 39   
 import org.objectweb.asm.ClassVisitor;
 40   
 import org.objectweb.asm.CodeVisitor;
 41   
 
 42   
 import java.util.*;
 43   
 
 44   
 /**
 45   
  * To generate a class that has all the fields and methods, except that fields are not initilized
 46   
  * and methods are empty. It's intended for being used as a place holder during code generation
 47   
  * of reference to the "this" class itself.
 48   
  *
 49   
  * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
 50   
  * @author <a href="mailto:b55r@sina.com">Bing Ran</a>
 51   
  *
 52   
  * @version $Revision: 1.1 $
 53   
  */
 54   
 public class DummyClassGenerator extends ClassGenerator {
 55   
 
 56   
     private ClassVisitor cw;
 57   
     private CodeVisitor cv;
 58   
     private GeneratorContext context;
 59   
 
 60   
     private String sourceFile;
 61   
 
 62   
     // current class details
 63   
     private ClassNode classNode;
 64   
     private String internalClassName;
 65   
     private String internalBaseClassName;
 66   
 
 67   
 
 68  0
     public DummyClassGenerator(
 69   
         GeneratorContext context,
 70   
         ClassVisitor classVisitor,
 71   
         ClassLoader classLoader,
 72   
         String sourceFile) {
 73  0
         super(classLoader);
 74  0
         this.context = context;
 75  0
         this.cw = classVisitor;
 76  0
         this.sourceFile = sourceFile;
 77   
     }
 78   
 
 79   
     // GroovyClassVisitor interface
 80   
     //-------------------------------------------------------------------------
 81  0
     public void visitClass(ClassNode classNode) {
 82  0
         try {
 83  0
             this.classNode = classNode;
 84  0
             this.internalClassName = BytecodeHelper.getClassInternalName(classNode.getName());
 85   
 
 86   
             //System.out.println("Generating class: " + classNode.getName());
 87   
 
 88   
             // lets check that the classes are all valid
 89  0
             classNode.setSuperClass(checkValidType(classNode.getSuperClass(), classNode, "Must be a valid base class"));
 90  0
             String[] interfaces = classNode.getInterfaces();
 91  0
             for (int i = 0; i < interfaces.length; i++ ) {
 92  0
                 interfaces[i] = checkValidType(interfaces[i], classNode, "Must be a valid interface name");
 93   
             }
 94   
 
 95  0
             this.internalBaseClassName = BytecodeHelper.getClassInternalName(classNode.getSuperClass());
 96   
 
 97  0
             cw.visit(
 98   
                 classNode.getModifiers(),
 99   
                 internalClassName,
 100   
                 internalBaseClassName,
 101   
                 BytecodeHelper.getClassInternalNames(classNode.getInterfaces()),
 102   
                 sourceFile);
 103   
 
 104  0
             classNode.visitContents(this);
 105   
 
 106  0
             for (Iterator iter = innerClasses.iterator(); iter.hasNext();) {
 107  0
                 ClassNode innerClass = (ClassNode) iter.next();
 108  0
                 String innerClassName = innerClass.getName();
 109  0
                 String innerClassInternalName = BytecodeHelper.getClassInternalName(innerClassName);
 110  0
                 String outerClassName = internalClassName; // default for inner classes
 111  0
                 MethodNode enclosingMethod = innerClass.getEnclosingMethod();
 112  0
                 if (enclosingMethod != null) {
 113   
                     // local inner classes do not specify the outer class name
 114  0
                     outerClassName = null;
 115   
                 }
 116  0
                 cw.visitInnerClass(
 117   
                     innerClassInternalName,
 118   
                     outerClassName,
 119   
                     innerClassName,
 120   
                     innerClass.getModifiers());
 121   
             }
 122  0
             cw.visitEnd();
 123   
         }
 124   
         catch (GroovyRuntimeException e) {
 125  0
             e.setModule(classNode.getModule());
 126  0
             throw e;
 127   
         }
 128   
     }
 129   
 
 130  0
     public void visitConstructor(ConstructorNode node) {
 131   
 
 132  0
         visitParameters(node, node.getParameters());
 133   
 
 134  0
         String methodType = BytecodeHelper.getMethodDescriptor("void", node.getParameters());
 135  0
         cv = cw.visitMethod(node.getModifiers(), "<init>", methodType, null, null);
 136  0
         cv.visitTypeInsn(NEW, "java/lang/RuntimeException");
 137  0
         cv.visitInsn(DUP);
 138  0
         cv.visitLdcInsn("not intended for execution");
 139  0
         cv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
 140  0
         cv.visitInsn(ATHROW);
 141  0
         cv.visitMaxs(0, 0);
 142   
     }
 143   
 
 144  0
     public void visitMethod(MethodNode node) {
 145   
 
 146  0
         visitParameters(node, node.getParameters());
 147  0
         node.setReturnType(checkValidType(node.getReturnType(), node, "Must be a valid return type"));
 148   
 
 149  0
         String methodType = BytecodeHelper.getMethodDescriptor(node.getReturnType(), node.getParameters());
 150  0
         cv = cw.visitMethod(node.getModifiers(), node.getName(), methodType, null, null);
 151   
 
 152  0
         cv.visitTypeInsn(NEW, "java/lang/RuntimeException");
 153  0
         cv.visitInsn(DUP);
 154  0
         cv.visitLdcInsn("not intended for execution");
 155  0
         cv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
 156  0
         cv.visitInsn(ATHROW);
 157   
 
 158  0
         cv.visitMaxs(0, 0);
 159   
     }
 160   
 
 161  0
     public void visitField(FieldNode fieldNode) {
 162   
 
 163   
         // lets check that the classes are all valid
 164  0
         fieldNode.setType(checkValidType(fieldNode.getType(), fieldNode, "Must be a valid field class for field: " + fieldNode.getName()));
 165   
 
 166  0
         cw.visitField(
 167   
             fieldNode.getModifiers(),
 168   
             fieldNode.getName(),
 169   
             BytecodeHelper.getTypeDescription(fieldNode.getType()),
 170   
             null, //fieldValue,  //br  all the sudden that one cannot init the field here. init is done in static initilizer and instace intializer.
 171   
             null);
 172   
     }
 173   
 
 174   
     /**
 175   
      * Creates a getter, setter and field
 176   
      */
 177  0
     public void visitProperty(PropertyNode statement) {
 178   
     }
 179   
 
 180   
 
 181  0
     protected String checkValidType(String type, ASTNode node, String message) {
 182  0
         if (type!= null && type.length() == 0)
 183  0
             return "java.lang.Object";
 184  0
         if (type.endsWith("[]")) {
 185  0
             String postfix = "[]";
 186  0
             String prefix = type.substring(0, type.length() - 2);
 187  0
             return checkValidType(prefix, node, message) + postfix;
 188   
         }
 189  0
         int idx = type.indexOf('$');
 190  0
         if (idx > 0) {
 191  0
             String postfix = type.substring(idx);
 192  0
             String prefix = type.substring(0, idx);
 193  0
             return checkValidType(prefix, node, message) + postfix;
 194   
         }
 195  0
         if (BytecodeHelper.isPrimitiveType(type) || "void".equals(type)) {
 196  0
             return type;
 197   
         }
 198  0
         String original = type;
 199  0
         type = resolveClassName(type);
 200  0
         if (type != null) {
 201  0
             return type;
 202   
         }
 203   
 
 204  0
         throw new MissingClassException(original, node, message + " for class: " + classNode.getName());
 205   
     }
 206  0
     protected String resolveClassName(String type) {
 207  0
         return classNode.resolveClassName(type);
 208   
     }
 209   
 
 210  0
     protected static boolean isPrimitiveFieldType(String type) {
 211  0
         return type.equals("java.lang.String")
 212   
             || type.equals("java.lang.Integer")
 213   
             || type.equals("java.lang.Double")
 214   
             || type.equals("java.lang.Long")
 215   
             || type.equals("java.lang.Float");
 216   
     }
 217  0
     protected Class loadClass(String name) {
 218  0
         if (name.equals(this.classNode.getName())) {
 219  0
             return Object.class;
 220   
         }
 221   
 
 222  0
         if (name == null) {
 223  0
             return null;
 224   
         }
 225  0
         else if (name.length() == 0) {
 226  0
             return Object.class;
 227   
         }
 228   
 
 229  0
         else if ("void".equals(name)) {
 230  0
             return void.class;
 231   
         }
 232  0
         else if ("boolean".equals(name)) {
 233  0
             return boolean.class;
 234   
         }
 235  0
         else if ("byte".equals(name)) {
 236  0
             return byte.class;
 237   
         }
 238  0
         else if ("short".equals(name)) {
 239  0
             return short.class;
 240   
         }
 241  0
         else if ("char".equals(name)) {
 242  0
             return char.class;
 243   
         }
 244  0
         else if ("int".equals(name)) {
 245  0
             return int.class;
 246   
         }
 247  0
         else if ("long".equals(name)) {
 248  0
             return long.class;
 249   
         }
 250  0
         else if ("float".equals(name)) {
 251  0
             return float.class;
 252   
         }
 253  0
         else if ("double".equals(name)) {
 254  0
             return double.class;
 255   
         }
 256   
 
 257  0
         name = BytecodeHelper.formatNameForClassLoading(name);
 258   
 
 259  0
         try {
 260  0
             Class cls = (Class)classCache.get(name);
 261  0
             if (cls != null)
 262  0
                 return cls;
 263   
 
 264  0
             CompileUnit compileUnit = getCompileUnit();
 265  0
             if (compileUnit != null) {
 266  0
                 cls = compileUnit.loadClass(name);
 267  0
                 classCache.put(name, cls);
 268  0
                 return cls;
 269   
             }
 270   
             else {
 271  0
                 throw new ClassGeneratorException("Could not load class: " + name);
 272   
             }
 273   
         }
 274   
         catch (ClassNotFoundException e) {
 275  0
             throw new ClassGeneratorException("Error when compiling class: " + classNode.getName() + ". Reason: could not load class: " + name + " reason: " + e, e);
 276   
         }
 277   
     }
 278   
 
 279   
     Map classCache = new HashMap();
 280   
     {
 281  0
         classCache.put("int", Integer.TYPE);
 282  0
         classCache.put("byte", Byte.TYPE);
 283  0
         classCache.put("short", Short.TYPE);
 284  0
         classCache.put("char", Character.TYPE);
 285  0
         classCache.put("boolean", Boolean.TYPE);
 286  0
         classCache.put("long", Long.TYPE);
 287  0
         classCache.put("double", Double.TYPE);
 288  0
         classCache.put("float", Float.TYPE);
 289   
     }
 290  0
     protected CompileUnit getCompileUnit() {
 291  0
         CompileUnit answer = classNode.getCompileUnit();
 292  0
         if (answer == null) {
 293  0
             answer = context.getCompileUnit();
 294   
         }
 295  0
         return answer;
 296   
     }
 297   
 
 298  0
     protected void visitParameters(ASTNode node, Parameter[] parameters) {
 299  0
         for (int i = 0, size = parameters.length; i < size; i++ ) {
 300  0
             visitParameter(node, parameters[i]);
 301   
         }
 302   
     }
 303   
 
 304  0
     protected void visitParameter(ASTNode node, Parameter parameter) {
 305  0
         if (! parameter.isDynamicType()) {
 306  0
             parameter.setType(checkValidType(parameter.getType(), node, "Must be a valid parameter class"));
 307   
         }
 308   
     }
 309   
 
 310   
 }
 311