SymbolMetadata.java revision 3828:d30434bde0a8
143166Snsouch/*
243166Snsouch * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
343166Snsouch * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
443166Snsouch *
543166Snsouch * This code is free software; you can redistribute it and/or modify it
643166Snsouch * under the terms of the GNU General Public License version 2 only, as
743166Snsouch * published by the Free Software Foundation.  Oracle designates this
843166Snsouch * particular file as subject to the "Classpath" exception as provided
943166Snsouch * by Oracle in the LICENSE file that accompanied this code.
1043166Snsouch *
1143166Snsouch * This code is distributed in the hope that it will be useful, but WITHOUT
1243166Snsouch * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1343166Snsouch * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1443166Snsouch * version 2 for more details (a copy is included in the LICENSE file that
1543166Snsouch * accompanied this code).
1643166Snsouch *
1743166Snsouch * You should have received a copy of the GNU General Public License version
1843166Snsouch * 2 along with this work; if not, write to the Free Software Foundation,
1943166Snsouch * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2043166Snsouch *
2143166Snsouch * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2243166Snsouch * or visit www.oracle.com if you need additional information or have any
2343166Snsouch * questions.
2443166Snsouch */
2543166Snsouch
2643166Snsouchpackage com.sun.tools.javac.code;
27116192Sobrien
28116192Sobrien
29116192Sobrienimport com.sun.tools.javac.code.Attribute.TypeCompound;
3043166Snsouchimport com.sun.tools.javac.code.Kinds.Kind;
3143166Snsouchimport com.sun.tools.javac.util.Assert;
32165951Sjhbimport com.sun.tools.javac.util.List;
3343166Snsouchimport com.sun.tools.javac.util.ListBuffer;
34165951Sjhb
3543166Snsouch/**
36165951Sjhb * Container for all annotations (attributes in javac) on a Symbol.
3746651Speter *
38165951Sjhb * This class is explicitly mutable. Its contents will change when attributes
3943166Snsouch * are annotated onto the Symbol. However this class depends on the facts that
4043166Snsouch * List (in javac) is immutable.
4143166Snsouch *
4243166Snsouch * An instance of this class can be in one of three states:
43119288Simp *
44119288Simp * NOT_STARTED indicates that the Symbol this instance belongs to has not been
4543166Snsouch * annotated (yet). Specifically if the declaration is not annotated this
4643166Snsouch * instance will never move past NOT_STARTED. You can never go back to
4743166Snsouch * NOT_STARTED.
4843166Snsouch *
49165951Sjhb * IN_PROGRESS annotations have been found on the declaration. Will be processed
50165951Sjhb * later. You can reset to IN_PROGRESS. While IN_PROGRESS you can set the list
51165951Sjhb * of attributes (and this moves out of the IN_PROGRESS state).
52165951Sjhb *
53165951Sjhb * "unnamed" this SymbolMetadata contains some attributes, possibly the final set.
54165951Sjhb * While in this state you can only prepend or append to the attributes not set
55165951Sjhb * it directly. You can also move back to the IN_PROGRESS state using reset().
56197128Savg *
57197128Savg * <p><b>This is NOT part of any supported API. If you write code that depends
58165951Sjhb * on this, you do so at your own risk. This code and its internal interfaces
5943166Snsouch * are subject to change or deletion without notice.</b>
60162289Sjhb */
61165951Sjhbpublic class SymbolMetadata {
62165951Sjhb
63165951Sjhb    private static final List<Attribute.Compound> DECL_NOT_STARTED = List.of(null);
64165951Sjhb    private static final List<Attribute.Compound> DECL_IN_PROGRESS = List.of(null);
6543166Snsouch
6643166Snsouch    /*
67165951Sjhb     * This field should never be null
68165951Sjhb     */
69165951Sjhb    private List<Attribute.Compound> attributes = DECL_NOT_STARTED;
70165951Sjhb
71162234Sjhb    /*
7243166Snsouch     * Type attributes for this symbol.
7343166Snsouch     * This field should never be null.
7443166Snsouch     */
7543166Snsouch    private List<Attribute.TypeCompound> type_attributes = List.nil();
7643166Snsouch
7743166Snsouch    /*
7843166Snsouch     * Type attributes of initializers in this class.
7943166Snsouch     * Unused if the current symbol is not a ClassSymbol.
8043166Snsouch     */
81162234Sjhb    private List<Attribute.TypeCompound> init_type_attributes = List.nil();
82165951Sjhb
83165951Sjhb    /*
84165951Sjhb     * Type attributes of class initializers in this class.
85165951Sjhb     * Unused if the current symbol is not a ClassSymbol.
86165951Sjhb     */
87162289Sjhb    private List<Attribute.TypeCompound> clinit_type_attributes = List.nil();
88165951Sjhb
89165951Sjhb    /*
90165951Sjhb     * The Symbol this SymbolMetadata instance belongs to
9143166Snsouch     */
92165951Sjhb    private final Symbol sym;
93165951Sjhb
94165951Sjhb    public SymbolMetadata(Symbol sym) {
95165951Sjhb        this.sym = sym;
96165951Sjhb    }
97165951Sjhb
98165951Sjhb    public List<Attribute.Compound> getDeclarationAttributes() {
99165951Sjhb        return filterDeclSentinels(attributes);
100165951Sjhb    }
101234677Savg
102234677Savg    public List<Attribute.TypeCompound> getTypeAttributes() {
103234677Savg        return type_attributes;
104197128Savg    }
105234213Savg
106234213Savg    public List<Attribute.TypeCompound> getInitTypeAttributes() {
107234213Savg        return init_type_attributes;
108197128Savg    }
109197128Savg
110197128Savg    public List<Attribute.TypeCompound> getClassInitTypeAttributes() {
111165951Sjhb        return clinit_type_attributes;
112165951Sjhb    }
113165951Sjhb
11443166Snsouch    public void setDeclarationAttributes(List<Attribute.Compound> a) {
115165951Sjhb        Assert.check(pendingCompletion() || !isStarted());
116165951Sjhb        if (a == null) {
117162289Sjhb            throw new NullPointerException();
118165951Sjhb        }
119165951Sjhb        attributes = a;
120165951Sjhb    }
121165951Sjhb
122165951Sjhb    public void setTypeAttributes(List<Attribute.TypeCompound> a) {
123197128Savg        if (a == null) {
124165951Sjhb            throw new NullPointerException();
125162289Sjhb        }
126178972Sjhb        type_attributes = a;
127178972Sjhb    }
128165951Sjhb
12943166Snsouch    public void setInitTypeAttributes(List<Attribute.TypeCompound> a) {
130197128Savg        if (a == null) {
131197128Savg            throw new NullPointerException();
132197128Savg        }
133197128Savg        init_type_attributes = a;
134197128Savg    }
135197128Savg
136197128Savg    public void setClassInitTypeAttributes(List<Attribute.TypeCompound> a) {
137197128Savg        if (a == null) {
138197128Savg            throw new NullPointerException();
139197128Savg        }
140197128Savg        clinit_type_attributes = a;
141165951Sjhb    }
142165951Sjhb
143165951Sjhb    public void setAttributes(SymbolMetadata other) {
144165951Sjhb        if (other == null) {
145165951Sjhb            throw new NullPointerException();
146165951Sjhb        }
147165951Sjhb        setDeclarationAttributes(other.getDeclarationAttributes());
148165951Sjhb        if ((sym.flags() & Flags.BRIDGE) != 0) {
14943166Snsouch            Assert.check(other.sym.kind == Kind.MTH);
150197128Savg            ListBuffer<TypeCompound> typeAttributes = new ListBuffer<>();
151197128Savg            for (TypeCompound tc : other.getTypeAttributes()) {
152197128Savg                // Carry over only contractual type annotations: i.e nothing interior to method body.
153197128Savg                if (!tc.position.type.isLocal())
154197128Savg                    typeAttributes.append(tc);
155165951Sjhb            }
156197128Savg            setTypeAttributes(typeAttributes.toList());
157197128Savg        } else {
158197128Savg            setTypeAttributes(other.getTypeAttributes());
159165951Sjhb        }
160165951Sjhb        if (sym.kind == Kind.TYP) {
161165951Sjhb            setInitTypeAttributes(other.getInitTypeAttributes());
162165951Sjhb            setClassInitTypeAttributes(other.getClassInitTypeAttributes());
163165951Sjhb        }
164165951Sjhb    }
165197128Savg
166197128Savg    public SymbolMetadata reset() {
167197128Savg        attributes = DECL_IN_PROGRESS;
168165951Sjhb        return this;
169165951Sjhb    }
170165951Sjhb
171197128Savg    public boolean isEmpty() {
172165951Sjhb        return !isStarted()
173197128Savg                || pendingCompletion()
174168870Sjhb                || attributes.isEmpty();
17543166Snsouch    }
176197325Savg
177197325Savg    public boolean isTypesEmpty() {
178197325Savg        return type_attributes.isEmpty();
179197325Savg    }
180197325Savg
181197325Savg    public boolean pendingCompletion() {
182197128Savg        return attributes == DECL_IN_PROGRESS;
183197128Savg    }
184197128Savg
185197128Savg    public SymbolMetadata append(List<Attribute.Compound> l) {
186165951Sjhb        attributes = filterDeclSentinels(attributes);
187165951Sjhb
188165951Sjhb        if (l.isEmpty()) {
189165951Sjhb            // no-op
19046651Speter        } else if (attributes.isEmpty()) {
191165951Sjhb            attributes = l;
192165951Sjhb        } else {
193197128Savg            attributes = attributes.appendList(l);
194197128Savg        }
195197128Savg        return this;
196165951Sjhb    }
197165951Sjhb
198165951Sjhb    public SymbolMetadata appendUniqueTypes(List<Attribute.TypeCompound> l) {
199165951Sjhb        if (l.isEmpty()) {
200165951Sjhb            // no-op
201165951Sjhb        } else if (type_attributes.isEmpty()) {
202165951Sjhb            type_attributes = l;
20343166Snsouch        } else {
204179622Sjhb            // TODO: in case we expect a large number of annotations, this
205179622Sjhb            // might be inefficient.
206165951Sjhb            for (Attribute.TypeCompound tc : l) {
207165951Sjhb                if (!type_attributes.contains(tc))
208165951Sjhb                    type_attributes = type_attributes.append(tc);
209165951Sjhb            }
210162289Sjhb        }
211197128Savg        return this;
212165951Sjhb    }
213165951Sjhb
214165951Sjhb    public SymbolMetadata appendInitTypeAttributes(List<Attribute.TypeCompound> l) {
215165951Sjhb        if (l.isEmpty()) {
216165951Sjhb            // no-op
217165951Sjhb        } else if (init_type_attributes.isEmpty()) {
218165951Sjhb            init_type_attributes = l;
219165951Sjhb        } else {
220165951Sjhb            init_type_attributes = init_type_attributes.appendList(l);
221162289Sjhb        }
222165951Sjhb        return this;
223165951Sjhb    }
224165951Sjhb
225165951Sjhb    public SymbolMetadata appendClassInitTypeAttributes(List<Attribute.TypeCompound> l) {
226165951Sjhb        if (l.isEmpty()) {
22743166Snsouch            // no-op
228165951Sjhb        } else if (clinit_type_attributes.isEmpty()) {
229165951Sjhb            clinit_type_attributes = l;
230165951Sjhb        } else {
231165951Sjhb            clinit_type_attributes = clinit_type_attributes.appendList(l);
232165951Sjhb        }
233162289Sjhb        return this;
234165951Sjhb    }
23543166Snsouch
236162289Sjhb    public SymbolMetadata prepend(List<Attribute.Compound> l) {
237165951Sjhb        attributes = filterDeclSentinels(attributes);
238162289Sjhb
239165951Sjhb        if (l.isEmpty()) {
240165951Sjhb            // no-op
241165951Sjhb        } else if (attributes.isEmpty()) {
242162289Sjhb            attributes = l;
243165951Sjhb        } else {
244165951Sjhb            attributes = attributes.prependList(l);
245165951Sjhb        }
246165951Sjhb        return this;
247165951Sjhb    }
248165951Sjhb
249165951Sjhb    private List<Attribute.Compound> filterDeclSentinels(List<Attribute.Compound> a) {
250165951Sjhb        return (a == DECL_IN_PROGRESS || a == DECL_NOT_STARTED)
251165951Sjhb                ? List.nil()
252165951Sjhb                : a;
253165951Sjhb    }
25443166Snsouch
255165951Sjhb    private boolean isStarted() {
256165951Sjhb        return attributes != DECL_NOT_STARTED;
257165951Sjhb    }
25843166Snsouch}
259165951Sjhb