View Javadoc

    1   /*
    2   $Id: ErrorCollector.java 4534 2006-12-21 17:34:36Z blackdrag $
    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
    47  package org.codehaus.groovy.control;
    48
    49  import java.io.PrintWriter;
    50  import java.util.Iterator;
    51  import java.util.LinkedList;
    52  import java.util.List;
    53
    54  import org.codehaus.groovy.control.messages.ExceptionMessage;
    55  import org.codehaus.groovy.control.messages.LocatedMessage;
    56  import org.codehaus.groovy.control.messages.Message;
    57  import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
    58  import org.codehaus.groovy.control.messages.WarningMessage;
    59  import org.codehaus.groovy.syntax.CSTNode;
    60  import org.codehaus.groovy.syntax.SyntaxException;
    61
    62  /***
    63   * A base class for collecting messages and errors during processing.
    64   * Each CompilationUnit should have one and SourceUnits should share
    65   * their ErrorCollector with the CompilationUnit.
    66   *
    67   * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
    68   * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
    69   * @version $Id: ErrorCollector.java 4534 2006-12-21 17:34:36Z blackdrag $
    70   */
    71  public class ErrorCollector {
    72
    73      /***
    74       * WarningMessages collected during processing
    75       */
    76      protected LinkedList warnings;
    77      /***
    78       * ErrorMessages collected during processing
    79       */
    80      protected LinkedList errors;
    81      /***
    82       * Configuration and other settings that control processing
    83       */
    84      protected CompilerConfiguration configuration;
    85
    86      /***
    87       * Initialize the ErrorReporter.
    88       */
    89      public ErrorCollector(CompilerConfiguration configuration) {
    90          this.warnings = null;
    91          this.errors = null;
    92
    93          this.configuration = configuration;
    94      }
    95
    96      public void addCollectorContents(ErrorCollector er) {
    97          if (er.errors!=null) {
    98              if (errors==null) {
    99                  errors = er.errors;
    100             } else {
    101                 errors.addAll(errors);
    102             }
    103         }
    104         if (er.warnings!=null) {
    105             if (warnings==null) {
    106                 warnings = er.warnings;
    107             } else {
    108                 warnings.addAll(warnings);
    109             }
    110         }
    111     }
    112
    113
    114
    115     /***
    116      * Adds an error to the message set, but don't fail.
    117      */
    118     public void addErrorAndContinue(Message message) {
    119         if (this.errors == null) {
    120             this.errors = new LinkedList();
    121         }
    122
    123         this.errors.add(message);
    124     }
    125
    126     /***
    127      * Adds a non-fatal error to the message set.
    128      */
    129     public void addError(Message message) throws CompilationFailedException {
    130         addErrorAndContinue(message);
    131
    132         if (errors!=null && this.errors.size() >= configuration.getTolerance()) {
    133             failIfErrors();
    134         }
    135     }
    136
    137     /***
    138      * Adds an optionally-fatal error to the message set.  Throws
    139      * the unit as a PhaseFailedException, if the error is fatal.
    140      */
    141     public void addError(Message message, boolean fatal) throws CompilationFailedException {
    142         if (fatal) {
    143             addFatalError(message);
    144         }
    145         else {
    146             addError(message);
    147         }
    148     }
    149
    150
    151     /***
    152      * Convenience wrapper for addError().
    153      */
    154     public void addError(SyntaxException error, SourceUnit source) throws CompilationFailedException {
    155         addError(Message.create(error, source), error.isFatal());
    156     }
    157
    158
    159     /***
    160      * Convenience wrapper for addError().
    161      */
    162     public void addError(String text, CSTNode context, SourceUnit source) throws CompilationFailedException {
    163         addError(new LocatedMessage(text, context, source));
    164     }
    165
    166
    167     /***
    168      * Adds a fatal exception to the message set and throws
    169      * the unit as a PhaseFailedException.
    170      */
    171     public void addFatalError(Message message) throws CompilationFailedException {
    172         addError(message);
    173         failIfErrors();
    174     }
    175
    176
    177     public void addException(Exception cause, SourceUnit source) throws CompilationFailedException {
    178         addError(new ExceptionMessage(cause,configuration.getDebug(),source));
    179         failIfErrors();
    180     }
    181
    182     /***
    183      * Returns true if there are any errors pending.
    184      */
    185     public boolean hasErrors() {
    186         return this.errors != null;
    187     }
    188
    189     /***
    190      * Returns true if there are any warnings pending.
    191      */
    192     public boolean hasWarnings() {
    193         return this.warnings != null;
    194     }
    195
    196     /***
    197      * Returns the list of warnings, or null if there are none.
    198      */
    199     public List getWarnings() {
    200         return this.warnings;
    201     }
    202
    203     /***
    204      * Returns the list of errors, or null if there are none.
    205      */
    206     public List getErrors() {
    207         return this.errors;
    208     }
    209
    210     /***
    211      * Returns the number of warnings.
    212      */
    213     public int getWarningCount() {
    214         return ((this.warnings == null) ? 0 : this.warnings.size());
    215     }
    216
    217     /***
    218      * Returns the number of errors.
    219      */
    220     public int getErrorCount() {
    221         return ((this.errors == null) ? 0 : this.errors.size());
    222     }
    223
    224     /***
    225      * Returns the specified warning message, or null.
    226      */
    227     public WarningMessage getWarning(int index) {
    228         if (index < getWarningCount()) {
    229             return (WarningMessage) this.warnings.get(index);
    230         }
    231         return null;
    232     }
    233
    234     /***
    235      * Returns the specified error message, or null.
    236      */
    237     public Message getError(int index) {
    238         if (index < getErrorCount()) {
    239             return (Message) this.errors.get(index);
    240         }
    241         return null;
    242     }
    243
    244     /***
    245      * Returns the last error reported
    246      */
    247     public Message getLastError() {
    248         return (Message) this.errors.getLast();
    249     }
    250
    251     /***
    252      * Convenience routine to return the specified error's
    253      * underlying SyntaxException, or null if it isn't one.
    254      */
    255     public SyntaxException getSyntaxError(int index) {
    256         SyntaxException exception = null;
    257
    258         Message message = getError(index);
    259         if (message != null && message instanceof SyntaxErrorMessage) {
    260             exception = ((SyntaxErrorMessage) message).getCause();
    261         }
    262         return exception;
    263     }
    264
    265     /***
    266      * Convenience routine to return the specified error's
    267      * underlying Exception, or null if it isn't one.
    268      */
    269     public Exception getException(int index) {
    270         Exception exception = null;
    271
    272         Message message = getError(index);
    273         if (message != null) {
    274             if (message instanceof ExceptionMessage) {
    275                 exception = ((ExceptionMessage) message).getCause();
    276             }
    277             else if (message instanceof SyntaxErrorMessage) {
    278                 exception = ((SyntaxErrorMessage) message).getCause();
    279             }
    280         }
    281         return exception;
    282     }
    283
    284     /***
    285      * Adds a WarningMessage to the message set.
    286      */
    287     public void addWarning(WarningMessage message) {
    288         if (message.isRelevant(configuration.getWarningLevel())) {
    289             if (this.warnings == null) {
    290                 this.warnings = new LinkedList();
    291             }
    292
    293             this.warnings.add(message);
    294         }
    295     }
    296
    297
    298     /***
    299      * Convenience wrapper for addWarning() that won't create an object
    300      * unless it is relevant.
    301      */
    302     public void addWarning(int importance, String text, CSTNode context, SourceUnit source) {
    303         if (WarningMessage.isRelevant(importance, configuration.getWarningLevel())) {
    304             addWarning(new WarningMessage(importance, text, context, source));
    305         }
    306     }
    307
    308
    309     /***
    310      * Convenience wrapper for addWarning() that won't create an object
    311      * unless it is relevant.
    312      */
    313     public void addWarning(int importance, String text, Object data, CSTNode context, SourceUnit source) {
    314         if (WarningMessage.isRelevant(importance, configuration.getWarningLevel())) {
    315             addWarning(new WarningMessage(importance, text, data, context, source));
    316         }
    317     }
    318
    319
    320     /***
    321      * Causes the current phase to fail by throwing a
    322      * CompilationFailedException.
    323      */
    324     protected void failIfErrors() throws CompilationFailedException {
    325         if (hasErrors()) {
    326             throw new MultipleCompilationErrorsException(this);
    327         }
    328     }
    329
    330     //---------------------------------------------------------------------------
    331     // OUTPUT
    332
    333
    334     private void write(PrintWriter writer, Janitor janitor, List messages, String txt) {
    335         if (messages==null || messages.size()==0) return;
    336         Iterator iterator = messages.iterator();
    337         while (iterator.hasNext()) {
    338             Message message = (Message) iterator.next();
    339             message.write(writer, janitor);
    340
    341             if (configuration.getDebug() && (message instanceof SyntaxErrorMessage)){
    342                 SyntaxErrorMessage sem = (SyntaxErrorMessage) message;
    343                 sem.getCause().printStackTrace(writer);
    344             }
    345         }
    346
    347         writer.println();
    348         writer.print(messages.size());
    349         writer.print(" "+txt);
    350         if (messages.size()>1) writer.print("s");
    351         writer.println();
    352     }
    353
    354     /***
    355      * Writes error messages to the specified PrintWriter.
    356      */
    357     public void write(PrintWriter writer, Janitor janitor) {
    358         write(writer,janitor,warnings,"warning");
    359         write(writer,janitor,errors,"error");
    360     }
    361
    362 }