Home | History | Annotate | Download | only in sig
      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. */
     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. */
     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. */
     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
     59   public String toString() {
     60     return sb.toString();
     61   }
     62 
     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 
     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 
     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 
    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 
    121   public void writeArrayTySig(ArrayTySig arrayTySig) {
    122     sb.append('[');
    123     writeTySig(arrayTySig.elementType());
    124   }
    125 
    126   public void writeTyVarSig(TyVarSig tyVarSig) {
    127     sb.append('T').append(tyVarSig.name()).append(';');
    128   }
    129 
    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 
    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 
    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 
    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