1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.  Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25/*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * ASM: a very small and fast Java bytecode manipulation framework
32 * Copyright (c) 2000-2011 INRIA, France Telecom
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 *    notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 *    notice, this list of conditions and the following disclaimer in the
42 *    documentation and/or other materials provided with the distribution.
43 * 3. Neither the name of the copyright holders nor the names of its
44 *    contributors may be used to endorse or promote products derived from
45 *    this software without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57 * THE POSSIBILITY OF SUCH DAMAGE.
58 */
59package jdk.internal.org.objectweb.asm.signature;
60
61import jdk.internal.org.objectweb.asm.Opcodes;
62
63/**
64 * A signature visitor that generates signatures in string format.
65 *
66 * @author Thomas Hallgren
67 * @author Eric Bruneton
68 */
69public class SignatureWriter extends SignatureVisitor {
70
71    /**
72     * Builder used to construct the signature.
73     */
74    private final StringBuilder buf = new StringBuilder();
75
76    /**
77     * Indicates if the signature contains formal type parameters.
78     */
79    private boolean hasFormals;
80
81    /**
82     * Indicates if the signature contains method parameter types.
83     */
84    private boolean hasParameters;
85
86    /**
87     * Stack used to keep track of class types that have arguments. Each element
88     * of this stack is a boolean encoded in one bit. The top of the stack is
89     * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
90     * /2.
91     */
92    private int argumentStack;
93
94    /**
95     * Constructs a new {@link SignatureWriter} object.
96     */
97    public SignatureWriter() {
98        super(Opcodes.ASM5);
99    }
100
101    // ------------------------------------------------------------------------
102    // Implementation of the SignatureVisitor interface
103    // ------------------------------------------------------------------------
104
105    @Override
106    public void visitFormalTypeParameter(final String name) {
107        if (!hasFormals) {
108            hasFormals = true;
109            buf.append('<');
110        }
111        buf.append(name);
112        buf.append(':');
113    }
114
115    @Override
116    public SignatureVisitor visitClassBound() {
117        return this;
118    }
119
120    @Override
121    public SignatureVisitor visitInterfaceBound() {
122        buf.append(':');
123        return this;
124    }
125
126    @Override
127    public SignatureVisitor visitSuperclass() {
128        endFormals();
129        return this;
130    }
131
132    @Override
133    public SignatureVisitor visitInterface() {
134        return this;
135    }
136
137    @Override
138    public SignatureVisitor visitParameterType() {
139        endFormals();
140        if (!hasParameters) {
141            hasParameters = true;
142            buf.append('(');
143        }
144        return this;
145    }
146
147    @Override
148    public SignatureVisitor visitReturnType() {
149        endFormals();
150        if (!hasParameters) {
151            buf.append('(');
152        }
153        buf.append(')');
154        return this;
155    }
156
157    @Override
158    public SignatureVisitor visitExceptionType() {
159        buf.append('^');
160        return this;
161    }
162
163    @Override
164    public void visitBaseType(final char descriptor) {
165        buf.append(descriptor);
166    }
167
168    @Override
169    public void visitTypeVariable(final String name) {
170        buf.append('T');
171        buf.append(name);
172        buf.append(';');
173    }
174
175    @Override
176    public SignatureVisitor visitArrayType() {
177        buf.append('[');
178        return this;
179    }
180
181    @Override
182    public void visitClassType(final String name) {
183        buf.append('L');
184        buf.append(name);
185        argumentStack *= 2;
186    }
187
188    @Override
189    public void visitInnerClassType(final String name) {
190        endArguments();
191        buf.append('.');
192        buf.append(name);
193        argumentStack *= 2;
194    }
195
196    @Override
197    public void visitTypeArgument() {
198        if (argumentStack % 2 == 0) {
199            ++argumentStack;
200            buf.append('<');
201        }
202        buf.append('*');
203    }
204
205    @Override
206    public SignatureVisitor visitTypeArgument(final char wildcard) {
207        if (argumentStack % 2 == 0) {
208            ++argumentStack;
209            buf.append('<');
210        }
211        if (wildcard != '=') {
212            buf.append(wildcard);
213        }
214        return this;
215    }
216
217    @Override
218    public void visitEnd() {
219        endArguments();
220        buf.append(';');
221    }
222
223    /**
224     * Returns the signature that was built by this signature writer.
225     *
226     * @return the signature that was built by this signature writer.
227     */
228    @Override
229    public String toString() {
230        return buf.toString();
231    }
232
233    // ------------------------------------------------------------------------
234    // Utility methods
235    // ------------------------------------------------------------------------
236
237    /**
238     * Ends the formal type parameters section of the signature.
239     */
240    private void endFormals() {
241        if (hasFormals) {
242            hasFormals = false;
243            buf.append('>');
244        }
245    }
246
247    /**
248     * Ends the type arguments of a class or inner class type.
249     */
250    private void endArguments() {
251        if (argumentStack % 2 != 0) {
252            buf.append('>');
253        }
254        argumentStack /= 2;
255    }
256}
257