| /* |
| * Copyright 2016 Google Inc. All Rights Reserved. |
| * |
| * 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.turbine.model; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.escape.SourceCodeEscapers; |
| import javax.lang.model.element.AnnotationValue; |
| import javax.lang.model.element.AnnotationValueVisitor; |
| import org.checkerframework.checker.nullness.qual.Nullable; |
| |
| /** |
| * Compile-time constant expressions, including literals of primitive or String type, class |
| * literals, enum constants, and annotation literals. |
| */ |
| public abstract class Const { |
| |
| @Override |
| public abstract int hashCode(); |
| |
| @Override |
| public abstract boolean equals(@Nullable Object obj); |
| |
| @Override |
| public abstract String toString(); |
| |
| /** The constant kind. */ |
| public abstract Kind kind(); |
| |
| /** A constant kind. */ |
| public enum Kind { |
| ARRAY, |
| PRIMITIVE, |
| CLASS_LITERAL, |
| ENUM_CONSTANT, |
| ANNOTATION |
| } |
| |
| /** An invalid constant cast. */ |
| public static class ConstCastError extends RuntimeException { |
| public ConstCastError(TurbineConstantTypeKind type, TurbineConstantTypeKind target) { |
| super(String.format("%s cannot be converted to %s", type, target)); |
| } |
| } |
| |
| /** Subtypes of {@link Const} for primitive and String literals. */ |
| public abstract static class Value extends Const implements AnnotationValue { |
| public abstract TurbineConstantTypeKind constantTypeKind(); |
| |
| @Override |
| public Kind kind() { |
| return Kind.PRIMITIVE; |
| } |
| } |
| |
| /** A boolean literal value. */ |
| public static class BooleanValue extends Value { |
| private final boolean value; |
| |
| public BooleanValue(boolean value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String toString() { |
| return String.valueOf(value); |
| } |
| |
| @Override |
| public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { |
| return v.visitBoolean(value, p); |
| } |
| |
| @Override |
| public TurbineConstantTypeKind constantTypeKind() { |
| return TurbineConstantTypeKind.BOOLEAN; |
| } |
| |
| public boolean value() { |
| return value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Boolean.hashCode(value); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof BooleanValue && value == ((BooleanValue) obj).value(); |
| } |
| } |
| |
| /** An int literal value. */ |
| public static class IntValue extends Value { |
| |
| private final int value; |
| |
| public IntValue(int value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String toString() { |
| return String.valueOf(value); |
| } |
| |
| @Override |
| public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { |
| return v.visitInt(value, p); |
| } |
| |
| @Override |
| public TurbineConstantTypeKind constantTypeKind() { |
| return TurbineConstantTypeKind.INT; |
| } |
| |
| public int value() { |
| return value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Integer.hashCode(value); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof IntValue && value == ((IntValue) obj).value; |
| } |
| } |
| |
| /** A long literal value. */ |
| public static class LongValue extends Value { |
| private final long value; |
| |
| public LongValue(long value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String toString() { |
| return value + "L"; |
| } |
| |
| @Override |
| public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { |
| return v.visitLong(value, p); |
| } |
| |
| @Override |
| public TurbineConstantTypeKind constantTypeKind() { |
| return TurbineConstantTypeKind.LONG; |
| } |
| |
| public long value() { |
| return value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Long.hashCode(value); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof LongValue && value == ((LongValue) obj).value; |
| } |
| } |
| |
| /** A char literal value. */ |
| public static class CharValue extends Value { |
| private final char value; |
| |
| public CharValue(char value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String toString() { |
| return "'" + SourceCodeEscapers.javaCharEscaper().escape(String.valueOf(value)) + "'"; |
| } |
| |
| @Override |
| public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { |
| return v.visitChar(value, p); |
| } |
| |
| @Override |
| public TurbineConstantTypeKind constantTypeKind() { |
| return TurbineConstantTypeKind.CHAR; |
| } |
| |
| public char value() { |
| return value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Character.hashCode(value); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof CharValue && value == ((CharValue) obj).value; |
| } |
| } |
| |
| /** A float literal value. */ |
| public static class FloatValue extends Value { |
| private final float value; |
| |
| public FloatValue(float value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String toString() { |
| if (Float.isNaN(value)) { |
| return "0.0f/0.0f"; |
| } |
| return value + "f"; |
| } |
| |
| @Override |
| public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { |
| return v.visitFloat(value, p); |
| } |
| |
| @Override |
| public TurbineConstantTypeKind constantTypeKind() { |
| return TurbineConstantTypeKind.FLOAT; |
| } |
| |
| public float value() { |
| return value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Float.hashCode(value); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof FloatValue && value == ((FloatValue) obj).value; |
| } |
| } |
| |
| /** A double literal value. */ |
| public static class DoubleValue extends Value { |
| private final double value; |
| |
| public DoubleValue(double value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String toString() { |
| if (Double.isNaN(value)) { |
| return "0.0/0.0"; |
| } |
| if (value == Double.POSITIVE_INFINITY) { |
| return "1.0/0.0"; |
| } |
| if (value == Double.NEGATIVE_INFINITY) { |
| return "-1.0/0.0"; |
| } |
| return String.valueOf(value); |
| } |
| |
| @Override |
| public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { |
| return v.visitDouble(value, p); |
| } |
| |
| @Override |
| public TurbineConstantTypeKind constantTypeKind() { |
| return TurbineConstantTypeKind.DOUBLE; |
| } |
| |
| public double value() { |
| return value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Double.hashCode(value); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof DoubleValue && value == ((DoubleValue) obj).value; |
| } |
| } |
| |
| /** A String literal value. */ |
| public static class StringValue extends Value { |
| private final String value; |
| |
| public StringValue(String value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String toString() { |
| return '"' + SourceCodeEscapers.javaCharEscaper().escape(value) + '"'; |
| } |
| |
| @Override |
| public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { |
| return v.visitString(value, p); |
| } |
| |
| @Override |
| public TurbineConstantTypeKind constantTypeKind() { |
| return TurbineConstantTypeKind.STRING; |
| } |
| |
| public String value() { |
| return value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public int hashCode() { |
| return value.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof StringValue && value.equals(((StringValue) obj).value); |
| } |
| } |
| |
| /** A short literal value. */ |
| public static class ShortValue extends Value { |
| private final short value; |
| |
| public ShortValue(short value) { |
| this.value = value; |
| } |
| |
| @Override |
| public String toString() { |
| return String.valueOf(value); |
| } |
| |
| @Override |
| public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { |
| return v.visitShort(value, p); |
| } |
| |
| @Override |
| public TurbineConstantTypeKind constantTypeKind() { |
| return TurbineConstantTypeKind.SHORT; |
| } |
| |
| public short value() { |
| return value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Short.hashCode(value); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof ShortValue && value == ((ShortValue) obj).value; |
| } |
| } |
| |
| /** A byte literal value. */ |
| public static class ByteValue extends Value { |
| |
| private final byte value; |
| |
| public ByteValue(byte value) { |
| this.value = value; |
| } |
| |
| @Override |
| public TurbineConstantTypeKind constantTypeKind() { |
| return TurbineConstantTypeKind.BYTE; |
| } |
| |
| public byte value() { |
| return value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Byte.hashCode(value); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof ByteValue && value == ((ByteValue) obj).value; |
| } |
| |
| @Override |
| public String toString() { |
| return String.format("(byte)0x%02x", value); |
| } |
| |
| @Override |
| public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) { |
| return v.visitByte(value, p); |
| } |
| } |
| |
| /** A constant array literal (e.g. in an annotation). */ |
| public static class ArrayInitValue extends Const { |
| |
| private final ImmutableList<Const> elements; |
| |
| public ArrayInitValue(ImmutableList<Const> elements) { |
| this.elements = elements; |
| } |
| |
| @Override |
| public Kind kind() { |
| return Kind.ARRAY; |
| } |
| |
| public ImmutableList<Const> elements() { |
| return elements; |
| } |
| |
| @Override |
| public int hashCode() { |
| return elements.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| return obj instanceof ArrayInitValue && elements.equals(((ArrayInitValue) obj).elements); |
| } |
| |
| @Override |
| public String toString() { |
| return "{" + Joiner.on(", ").join(elements) + "}"; |
| } |
| } |
| } |