Home | History | Annotate | Download | only in diag
      1 /*
      2  * Copyright 2016 Google Inc. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.turbine.diag;
     18 
     19 import static com.google.common.base.MoreObjects.firstNonNull;
     20 
     21 import com.google.common.base.CharMatcher;
     22 import com.google.common.base.Strings;
     23 
     24 /** A compilation error. */
     25 public class TurbineError extends Error {
     26 
     27   /** A diagnostic kind. */
     28   public enum ErrorKind {
     29     UNEXPECTED_INPUT("unexpected input: %c"),
     30     UNEXPECTED_IDENTIFIER("unexpected identifier '%s'"),
     31     UNEXPECTED_EOF("unexpected end of input"),
     32     EXPECTED_TOKEN("expected token %s"),
     33     INVALID_LITERAL("invalid literal: %s"),
     34     UNEXPECTED_TYPE_PARAMETER("unexpected type parameter %s"),
     35     SYMBOL_NOT_FOUND("symbol not found %s"),
     36     TYPE_PARAMETER_QUALIFIER("type parameter used as type qualifier"),
     37     UNEXPECTED_TOKEN("unexpected token: %s"),
     38     INVALID_ANNOTATION_ARGUMENT("invalid annotation argument"),
     39     CANNOT_RESOLVE("cannot resolve %s"),
     40     EXPRESSION_ERROR("could not evaluate constant expression"),
     41     CYCLIC_HIERARCHY("cycle in class hierarchy: %s"),
     42     NOT_AN_ANNOTATION("%s is not an annotation"),
     43     NONREPEATABLE_ANNOTATION("%s is not @Repeatable"),
     44     DUPLICATE_DECLARATION("duplicate declaration of %s");
     45 
     46     private final String message;
     47 
     48     ErrorKind(String message) {
     49       this.message = message;
     50     }
     51 
     52     String format(Object... args) {
     53       return String.format(message, args);
     54     }
     55   }
     56 
     57   /**
     58    * Formats a diagnostic.
     59    *
     60    * @param source the source file
     61    * @param position the diagnostic position
     62    * @param kind the error kind
     63    * @param args format args
     64    */
     65   public static TurbineError format(
     66       SourceFile source, int position, ErrorKind kind, Object... args) {
     67     String path = firstNonNull(source.path(), "<>");
     68     LineMap lineMap = LineMap.create(source.source());
     69     int lineNumber = lineMap.lineNumber(position);
     70     int column = lineMap.column(position);
     71     String message = kind.format(args);
     72 
     73     StringBuilder sb = new StringBuilder(path).append(":");
     74     sb.append(lineNumber).append(": error: ");
     75     sb.append(message.trim()).append(System.lineSeparator());
     76     sb.append(CharMatcher.breakingWhitespace().trimTrailingFrom(lineMap.line(position)))
     77         .append(System.lineSeparator());
     78     sb.append(Strings.repeat(" ", column)).append('^');
     79     String diagnostic = sb.toString();
     80     return new TurbineError(kind, diagnostic);
     81   }
     82 
     83   final ErrorKind kind;
     84 
     85   private TurbineError(ErrorKind kind, String diagnostic) {
     86     super(diagnostic);
     87     this.kind = kind;
     88   }
     89 
     90   /** The diagnostic kind. */
     91   public ErrorKind kind() {
     92     return kind;
     93   }
     94 }
     95