duke@1: /* ohair@554: * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package com.sun.tools.javac.code; duke@1: duke@1: import java.util.LinkedHashMap; duke@1: import java.util.Map; duke@1: import javax.lang.model.element.AnnotationMirror; duke@1: import javax.lang.model.element.AnnotationValue; duke@1: import javax.lang.model.element.AnnotationValueVisitor; duke@1: import javax.lang.model.type.DeclaredType; duke@1: import com.sun.tools.javac.code.Symbol.*; duke@1: import com.sun.tools.javac.util.*; duke@1: duke@1: import static com.sun.tools.javac.code.TypeTags.*; duke@1: duke@1: /** An annotation value. duke@1: * duke@1: *

This is NOT part of any API supported by Sun Microsystems. If duke@1: * you write code that depends on this, you do so at your own risk. duke@1: * This code and its internal interfaces are subject to change or duke@1: * deletion without notice. duke@1: */ duke@1: public abstract class Attribute implements AnnotationValue { duke@1: duke@1: /** The type of the annotation element. */ duke@1: public Type type; duke@1: duke@1: public Attribute(Type type) { duke@1: this.type = type; duke@1: } duke@1: duke@1: public abstract void accept(Visitor v); duke@1: duke@1: public Object getValue() { duke@1: throw new UnsupportedOperationException(); duke@1: } duke@1: duke@1: public R accept(AnnotationValueVisitor v, P p) { duke@1: throw new UnsupportedOperationException(); duke@1: } duke@1: duke@1: duke@1: /** The value for an annotation element of primitive type or String. */ duke@1: public static class Constant extends Attribute { duke@1: public final Object value; duke@1: public void accept(Visitor v) { v.visitConstant(this); } duke@1: public Constant(Type type, Object value) { duke@1: super(type); duke@1: this.value = value; duke@1: } duke@1: public String toString() { duke@1: return Constants.format(value, type); duke@1: } duke@1: public Object getValue() { duke@1: return Constants.decode(value, type); duke@1: } duke@1: public R accept(AnnotationValueVisitor v, P p) { duke@1: if (value instanceof String) duke@1: return v.visitString((String) value, p); duke@1: if (value instanceof Integer) { duke@1: int i = (Integer) value; duke@1: switch (type.tag) { duke@1: case BOOLEAN: return v.visitBoolean(i != 0, p); duke@1: case CHAR: return v.visitChar((char) i, p); duke@1: case BYTE: return v.visitByte((byte) i, p); duke@1: case SHORT: return v.visitShort((short) i, p); duke@1: case INT: return v.visitInt(i, p); duke@1: } duke@1: } duke@1: switch (type.tag) { duke@1: case LONG: return v.visitLong((Long) value, p); duke@1: case FLOAT: return v.visitFloat((Float) value, p); duke@1: case DOUBLE: return v.visitDouble((Double) value, p); duke@1: } duke@1: throw new AssertionError("Bad annotation element value: " + value); duke@1: } duke@1: } duke@1: duke@1: /** The value for an annotation element of type java.lang.Class, duke@1: * represented as a ClassSymbol. duke@1: */ duke@1: public static class Class extends Attribute { duke@1: public final Type type; duke@1: public void accept(Visitor v) { v.visitClass(this); } duke@1: public Class(Types types, Type type) { duke@1: super(makeClassType(types, type)); duke@1: this.type = type; duke@1: } duke@1: static Type makeClassType(Types types, Type type) { duke@1: Type arg = type.isPrimitive() duke@1: ? types.boxedClass(type).type duke@1: : types.erasure(type); duke@1: return new Type.ClassType(types.syms.classType.getEnclosingType(), duke@1: List.of(arg), duke@1: types.syms.classType.tsym); duke@1: } duke@1: public String toString() { duke@1: return type + ".class"; duke@1: } duke@1: public Type getValue() { duke@1: return type; duke@1: } duke@1: public R accept(AnnotationValueVisitor v, P p) { duke@1: return v.visitType(type, p); duke@1: } duke@1: } duke@1: duke@1: /** A compound annotation element value, the type of which is an duke@1: * attribute interface. duke@1: */ duke@1: public static class Compound extends Attribute implements AnnotationMirror { duke@1: /** The attributes values, as pairs. Each pair contains a duke@1: * reference to the accessing method in the attribute interface duke@1: * and the value to be returned when that method is called to duke@1: * access this attribute. duke@1: */ duke@1: public final List> values; duke@1: public Compound(Type type, duke@1: List> values) { duke@1: super(type); duke@1: this.values = values; duke@1: } duke@1: public void accept(Visitor v) { v.visitCompound(this); } duke@1: duke@1: /** duke@1: * Returns a string representation of this annotation. duke@1: * String is of one of the forms: duke@1: * @com.example.foo(name1=val1, name2=val2) duke@1: * @com.example.foo(val) duke@1: * @com.example.foo duke@1: * Omit parens for marker annotations, and omit "value=" when allowed. duke@1: */ duke@1: public String toString() { duke@1: StringBuilder buf = new StringBuilder(); duke@1: buf.append("@"); duke@1: buf.append(type); duke@1: int len = values.length(); duke@1: if (len > 0) { duke@1: buf.append('('); duke@1: boolean first = true; duke@1: for (Pair value : values) { duke@1: if (!first) buf.append(", "); duke@1: first = false; duke@1: duke@1: Name name = value.fst.name; jjg@113: if (len > 1 || name != name.table.names.value) { duke@1: buf.append(name); duke@1: buf.append('='); duke@1: } duke@1: buf.append(value.snd); duke@1: } duke@1: buf.append(')'); duke@1: } duke@1: return buf.toString(); duke@1: } duke@1: duke@1: public Attribute member(Name member) { duke@1: for (Pair pair : values) duke@1: if (pair.fst.name == member) return pair.snd; duke@1: return null; duke@1: } duke@1: duke@1: public Attribute.Compound getValue() { duke@1: return this; duke@1: } duke@1: duke@1: public R accept(AnnotationValueVisitor v, P p) { duke@1: return v.visitAnnotation(this, p); duke@1: } duke@1: duke@1: public DeclaredType getAnnotationType() { duke@1: return (DeclaredType) type; duke@1: } duke@1: duke@1: public Map getElementValues() { duke@1: Map valmap = duke@1: new LinkedHashMap(); duke@1: for (Pair value : values) duke@1: valmap.put(value.fst, value.snd); duke@1: return valmap; duke@1: } duke@1: } duke@1: jjg@308: public static class TypeCompound extends Compound { jjg@308: public TypeAnnotationPosition position; jjg@308: public TypeCompound(Compound compound, jjg@308: TypeAnnotationPosition position) { jjg@308: this(compound.type, compound.values, position); jjg@308: } jjg@308: public TypeCompound(Type type, jjg@308: List> values, jjg@308: TypeAnnotationPosition position) { jjg@308: super(type, values); jjg@308: this.position = position; jjg@308: } jjg@308: jjg@308: } jjg@308: duke@1: /** The value for an annotation element of an array type. duke@1: */ duke@1: public static class Array extends Attribute { duke@1: public final Attribute[] values; duke@1: public Array(Type type, Attribute[] values) { duke@1: super(type); duke@1: this.values = values; duke@1: } duke@1: public void accept(Visitor v) { v.visitArray(this); } duke@1: public String toString() { duke@1: StringBuilder buf = new StringBuilder(); duke@1: buf.append('{'); duke@1: boolean first = true; duke@1: for (Attribute value : values) { duke@1: if (!first) duke@1: buf.append(", "); duke@1: first = false; duke@1: buf.append(value); duke@1: } duke@1: buf.append('}'); duke@1: return buf.toString(); duke@1: } duke@1: public List getValue() { duke@1: return List.from(values); duke@1: } duke@1: public R accept(AnnotationValueVisitor v, P p) { duke@1: return v.visitArray(getValue(), p); duke@1: } duke@1: } duke@1: duke@1: /** The value for an annotation element of an enum type. duke@1: */ duke@1: public static class Enum extends Attribute { duke@1: public VarSymbol value; duke@1: public Enum(Type type, VarSymbol value) { duke@1: super(type); duke@1: assert value != null; duke@1: this.value = value; duke@1: } duke@1: public void accept(Visitor v) { v.visitEnum(this); } duke@1: public String toString() { duke@1: return value.enclClass() + "." + value; // qualified name duke@1: } duke@1: public VarSymbol getValue() { duke@1: return value; duke@1: } duke@1: public R accept(AnnotationValueVisitor v, P p) { duke@1: return v.visitEnumConstant(value, p); duke@1: } duke@1: } duke@1: duke@1: public static class Error extends Attribute { duke@1: public Error(Type type) { duke@1: super(type); duke@1: } duke@1: public void accept(Visitor v) { v.visitError(this); } duke@1: public String toString() { duke@1: return ""; duke@1: } duke@1: public String getValue() { duke@1: return toString(); duke@1: } duke@1: public R accept(AnnotationValueVisitor v, P p) { duke@1: return v.visitString(toString(), p); duke@1: } duke@1: } duke@1: duke@1: /** A visitor type for dynamic dispatch on the kind of attribute value. */ duke@1: public static interface Visitor { duke@1: void visitConstant(Attribute.Constant value); duke@1: void visitClass(Attribute.Class clazz); duke@1: void visitCompound(Attribute.Compound compound); duke@1: void visitArray(Attribute.Array array); duke@1: void visitEnum(Attribute.Enum e); duke@1: void visitError(Attribute.Error e); duke@1: } duke@1: }