• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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