/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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.dart.engine.error; import com.google.dart.engine.source.Source; import com.google.dart.engine.utilities.general.ObjectUtilities; import java.util.Comparator; /** * Instances of the class {@code AnalysisError} represent an error discovered during the analysis of * some Dart code. * * @see AnalysisErrorListener * @coverage dart.engine.error */ public class AnalysisError { /** * An empty array of errors used when no errors are expected. */ public static final AnalysisError[] NO_ERRORS = new AnalysisError[0]; /** * A {@link Comparator} that sorts by the name of the file that the {@link AnalysisError} was * found. */ public static final Comparator<AnalysisError> FILE_COMPARATOR = new Comparator<AnalysisError>() { @Override public int compare(AnalysisError o1, AnalysisError o2) { return o1.getSource().getShortName().compareTo(o2.getSource().getShortName()); } }; /** * A {@link Comparator} that sorts error codes first by their severity (errors first, warnings * second), and then by the the error code type. */ public static final Comparator<AnalysisError> ERROR_CODE_COMPARATOR = new Comparator<AnalysisError>() { @Override public int compare(AnalysisError o1, AnalysisError o2) { ErrorCode errorCode1 = o1.getErrorCode(); ErrorCode errorCode2 = o2.getErrorCode(); ErrorSeverity errorSeverity1 = errorCode1.getErrorSeverity(); ErrorSeverity errorSeverity2 = errorCode2.getErrorSeverity(); ErrorType errorType1 = errorCode1.getType(); ErrorType errorType2 = errorCode2.getType(); if (errorSeverity1.equals(errorSeverity2)) { return errorType1.compareTo(errorType2); } else { return errorSeverity2.compareTo(errorSeverity1); } } }; /** * The error code associated with the error. */ private ErrorCode errorCode; /** * The localized error message. */ private String message; /** * The correction to be displayed for this error, or {@code null} if there is no correction * information for this error. */ private String correction; /** * The source in which the error occurred, or {@code null} if unknown. */ private Source source; /** * The character offset from the beginning of the source (zero based) where the error occurred. */ private int offset = 0; /** * The number of characters from the offset to the end of the source which encompasses the * compilation error. */ private int length = 0; /** * A flag indicating whether this error can be shown to be a non-issue because of the result of * type propagation. */ private boolean isStaticOnly = false; /** * Initialize a newly created analysis error for the specified source. The error has no location * information. * * @param source the source for which the exception occurred * @param errorCode the error code to be associated with this error * @param arguments the arguments used to build the error message */ public AnalysisError(Source source, ErrorCode errorCode, Object... arguments) { this.source = source; this.errorCode = errorCode; this.message = String.format(errorCode.getMessage(), arguments); } /** * Initialize a newly created analysis error for the specified source at the given location. * * @param source the source for which the exception occurred * @param offset the offset of the location of the error * @param length the length of the location of the error * @param errorCode the error code to be associated with this error * @param arguments the arguments used to build the error message */ public AnalysisError(Source source, int offset, int length, ErrorCode errorCode, Object... arguments) { this.source = source; this.offset = offset; this.length = length; this.errorCode = errorCode; this.message = String.format(errorCode.getMessage(), arguments); String correctionTemplate = errorCode.getCorrection(); if (correctionTemplate != null) { this.correction = String.format(correctionTemplate, arguments); } } @Override public boolean equals(Object obj) { if (obj == this) { return true; } // prepare other AnalysisError if (!(obj instanceof AnalysisError)) { return false; } AnalysisError other = (AnalysisError) obj; // Quick checks. if (errorCode != other.errorCode) { return false; } if (offset != other.offset || length != other.length) { return false; } if (isStaticOnly != other.isStaticOnly) { return false; } // Deep checks. if (!ObjectUtilities.equals(message, other.message)) { return false; } if (!ObjectUtilities.equals(source, other.source)) { return false; } // OK return true; } /** * Return the correction to be displayed for this error, or {@code null} if there is no correction * information for this error. The correction should indicate how the user can fix the error. * * @return the template used to create the correction to be displayed for this error */ public String getCorrection() { return correction; } /** * Return the error code associated with the error. * * @return the error code associated with the error */ public ErrorCode getErrorCode() { return errorCode; } /** * Return the number of characters from the offset to the end of the source which encompasses the * compilation error. * * @return the length of the error location */ public int getLength() { return length; } /** * Return the message to be displayed for this error. The message should indicate what is wrong * and why it is wrong. * * @return the message to be displayed for this error */ public String getMessage() { return message; } /** * Return the character offset from the beginning of the source (zero based) where the error * occurred. * * @return the offset to the start of the error location */ public int getOffset() { return offset; } /** * Return the value of the given property, or {@code null} if the given property is not defined * for this error. * * @param property the property whose value is to be returned * @return the value of the given property */ public Object getProperty(ErrorProperty property) { return null; } /** * Return the source in which the error occurred, or {@code null} if unknown. * * @return the source in which the error occurred */ public Source getSource() { return source; } @Override public int hashCode() { int hashCode = offset; hashCode ^= (message != null) ? message.hashCode() : 0; hashCode ^= (source != null) ? source.hashCode() : 0; return hashCode; } /** * Return {@code true} if this error can be shown to be a non-issue because of the result of type * propagation. * * @return {@code true} if this error can be shown to be a non-issue */ public boolean isStaticOnly() { return isStaticOnly; } /** * Set whether this error can be shown to be a non-issue because of the result of type propagation * to the given value. * * @param isStaticOnly {@code true} if this error can be shown to be a non-issue */ public void setIsStaticOnly(boolean isStaticOnly) { this.isStaticOnly = isStaticOnly; } /** * Set the source in which the error occurred to the given source. * * @param source the source in which the error occurred */ public void setSource(Source source) { this.source = source; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append((source != null) ? source.getFullName() : "<unknown source>"); builder.append("("); builder.append(offset); builder.append(".."); builder.append(offset + length - 1); builder.append("): "); //builder.append("(" + lineNumber + ":" + columnNumber + "): "); builder.append(message); return builder.toString(); } }