1 /* 2 * Copyright 2016 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.turbine.bytecode.sig; 18 19 import com.google.turbine.bytecode.sig.Sig.ArrayTySig; 20 import com.google.turbine.bytecode.sig.Sig.BaseTySig; 21 import com.google.turbine.bytecode.sig.Sig.ClassSig; 22 import com.google.turbine.bytecode.sig.Sig.ClassTySig; 23 import com.google.turbine.bytecode.sig.Sig.LowerBoundTySig; 24 import com.google.turbine.bytecode.sig.Sig.MethodSig; 25 import com.google.turbine.bytecode.sig.Sig.SimpleClassTySig; 26 import com.google.turbine.bytecode.sig.Sig.TyParamSig; 27 import com.google.turbine.bytecode.sig.Sig.TySig; 28 import com.google.turbine.bytecode.sig.Sig.TyVarSig; 29 import com.google.turbine.bytecode.sig.Sig.UpperBoundTySig; 30 import com.google.turbine.bytecode.sig.Sig.WildTySig; 31 32 /** Writes {@link Sig}s to their serialized string equivalents. */ 33 public class SigWriter { 34 35 /** Writes a {@link ClassSig} to a string. */ classSig(ClassSig classSig)36 public static String classSig(ClassSig classSig) { 37 SigWriter writer = new SigWriter(); 38 writer.printClassSig(classSig); 39 return writer.toString(); 40 } 41 42 /** Writes a {@link TySig} to a string. */ type(TySig tySig)43 public static String type(TySig tySig) { 44 SigWriter writer = new SigWriter(); 45 writer.writeTySig(tySig); 46 return writer.toString(); 47 } 48 49 /** Writes a {@link MethodSig} to a string. */ method(MethodSig methodSig)50 public static String method(MethodSig methodSig) { 51 SigWriter writer = new SigWriter(); 52 writer.writeMethodSig(methodSig); 53 return writer.toString(); 54 } 55 56 private final StringBuilder sb = new StringBuilder(); 57 58 @Override toString()59 public String toString() { 60 return sb.toString(); 61 } 62 writeFormalTyParamSig(TyParamSig tyParamSig)63 private void writeFormalTyParamSig(TyParamSig tyParamSig) { 64 sb.append(tyParamSig.name()); 65 sb.append(':'); 66 if (tyParamSig.classBound() != null) { 67 writeTySig(tyParamSig.classBound()); 68 } 69 for (Sig.TySig f : tyParamSig.interfaceBounds()) { 70 sb.append(':'); 71 writeTySig(f); 72 } 73 } 74 writeClassTySig(ClassTySig classTySig)75 private void writeClassTySig(ClassTySig classTySig) { 76 sb.append('L'); 77 if (!classTySig.pkg().isEmpty()) { 78 sb.append(classTySig.pkg()).append('/'); 79 } 80 boolean first = true; 81 for (SimpleClassTySig c : classTySig.classes()) { 82 if (first) { 83 first = false; 84 } else { 85 sb.append('.'); 86 } 87 writeSimpleClassTySig(c); 88 } 89 sb.append(';'); 90 } 91 writeSimpleClassTySig(SimpleClassTySig simpleClassTySig)92 public void writeSimpleClassTySig(SimpleClassTySig simpleClassTySig) { 93 sb.append(simpleClassTySig.simpleName()); 94 if (!simpleClassTySig.tyArgs().isEmpty()) { 95 sb.append('<'); 96 for (Sig.TySig x : simpleClassTySig.tyArgs()) { 97 writeTySig(x); 98 } 99 sb.append('>'); 100 } 101 } 102 wildTyArgSig(WildTySig sig)103 private void wildTyArgSig(WildTySig sig) { 104 switch (sig.boundKind()) { 105 case NONE: 106 sb.append('*'); 107 break; 108 case LOWER: 109 sb.append('-'); 110 writeTySig(((LowerBoundTySig) sig).bound()); 111 break; 112 case UPPER: 113 sb.append('+'); 114 writeTySig(((UpperBoundTySig) sig).bound()); 115 break; 116 default: 117 throw new AssertionError(sig.kind()); 118 } 119 } 120 writeArrayTySig(ArrayTySig arrayTySig)121 public void writeArrayTySig(ArrayTySig arrayTySig) { 122 sb.append('['); 123 writeTySig(arrayTySig.elementType()); 124 } 125 writeTyVarSig(TyVarSig tyVarSig)126 public void writeTyVarSig(TyVarSig tyVarSig) { 127 sb.append('T').append(tyVarSig.name()).append(';'); 128 } 129 writePrimitiveTySig(BaseTySig ty)130 public void writePrimitiveTySig(BaseTySig ty) { 131 switch (ty.type()) { 132 case BYTE: 133 sb.append('B'); 134 break; 135 case CHAR: 136 sb.append('C'); 137 break; 138 case DOUBLE: 139 sb.append('D'); 140 break; 141 case FLOAT: 142 sb.append('F'); 143 break; 144 case INT: 145 sb.append('I'); 146 break; 147 case LONG: 148 sb.append('J'); 149 break; 150 case SHORT: 151 sb.append('S'); 152 break; 153 case BOOLEAN: 154 sb.append('Z'); 155 break; 156 default: 157 throw new AssertionError(ty.type()); 158 } 159 } 160 writeMethodSig(MethodSig methodSig)161 private void writeMethodSig(MethodSig methodSig) { 162 if (!methodSig.tyParams().isEmpty()) { 163 sb.append('<'); 164 for (TyParamSig x : methodSig.tyParams()) { 165 writeFormalTyParamSig(x); 166 } 167 sb.append('>'); 168 } 169 sb.append('('); 170 for (TySig p : methodSig.params()) { 171 writeTySig(p); 172 } 173 sb.append(')'); 174 writeTySig(methodSig.returnType()); 175 for (TySig e : methodSig.exceptions()) { 176 sb.append('^'); 177 writeTySig(e); 178 } 179 } 180 writeTySig(TySig p)181 private void writeTySig(TySig p) { 182 switch (p.kind()) { 183 case VOID_TY_SIG: 184 sb.append('V'); 185 break; 186 case BASE_TY_SIG: 187 writePrimitiveTySig((BaseTySig) p); 188 break; 189 case CLASS_TY_SIG: 190 writeClassTySig((ClassTySig) p); 191 break; 192 case ARRAY_TY_SIG: 193 writeArrayTySig((ArrayTySig) p); 194 break; 195 case TY_VAR_SIG: 196 writeTyVarSig((TyVarSig) p); 197 break; 198 case WILD_TY_SIG: 199 wildTyArgSig((WildTySig) p); 200 break; 201 default: 202 throw new AssertionError(p.kind()); 203 } 204 } 205 printClassSig(ClassSig classSig)206 private void printClassSig(ClassSig classSig) { 207 if (!classSig.tyParams().isEmpty()) { 208 sb.append('<'); 209 for (TyParamSig x : classSig.tyParams()) { 210 writeFormalTyParamSig(x); 211 } 212 sb.append('>'); 213 } 214 writeClassTySig(classSig.superClass()); 215 for (ClassTySig i : classSig.interfaces()) { 216 writeClassTySig(i); 217 } 218 } 219 } 220