View Javadoc
Minimize
Table

Bug Overview

linebug prioritybugbug descriptionexisting sinceauthor
297highOBL_UNSATISFIED_OBLIGATIONÖffnet eine Methode einen Stream oder eine andere Ressource muss diese mit einem try/finally-Block geschlossen werden. Bitte Code auf eine entsprechende cleanup-Operation hin überprüfen!  Details zum Fehler...18.06.2012-10:31Unbekannt
298mediumSystemPrintlnBitte keine System.(out|err).print-Ausgaben verwenden, stattdessen Logger-Klassen nutzen. Details zum Fehler...18.06.2012-10:31Unbekannt
300mediumSystemPrintlnBitte keine System.(out|err).print-Ausgaben verwenden, stattdessen Logger-Klassen nutzen. Details zum Fehler...18.06.2012-10:31Unbekannt

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.control;
18  
19  import groovy.lang.GroovyClassLoader;
20  
21  import java.io.File;
22  import java.io.FileWriter;
23  import java.io.IOException;
24  import java.io.Reader;
25  import java.net.URL;
26  import java.security.AccessController;
27  import java.security.PrivilegedAction;
28  
29  import org.codehaus.groovy.GroovyBugError;
30  import org.codehaus.groovy.ast.ModuleNode;
31  import org.codehaus.groovy.control.io.FileReaderSource;
32  import org.codehaus.groovy.control.io.ReaderSource;
33  import org.codehaus.groovy.control.io.StringReaderSource;
34  import org.codehaus.groovy.control.io.URLReaderSource;
35  import org.codehaus.groovy.control.messages.Message;
36  import org.codehaus.groovy.control.messages.SimpleMessage;
37  import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
38  import org.codehaus.groovy.syntax.*;
39  import org.codehaus.groovy.tools.Utilities;
40  
41  import antlr.CharScanner;
42  import antlr.MismatchedTokenException;
43  import antlr.MismatchedCharException;
44  import antlr.NoViableAltException;
45  import antlr.NoViableAltForCharException;
46  
47  import com.thoughtworks.xstream.XStream;
48  
49  /**
50   * Provides an anchor for a single source unit (usually a script file)
51   * as it passes through the compiler system.
52   *
53   * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
54   * @author <a href="mailto:b55r@sina.com">Bing Ran</a>
55   * @version $Id: SourceUnit.java 22161 2011-05-09 05:03:04Z paulk $
56   */
57  
58  public class SourceUnit extends ProcessingUnit {
59  
60      /**
61       * The pluggable parser used to generate the AST - we allow
62       * pluggability currently as we need to have Classic and JSR support
63       */
64      private ParserPlugin parserPlugin;
65  
66      /**
67       * Where we can get Readers for our source unit
68       */
69      protected ReaderSource source;
70  
71      /**
72       * A descriptive name of the source unit. This name shouldn't
73       * be used for controlling the SourceUnit, it is only for error
74       * messages and to determine the name of the class for
75       * a script.
76       */
77      protected String name;
78  
79      /**
80       * A Concrete Syntax Tree of the source
81       */
82      protected Reduction cst;
83  
84      /**
85       * The root of the Abstract Syntax Tree for the source
86       */
87      protected ModuleNode ast;
88  
89      /**
90       * Initializes the SourceUnit from existing machinery.
91       */
92      public SourceUnit(String name, ReaderSource source, CompilerConfiguration flags,
93                        GroovyClassLoader loader, ErrorCollector er) {
94          super(flags, loader, er);
95  
96          this.name = name;
97          this.source = source;
98      }
99  
100     /**
101      * Initializes the SourceUnit from the specified file.
102      */
103     public SourceUnit(File source, CompilerConfiguration configuration, GroovyClassLoader loader, ErrorCollector er) {
104         this(source.getPath(), new FileReaderSource(source, configuration), configuration, loader, er);
105     }
106 
107     /**
108      * Initializes the SourceUnit from the specified URL.
109      */
110     public SourceUnit(URL source, CompilerConfiguration configuration, GroovyClassLoader loader, ErrorCollector er) {
111         this(source.getPath(), new URLReaderSource(source, configuration), configuration, loader, er);
112     }
113 
114     /**
115      * Initializes the SourceUnit for a string of source.
116      */
117     public SourceUnit(String name, String source, CompilerConfiguration configuration,
118                       GroovyClassLoader loader, ErrorCollector er) {
119         this(name, new StringReaderSource(source, configuration), configuration, loader, er);
120     }
121 
122     /**
123      * Returns the name for the SourceUnit. This name shouldn't
124      * be used for controlling the SourceUnit, it is only for error
125      * messages
126      */
127     public String getName() {
128         return name;
129     }
130 
131 
132     /**
133      * Returns the Concrete Syntax Tree produced during parse()ing.
134      */
135     public Reduction getCST() {
136         return this.cst;
137     }
138 
139     /**
140      * Returns the Abstract Syntax Tree produced during convert()ing
141      * and expanded during later phases.
142      */
143     public ModuleNode getAST() {
144         return this.ast;
145     }
146 
147 
148     /**
149      * Convenience routine, primarily for use by the InteractiveShell,
150      * that returns true if parse() failed with an unexpected EOF.
151      */
152     public boolean failedWithUnexpectedEOF() {
153         // Implementation note - there are several ways for the Groovy compiler
154         // to report an unexpected EOF. Perhaps this implementation misses some.
155         // If you find another way, please add it.
156         if (getErrorCollector().hasErrors()) {
157             Message last = (Message) getErrorCollector().getLastError();
158             Throwable cause = null;
159             if (last instanceof SyntaxErrorMessage) {
160                 cause = ((SyntaxErrorMessage) last).getCause().getCause();
161             }
162             if (cause != null) {
163                 if (cause instanceof NoViableAltException) {
164                     return isEofToken(((NoViableAltException) cause).token);
165                 } else if (cause instanceof NoViableAltForCharException) {
166                     char badChar = ((NoViableAltForCharException) cause).foundChar;
167                     return badChar == CharScanner.EOF_CHAR;
168                 } else if (cause instanceof MismatchedCharException) {
169                     char badChar = (char) ((MismatchedCharException) cause).foundChar;
170                     return badChar == CharScanner.EOF_CHAR;
171                 } else if (cause instanceof MismatchedTokenException) {
172                     return isEofToken(((MismatchedTokenException) cause).token);
173                 }
174             }
175         }
176         return false;
177     }
178 
179     protected boolean isEofToken(antlr.Token token) {
180         return token.getType() == antlr.Token.EOF_TYPE;
181     }
182 
183 
184     //---------------------------------------------------------------------------
185     // FACTORIES
186 
187 
188     /**
189      * A convenience routine to create a standalone SourceUnit on a String
190      * with defaults for almost everything that is configurable.
191      */
192     public static SourceUnit create(String name, String source) {
193         CompilerConfiguration configuration = new CompilerConfiguration();
194         configuration.setTolerance(1);
195 
196         return new SourceUnit(name, source, configuration, null, new ErrorCollector(configuration));
197     }
198 
199 
200     /**
201      * A convenience routine to create a standalone SourceUnit on a String
202      * with defaults for almost everything that is configurable.
203      */
204     public static SourceUnit create(String name, String source, int tolerance) {
205         CompilerConfiguration configuration = new CompilerConfiguration();
206         configuration.setTolerance(tolerance);
207 
208         return new SourceUnit(name, source, configuration, null, new ErrorCollector(configuration));
209     }
210 
211     //---------------------------------------------------------------------------
212     // PROCESSING
213 
214     /**
215      * Parses the source to a CST.  You can retrieve it with getCST().
216      */
217     public void parse() throws CompilationFailedException {
218         if (this.phase > Phases.PARSING) {
219             throw new GroovyBugError("parsing is already complete");
220         }
221 
222         if (this.phase == Phases.INITIALIZATION) {
223             nextPhase();
224         }
225 
226         //
227         // Create a reader on the source and run the parser.
228 
229         Reader reader = null;
230         try {
231             reader = source.getReader();
232 
233             // let's recreate the parser each time as it tends to keep around state
234             parserPlugin = getConfiguration().getPluginFactory().createParserPlugin();
235 
236             cst = parserPlugin.parseCST(this, reader);
237 
238             reader.close();
239 
240         }
241         catch (IOException e) {
242             getErrorCollector().addFatalError(new SimpleMessage(e.getMessage(), this));
243         }
244         finally {
245             if (reader != null) {
246                 try {
247                     reader.close();
248                 }
249                 catch (IOException e) {
250                     // Ignore
251                 }
252             }
253         }
254     }
255 
256     /**
257      * Generates an AST from the CST.  You can retrieve it with getAST().
258      */
259     public void convert() throws CompilationFailedException {
260         if (this.phase == Phases.PARSING && this.phaseComplete) {
261             gotoPhase(Phases.CONVERSION);
262         }
263 
264         if (this.phase != Phases.CONVERSION) {
265             throw new GroovyBugError("SourceUnit not ready for convert()");
266         }
267 
268         //
269         // Build the AST
270 
271         try {
272             this.ast = parserPlugin.buildAST(this, this.classLoader, this.cst);
273             this.ast.setDescription(this.name);
274         }
275         catch (SyntaxException e) {
276             if (this.ast == null) {
277                 // Create a dummy ModuleNode to represent a failed parse - in case a later phase attempts to use the ast
278                 this.ast = new ModuleNode(this);
279             }
280             getErrorCollector().addError(new SyntaxErrorMessage(e, this));
281         }
282 
283         String property = (String) AccessController.doPrivileged(new PrivilegedAction() {
284             public Object run() {
285                 return System.getProperty("groovy.ast");
286             }
287         });
288 
289         if ("xml".equals(property)) {
290             saveAsXML(name, ast);
291         }
292     }
293 
294     private void saveAsXML(String name, ModuleNode ast) {
295         XStream xstream = new XStream();
296         try {
297 bug overview next bug               xstream.toXML(ast, new FileWriter(name + ".xml"));  HEALTH4J >>  :  OBL_UNSATISFIED_OBLIGATION 
298 previous bug bug overview next bug               System.out.println("Written AST to " + name + ".xml");  HEALTH4J >>  :  SystemPrintln 
299         } catch (Exception e) {
300 previous bug bug overview               System.out.println("Couldn't write to " + name + ".xml");  HEALTH4J >>  :  SystemPrintln 
301             e.printStackTrace();
302         }
303     }
304 
305     //---------------------------------------------------------------------------    // SOURCE SAMPLING
306 
307     /**
308      * Returns a sampling of the source at the specified line and column,
309      * of null if it is unavailable.
310      */
311     public String getSample(int line, int column, Janitor janitor) {
312         String sample = null;
313         String text = source.getLine(line, janitor);
314 
315         if (text != null) {
316             if (column > 0) {
317                 String marker = Utilities.repeatString(" ", column - 1) + "^";
318 
319                 if (column > 40) {
320                     int start = column - 30 - 1;
321                     int end = (column + 10 > text.length() ? text.length() : column + 10 - 1);
322                     sample = "   " + text.substring(start, end) + Utilities.eol() + "   " +
323                             marker.substring(start, marker.length());
324                 } else {
325                     sample = "   " + text + Utilities.eol() + "   " + marker;
326                 }
327             } else {
328                 sample = text;
329             }
330         }
331 
332         return sample;
333     }
334 
335     /**
336      * This method adds an exception to the error collector. The Exception most likely has no line number attached to it.
337      * For this reason you should use this method sparingly. Prefer using addError for syntax errors or add an error
338      * to the {@link ErrorCollector} directly by retrieving it with getErrorCollector().
339      * @param e
340      *      the exception that occurred
341      * @throws CompilationFailedException
342      *      on error
343      */
344     public void addException(Exception e) throws CompilationFailedException {
345         getErrorCollector().addException(e, this);
346     }
347 
348     /**
349      * This method adds a SyntaxException to the error collector. The exception should specify the line and column
350      * number of the error.  This method should be reserved for real errors in the syntax of the SourceUnit. If
351      * your error is not in syntax, and is a semantic error, or more general error, then use addException or use
352      * the error collector directly by retrieving it with getErrorCollector().
353      * @param se
354      *      the exception, which should have line and column information
355      * @throws CompilationFailedException
356      *      on error
357      */
358     public void addError(SyntaxException se) throws CompilationFailedException {
359         getErrorCollector().addError(se, this);
360     }
361 
362     public ReaderSource getSource() { return source; }
363 }