/* * Copyright 2009 Google Inc. * * 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.common.css.compiler.ast; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.css.SourceCodeLocation; import java.text.MessageFormat; /** * GSS parser error description. * */ public class GssError implements Comparable<GssError> { private String message; private SourceCodeLocation location; private String line = null; private String format = null; public GssError(String message, SourceCodeLocation location) { Preconditions.checkNotNull(message); Preconditions.checkNotNull(location); this.message = message; this.location = location; } public SourceCodeLocation getLocation() { return location; } public String getMessage() { return message; } public String getLine() { if (line == null) { String source = location.getSourceCode().getFileContents(); int beginLineIndex = location.getBeginCharacterIndex() - location.getBeginIndexInLine() + 1; int endLineIndex = source.indexOf('\n', location.getBeginCharacterIndex()); if (endLineIndex == -1) { endLineIndex = source.length(); } line = source.substring(beginLineIndex, endLineIndex); } return line; } public String format() { if (format == null) { format = messageFormat().apply(); } return format; } /** * A String template, together with values for the template holes. * {@see java.text.MessageFormat} */ public static class MessageFormatArgs { public final String pattern; public final Object[] arguments; public MessageFormatArgs(String pattern, Object... arguments) { this.pattern = pattern; this.arguments = arguments; } public String apply() { return MessageFormat.format(pattern, arguments); } } /** * Returns a MessageFormatArgs representation of the object. This is * a parbaked precursor to the value given by {@link #format}, * intended for use in FormattingLoggers and other contexts where it * is useful to maintain separation between boilerplate and details. */ public MessageFormatArgs messageFormat() { if (location.isUnknown()) { return new MessageFormatArgs("{0} at unknown location", message); } else if (location.getSourceCode().getFileName() == null) { return new MessageFormatArgs( "{0} at line {1} column {2}:\n{3}\n{4}^\n", message, location.getBeginLineNumber(), location.getBeginIndexInLine(), getLine(), Strings.repeat(" ", location.getBeginIndexInLine() - 1)); } else { return new MessageFormatArgs( "{0} in {1} at line {2} column {3}:\n{4}\n{5}^\n", message, location.getSourceCode().getFileName(), location.getBeginLineNumber(), location.getBeginIndexInLine(), getLine(), Strings.repeat(" ", location.getBeginIndexInLine() - 1)); } } @Override public boolean equals(Object o) { // Generated by Intellij IDEA if (this == o) return true; if (!(o instanceof GssError)) return false; GssError gssError = (GssError) o; if (!location.equals(gssError.location)) return false; if (!message.equals(gssError.message)) return false; return true; } @Override public int hashCode() { return 31 * message.hashCode() + location.hashCode(); } /** * Compare errors by source name, location and message. */ @Override public int compareTo(GssError o) { String source1 = location.getSourceCode().getFileName(); String source2 = o.location.getSourceCode().getFileName(); if (source1 != null && source2 != null) { int sourceCompare = source1.compareTo(source2); if (sourceCompare != 0) { return sourceCompare; } } else if (source1 == null && source2 != null) { return -1; } else if (source1 != null && source2 == null) { return 1; } // source1 and source2 are the same file. int locationCompare = location.compareTo(o.location); if (locationCompare != 0) { return locationCompare; } return message.compareTo(o.message); } }