All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.javascript.jscomp.RhinoErrorReporter Maven / Gradle / Ivy

/*
 * Copyright 2009 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.javascript.jscomp;

import com.google.common.collect.ImmutableMap;
import com.google.javascript.rhino.ErrorReporter;
import com.google.javascript.rhino.SimpleErrorReporter;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;

/**
 * An error reporter for serializing Rhino errors into our error format.
 */
class RhinoErrorReporter {

  static final DiagnosticType PARSE_ERROR =
      DiagnosticType.error("JSC_PARSE_ERROR", "Parse error. {0}");

  static final DiagnosticType TYPE_PARSE_ERROR =
      DiagnosticType.warning("JSC_TYPE_PARSE_ERROR", "{0}");

  static final DiagnosticType UNRECOGNIZED_TYPE_ERROR =
      DiagnosticType.warning("JSC_UNRECOGNIZED_TYPE_ERROR", "{0}");

  // This is separate from TYPE_PARSE_ERROR because there are many instances of this warning
  // and it is unfeasible to fix them all right away.
  static final DiagnosticType JSDOC_MISSING_BRACES_WARNING =
      DiagnosticType.disabled("JSC_JSDOC_MISSING_BRACES_WARNING", "{0}");

  // This is separate from TYPE_PARSE_ERROR because there are many instances of this warning
  // and it is unfeasible to fix them all right away.
  static final DiagnosticType JSDOC_MISSING_TYPE_WARNING =
      DiagnosticType.disabled("JSC_JSDOC_MISSING_TYPE_WARNING", "{0}");

  // Import is supported by VSCode and is pretty much a standard now.
  static final DiagnosticType JSDOC_IMPORT_TYPE_WARNING =
      DiagnosticType.disabled("JSC_JSDOC_IMPORT_TYPE_WARNING", "{0}");

  static final DiagnosticType TOO_MANY_TEMPLATE_PARAMS =
      DiagnosticType.disabled("JSC_TOO_MANY_TEMPLATE_PARAMS", "{0}");

  // Special-cased errors, so that they can be configured via the
  // warnings API.
  static final DiagnosticType TRAILING_COMMA =
      DiagnosticType.error("JSC_TRAILING_COMMA",
          "Parse error. IE8 (and below) will parse trailing commas in " +
          "array and object literals incorrectly. " +
          "If you are targeting newer versions of JS, " +
          "set the appropriate language_in option.");

  static final DiagnosticType DUPLICATE_PARAM =
      DiagnosticType.error("JSC_DUPLICATE_PARAM", "Parse error. {0}");

  static final DiagnosticType UNNECESSARY_ESCAPE =
      DiagnosticType.disabled("JSC_UNNECESSARY_ESCAPE", "Parse error. {0}");

  static final DiagnosticType INVALID_PARAM =
      DiagnosticType.warning("JSC_INVALID_PARAM", "Parse error. {0}");

  static final DiagnosticType BAD_JSDOC_ANNOTATION =
      DiagnosticType.warning("JSC_BAD_JSDOC_ANNOTATION", "Parse error. {0}");

  static final DiagnosticType INVALID_ES3_PROP_NAME = DiagnosticType.warning(
      "JSC_INVALID_ES3_PROP_NAME",
      "Keywords and reserved words are not allowed as unquoted property " +
      "names in older versions of JavaScript. " +
      "If you are targeting newer versions of JavaScript, " +
      "set the appropriate language_in option.");

  static final DiagnosticType PARSE_TREE_TOO_DEEP =
      DiagnosticType.error("JSC_PARSE_TREE_TOO_DEEP", "Parse tree too deep.");

  static final DiagnosticType INVALID_OCTAL_LITERAL =
      DiagnosticType.warning(
          "JSC_INVALID_OCTAL_LITERAL",
          "This style of octal literal is not supported in strict mode.");

  static final DiagnosticType STRING_CONTINUATION =
      DiagnosticType.warning("JSC_STRING_CONTINUATION", "{0}");

  static final DiagnosticType LANGUAGE_FEATURE =
      DiagnosticType.error("JSC_LANGUAGE_FEATURE", "{0}.");

  static final DiagnosticType UNSUPPORTED_LANGUAGE_FEATURE =
      DiagnosticType.error("JSC_UNSUPPORTED_LANGUAGE_FEATURE", "{0}.");

  static final DiagnosticType ES6_TYPED =
      DiagnosticType.error(
          "JSC_ES6_TYPED",
          "{0}. Use --language_in=ECMASCRIPT6_TYPED to enable ES6 typed features.");

  static final DiagnosticType MISPLACED_TYPE_SYNTAX =
      DiagnosticType.error(
          "JSC_MISPLACED_TYPE_SYNTAX", "Can only have JSDoc or inline type annotations, not both");

  static final DiagnosticType UNSUPPORTED_BOUNDED_GENERIC_TYPES =
      DiagnosticType.error(
          "JSC_UNSUPPORTED_BOUNDED_GENERIC_TYPES",
          "Bounded generic semantics are currently still in development");

  static final DiagnosticType BOUNDED_GENERIC_TYPE_ERROR =
      DiagnosticType.error(
          "JSC_BOUNDED_GENERIC_TYPE_ERROR",
          "Bounded generic type error. "
              + "{0} assigned to template type {1} is not a subtype of bound {2}");

