/* * Copyright 2004 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.javascript.rhino.Node; import java.io.Serializable; import javax.annotation.Nullable; /** * Compile error description * */ public final class JSError implements Serializable { /** A type of the error */ private final DiagnosticType type; /** Description of the error */ public final String description; /** Name of the source */ public final String sourceName; /** Node where the warning occurred. */ public final Node node; /** Line number of the source */ public final int lineNumber; /** @deprecated Use #getDefaultLevel */ @Deprecated public final CheckLevel level; private final CheckLevel defaultLevel; // character number private final int charno; // // JSError.make - static factory methods for creating JSError objects // // The general form of the arguments is // // [source location] [level] DiagnosticType [argument ...] // // This order echos a typical command line diagnostic. Source location // arguments are arranged to be sources of information in the order // file-line-column. // // If the level is not given, it is taken from the level of the // DiagnosticType. /** * Creates a JSError with no source information * * @param type The DiagnosticType * @param arguments Arguments to be incorporated into the message */ public static JSError make(DiagnosticType type, String... arguments) { return new JSError(null, null, -1, -1, type, null, arguments); } /** * Creates a JSError at a given source location * * @param sourceName The source file name * @param lineno Line number with source file, or -1 if unknown * @param charno Column number within line, or -1 for whole line. * @param type The DiagnosticType * @param arguments Arguments to be incorporated into the message */ public static JSError make(String sourceName, int lineno, int charno, DiagnosticType type, String... arguments) { return new JSError(sourceName, null, lineno, charno, type, null, arguments); } /** * Creates a JSError at a given source location * * @param sourceName The source file name * @param lineno Line number with source file, or -1 if unknown * @param charno Column number within line, or -1 for whole line. * @param type The DiagnosticType * @param arguments Arguments to be incorporated into the message */ public static JSError make(String sourceName, int lineno, int charno, CheckLevel level, DiagnosticType type, String... arguments) { return new JSError( sourceName, null, lineno, charno, type, level, arguments); } /** * Creates a JSError from a file and Node position. * * @param n Determines the line and char position and source file name * @param type The DiagnosticType * @param arguments Arguments to be incorporated into the message */ public static JSError make(Node n, DiagnosticType type, String... arguments) { // TODO(tbreisacher): Get rid of this null check once all tests pass without it. return new JSError(n == null ? null : n.getSourceFileName(), n, type, arguments); } public static JSError make(Node n, CheckLevel level, DiagnosticType type, String... arguments) { return new JSError( n.getSourceFileName(), n, n.getLineno(), n.getCharno(), type, level, arguments); } // // JSError constructors // /** * Creates a JSError at a CheckLevel for a source file location. * Private to avoid any entanglement with code outside of the compiler. */ private JSError( String sourceName, @Nullable Node node, int lineno, int charno, DiagnosticType type, CheckLevel level, String... arguments) { this.type = type; this.node = node; this.description = type.format.format(arguments); this.lineNumber = lineno; this.charno = charno; this.sourceName = sourceName; this.defaultLevel = level == null ? type.level : level; this.level = level == null ? type.level : level; } /** * Creates a JSError for a source file location. Private to avoid * any entanglement with code outside of the compiler. */ private JSError(String sourceName, @Nullable Node node, DiagnosticType type, String... arguments) { this(sourceName, node, (node != null) ? node.getLineno() : -1, (node != null) ? node.getCharno() : -1, type, null, arguments); } public DiagnosticType getType() { return type; } /** * Format a message at the given level. * * @return the formatted message or {@code null} */ public String format(CheckLevel level, MessageFormatter formatter) { switch (level) { case ERROR: return formatter.formatError(this); case WARNING: return formatter.formatWarning(this); default: return null; } } @Override public String toString() { // TODO(user): remove custom toString. return type.key + ". " + description + " at " + (sourceName != null && sourceName.length() > 0 ? sourceName : "(unknown source)") + " line " + (lineNumber != -1 ? String.valueOf(lineNumber) : "(unknown line)") + " : " + (charno != -1 ? String.valueOf(charno) : "(unknown column)"); } /** * Get the character number. */ public int getCharno() { return charno; } /** * Get the line number. One-based. */ public int getLineNumber() { return lineNumber; } /** * @return the offset of the region the Error applies to, or -1 if the offset * is unknown. */ public int getNodeSourceOffset() { return node != null ? node.getSourceOffset() : -1; } /** * @return the length of the region the Error applies to, or 0 if the length * is unknown. */ public int getNodeLength() { return node != null ? node.getLength() : 0; } /** The default level, before any of the WarningsGuards are applied. */ public CheckLevel getDefaultLevel() { return defaultLevel; } @Override public boolean equals(Object o) { // Generated by Intellij IDEA if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } JSError jsError = (JSError) o; if (charno != jsError.charno) { return false; } if (lineNumber != jsError.lineNumber) { return false; } if (!description.equals(jsError.description)) { return false; } if (defaultLevel != jsError.defaultLevel) { return false; } if (sourceName != null ? !sourceName.equals(jsError.sourceName) : jsError.sourceName != null) { return false; } return type.equals(jsError.type); } @Override public int hashCode() { // Generated by Intellij IDEA int result = type.hashCode(); result = 31 * result + description.hashCode(); result = 31 * result + (sourceName != null ? sourceName.hashCode() : 0); result = 31 * result + lineNumber; result = 31 * result + defaultLevel.hashCode(); result = 31 * result + charno; return result; } }