1674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/***
2674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ASM: a very small and fast Java bytecode manipulation framework
3674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Copyright (c) 2000-2007 INRIA, France Telecom
4674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * All rights reserved.
5674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
6674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * Redistribution and use in source and binary forms, with or without
7674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * modification, are permitted provided that the following conditions
8674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * are met:
9674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 1. Redistributions of source code must retain the above copyright
10674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    notice, this list of conditions and the following disclaimer.
11674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 2. Redistributions in binary form must reproduce the above copyright
12674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    notice, this list of conditions and the following disclaimer in the
13674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    documentation and/or other materials provided with the distribution.
14674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * 3. Neither the name of the copyright holders nor the names of its
15674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    contributors may be used to endorse or promote products derived from
16674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *    this software without specific prior written permission.
17674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
18674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * THE POSSIBILITY OF SUCH DAMAGE.
29674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
30674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpackage org.mockito.asm.signature;
31674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
32674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen/**
33674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * A signature visitor that generates signatures in string format.
34674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen *
35674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Thomas Hallgren
36674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen * @author Eric Bruneton
37674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen */
38674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogenpublic class SignatureWriter implements SignatureVisitor {
39674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
40674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
41674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Buffer used to construct the signature.
42674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
43674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private final StringBuffer buf = new StringBuffer();
44674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
45674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
46674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Indicates if the signature contains formal type parameters.
47674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
48674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private boolean hasFormals;
49674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
50674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
51674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Indicates if the signature contains method parameter types.
52674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
53674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private boolean hasParameters;
54674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
55674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
56674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Stack used to keep track of class types that have arguments. Each element
57674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * of this stack is a boolean encoded in one bit. The top of the stack is
58674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
59674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * /2.
60674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
61674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private int argumentStack;
62674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
63674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
64674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Constructs a new {@link SignatureWriter} object.
65674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
66674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureWriter() {
67674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
68674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
69674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
70674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // Implementation of the SignatureVisitor interface
71674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
72674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
73674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitFormalTypeParameter(final String name) {
74674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!hasFormals) {
75674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            hasFormals = true;
76674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            buf.append('<');
77674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
78674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(name);
79674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(':');
80674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
81674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
82674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureVisitor visitClassBound() {
83674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return this;
84674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
85674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
86674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureVisitor visitInterfaceBound() {
87674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(':');
88674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return this;
89674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
90674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
91674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureVisitor visitSuperclass() {
92674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        endFormals();
93674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return this;
94674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
95674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
96674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureVisitor visitInterface() {
97674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return this;
98674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
99674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
100674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureVisitor visitParameterType() {
101674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        endFormals();
102674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!hasParameters) {
103674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            hasParameters = true;
104674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            buf.append('(');
105674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
106674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return this;
107674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
108674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
109674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureVisitor visitReturnType() {
110674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        endFormals();
111674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (!hasParameters) {
112674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            buf.append('(');
113674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
114674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(')');
115674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return this;
116674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
117674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
118674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureVisitor visitExceptionType() {
119674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append('^');
120674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return this;
121674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
122674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
123674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitBaseType(final char descriptor) {
124674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(descriptor);
125674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
126674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
127674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitTypeVariable(final String name) {
128674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append('T');
129674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(name);
130674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(';');
131674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
132674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
133674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureVisitor visitArrayType() {
134674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append('[');
135674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return this;
136674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
137674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
138674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitClassType(final String name) {
139674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append('L');
140674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(name);
141674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        argumentStack *= 2;
142674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
143674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
144674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitInnerClassType(final String name) {
145674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        endArguments();
146674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append('.');
147674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(name);
148674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        argumentStack *= 2;
149674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
150674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
151674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitTypeArgument() {
152674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (argumentStack % 2 == 0) {
153674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++argumentStack;
154674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            buf.append('<');
155674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
156674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append('*');
157674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
158674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
159674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public SignatureVisitor visitTypeArgument(final char wildcard) {
160674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (argumentStack % 2 == 0) {
161674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            ++argumentStack;
162674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            buf.append('<');
163674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
164674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (wildcard != '=') {
165674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            buf.append(wildcard);
166674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
167674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return this;
168674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
169674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
170674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public void visitEnd() {
171674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        endArguments();
172674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        buf.append(';');
173674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
174674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
175674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
176674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Returns the signature that was built by this signature writer.
177674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     *
178674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * @return the signature that was built by this signature writer.
179674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
180674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    public String toString() {
181674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        return buf.toString();
182674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
183674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
184674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
185674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // Utility methods
186674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    // ------------------------------------------------------------------------
187674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
188674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
189674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Ends the formal type parameters section of the signature.
190674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
191674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void endFormals() {
192674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (hasFormals) {
193674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            hasFormals = false;
194674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            buf.append('>');
195674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
196674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
197674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen
198674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    /**
199674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     * Ends the type arguments of a class or inner class type.
200674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen     */
201674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    private void endArguments() {
202674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        if (argumentStack % 2 != 0) {
203674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen            buf.append('>');
204674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        }
205674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen        argumentStack /= 2;
206674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen    }
207674060f01e9090cd21b3c5656cc3204912ad17a6Jon Boekenoogen}