  // A map of Rhino messages to their DiagnosticType.
  private static final Map typeMap =
      ImmutableMap.builder()
          // Trailing comma
          .put(
              Pattern.compile("Trailing comma is not legal in an ECMA-262 object initializer"),
              TRAILING_COMMA)
          // Duplicate parameter
          .put(replacePlaceHolders("Duplicate parameter name \"{0}\""), DUPLICATE_PARAM)
          .put(Pattern.compile("Unnecessary escape:.*"), UNNECESSARY_ESCAPE)
          .put(Pattern.compile("^invalid param name.*"), INVALID_PARAM)
          // Unknown @annotations.
          .put(
              replacePlaceHolders(SimpleErrorReporter.getMessage0("msg.bad.jsdoc.tag")),
              BAD_JSDOC_ANNOTATION)
          .put(
              Pattern.compile(
                  "^Keywords and reserved words are not allowed as unquoted property.*"),
              INVALID_ES3_PROP_NAME)
          .put(Pattern.compile("^Too many template parameters"), TOO_MANY_TEMPLATE_PARAMS)
          // Type annotation warnings.
          .put(
              Pattern.compile(".*Type annotations should have curly braces.*"),
              JSDOC_MISSING_BRACES_WARNING)
          .put(Pattern.compile("Missing type declaration\\."), JSDOC_MISSING_TYPE_WARNING)
          // Unresolved types that aren't forward declared.
          .put(Pattern.compile(".*Unknown type.*"), UNRECOGNIZED_TYPE_ERROR)
          .put(Pattern.compile(".*Unknown type.*\n.*"), UNRECOGNIZED_TYPE_ERROR)
          // Import annotation errors.
          .put(
              Pattern.compile("^Bad type annotation. Import in typedef.*"),
              JSDOC_IMPORT_TYPE_WARNING)
          // Type annotation errors.
          .put(Pattern.compile("^Bad type annotation.*"), TYPE_PARSE_ERROR)
          // Parse tree too deep.
          .put(Pattern.compile("Too deep recursion while parsing"), PARSE_TREE_TOO_DEEP)
          // Old-style octal literals
          .put(Pattern.compile("^Octal .*literal.*"), INVALID_OCTAL_LITERAL)
          .put(Pattern.compile("^String continuations.*"), STRING_CONTINUATION)
          .put(Pattern.compile("^This language feature is only supported for .*"), LANGUAGE_FEATURE)
          .put(
              Pattern.compile(
                  "^This language feature is not currently supported by the internalReporter:"
                      + " .*"),
              UNSUPPORTED_LANGUAGE_FEATURE)
          .put(Pattern.compile("^type syntax is only supported in ES6 typed mode.*"), ES6_TYPED)
          .put(Pattern.compile("^Can only have JSDoc or inline type.*"), MISPLACED_TYPE_SYNTAX)
          .put(
              Pattern.compile("Bounded generic semantics are currently still in development"),
              UNSUPPORTED_BOUNDED_GENERIC_TYPES)
          .put(Pattern.compile("^Bounded generic type error.*"), BOUNDED_GENERIC_TYPE_ERROR)
          .build();

  private final ErrorHandler internalReporter;

  /**
   * For each message such as "Not a good use of {0}", replace the place holder {0} with a wild card
   * that matches all possible strings. Also put the any non-place-holder in quotes for regex
   * matching later.
   */
  private static Pattern replacePlaceHolders(String s) {
    s = Pattern.quote(s);
    return Pattern.compile(s.replaceAll("\\{\\d+\\}", "\\\\E.*\\\\Q"));
  }

  private RhinoErrorReporter(ErrorHandler internalReporter) {
    this.internalReporter = internalReporter;
  }

  public static ErrorReporter forOldRhino(ErrorHandler internalReporter) {
    return new OldRhinoErrorReporter(internalReporter);
  }

  void warningAtLine(String message, String sourceName, int line,
      int lineOffset) {
    internalReporter.report(
        null, makeError(message, sourceName, line, lineOffset, CheckLevel.WARNING));
  }

  void errorAtLine(String message, String sourceName, int line,
      int lineOffset) {
    internalReporter.report(
        null, makeError(message, sourceName, line, lineOffset, CheckLevel.ERROR));
  }

  protected static DiagnosticType mapError(String message) {
    for (Entry entry : typeMap.entrySet()) {
      if (entry.getKey().matcher(message).matches()) {
        return entry.getValue();
      }
    }
    return null;
  }

  private static JSError makeError(
      String message, String sourceName, int line, int lineOffset, CheckLevel defaultLevel) {
    // Try to see if the message is one of the rhino errors we want to
    // expose as DiagnosticType by matching it with the regex key.
    DiagnosticType type = mapError(message);
    return (type != null)
        ? JSError.make(sourceName, line, lineOffset, type, message)
        : JSError.make(sourceName, line, lineOffset, defaultLevel, PARSE_ERROR, message);
  }

  private static class OldRhinoErrorReporter extends RhinoErrorReporter
      implements ErrorReporter {

    private OldRhinoErrorReporter(ErrorHandler internalReporter) {
      super(internalReporter);
    }

    @Override
    public void error(String message, String sourceName, int line,
        int lineOffset) {
      super.errorAtLine(message, sourceName, line, lineOffset);
    }

    @Override
    public void warning(String message, String sourceName, int line,
        int lineOffset) {
      super.warningAtLine(message, sourceName, line, lineOffset);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy