Clover coverage report - groovy - 1.0-beta-6
Coverage timestamp: Thu Jul 15 2004 13:18:22 BST
file stats: LOC: 309   Methods: 25
NCLOC: 199   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
ModuleNode.java 0% 0% 0% 0%
coverage
 1   
 /*
 2   
  $Id: ModuleNode.java,v 1.25 2004/07/10 03:31:38 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
 8   
  that the following conditions are met:
 9   
 
 10   
  1. Redistributions of source code must retain copyright
 11   
     statements and notices.  Redistributions must also contain a
 12   
     copy of this document.
 13   
 
 14   
  2. Redistributions in binary form must reproduce the
 15   
     above copyright notice, this list of conditions and the
 16   
     following disclaimer in the documentation and/or other
 17   
     materials provided with the distribution.
 18   
 
 19   
  3. The name "groovy" must not be used to endorse or promote
 20   
     products derived from this Software without prior written
 21   
     permission of The Codehaus.  For written permission,
 22   
     please contact info@codehaus.org.
 23   
 
 24   
  4. Products derived from this Software may not be called "groovy"
 25   
     nor may "groovy" appear in their names without prior written
 26   
     permission of The Codehaus. "groovy" is a registered
 27   
     trademark of The Codehaus.
 28   
 
 29   
  5. Due credit should be given to The Codehaus -
 30   
     http://groovy.codehaus.org/
 31   
 
 32   
  THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
 33   
  ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
 34   
  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 35   
  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 36   
  THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 37   
  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 38   
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 39   
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 40   
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 41   
  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 42   
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 43   
  OF THE POSSIBILITY OF SUCH DAMAGE.
 44   
 
 45   
  */
 46   
 package org.codehaus.groovy.ast;
 47   
 
 48   
 import groovy.lang.Script;
 49   
 import groovy.lang.Binding;
 50   
 
 51   
 import java.io.File;
 52   
 import java.util.ArrayList;
 53   
 import java.util.HashMap;
 54   
 import java.util.Iterator;
 55   
 import java.util.List;
 56   
 import java.util.Map;
 57   
 
 58   
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 59   
 import org.codehaus.groovy.ast.expr.ClassExpression;
 60   
 import org.codehaus.groovy.ast.expr.Expression;
 61   
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
 62   
 import org.codehaus.groovy.ast.expr.VariableExpression;
 63   
 import org.codehaus.groovy.ast.stmt.BlockStatement;
 64   
 import org.codehaus.groovy.ast.stmt.ExpressionStatement;
 65   
 import org.codehaus.groovy.ast.stmt.Statement;
 66   
 import org.codehaus.groovy.control.SourceUnit;
 67   
 import org.codehaus.groovy.runtime.InvokerHelper;
 68   
 import org.objectweb.asm.Constants;
 69   
 
 70   
 /**
 71   
  * Represents a module, which consists typically of a class declaration
 72   
  * but could include some imports, some statements and multiple classes
 73   
  * intermixed with statements like scripts in Python or Ruby
 74   
  *
 75   
  * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
 76   
  * @version $Revision: 1.25 $
 77   
  */
 78   
 public class ModuleNode extends ASTNode implements Constants {
 79   
 
 80   
     private BlockStatement statementBlock = new BlockStatement();
 81   
     List classes = new ArrayList();
 82   
     private List methods = new ArrayList();
 83   
     private List imports = new ArrayList();
 84   
     private List importPackages = new ArrayList();
 85   
     private Map importIndex = new HashMap();
 86   
     private CompileUnit unit;
 87   
     private String packageName;
 88   
     private String description;
 89   
     private boolean createClassForStatements = true;
 90   
     private SourceUnit context;
 91   
 
 92   
 
 93  0
     public ModuleNode( SourceUnit context ) {
 94  0
         this.context = context;
 95   
     }
 96   
 
 97  0
     public ModuleNode(CompileUnit unit) {
 98  0
         this.unit = unit;
 99   
     }
 100   
 
 101  0
     public BlockStatement getStatementBlock() {
 102  0
         return statementBlock;
 103   
     }
 104   
 
 105  0
     public List getMethods() {
 106  0
         return methods;
 107   
     }
 108   
 
 109  0
     public List getClasses() {
 110  0
         if (createClassForStatements && (!statementBlock.isEmpty() || !methods.isEmpty())) {
 111  0
             ClassNode mainClass = createStatementsClass();
 112  0
             createClassForStatements = false;
 113  0
             classes.add(0, mainClass);
 114  0
             mainClass.setModule(this);
 115  0
             addToCompileUnit(mainClass);
 116   
         }
 117  0
         return classes;
 118   
     }
 119   
 
 120  0
     public List getImports() {
 121  0
         return imports;
 122   
     }
 123   
 
 124  0
     public List getImportPackages() {
 125  0
         return importPackages;
 126   
     }
 127   
 
 128   
     /**
 129   
      * @return the class name for the given alias or null if none is available
 130   
      */
 131  0
     public String getImport(String alias) {
 132  0
         return (String) importIndex.get(alias);
 133   
     }
 134   
 
 135  0
     public void addImport(String alias, String className) {
 136  0
         imports.add(new ImportNode(className, alias));
 137  0
         importIndex.put(alias, className);
 138   
     }
 139   
 
 140  0
     public String[]  addImportPackage(String packageName) {
 141  0
         importPackages.add(packageName);
 142  0
         return new String[] { /* class names, not qualified */ };
 143   
     }
 144   
 
 145  0
     public void addStatement(Statement node) {
 146  0
         statementBlock.addStatement(node);
 147   
     }
 148   
 
 149  0
     public void addClass(ClassNode node) {
 150  0
         classes.add(node);
 151  0
         node.setModule(this);
 152  0
         addToCompileUnit(node);
 153   
     }
 154   
 
 155   
     /**
 156   
      * @param node
 157   
      */
 158  0
     private void addToCompileUnit(ClassNode node) {
 159   
         // register the new class with the compile unit
 160  0
         if (unit != null) {
 161  0
             unit.addClass(node);
 162   
         }
 163   
     }
 164   
 
 165  0
     public void addMethod(MethodNode node) {
 166  0
         methods.add(node);
 167   
     }
 168   
 
 169  0
     public void visit(GroovyCodeVisitor visitor) {
 170   
     }
 171   
 
 172  0
     public String getPackageName() {
 173  0
         return packageName;
 174   
     }
 175   
 
 176  0
     public void setPackageName(String packageName) {
 177  0
         this.packageName = packageName;
 178   
     }
 179   
 
 180  0
     public SourceUnit getContext() {
 181  0
         return context;
 182   
     }
 183   
 
 184   
     /**
 185   
      * @return the underlying character stream description
 186   
      */
 187  0
     public String getDescription() {
 188  0
         if( context != null )
 189   
         {
 190  0
             return context.getName();
 191   
         }
 192   
         else
 193   
         {
 194  0
             return this.description;
 195   
         }
 196   
     }
 197   
 
 198  0
     public void setDescription(String description) {
 199   
         // DEPRECATED -- context.getName() is now sufficient
 200  0
         this.description = description;
 201   
     }
 202   
 
 203  0
     public CompileUnit getUnit() {
 204  0
         return unit;
 205   
     }
 206   
 
 207  0
     void setUnit(CompileUnit unit) {
 208  0
         this.unit = unit;
 209   
     }
 210   
 
 211  0
     protected ClassNode createStatementsClass() {
 212  0
         String name = getPackageName();
 213  0
         if (name == null) {
 214  0
             name = "";
 215   
         }
 216   
         else {
 217  0
             name = name + ".";
 218   
         }
 219   
         // now lets use the file name to determine the class name
 220  0
         if (getDescription() == null) {
 221  0
             throw new RuntimeException("Cannot generate main(String[]) class for statements when we have no file description");
 222   
         }
 223  0
         name += extractClassFromFileDescription();
 224   
 
 225  0
         String baseClass = null;
 226  0
         if (unit != null) {
 227  0
             baseClass = unit.getConfig().getScriptBaseClass();
 228   
         }
 229  0
         if (baseClass == null) {
 230  0
             baseClass = Script.class.getName();
 231   
         }
 232  0
         ClassNode classNode = new ClassNode(name, ACC_PUBLIC, baseClass);
 233  0
         classNode.setScript(true);
 234   
 
 235   
         // return new Foo(new ShellContext(args)).run()
 236  0
         classNode.addMethod(
 237   
             new MethodNode(
 238   
                 "main",
 239   
                 ACC_PUBLIC | ACC_STATIC,
 240   
                 "void",
 241   
                 new Parameter[] { new Parameter("java.lang.String[]", "args")},
 242   
                 new ExpressionStatement(
 243   
                     new MethodCallExpression(
 244   
                         new ClassExpression(InvokerHelper.class.getName()),
 245   
                         "runScript",
 246   
                         new ArgumentListExpression(
 247   
                             new Expression[] {
 248   
                                 new ClassExpression(classNode.getName()),
 249   
                                 new VariableExpression("args")})))));
 250   
 
 251  0
         classNode.addMethod(
 252   
             new MethodNode("run", ACC_PUBLIC, Object.class.getName(), Parameter.EMPTY_ARRAY, statementBlock));
 253   
 
 254  0
         classNode.addConstructor(ACC_PUBLIC, Parameter.EMPTY_ARRAY, new BlockStatement());
 255  0
         Statement stmt = new ExpressionStatement(
 256   
                         new MethodCallExpression(
 257   
                             new VariableExpression("super"),
 258   
                             "setBinding",
 259   
                             new ArgumentListExpression(
 260   
                                     new Expression[] {
 261   
                                         new VariableExpression("context")})));
 262   
 
 263  0
         classNode.addConstructor(
 264   
             ACC_PUBLIC,
 265   
             new Parameter[] { new Parameter(Binding.class.getName(), "context")},
 266   
             stmt);
 267   
 
 268  0
         for (Iterator iter = methods.iterator(); iter.hasNext();) {
 269  0
             MethodNode node = (MethodNode) iter.next();
 270  0
             int modifiers = node.getModifiers();
 271  0
             if ((modifiers & ACC_ABSTRACT) != 0) {
 272  0
                 throw new RuntimeException(
 273   
                     "Cannot use abstract methods in a script, they are only available inside classes. Method: "
 274   
                         + node.getName());
 275   
             }
 276   
             // br: the old logic seems to add static to all def f().... in a script, which makes enclosing
 277   
             // inner classes (including closures) in a def function difficult. Comment it out.
 278  0
             node.setModifiers(modifiers /*| ACC_STATIC*/);
 279   
 
 280  0
             classNode.addMethod(node);
 281   
         }
 282  0
         return classNode;
 283   
     }
 284   
 
 285  0
     protected String extractClassFromFileDescription() {
 286   
         // lets strip off everything after the last .
 287  0
         String answer = getDescription();
 288  0
         int idx = answer.lastIndexOf('.');
 289  0
         if (idx > 0) {
 290  0
             answer = answer.substring(0, idx);
 291   
         }
 292   
         // new lets trip the path separators
 293  0
         idx = answer.lastIndexOf('/');
 294  0
         if (idx >= 0) {
 295  0
             answer = answer.substring(idx + 1);
 296   
         }
 297  0
         idx = answer.lastIndexOf(File.separatorChar);
 298  0
         if (idx >= 0) {
 299  0
             answer = answer.substring(idx + 1);
 300   
         }
 301  0
         return answer;
 302   
     }
 303   
 
 304  0
     public boolean isEmpty() {
 305  0
         return classes.isEmpty() && statementBlock.getStatements().isEmpty();
 306   
     }
 307   
 
 308   
 }
 309