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 } 117 } 118 writeArrayTySig(ArrayTySig arrayTySig)119 public void writeArrayTySig(ArrayTySig arrayTySig) { 120 sb.append('['); 121 writeTySig(arrayTySig.elementType()); 122 } 123 writeTyVarSig(TyVarSig tyVarSig)124 public void writeTyVarSig(TyVarSig tyVarSig) { 125 sb.append('T').append(tyVarSig.name()).append(';'); 126 } 127 writePrimitiveTySig(BaseTySig ty)128 public void writePrimitiveTySig(BaseTySig ty) { 129 switch (ty.type()) { 130 case BYTE: 131 sb.append('B'); 132 break; 133 case CHAR: 134 sb.append('C'); 135 break; 136 case DOUBLE: 137 sb.append('D'); 138 break; 139 case FLOAT: 140 sb.append('F'); 141 break; 142 case INT: 143 sb.append('I'); 144 break; 145 case LONG: 146 sb.append('J'); 147 break; 148 case SHORT: 149 sb.append('S'); 150 break; 151 case BOOLEAN: 152 sb.append('Z'); 153 break; 154 default: 155 throw new AssertionError(ty.type()); 156 } 157 } 158 writeMethodSig(MethodSig methodSig)159 private void writeMethodSig(MethodSig methodSig) { 160 if (!methodSig.tyParams().isEmpty()) { 161 sb.append('<'); 162 for (TyParamSig x : methodSig.tyParams()) { 163 writeFormalTyParamSig(x); 164 } 165 sb.append('>'); 166 } 167 sb.append('('); 168 for (TySig p : methodSig.params()) { 169 writeTySig(p); 170 } 171 sb.append(')'); 172 writeTySig(methodSig.returnType()); 173 for (TySig e : methodSig.exceptions()) { 174 sb.append('^'); 175 writeTySig(e); 176 } 177 } 178 writeTySig(TySig p)179 private void writeTySig(TySig p) { 180 switch (p.kind()) { 181 case VOID_TY_SIG: 182 sb.append('V'); 183 break; 184 case BASE_TY_SIG: 185 writePrimitiveTySig((BaseTySig) p); 186 break; 187 case CLASS_TY_SIG: 188 writeClassTySig((ClassTySig) p); 189 break; 190 case ARRAY_TY_SIG: 191 writeArrayTySig((ArrayTySig) p); 192 break; 193 case TY_VAR_SIG: 194 writeTyVarSig((TyVarSig) p); 195 break; 196 case WILD_TY_SIG: 197 wildTyArgSig((WildTySig) p); 198 break; 199 } 200 } 201 printClassSig(ClassSig classSig)202 private void printClassSig(ClassSig classSig) { 203 if (!classSig.tyParams().isEmpty()) { 204 sb.append('<'); 205 for (TyParamSig x : classSig.tyParams()) { 206 writeFormalTyParamSig(x); 207 } 208 sb.append('>'); 209 } 210 writeClassTySig(classSig.superClass()); 211 for (ClassTySig i : classSig.interfaces()) { 212 writeClassTySig(i); 213 } 214 } 215 } 216