Source Code Cross Referenced for CompilationUnit.java in  » Scripting » groovy-1.0 » org » codehaus » groovy » control » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » groovy 1.0 » org.codehaus.groovy.control 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         $Id: CompilationUnit.java 4661 2007-01-02 16:52:26Z blackdrag $
0003:
0004:
0005:         Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
0006:
0007:
0008:         Redistribution and use of this software and associated documentation
0009:         ("Software"), with or without modification, are permitted provided
0010:         that the following conditions are met:
0011:
0012:         1. Redistributions of source code must retain copyright
0013:            statements and notices.  Redistributions must also contain a
0014:            copy of this document.
0015:
0016:
0017:         2. Redistributions in binary form must reproduce the
0018:            above copyright notice, this list of conditions and the
0019:            following disclaimer in the documentation and/or other
0020:            materials provided with the distribution.
0021:
0022:
0023:         3. The name "groovy" must not be used to endorse or promote
0024:            products derived from this Software without prior written
0025:            permission of The Codehaus.  For written permission,
0026:            please contact info@codehaus.org.
0027:
0028:
0029:         4. Products derived from this Software may not be called "groovy"
0030:            nor may "groovy" appear in their names without prior written
0031:            permission of The Codehaus. "groovy" is a registered
0032:            trademark of The Codehaus.
0033:
0034:
0035:         5. Due credit should be given to The Codehaus -
0036:            http://groovy.codehaus.org/
0037:
0038:
0039:         THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
0040:         ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
0041:         NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
0042:         FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
0043:         THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
0044:         INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0045:         (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
0046:         SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0047:         HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0048:         STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0049:         ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
0050:         OF THE POSSIBILITY OF SUCH DAMAGE.
0051:         */
0052:
0053:        package org.codehaus.groovy.control;
0054:
0055:        import java.io.File;
0056:        import java.io.FileOutputStream;
0057:        import java.io.IOException;
0058:        import java.io.InputStream;
0059:        import java.net.URL;
0060:        import java.security.CodeSource;
0061:        import java.util.*;
0062:
0063:        import org.codehaus.groovy.GroovyBugError;
0064:        import org.codehaus.groovy.ast.ASTNode;
0065:        import org.codehaus.groovy.ast.ClassNode;
0066:        import org.codehaus.groovy.ast.CompileUnit;
0067:        import org.codehaus.groovy.ast.ModuleNode;
0068:        import org.codehaus.groovy.classgen.AsmClassGenerator;
0069:        import org.codehaus.groovy.classgen.ClassCompletionVerifier;
0070:        import org.codehaus.groovy.classgen.ClassGenerator;
0071:        import org.codehaus.groovy.classgen.GeneratorContext;
0072:        import org.codehaus.groovy.classgen.VariableScopeVisitor;
0073:        import org.codehaus.groovy.classgen.Verifier;
0074:        import org.codehaus.groovy.control.io.InputStreamReaderSource;
0075:        import org.codehaus.groovy.control.io.ReaderSource;
0076:        import org.codehaus.groovy.control.messages.ExceptionMessage;
0077:        import org.codehaus.groovy.control.messages.Message;
0078:        import org.codehaus.groovy.control.messages.SimpleMessage;
0079:        import org.codehaus.groovy.syntax.SyntaxException;
0080:        import org.codehaus.groovy.syntax.ClassSource;
0081:        import org.codehaus.groovy.syntax.SourceSummary;
0082:        import org.codehaus.groovy.tools.GroovyClass;
0083:        import org.objectweb.asm.ClassVisitor;
0084:        import org.objectweb.asm.ClassWriter;
0085:
0086:        import groovy.lang.GroovyClassLoader;
0087:        import groovy.lang.GroovyRuntimeException;
0088:
0089:        /**
0090:         * Collects all compilation data as it is generated by the compiler system.
0091:         * Allows additional source units to be added and compilation run again (to
0092:         * affect only the deltas).
0093:         *
0094:         * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
0095:         * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
0096:         * @version $Id: CompilationUnit.java 4661 2007-01-02 16:52:26Z blackdrag $
0097:         */
0098:
0099:        public class CompilationUnit extends ProcessingUnit {
0100:
0101:            //---------------------------------------------------------------------------
0102:            // CONSTRUCTION AND SUCH
0103:
0104:            protected HashMap sources; // The SourceUnits from which this unit is built
0105:            protected Map summariesBySourceName; // Summary of each SourceUnit
0106:            protected Map summariesByPublicClassName; // Summary of each SourceUnit
0107:            protected Map classSourcesByPublicClassName; // Summary of each Class
0108:            protected ArrayList names; // Names for each SourceUnit in sources.
0109:            protected LinkedList queuedSources;
0110:
0111:            protected CompileUnit ast; // The overall AST for this CompilationUnit.
0112:            protected ArrayList generatedClasses; // The classes generated during classgen.
0113:
0114:            protected Verifier verifier; // For use by verify().
0115:
0116:            protected boolean debug; // Controls behaviour of classgen() and other routines.
0117:            protected boolean configured; // Set true after the first configure() operation
0118:
0119:            protected ClassgenCallback classgenCallback; // A callback for use during classgen()
0120:            protected ProgressCallback progressCallback; // A callback for use during compile()
0121:            protected ResolveVisitor resolveVisitor;
0122:
0123:            LinkedList[] phaseOperations;
0124:
0125:            /**
0126:             * Initializes the CompilationUnit with defaults.
0127:             */
0128:            public CompilationUnit() {
0129:                this (null, null, null);
0130:            }
0131:
0132:            /**
0133:             * Initializes the CompilationUnit with defaults except for class loader.
0134:             */
0135:            public CompilationUnit(GroovyClassLoader loader) {
0136:                this (null, null, loader);
0137:            }
0138:
0139:            /**
0140:             * Initializes the CompilationUnit with no security considerations.
0141:             */
0142:            public CompilationUnit(CompilerConfiguration configuration) {
0143:                this (configuration, null, null);
0144:            }
0145:
0146:            /**
0147:             * Initializes the CompilationUnit with a CodeSource for controlling
0148:             * security stuff and a class loader for loading classes.
0149:             */
0150:            public CompilationUnit(CompilerConfiguration configuration,
0151:                    CodeSource security, GroovyClassLoader loader) {
0152:                super (configuration, loader, null);
0153:                this .names = new ArrayList();
0154:                this .queuedSources = new LinkedList();
0155:                this .sources = new HashMap();
0156:                this .summariesBySourceName = new HashMap();
0157:                this .summariesByPublicClassName = new HashMap();
0158:                this .classSourcesByPublicClassName = new HashMap();
0159:
0160:                this .ast = new CompileUnit(this .classLoader, security,
0161:                        this .configuration);
0162:                this .generatedClasses = new ArrayList();
0163:
0164:                this .verifier = new Verifier();
0165:                this .resolveVisitor = new ResolveVisitor(this );
0166:
0167:                phaseOperations = new LinkedList[Phases.ALL + 1];
0168:                for (int i = 0; i < phaseOperations.length; i++) {
0169:                    phaseOperations[i] = new LinkedList();
0170:                }
0171:                addPhaseOperation(new SourceUnitOperation() {
0172:                    public void call(SourceUnit source)
0173:                            throws CompilationFailedException {
0174:                        source.parse();
0175:                    }
0176:                }, Phases.PARSING);
0177:                addPhaseOperation(summarize, Phases.PARSING);
0178:                addPhaseOperation(convert, Phases.CONVERSION);
0179:                addPhaseOperation(resolve, Phases.SEMANTIC_ANALYSIS);
0180:                addPhaseOperation(compileCompleteCheck, Phases.CANONICALIZATION);
0181:                addPhaseOperation(classgen, Phases.CLASS_GENERATION);
0182:                addPhaseOperation(output);
0183:
0184:                this .classgenCallback = null;
0185:            }
0186:
0187:            public void addPhaseOperation(SourceUnitOperation op, int phase) {
0188:                if (phase < 0 || phase > Phases.ALL)
0189:                    throw new IllegalArgumentException("phase " + phase
0190:                            + " is unknown");
0191:                phaseOperations[phase].add(op);
0192:            }
0193:
0194:            public void addPhaseOperation(PrimaryClassNodeOperation op,
0195:                    int phase) {
0196:                if (phase < 0 || phase > Phases.ALL)
0197:                    throw new IllegalArgumentException("phase " + phase
0198:                            + " is unknown");
0199:                phaseOperations[phase].add(op);
0200:            }
0201:
0202:            public void addPhaseOperation(GroovyClassOperation op) {
0203:                phaseOperations[Phases.OUTPUT].addFirst(op);
0204:            }
0205:
0206:            /**
0207:             * Configures its debugging mode and classloader classpath from a given compiler configuration.
0208:             * This cannot be done more than once due to limitations in {@link java.net.URLClassLoader URLClassLoader}.
0209:             */
0210:            public void configure(CompilerConfiguration configuration) {
0211:                super .configure(configuration);
0212:                this .debug = configuration.getDebug();
0213:
0214:                if (!this .configured
0215:                        && this .classLoader instanceof  GroovyClassLoader) {
0216:                    appendCompilerConfigurationClasspathToClassLoader(
0217:                            configuration, (GroovyClassLoader) this .classLoader);
0218:                }
0219:
0220:                this .configured = true;
0221:            }
0222:
0223:            private void appendCompilerConfigurationClasspathToClassLoader(
0224:                    CompilerConfiguration configuration,
0225:                    GroovyClassLoader classLoader) {
0226:                /*for (Iterator iterator = configuration.getClasspath().iterator(); iterator.hasNext(); ) {
0227:                    classLoader.addClasspath((String) iterator.next());
0228:                }*/
0229:            }
0230:
0231:            /**
0232:             * Returns the CompileUnit that roots our AST.
0233:             */
0234:            public CompileUnit getAST() {
0235:                return this .ast;
0236:            }
0237:
0238:            /**
0239:             * Get the source summaries
0240:             */
0241:            public Map getSummariesBySourceName() {
0242:                return summariesBySourceName;
0243:            }
0244:
0245:            public Map getSummariesByPublicClassName() {
0246:                return summariesByPublicClassName;
0247:            }
0248:
0249:            public Map getClassSourcesByPublicClassName() {
0250:                return classSourcesByPublicClassName;
0251:            }
0252:
0253:            public boolean isPublicClass(String className) {
0254:                return summariesByPublicClassName.containsKey(className);
0255:            }
0256:
0257:            /**
0258:             * Get the GroovyClasses generated by compile().
0259:             */
0260:            public List getClasses() {
0261:                return generatedClasses;
0262:            }
0263:
0264:            /**
0265:             * Convenience routine to get the first ClassNode, for
0266:             * when you are sure there is only one.
0267:             */
0268:            public ClassNode getFirstClassNode() {
0269:                return (ClassNode) ((ModuleNode) this .ast.getModules().get(0))
0270:                        .getClasses().get(0);
0271:            }
0272:
0273:            /**
0274:             * Convenience routine to get the named ClassNode.
0275:             */
0276:            public ClassNode getClassNode(final String name) {
0277:                final ClassNode[] result = new ClassNode[] { null };
0278:                PrimaryClassNodeOperation handler = new PrimaryClassNodeOperation() {
0279:                    public void call(SourceUnit source,
0280:                            GeneratorContext context, ClassNode classNode) {
0281:                        if (classNode.getName().equals(name)) {
0282:                            result[0] = classNode;
0283:                        }
0284:                    }
0285:                };
0286:
0287:                try {
0288:                    applyToPrimaryClassNodes(handler);
0289:                } catch (CompilationFailedException e) {
0290:                    if (debug)
0291:                        e.printStackTrace();
0292:                }
0293:                return result[0];
0294:            }
0295:
0296:            //---------------------------------------------------------------------------
0297:            // SOURCE CREATION
0298:
0299:            /**
0300:             * Adds a set of file paths to the unit.
0301:             */
0302:            public void addSources(String[] paths) {
0303:                for (int i = 0; i < paths.length; i++) {
0304:                    File file = new File(paths[i]);
0305:                    addSource(file);
0306:                }
0307:            }
0308:
0309:            /**
0310:             * Adds a set of source files to the unit.
0311:             */
0312:            public void addSources(File[] files) {
0313:                for (int i = 0; i < files.length; i++) {
0314:                    addSource(files[i]);
0315:                }
0316:            }
0317:
0318:            /**
0319:             * Adds a source file to the unit.
0320:             */
0321:            public SourceUnit addSource(File file) {
0322:                return addSource(new SourceUnit(file, configuration,
0323:                        classLoader, getErrorCollector()));
0324:            }
0325:
0326:            /**
0327:             * Adds a source file to the unit.
0328:             */
0329:            public SourceUnit addSource(URL url) {
0330:                return addSource(new SourceUnit(url, configuration,
0331:                        classLoader, getErrorCollector()));
0332:            }
0333:
0334:            /**
0335:             * Adds a InputStream source to the unit.
0336:             */
0337:            public SourceUnit addSource(String name, InputStream stream) {
0338:                ReaderSource source = new InputStreamReaderSource(stream,
0339:                        configuration);
0340:                return addSource(new SourceUnit(name, source, configuration,
0341:                        classLoader, getErrorCollector()));
0342:            }
0343:
0344:            /**
0345:             * Adds a SourceUnit to the unit.
0346:             */
0347:            public SourceUnit addSource(SourceUnit source) {
0348:                String name = source.getName();
0349:                source.setClassLoader(this .classLoader);
0350:                for (Iterator iter = queuedSources.iterator(); iter.hasNext();) {
0351:                    SourceUnit su = (SourceUnit) iter.next();
0352:                    if (name.equals(su.getName()))
0353:                        return su;
0354:                }
0355:                queuedSources.add(source);
0356:                return source;
0357:            }
0358:
0359:            /**
0360:             * Returns an iterator on the unit's SourceUnits.
0361:             */
0362:            public Iterator iterator() {
0363:                return new Iterator() {
0364:                    Iterator nameIterator = names.iterator();
0365:
0366:                    public boolean hasNext() {
0367:                        return nameIterator.hasNext();
0368:                    }
0369:
0370:                    public Object next() {
0371:                        String name = (String) nameIterator.next();
0372:                        return sources.get(name);
0373:                    }
0374:
0375:                    public void remove() {
0376:                        throw new UnsupportedOperationException();
0377:                    }
0378:                };
0379:            }
0380:
0381:            /**
0382:             * Adds a ClassNode directly to the unit (ie. without source).
0383:             * WARNING: the source is needed for error reporting, using
0384:             *          this method without setting a SourceUnit will cause
0385:             *          NullPinterExceptions
0386:             */
0387:            public void addClassNode(ClassNode node) {
0388:                ModuleNode module = new ModuleNode(this .ast);
0389:                this .ast.addModule(module);
0390:                module.addClass(node);
0391:            }
0392:
0393:            //---------------------------------------------------------------------------
0394:            // EXTERNAL CALLBACKS
0395:
0396:            /**
0397:             * A callback interface you can use to "accompany" the classgen()
0398:             * code as it traverses the ClassNode tree.  You will be called-back
0399:             * for each primary and inner class.  Use setClassgenCallback() before
0400:             * running compile() to set your callback.
0401:             */
0402:            public static abstract class ClassgenCallback {
0403:                public abstract void call(ClassVisitor writer, ClassNode node)
0404:                        throws CompilationFailedException;
0405:            }
0406:
0407:            /**
0408:             * Sets a ClassgenCallback.  You can have only one, and setting
0409:             * it to null removes any existing setting.
0410:             */
0411:            public void setClassgenCallback(ClassgenCallback visitor) {
0412:                this .classgenCallback = visitor;
0413:            }
0414:
0415:            /**
0416:             * A callback interface you can use to get a callback after every
0417:             * unit of the compile process.  You will be called-back with a
0418:             * ProcessingUnit and a phase indicator.  Use setProgressCallback()
0419:             * before running compile() to set your callback.
0420:             */
0421:            public static abstract class ProgressCallback {
0422:
0423:                public abstract void call(ProcessingUnit context, int phase)
0424:                        throws CompilationFailedException;
0425:            }
0426:
0427:            /**
0428:             * Sets a ProgressCallback.  You can have only one, and setting
0429:             * it to null removes any existing setting.
0430:             */
0431:            public void setProgressCallback(ProgressCallback callback) {
0432:                this .progressCallback = callback;
0433:            }
0434:
0435:            //---------------------------------------------------------------------------
0436:            // ACTIONS
0437:
0438:            /**
0439:             * Synonym for compile(Phases.ALL).
0440:             */
0441:            public void compile() throws CompilationFailedException {
0442:                compile(Phases.ALL);
0443:            }
0444:
0445:            /**
0446:             * Compiles the compilation unit from sources.
0447:             */
0448:            public void compile(int throughPhase)
0449:                    throws CompilationFailedException {
0450:                //
0451:                // To support delta compilations, we always restart
0452:                // the compiler.  The individual passes are responsible
0453:                // for not reprocessing old code.
0454:                gotoPhase(Phases.INITIALIZATION);
0455:                throughPhase = Math.min(throughPhase, Phases.ALL);
0456:
0457:                while (throughPhase >= phase && phase <= Phases.ALL) {
0458:
0459:                    for (Iterator it = phaseOperations[phase].iterator(); it
0460:                            .hasNext();) {
0461:                        Object operation = it.next();
0462:                        if (operation instanceof  PrimaryClassNodeOperation) {
0463:                            applyToPrimaryClassNodes((PrimaryClassNodeOperation) operation);
0464:                        } else if (operation instanceof  SourceUnitOperation) {
0465:                            applyToSourceUnits((SourceUnitOperation) operation);
0466:                        } else {
0467:                            applyToGeneratedGroovyClasses((GroovyClassOperation) operation);
0468:                        }
0469:                    }
0470:
0471:                    if (dequeued())
0472:                        continue;
0473:
0474:                    if (progressCallback != null)
0475:                        progressCallback.call(this , phase);
0476:                    completePhase();
0477:                    applyToSourceUnits(mark);
0478:
0479:                    gotoPhase(phase + 1);
0480:
0481:                    if (phase == Phases.CLASS_GENERATION) {
0482:                        sortClasses();
0483:                    }
0484:                }
0485:
0486:                errorCollector.failIfErrors();
0487:            }
0488:
0489:            private void sortClasses() throws CompilationFailedException {
0490:                Iterator modules = this .ast.getModules().iterator();
0491:                while (modules.hasNext()) {
0492:                    ModuleNode module = (ModuleNode) modules.next();
0493:
0494:                    // before we actually do the sorting we should check
0495:                    // for cyclic references
0496:                    List classes = module.getClasses();
0497:                    for (Iterator iter = classes.iterator(); iter.hasNext();) {
0498:                        ClassNode start = (ClassNode) iter.next();
0499:                        ClassNode cn = start;
0500:                        HashSet parents = new HashSet();
0501:                        do {
0502:                            if (parents.contains(cn.getName())) {
0503:                                getErrorCollector()
0504:                                        .addErrorAndContinue(
0505:                                                new SimpleMessage(
0506:                                                        "cyclic inheritance involving "
0507:                                                                + cn.getName()
0508:                                                                + " in class "
0509:                                                                + start
0510:                                                                        .getName(),
0511:                                                        this ));
0512:                                cn = null;
0513:                            } else {
0514:                                parents.add(cn.getName());
0515:                                cn = cn.getSuperClass();
0516:                            }
0517:                        } while (cn != null);
0518:                    }
0519:                    errorCollector.failIfErrors();
0520:                    module.sortClasses();
0521:
0522:                }
0523:            }
0524:
0525:            /**
0526:             * Dequeues any source units add through addSource and resets the compiler phase
0527:             * to initialization. 
0528:             * 
0529:             * Note: this does not mean a file is recompiled. If a SoucreUnit has already passed
0530:             * a phase it is skipped until a higher phase is reached. 
0531:             * @return TODO
0532:             * 
0533:             * @throws CompilationFailedException
0534:             */
0535:            protected boolean dequeued() throws CompilationFailedException {
0536:                boolean dequeue = !queuedSources.isEmpty();
0537:                while (!queuedSources.isEmpty()) {
0538:                    SourceUnit su = (SourceUnit) queuedSources.removeFirst();
0539:                    String name = su.getName();
0540:                    names.add(name);
0541:                    sources.put(name, su);
0542:                }
0543:                if (dequeue) {
0544:                    gotoPhase(Phases.INITIALIZATION);
0545:                }
0546:                return dequeue;
0547:            }
0548:
0549:            /**
0550:             * Adds summary of each class to maps
0551:             */
0552:            private SourceUnitOperation summarize = new SourceUnitOperation() {
0553:                public void call(SourceUnit source)
0554:                        throws CompilationFailedException {
0555:                    SourceSummary sourceSummary = source.getSourceSummary();
0556:                    if (sourceSummary != null) {
0557:                        summariesBySourceName.put(source.getName(),
0558:                                sourceSummary);
0559:                        List publicClassSources = sourceSummary
0560:                                .getPublicClassSources();
0561:                        if (publicClassSources == null
0562:                                || publicClassSources.size() == 0) {
0563:                            //todo - is this the best way to handle scripts?
0564:                            summariesByPublicClassName.put("*NoName*",
0565:                                    sourceSummary);
0566:                            // nothing to put into classSourcesByClassName as no ClassSource
0567:                        } else {
0568:                            Iterator itr = publicClassSources.iterator();
0569:                            while (itr.hasNext()) {
0570:                                ClassSource classSource = (ClassSource) itr
0571:                                        .next();
0572:                                summariesByPublicClassName.put(classSource
0573:                                        .getName(), sourceSummary);
0574:                                classSourcesByPublicClassName.put(classSource
0575:                                        .getName(), classSource);
0576:                            }
0577:                        }
0578:                    }
0579:                }
0580:            };
0581:
0582:            /**
0583:             * Resolves all types
0584:             */
0585:            private SourceUnitOperation resolve = new SourceUnitOperation() {
0586:                public void call(SourceUnit source)
0587:                        throws CompilationFailedException {
0588:                    List classes = source.ast.getClasses();
0589:                    for (Iterator it = classes.iterator(); it.hasNext();) {
0590:                        ClassNode node = (ClassNode) it.next();
0591:
0592:                        VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(
0593:                                source);
0594:                        scopeVisitor.visitClass(node);
0595:
0596:                        resolveVisitor.startResolving(node, source);
0597:                    }
0598:
0599:                }
0600:            };
0601:
0602:            /**
0603:             * Runs convert() on a single SourceUnit.
0604:             */
0605:            private SourceUnitOperation convert = new SourceUnitOperation() {
0606:                public void call(SourceUnit source)
0607:                        throws CompilationFailedException {
0608:                    source.convert();
0609:                    CompilationUnit.this .ast.addModule(source.getAST());
0610:
0611:                    if (CompilationUnit.this .progressCallback != null) {
0612:                        CompilationUnit.this .progressCallback.call(source,
0613:                                CompilationUnit.this .phase);
0614:                    }
0615:                }
0616:            };
0617:
0618:            private GroovyClassOperation output = new GroovyClassOperation() {
0619:                public void call(GroovyClass gclass)
0620:                        throws CompilationFailedException {
0621:                    boolean failures = false;
0622:                    String name = gclass.getName().replace('.',
0623:                            File.separatorChar)
0624:                            + ".class";
0625:                    File path = new File(configuration.getTargetDirectory(),
0626:                            name);
0627:
0628:                    //
0629:                    // Ensure the path is ready for the file
0630:                    //
0631:                    File directory = path.getParentFile();
0632:                    if (directory != null && !directory.exists()) {
0633:                        directory.mkdirs();
0634:                    }
0635:
0636:                    //
0637:                    // Create the file and write out the data
0638:                    //
0639:                    byte[] bytes = gclass.getBytes();
0640:
0641:                    FileOutputStream stream = null;
0642:                    try {
0643:                        stream = new FileOutputStream(path);
0644:                        stream.write(bytes, 0, bytes.length);
0645:                    } catch (IOException e) {
0646:                        getErrorCollector().addError(
0647:                                Message.create(e.getMessage(),
0648:                                        CompilationUnit.this ));
0649:                        failures = true;
0650:                    } finally {
0651:                        if (stream != null) {
0652:                            try {
0653:                                stream.close();
0654:                            } catch (Exception e) {
0655:                            }
0656:                        }
0657:                    }
0658:                }
0659:            };
0660:
0661:            /* checks if all needed classes are compiled before generating the bytecode */
0662:            private SourceUnitOperation compileCompleteCheck = new SourceUnitOperation() {
0663:                public void call(SourceUnit source)
0664:                        throws CompilationFailedException {
0665:                    List classes = source.ast.getClasses();
0666:                    for (Iterator it = classes.iterator(); it.hasNext();) {
0667:                        ClassNode node = (ClassNode) it.next();
0668:                        CompileUnit cu = node.getCompileUnit();
0669:                        for (Iterator iter = cu.iterateClassNodeToCompile(); iter
0670:                                .hasNext();) {
0671:                            String name = (String) iter.next();
0672:                            SourceUnit su = ast.getScriptSourceLocation(name);
0673:                            List classesInSourceUnit = su.ast.getClasses();
0674:                            StringBuffer message = new StringBuffer();
0675:                            message
0676:                                    .append(
0677:                                            "Compilation incomplete: expected to find the class ")
0678:                                    .append(name).append(" in ").append(
0679:                                            su.getName());
0680:                            if (classesInSourceUnit.size() == 0) {
0681:                                message
0682:                                        .append(", but the file seems not to contain any classes");
0683:                            } else {
0684:                                message
0685:                                        .append(", but the file contains the classes: ");
0686:                                boolean first = true;
0687:                                for (Iterator suClassesIter = classesInSourceUnit
0688:                                        .iterator(); suClassesIter.hasNext();) {
0689:                                    ClassNode cn = (ClassNode) suClassesIter
0690:                                            .next();
0691:                                    if (!first) {
0692:                                        message.append(", ");
0693:                                    } else {
0694:                                        first = false;
0695:                                    }
0696:                                    message.append(cn.getName());
0697:                                }
0698:                            }
0699:
0700:                            getErrorCollector().addErrorAndContinue(
0701:                                    new SimpleMessage(message.toString(),
0702:                                            CompilationUnit.this ));
0703:                            iter.remove();
0704:                        }
0705:                    }
0706:                }
0707:            };
0708:
0709:            /**
0710:             * Runs classgen() on a single ClassNode.
0711:             */
0712:            private PrimaryClassNodeOperation classgen = new PrimaryClassNodeOperation() {
0713:                public boolean needSortedInput() {
0714:                    return true;
0715:                }
0716:
0717:                public void call(SourceUnit source, GeneratorContext context,
0718:                        ClassNode classNode) throws CompilationFailedException {
0719:
0720:                    //
0721:                    // Run the Verifier on the outer class
0722:                    //
0723:                    try {
0724:                        verifier.visitClass(classNode);
0725:                    } catch (GroovyRuntimeException rpe) {
0726:                        ASTNode node = rpe.getNode();
0727:                        getErrorCollector().addError(
0728:                                new SyntaxException(rpe.getMessage(), null,
0729:                                        node.getLineNumber(), node
0730:                                                .getColumnNumber()), source);
0731:                    }
0732:
0733:                    LabelVerifier lv = new LabelVerifier(source);
0734:                    lv.visitClass(classNode);
0735:
0736:                    ClassCompletionVerifier completionVerifier = new ClassCompletionVerifier(
0737:                            source);
0738:                    completionVerifier.visitClass(classNode);
0739:
0740:                    // because the class may be generated even if a error was found
0741:                    // and that class may have an invalid format we fail here if needed
0742:                    getErrorCollector().failIfErrors();
0743:
0744:                    //
0745:                    // Prep the generator machinery
0746:                    //
0747:                    ClassVisitor visitor = createClassVisitor();
0748:
0749:                    String sourceName = (source == null ? classNode.getModule()
0750:                            .getDescription() : source.getName());
0751:                    // only show the file name and its extension like javac does in its stacktraces rather than the full path
0752:                    // also takes care of both \ and / depending on the host compiling environment
0753:                    if (sourceName != null)
0754:                        sourceName = sourceName.substring(Math
0755:                                .max(sourceName.lastIndexOf('\\'), sourceName
0756:                                        .lastIndexOf('/')) + 1);
0757:                    ClassGenerator generator = new AsmClassGenerator(context,
0758:                            visitor, classLoader, sourceName);
0759:
0760:                    //
0761:                    // Run the generation and create the class (if required)
0762:                    //
0763:                    generator.visitClass(classNode);
0764:
0765:                    byte[] bytes = ((ClassWriter) visitor).toByteArray();
0766:                    generatedClasses.add(new GroovyClass(classNode.getName(),
0767:                            bytes));
0768:
0769:                    //
0770:                    // Handle any callback that's been set
0771:                    //
0772:                    if (CompilationUnit.this .classgenCallback != null) {
0773:                        classgenCallback.call(visitor, classNode);
0774:                    }
0775:
0776:                    //
0777:                    // Recurse for inner classes
0778:                    //
0779:                    LinkedList innerClasses = generator.getInnerClasses();
0780:                    while (!innerClasses.isEmpty()) {
0781:                        classgen.call(source, context, (ClassNode) innerClasses
0782:                                .removeFirst());
0783:                    }
0784:                }
0785:            };
0786:
0787:            protected ClassVisitor createClassVisitor() {
0788:                return new ClassWriter(true);
0789:            }
0790:
0791:            //---------------------------------------------------------------------------
0792:            // PHASE HANDLING
0793:
0794:            /**
0795:             * Updates the phase marker on all sources.
0796:             */
0797:            protected void mark() throws CompilationFailedException {
0798:                applyToSourceUnits(mark);
0799:            }
0800:
0801:            /**
0802:             * Marks a single SourceUnit with the current phase,
0803:             * if it isn't already there yet.
0804:             */
0805:            private SourceUnitOperation mark = new SourceUnitOperation() {
0806:                public void call(SourceUnit source)
0807:                        throws CompilationFailedException {
0808:                    if (source.phase < phase) {
0809:                        source.gotoPhase(phase);
0810:                    }
0811:
0812:                    if (source.phase == phase && phaseComplete
0813:                            && !source.phaseComplete) {
0814:                        source.completePhase();
0815:                    }
0816:                }
0817:            };
0818:
0819:            //---------------------------------------------------------------------------
0820:            // LOOP SIMPLIFICATION FOR SourceUnit OPERATIONS
0821:
0822:            /**
0823:             * An callback interface for use in the applyToSourceUnits loop driver.
0824:             */
0825:            public static abstract class SourceUnitOperation {
0826:                public abstract void call(SourceUnit source)
0827:                        throws CompilationFailedException;
0828:            }
0829:
0830:            /**
0831:             * A loop driver for applying operations to all SourceUnits.
0832:             * Automatically skips units that have already been processed
0833:             * through the current phase.
0834:             */
0835:            public void applyToSourceUnits(SourceUnitOperation body)
0836:                    throws CompilationFailedException {
0837:                Iterator keys = names.iterator();
0838:                while (keys.hasNext()) {
0839:                    String name = (String) keys.next();
0840:                    SourceUnit source = (SourceUnit) sources.get(name);
0841:                    if ((source.phase < phase)
0842:                            || (source.phase == phase && !source.phaseComplete)) {
0843:                        try {
0844:                            body.call(source);
0845:                        } catch (CompilationFailedException e) {
0846:                            throw e;
0847:                        } catch (Exception e) {
0848:                            GroovyBugError gbe = new GroovyBugError(e);
0849:                            changeBugText(gbe, source);
0850:                            throw gbe;
0851:                        } catch (GroovyBugError e) {
0852:                            changeBugText(e, source);
0853:                            throw e;
0854:                        }
0855:                    }
0856:                }
0857:
0858:                getErrorCollector().failIfErrors();
0859:            }
0860:
0861:            //---------------------------------------------------------------------------
0862:            // LOOP SIMPLIFICATION FOR PRIMARY ClassNode OPERATIONS
0863:
0864:            /**
0865:             * An callback interface for use in the applyToSourceUnits loop driver.
0866:             */
0867:            public static abstract class PrimaryClassNodeOperation {
0868:                public abstract void call(SourceUnit source,
0869:                        GeneratorContext context, ClassNode classNode)
0870:                        throws CompilationFailedException;
0871:
0872:                public boolean needSortedInput() {
0873:                    return false;
0874:                }
0875:            }
0876:
0877:            public static abstract class GroovyClassOperation {
0878:                public abstract void call(GroovyClass gclass)
0879:                        throws CompilationFailedException;
0880:            }
0881:
0882:            private List getPrimaryClassNodes(boolean sort) {
0883:                ArrayList unsorted = new ArrayList();
0884:                Iterator modules = this .ast.getModules().iterator();
0885:                while (modules.hasNext()) {
0886:                    ModuleNode module = (ModuleNode) modules.next();
0887:
0888:                    Iterator classNodes = module.getClasses().iterator();
0889:                    while (classNodes.hasNext()) {
0890:                        ClassNode classNode = (ClassNode) classNodes.next();
0891:                        unsorted.add(classNode);
0892:                    }
0893:                }
0894:
0895:                if (sort == false)
0896:                    return unsorted;
0897:
0898:                int[] indexClass = new int[unsorted.size()];
0899:                int[] indexInterface = new int[unsorted.size()];
0900:                {
0901:                    int i = 0;
0902:                    for (Iterator iter = unsorted.iterator(); iter.hasNext(); i++) {
0903:                        ClassNode node = (ClassNode) iter.next();
0904:                        int count = 0;
0905:                        ClassNode element = node;
0906:                        while (element != null) {
0907:                            count++;
0908:                            element = element.getSuperClass();
0909:                        }
0910:                        if (node.isInterface()) {
0911:                            indexInterface[i] = count;
0912:                            indexClass[i] = -1;
0913:                        } else {
0914:                            indexClass[i] = count;
0915:                            indexInterface[i] = -1;
0916:                        }
0917:                    }
0918:                }
0919:
0920:                List sorted = getSorted(indexInterface, unsorted);
0921:                sorted.addAll(getSorted(indexClass, unsorted));
0922:
0923:                return sorted;
0924:            }
0925:
0926:            private List getSorted(int[] index, List unsorted) {
0927:                ArrayList sorted = new ArrayList(unsorted.size());
0928:                int start = 0;
0929:                for (int i = 0; i < unsorted.size(); i++) {
0930:                    int min = -1;
0931:                    for (int j = 0; j < unsorted.size(); j++) {
0932:                        if (index[j] == -1)
0933:                            continue;
0934:                        if (min == -1) {
0935:                            min = j;
0936:                        } else if (index[j] < index[min]) {
0937:                            min = j;
0938:                        }
0939:                    }
0940:                    if (min == -1)
0941:                        break;
0942:                    sorted.add(unsorted.get(min));
0943:                    index[min] = -1;
0944:                }
0945:                return sorted;
0946:            }
0947:
0948:            /**
0949:             * A loop driver for applying operations to all primary ClassNodes in
0950:             * our AST.  Automatically skips units that have already been processed
0951:             * through the current phase.
0952:             */
0953:            public void applyToPrimaryClassNodes(PrimaryClassNodeOperation body)
0954:                    throws CompilationFailedException {
0955:                Iterator classNodes = getPrimaryClassNodes(
0956:                        body.needSortedInput()).iterator();
0957:                while (classNodes.hasNext()) {
0958:                    SourceUnit context = null;
0959:                    try {
0960:                        ClassNode classNode = (ClassNode) classNodes.next();
0961:                        context = classNode.getModule().getContext();
0962:                        if (context == null || context.phase <= phase) {
0963:                            body.call(context, new GeneratorContext(this .ast),
0964:                                    classNode);
0965:                        }
0966:                    } catch (CompilationFailedException e) {
0967:                        // fall thorugh, getErrorREporter().failIfErrors() will triger
0968:                    } catch (NullPointerException npe) {
0969:                        throw npe;
0970:                    } catch (GroovyBugError e) {
0971:                        changeBugText(e, context);
0972:                        throw e;
0973:                    } catch (Exception e) {
0974:                        // check the exception for a nested compilation exception
0975:                        ErrorCollector nestedCollector = null;
0976:                        for (Throwable next = e.getCause(); next != e
0977:                                && next != null; next = next.getCause()) {
0978:                            if (!(next instanceof  MultipleCompilationErrorsException))
0979:                                continue;
0980:                            MultipleCompilationErrorsException mcee = (MultipleCompilationErrorsException) next;
0981:                            nestedCollector = mcee.collector;
0982:                            break;
0983:                        }
0984:
0985:                        if (nestedCollector != null) {
0986:                            getErrorCollector().addCollectorContents(
0987:                                    nestedCollector);
0988:                        } else {
0989:                            getErrorCollector().addError(
0990:                                    new ExceptionMessage(e, configuration
0991:                                            .getDebug(), this ));
0992:                        }
0993:                    }
0994:                }
0995:
0996:                getErrorCollector().failIfErrors();
0997:            }
0998:
0999:            public void applyToGeneratedGroovyClasses(GroovyClassOperation body)
1000:                    throws CompilationFailedException {
1001:                if (this .phase != Phases.OUTPUT
1002:                        && !(this .phase == Phases.CLASS_GENERATION && this .phaseComplete)) {
1003:                    throw new GroovyBugError(
1004:                            "CompilationUnit not ready for output(). Current phase="
1005:                                    + getPhaseDescription());
1006:                }
1007:
1008:                boolean failures = false;
1009:
1010:                Iterator iterator = this .generatedClasses.iterator();
1011:                while (iterator.hasNext()) {
1012:                    //
1013:                    // Get the class and calculate its filesystem name
1014:                    //
1015:                    GroovyClass gclass = (GroovyClass) iterator.next();
1016:                    try {
1017:                        body.call(gclass);
1018:                    } catch (CompilationFailedException e) {
1019:                        // fall thorugh, getErrorREporter().failIfErrors() will triger
1020:                    } catch (NullPointerException npe) {
1021:                        throw npe;
1022:                    } catch (GroovyBugError e) {
1023:                        changeBugText(e, null);
1024:                        throw e;
1025:                    } catch (Exception e) {
1026:                        GroovyBugError gbe = new GroovyBugError(e);
1027:                        throw gbe;
1028:                    }
1029:                }
1030:
1031:                getErrorCollector().failIfErrors();
1032:            }
1033:
1034:            private void changeBugText(GroovyBugError e, SourceUnit context) {
1035:                e.setBugText("exception in phase '" + getPhaseDescription()
1036:                        + "' in source unit '"
1037:                        + ((context != null) ? context.getName() : "?") + "' "
1038:                        + e.getBugText());
1039:            }
1040:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.