6994946: option to specify only syntax errors as unrecoverable

Thu, 28 Oct 2010 18:58:43 -0700

author
jjg
date
Thu, 28 Oct 2010 18:58:43 -0700
changeset 726
2974d3800eb1
parent 725
601160d857ef
child 727
460b2f588d0d

6994946: option to specify only syntax errors as unrecoverable
Reviewed-by: darcy, mcimadamore

src/share/classes/com/sun/tools/javac/main/JavaCompiler.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/parser/JavacParser.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/AbstractLog.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java file | annotate | diff | comparison | revisions
test/tools/javac/processing/6994946/SemanticErrorTest.1.out file | annotate | diff | comparison | revisions
test/tools/javac/processing/6994946/SemanticErrorTest.2.out file | annotate | diff | comparison | revisions
test/tools/javac/processing/6994946/SemanticErrorTest.java file | annotate | diff | comparison | revisions
test/tools/javac/processing/6994946/SyntaxErrorTest.java file | annotate | diff | comparison | revisions
test/tools/javac/processing/6994946/SyntaxErrorTest.out file | annotate | diff | comparison | revisions
test/tools/javac/processing/6994946/TestProcessor.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Oct 28 10:17:47 2010 -0700
     1.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Oct 28 18:58:43 2010 -0700
     1.3 @@ -1090,7 +1090,7 @@
     1.4  
     1.5      private boolean unrecoverableError() {
     1.6          for (JCDiagnostic d: log.deferredDiagnostics) {
     1.7 -            if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RESOLVE_ERROR))
     1.8 +            if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RECOVERABLE))
     1.9                  return true;
    1.10          }
    1.11          return false;
     2.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Oct 28 10:17:47 2010 -0700
     2.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Oct 28 18:58:43 2010 -0700
     2.3 @@ -30,6 +30,7 @@
     2.4  import com.sun.tools.javac.tree.*;
     2.5  import com.sun.tools.javac.code.*;
     2.6  import com.sun.tools.javac.util.*;
     2.7 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
     2.8  import com.sun.tools.javac.util.List;
     2.9  import static com.sun.tools.javac.util.ListBuffer.lb;
    2.10  
    2.11 @@ -266,9 +267,9 @@
    2.12      private void reportSyntaxError(int pos, String key, Object... args) {
    2.13          if (pos > S.errPos() || pos == Position.NOPOS) {
    2.14              if (S.token() == EOF)
    2.15 -                log.error(pos, "premature.eof");
    2.16 +                error(pos, "premature.eof");
    2.17              else
    2.18 -                log.error(pos, key, args);
    2.19 +                error(pos, key, args);
    2.20          }
    2.21          S.errPos(pos);
    2.22          if (S.pos() == errorPos)
    2.23 @@ -324,7 +325,7 @@
    2.24      void checkNoMods(long mods) {
    2.25          if (mods != 0) {
    2.26              long lowestMod = mods & -mods;
    2.27 -            log.error(S.pos(), "mod.not.allowed.here",
    2.28 +            error(S.pos(), "mod.not.allowed.here",
    2.29                        Flags.asFlagSet(lowestMod));
    2.30          }
    2.31      }
    2.32 @@ -418,22 +419,22 @@
    2.33              return name;
    2.34          } else if (S.token() == ASSERT) {
    2.35              if (allowAsserts) {
    2.36 -                log.error(S.pos(), "assert.as.identifier");
    2.37 +                error(S.pos(), "assert.as.identifier");
    2.38                  S.nextToken();
    2.39                  return names.error;
    2.40              } else {
    2.41 -                log.warning(S.pos(), "assert.as.identifier");
    2.42 +                warning(S.pos(), "assert.as.identifier");
    2.43                  Name name = S.name();
    2.44                  S.nextToken();
    2.45                  return name;
    2.46              }
    2.47          } else if (S.token() == ENUM) {
    2.48              if (allowEnums) {
    2.49 -                log.error(S.pos(), "enum.as.identifier");
    2.50 +                error(S.pos(), "enum.as.identifier");
    2.51                  S.nextToken();
    2.52                  return names.error;
    2.53              } else {
    2.54 -                log.warning(S.pos(), "enum.as.identifier");
    2.55 +                warning(S.pos(), "enum.as.identifier");
    2.56                  Name name = S.name();
    2.57                  S.nextToken();
    2.58                  return name;
    2.59 @@ -479,7 +480,7 @@
    2.60                      TypeTags.INT,
    2.61                      Convert.string2int(strval(prefix), S.radix()));
    2.62              } catch (NumberFormatException ex) {
    2.63 -                log.error(S.pos(), "int.number.too.large", strval(prefix));
    2.64 +                error(S.pos(), "int.number.too.large", strval(prefix));
    2.65              }
    2.66              break;
    2.67          case LONGLITERAL:
    2.68 @@ -488,7 +489,7 @@
    2.69                      TypeTags.LONG,
    2.70                      new Long(Convert.string2long(strval(prefix), S.radix())));
    2.71              } catch (NumberFormatException ex) {
    2.72 -                log.error(S.pos(), "int.number.too.large", strval(prefix));
    2.73 +                error(S.pos(), "int.number.too.large", strval(prefix));
    2.74              }
    2.75              break;
    2.76          case FLOATLITERAL: {
    2.77 @@ -501,9 +502,9 @@
    2.78                  n = Float.NaN;
    2.79              }
    2.80              if (n.floatValue() == 0.0f && !isZero(proper))
    2.81 -                log.error(S.pos(), "fp.number.too.small");
    2.82 +                error(S.pos(), "fp.number.too.small");
    2.83              else if (n.floatValue() == Float.POSITIVE_INFINITY)
    2.84 -                log.error(S.pos(), "fp.number.too.large");
    2.85 +                error(S.pos(), "fp.number.too.large");
    2.86              else
    2.87                  t = F.at(pos).Literal(TypeTags.FLOAT, n);
    2.88              break;
    2.89 @@ -518,9 +519,9 @@
    2.90                  n = Double.NaN;
    2.91              }
    2.92              if (n.doubleValue() == 0.0d && !isZero(proper))
    2.93 -                log.error(S.pos(), "fp.number.too.small");
    2.94 +                error(S.pos(), "fp.number.too.small");
    2.95              else if (n.doubleValue() == Double.POSITIVE_INFINITY)
    2.96 -                log.error(S.pos(), "fp.number.too.large");
    2.97 +                error(S.pos(), "fp.number.too.large");
    2.98              else
    2.99                  t = F.at(pos).Literal(TypeTags.DOUBLE, n);
   2.100              break;
   2.101 @@ -1581,7 +1582,7 @@
   2.102              case ENUM:
   2.103              case ASSERT:
   2.104                  if (allowEnums && S.token() == ENUM) {
   2.105 -                    log.error(S.pos(), "local.enum");
   2.106 +                    error(S.pos(), "local.enum");
   2.107                      stats.
   2.108                          append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
   2.109                                                                   S.docComment()));
   2.110 @@ -1728,9 +1729,9 @@
   2.111              } else {
   2.112                  if (allowTWR) {
   2.113                      if (resources.isEmpty())
   2.114 -                        log.error(pos, "try.without.catch.finally.or.resource.decls");
   2.115 +                        error(pos, "try.without.catch.finally.or.resource.decls");
   2.116                  } else
   2.117 -                    log.error(pos, "try.without.catch.or.finally");
   2.118 +                    error(pos, "try.without.catch.or.finally");
   2.119              }
   2.120              return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
   2.121          }
   2.122 @@ -1985,7 +1986,7 @@
   2.123              case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
   2.124              default: break loop;
   2.125              }
   2.126 -            if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
   2.127 +            if ((flags & flag) != 0) error(S.pos(), "repeated.modifier");
   2.128              lastPos = S.pos();
   2.129              S.nextToken();
   2.130              if (flag == Flags.ANNOTATION) {
   2.131 @@ -2331,7 +2332,7 @@
   2.132              }
   2.133          } else {
   2.134              if (S.token() == ENUM) {
   2.135 -                log.error(S.pos(), "enums.not.supported.in.source", source.name);
   2.136 +                error(S.pos(), "enums.not.supported.in.source", source.name);
   2.137                  allowEnums = true;
   2.138                  return enumDeclaration(mods, dc);
   2.139              }
   2.140 @@ -2580,7 +2581,7 @@
   2.141                  }
   2.142                  if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
   2.143                      if (isInterface || name != className)
   2.144 -                        log.error(pos, "invalid.meth.decl.ret.type.req");
   2.145 +                        error(pos, "invalid.meth.decl.ret.type.req");
   2.146                      return List.of(methodDeclaratorRest(
   2.147                          pos, mods, null, names.init, typarams,
   2.148                          isInterface, true, dc));
   2.149 @@ -2759,6 +2760,14 @@
   2.150  
   2.151  /* ---------- auxiliary methods -------------- */
   2.152  
   2.153 +    void error(int pos, String key, Object ... args) {
   2.154 +        log.error(DiagnosticFlag.SYNTAX, pos, key, args);
   2.155 +    }
   2.156 +
   2.157 +    void warning(int pos, String key, Object ... args) {
   2.158 +        log.warning(pos, key, args);
   2.159 +    }
   2.160 +
   2.161      /** Check that given tree is a legal expression statement.
   2.162       */
   2.163      protected JCExpression checkExprStat(JCExpression t) {
   2.164 @@ -2774,7 +2783,7 @@
   2.165          case JCTree.ERRONEOUS:
   2.166              return t;
   2.167          default:
   2.168 -            log.error(t.pos, "not.stmt");
   2.169 +            error(t.pos, "not.stmt");
   2.170              return F.at(t.pos).Erroneous(List.<JCTree>of(t));
   2.171          }
   2.172      }
   2.173 @@ -2921,49 +2930,49 @@
   2.174  
   2.175      void checkGenerics() {
   2.176          if (!allowGenerics) {
   2.177 -            log.error(S.pos(), "generics.not.supported.in.source", source.name);
   2.178 +            error(S.pos(), "generics.not.supported.in.source", source.name);
   2.179              allowGenerics = true;
   2.180          }
   2.181      }
   2.182      void checkVarargs() {
   2.183          if (!allowVarargs) {
   2.184 -            log.error(S.pos(), "varargs.not.supported.in.source", source.name);
   2.185 +            error(S.pos(), "varargs.not.supported.in.source", source.name);
   2.186              allowVarargs = true;
   2.187          }
   2.188      }
   2.189      void checkForeach() {
   2.190          if (!allowForeach) {
   2.191 -            log.error(S.pos(), "foreach.not.supported.in.source", source.name);
   2.192 +            error(S.pos(), "foreach.not.supported.in.source", source.name);
   2.193              allowForeach = true;
   2.194          }
   2.195      }
   2.196      void checkStaticImports() {
   2.197          if (!allowStaticImport) {
   2.198 -            log.error(S.pos(), "static.import.not.supported.in.source", source.name);
   2.199 +            error(S.pos(), "static.import.not.supported.in.source", source.name);
   2.200              allowStaticImport = true;
   2.201          }
   2.202      }
   2.203      void checkAnnotations() {
   2.204          if (!allowAnnotations) {
   2.205 -            log.error(S.pos(), "annotations.not.supported.in.source", source.name);
   2.206 +            error(S.pos(), "annotations.not.supported.in.source", source.name);
   2.207              allowAnnotations = true;
   2.208          }
   2.209      }
   2.210      void checkDiamond() {
   2.211          if (!allowDiamond) {
   2.212 -            log.error(S.pos(), "diamond.not.supported.in.source", source.name);
   2.213 +            error(S.pos(), "diamond.not.supported.in.source", source.name);
   2.214              allowDiamond = true;
   2.215          }
   2.216      }
   2.217      void checkMulticatch() {
   2.218          if (!allowMulticatch) {
   2.219 -            log.error(S.pos(), "multicatch.not.supported.in.source", source.name);
   2.220 +            error(S.pos(), "multicatch.not.supported.in.source", source.name);
   2.221              allowMulticatch = true;
   2.222          }
   2.223      }
   2.224      void checkAutomaticResourceManagement() {
   2.225          if (!allowTWR) {
   2.226 -            log.error(S.pos(), "automatic.resource.management.not.supported.in.source", source.name);
   2.227 +            error(S.pos(), "automatic.resource.management.not.supported.in.source", source.name);
   2.228              allowTWR = true;
   2.229          }
   2.230      }
     3.1 --- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Thu Oct 28 10:17:47 2010 -0700
     3.2 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Thu Oct 28 18:58:43 2010 -0700
     3.3 @@ -939,7 +939,7 @@
     3.4                          break;
     3.5  
     3.6                      case ERROR:
     3.7 -                        if (fatalErrors || !d.isFlagSet(RESOLVE_ERROR))
     3.8 +                        if (fatalErrors || !d.isFlagSet(RECOVERABLE))
     3.9                              return true;
    3.10                          break;
    3.11                  }
     4.1 --- a/src/share/classes/com/sun/tools/javac/util/AbstractLog.java	Thu Oct 28 10:17:47 2010 -0700
     4.2 +++ b/src/share/classes/com/sun/tools/javac/util/AbstractLog.java	Thu Oct 28 18:58:43 2010 -0700
     4.3 @@ -30,6 +30,7 @@
     4.4  import javax.tools.JavaFileObject;
     4.5  
     4.6  import com.sun.tools.javac.code.Lint.LintCategory;
     4.7 +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
     4.8  import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
     4.9  import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
    4.10  
    4.11 @@ -103,6 +104,19 @@
    4.12          report(diags.error(source, wrap(pos), key, args));
    4.13      }
    4.14  
    4.15 +    /** Report an error, unless another error was already reported at same
    4.16 +     *  source position.
    4.17 +     *  @param flag   A flag to set on the diagnostic
    4.18 +     *  @param pos    The source position at which to report the error.
    4.19 +     *  @param key    The key for the localized error message.
    4.20 +     *  @param args   Fields of the error message.
    4.21 +     */
    4.22 +    public void error(DiagnosticFlag flag, int pos, String key, Object ... args) {
    4.23 +        JCDiagnostic d = diags.error(source, wrap(pos), key, args);
    4.24 +        d.setFlag(flag);
    4.25 +        report(d);
    4.26 +    }
    4.27 +
    4.28      /** Report a warning, unless suppressed by the  -nowarn option or the
    4.29       *  maximum number of warnings has been reached.
    4.30       *  @param pos    The source position at which to report the warning.
     5.1 --- a/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Thu Oct 28 10:17:47 2010 -0700
     5.2 +++ b/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Thu Oct 28 18:58:43 2010 -0700
     5.3 @@ -63,17 +63,23 @@
     5.4  
     5.5          DiagnosticFormatter<JCDiagnostic> formatter;
     5.6          final String prefix;
     5.7 +        final Set<DiagnosticFlag> defaultErrorFlags;
     5.8  
     5.9          /** Create a new diagnostic factory. */
    5.10          protected Factory(Context context) {
    5.11              this(JavacMessages.instance(context), "compiler");
    5.12              context.put(diagnosticFactoryKey, this);
    5.13 +
    5.14 +            Options options = Options.instance(context);
    5.15 +            if (options.isSet("onlySyntaxErrorsUnrecoverable"))
    5.16 +                defaultErrorFlags.add(DiagnosticFlag.RECOVERABLE);
    5.17          }
    5.18  
    5.19          /** Create a new diagnostic factory. */
    5.20          public Factory(JavacMessages messages, String prefix) {
    5.21              this.prefix = prefix;
    5.22              this.formatter = new BasicDiagnosticFormatter(messages);
    5.23 +            defaultErrorFlags = EnumSet.of(DiagnosticFlag.MANDATORY);
    5.24          }
    5.25  
    5.26          /**
    5.27 @@ -85,7 +91,7 @@
    5.28           */
    5.29          public JCDiagnostic error(
    5.30                  DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
    5.31 -            return create(ERROR, null, EnumSet.of(DiagnosticFlag.MANDATORY), source, pos, key, args);
    5.32 +            return create(ERROR, null, defaultErrorFlags, source, pos, key, args);
    5.33          }
    5.34  
    5.35          /**
    5.36 @@ -331,7 +337,9 @@
    5.37  
    5.38      public enum DiagnosticFlag {
    5.39          MANDATORY,
    5.40 -        RESOLVE_ERROR
    5.41 +        RESOLVE_ERROR,
    5.42 +        SYNTAX,
    5.43 +        RECOVERABLE
    5.44      }
    5.45  
    5.46      private final DiagnosticType type;
    5.47 @@ -547,6 +555,17 @@
    5.48  
    5.49      public void setFlag(DiagnosticFlag flag) {
    5.50          flags.add(flag);
    5.51 +
    5.52 +        if (type == DiagnosticType.ERROR) {
    5.53 +            switch (flag) {
    5.54 +                case SYNTAX:
    5.55 +                    flags.remove(DiagnosticFlag.RECOVERABLE);
    5.56 +                    break;
    5.57 +                case RESOLVE_ERROR:
    5.58 +                    flags.add(DiagnosticFlag.RECOVERABLE);
    5.59 +                    break;
    5.60 +            }
    5.61 +        }
    5.62      }
    5.63  
    5.64      public boolean isFlagSet(DiagnosticFlag flag) {
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/tools/javac/processing/6994946/SemanticErrorTest.1.out	Thu Oct 28 18:58:43 2010 -0700
     6.3 @@ -0,0 +1,2 @@
     6.4 +SemanticErrorTest.java:11:46: compiler.err.repeated.interface
     6.5 +1 error
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/tools/javac/processing/6994946/SemanticErrorTest.2.out	Thu Oct 28 18:58:43 2010 -0700
     7.3 @@ -0,0 +1,4 @@
     7.4 +SemanticErrorTest.java:11:46: compiler.err.repeated.interface
     7.5 +- compiler.err.proc.messager: Deliberate Error
     7.6 +SemanticErrorTest.java:11:46: compiler.err.repeated.interface
     7.7 +1 error
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/test/tools/javac/processing/6994946/SemanticErrorTest.java	Thu Oct 28 18:58:43 2010 -0700
     8.3 @@ -0,0 +1,13 @@
     8.4 +/*
     8.5 + * @test /nodynamiccopyright/
     8.6 + * @bug 6994946
     8.7 + * @summary option to specify only syntax errors as unrecoverable
     8.8 + * @library ../../lib
     8.9 + * @build JavacTestingAbstractProcessor TestProcessor
    8.10 + * @compile/fail/ref=SemanticErrorTest.1.out -XDrawDiagnostics                                  -processor TestProcessor SemanticErrorTest.java
    8.11 + * @compile/fail/ref=SemanticErrorTest.2.out -XDrawDiagnostics -XDonlySyntaxErrorsUnrecoverable -processor TestProcessor SemanticErrorTest.java
    8.12 + */
    8.13 +
    8.14 +class SemanticErrorTest implements Runnable, Runnable {
    8.15 +    public void run() { }
    8.16 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/test/tools/javac/processing/6994946/SyntaxErrorTest.java	Thu Oct 28 18:58:43 2010 -0700
     9.3 @@ -0,0 +1,13 @@
     9.4 +/*
     9.5 + * @test /nodynamiccopyright/
     9.6 + * @bug 6994946
     9.7 + * @summary option to specify only syntax errors as unrecoverable
     9.8 + * @library ../../lib
     9.9 + * @build JavacTestingAbstractProcessor TestProcessor
    9.10 + * @compile/fail/ref=SyntaxErrorTest.out -XDrawDiagnostics                                  -processor TestProcessor SyntaxErrorTest.java
    9.11 + * @compile/fail/ref=SyntaxErrorTest.out -XDrawDiagnostics -XDonlySyntaxErrorsUnrecoverable -processor TestProcessor SyntaxErrorTest.java
    9.12 + */
    9.13 +
    9.14 +class SyntaxErrorTest {
    9.15 +    int i
    9.16 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/test/tools/javac/processing/6994946/SyntaxErrorTest.out	Thu Oct 28 18:58:43 2010 -0700
    10.3 @@ -0,0 +1,2 @@
    10.4 +SyntaxErrorTest.java:12:10: compiler.err.expected: ';'
    10.5 +1 error
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/test/tools/javac/processing/6994946/TestProcessor.java	Thu Oct 28 18:58:43 2010 -0700
    11.3 @@ -0,0 +1,40 @@
    11.4 +/*
    11.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.
   11.11 + *
   11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.15 + * version 2 for more details (a copy is included in the LICENSE file that
   11.16 + * accompanied this code).
   11.17 + *
   11.18 + * You should have received a copy of the GNU General Public License version
   11.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.21 + *
   11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   11.23 + * or visit www.oracle.com if you need additional information or have any
   11.24 + * questions.
   11.25 + */
   11.26 +
   11.27 +import java.util.*;
   11.28 +import javax.annotation.processing.*;
   11.29 +import javax.lang.model.*;
   11.30 +import javax.lang.model.element.*;
   11.31 +import static javax.tools.Diagnostic.Kind.*;
   11.32 +
   11.33 +public class TestProcessor extends JavacTestingAbstractProcessor {
   11.34 +   private int round = 0;
   11.35 +
   11.36 +   public boolean process(Set<? extends TypeElement> annotations,
   11.37 +                  RoundEnvironment roundEnv) {
   11.38 +        if (++round == 1)
   11.39 +            messager.printMessage(ERROR, "Deliberate Error");
   11.40 +        return false;
   11.41 +   }
   11.42 +}
   11.43 +

mercurial