1 /*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2007 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package org.mockito.asm.signature; 31 32 /** 33 * A signature visitor that generates signatures in string format. 34 * 35 * @author Thomas Hallgren 36 * @author Eric Bruneton 37 */ 38 public class SignatureWriter implements SignatureVisitor { 39 40 /** 41 * Buffer used to construct the signature. 42 */ 43 private final StringBuffer buf = new StringBuffer(); 44 45 /** 46 * Indicates if the signature contains formal type parameters. 47 */ 48 private boolean hasFormals; 49 50 /** 51 * Indicates if the signature contains method parameter types. 52 */ 53 private boolean hasParameters; 54 55 /** 56 * Stack used to keep track of class types that have arguments. Each element 57 * of this stack is a boolean encoded in one bit. The top of the stack is 58 * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping = 59 * /2. 60 */ 61 private int argumentStack; 62 63 /** 64 * Constructs a new {@link SignatureWriter} object. 65 */ SignatureWriter()66 public SignatureWriter() { 67 } 68 69 // ------------------------------------------------------------------------ 70 // Implementation of the SignatureVisitor interface 71 // ------------------------------------------------------------------------ 72 visitFormalTypeParameter(final String name)73 public void visitFormalTypeParameter(final String name) { 74 if (!hasFormals) { 75 hasFormals = true; 76 buf.append('<'); 77 } 78 buf.append(name); 79 buf.append(':'); 80 } 81 visitClassBound()82 public SignatureVisitor visitClassBound() { 83 return this; 84 } 85 visitInterfaceBound()86 public SignatureVisitor visitInterfaceBound() { 87 buf.append(':'); 88 return this; 89 } 90 visitSuperclass()91 public SignatureVisitor visitSuperclass() { 92 endFormals(); 93 return this; 94 } 95 visitInterface()96 public SignatureVisitor visitInterface() { 97 return this; 98 } 99 visitParameterType()100 public SignatureVisitor visitParameterType() { 101 endFormals(); 102 if (!hasParameters) { 103 hasParameters = true; 104 buf.append('('); 105 } 106 return this; 107 } 108 visitReturnType()109 public SignatureVisitor visitReturnType() { 110 endFormals(); 111 if (!hasParameters) { 112 buf.append('('); 113 } 114 buf.append(')'); 115 return this; 116 } 117 visitExceptionType()118 public SignatureVisitor visitExceptionType() { 119 buf.append('^'); 120 return this; 121 } 122 visitBaseType(final char descriptor)123 public void visitBaseType(final char descriptor) { 124 buf.append(descriptor); 125 } 126 visitTypeVariable(final String name)127 public void visitTypeVariable(final String name) { 128 buf.append('T'); 129 buf.append(name); 130 buf.append(';'); 131 } 132 visitArrayType()133 public SignatureVisitor visitArrayType() { 134 buf.append('['); 135 return this; 136 } 137 visitClassType(final String name)138 public void visitClassType(final String name) { 139 buf.append('L'); 140 buf.append(name); 141 argumentStack *= 2; 142 } 143 visitInnerClassType(final String name)144 public void visitInnerClassType(final String name) { 145 endArguments(); 146 buf.append('.'); 147 buf.append(name); 148 argumentStack *= 2; 149 } 150 visitTypeArgument()151 public void visitTypeArgument() { 152 if (argumentStack % 2 == 0) { 153 ++argumentStack; 154 buf.append('<'); 155 } 156 buf.append('*'); 157 } 158 visitTypeArgument(final char wildcard)159 public SignatureVisitor visitTypeArgument(final char wildcard) { 160 if (argumentStack % 2 == 0) { 161 ++argumentStack; 162 buf.append('<'); 163 } 164 if (wildcard != '=') { 165 buf.append(wildcard); 166 } 167 return this; 168 } 169 visitEnd()170 public void visitEnd() { 171 endArguments(); 172 buf.append(';'); 173 } 174 175 /** 176 * Returns the signature that was built by this signature writer. 177 * 178 * @return the signature that was built by this signature writer. 179 */ toString()180 public String toString() { 181 return buf.toString(); 182 } 183 184 // ------------------------------------------------------------------------ 185 // Utility methods 186 // ------------------------------------------------------------------------ 187 188 /** 189 * Ends the formal type parameters section of the signature. 190 */ endFormals()191 private void endFormals() { 192 if (hasFormals) { 193 hasFormals = false; 194 buf.append('>'); 195 } 196 } 197 198 /** 199 * Ends the type arguments of a class or inner class type. 200 */ endArguments()201 private void endArguments() { 202 if (argumentStack % 2 != 0) { 203 buf.append('>'); 204 } 205 argumentStack /= 2; 206 } 207 }