Home | History | Annotate | Download | only in sourcer
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      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.android.mkstubs.sourcer;
     18 
     19 import org.objectweb.asm.Type;
     20 import org.objectweb.asm.signature.SignatureReader;
     21 import org.objectweb.asm.signature.SignatureVisitor;
     22 import org.objectweb.asm.signature.SignatureWriter;
     23 
     24 import java.util.ArrayList;
     25 
     26 /**
     27  * A signature visitor that can be used to generate Java source corresponding to
     28  * various types of signatures.
     29  * <p/>
     30  * Terminology: a "signature" is a type descriptor for generics. There are different types
     31  * of signatures depending on the context where they are used, e.g. method declarations,
     32  * method parameters, class declarations, etc..
     33  * <p/>
     34  * Note: most of the implementation is a duplicate of ASM's SignatureWriter with some
     35  * slight variations.
     36  * <p/>
     37  * Note: When processing a method's signature, the signature order is the reverse of the source
     38  * order, e.g. the signature is written as "(parameters)return-type" where we want to generate
     39  * "return-type method-name (parameters)". To hanlde this case, the return-type and parameters
     40  * are <em>not</em> output directly but are instead accumulated in internal variables that you can
     41  * get later using {@link #getReturnType()}, {@link #getParameters()}, {@link #getSuperClass()}
     42  * and {@link #formalsToString()}.
     43  */
     44 class SignatureSourcer implements SignatureVisitor {
     45 
     46     /**
     47      * Buffer used to construct the signature.
     48      */
     49     private final StringBuilder mBuf = new StringBuilder();
     50 
     51     /**
     52      * Buffer used to construct the formals signature.
     53      */
     54     private final StringBuilder mFormalsBuf = new StringBuilder();
     55 
     56     /**
     57      * Indicates if the signature is currently processing formal type parameters.
     58      */
     59     private boolean mWritingFormals;
     60 
     61     /**
     62      * Stack used to keep track of class types that have arguments. Each element
     63      * of this stack is a boolean encoded in one bit. The top of the stack is
     64      * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
     65      * /2.
     66      */
     67     private int mArgumentStack;
     68 
     69     /**
     70      * {@link SignatureSourcer} generated when parsing the return type of <em>this</em>
     71      * signature. Initially null.
     72      */
     73     private SignatureSourcer mReturnType;
     74 
     75     /**
     76      * {@link SignatureSourcer} generated when parsing the super class of <em>this</em>
     77      * signature. Initially null.
     78      */
     79     private SignatureSourcer mSuperClass;
     80 
     81     /**
     82      * {@link SignatureSourcer}s for each parameters generated when parsing the method parameters
     83      * of <em>this</em> signature. Initially empty but not null.
     84      */
     85     private ArrayList<SignatureSourcer> mParameters = new ArrayList<SignatureSourcer>();
     86 
     87 
     88 
     89     /**
     90      * Constructs a new {@link SignatureWriter} object.
     91      */
     92     public SignatureSourcer() {
     93     }
     94 
     95     private StringBuilder getBuf() {
     96         if (mWritingFormals) {
     97             return mFormalsBuf;
     98         } else {
     99             return mBuf;
    100         }
    101     }
    102 
    103     /**
    104      * Contains the whole signature type when called by
    105      * {@link SignatureReader#acceptType(SignatureVisitor)} or just the formals if
    106      * called by {@link SignatureReader#accept(SignatureVisitor)}.
    107      */
    108     @Override
    109     public String toString() {
    110         return mBuf.toString();
    111     }
    112 
    113     /**
    114      * Will be non-null if a return type was processed
    115      * by {@link SignatureReader#accept(SignatureVisitor)}
    116      */
    117     public SignatureSourcer getReturnType() {
    118         return mReturnType;
    119     }
    120 
    121     /**
    122      * Will be non-empty if a parameters were processed
    123      * by {@link SignatureReader#accept(SignatureVisitor)}
    124      */
    125     public ArrayList<SignatureSourcer> getParameters() {
    126         return mParameters;
    127     }
    128 
    129     /**
    130      * True if the signature contains formal type parameters, which are available
    131      * via {@link #formalsToString()} after calling {@link SignatureReader#accept(SignatureVisitor)}
    132      */
    133     public boolean hasFormalsContent() {
    134         return mFormalsBuf.length() > 0;
    135     }
    136 
    137     public String formalsToString() {
    138         return mFormalsBuf.toString();
    139     }
    140 
    141     /**
    142      * Will be non-null if a super class was processed
    143      * by {@link SignatureReader#accept(SignatureVisitor)}
    144      */
    145     public SignatureSourcer getSuperClass() {
    146         return mSuperClass;
    147     }
    148 
    149     // ------------------------------------------------------------------------
    150     // Implementation of the SignatureVisitor interface
    151     // ------------------------------------------------------------------------
    152 
    153     public void visitFormalTypeParameter(final String name) {
    154         if (!mWritingFormals) {
    155             mWritingFormals = true;
    156             getBuf().append('<');
    157         } else {
    158             getBuf().append(", ");
    159         }
    160         getBuf().append(name);
    161         getBuf().append(" extends ");
    162     }
    163 
    164     public SignatureVisitor visitClassBound() {
    165         // we don't differentiate between visiting a sub class or interface type
    166         return this;
    167     }
    168 
    169     public SignatureVisitor visitInterfaceBound() {
    170         // we don't differentiate between visiting a sub class or interface type
    171         return this;
    172     }
    173 
    174     public SignatureVisitor visitSuperclass() {
    175         endFormals();
    176         SignatureSourcer sourcer = new SignatureSourcer();
    177         assert mSuperClass == null;
    178         mSuperClass = sourcer;
    179         return sourcer;
    180     }
    181 
    182     public SignatureVisitor visitInterface() {
    183         return this;
    184     }
    185 
    186     public SignatureVisitor visitParameterType() {
    187         endFormals();
    188         SignatureSourcer sourcer = new SignatureSourcer();
    189         mParameters.add(sourcer);
    190         return sourcer;
    191     }
    192 
    193     public SignatureVisitor visitReturnType() {
    194         endFormals();
    195         SignatureSourcer sourcer = new SignatureSourcer();
    196         assert mReturnType == null;
    197         mReturnType = sourcer;
    198         return sourcer;
    199     }
    200 
    201     public SignatureVisitor visitExceptionType() {
    202         getBuf().append('^');
    203         return this;
    204     }
    205 
    206     public void visitBaseType(final char descriptor) {
    207         getBuf().append(Type.getType(Character.toString(descriptor)).getClassName());
    208     }
    209 
    210     public void visitTypeVariable(final String name) {
    211         getBuf().append(name.replace('/', '.'));
    212     }
    213 
    214     public SignatureVisitor visitArrayType() {
    215         getBuf().append('[');
    216         return this;
    217     }
    218 
    219     public void visitClassType(final String name) {
    220         getBuf().append(name.replace('/', '.'));
    221         mArgumentStack *= 2;
    222     }
    223 
    224     public void visitInnerClassType(final String name) {
    225         endArguments();
    226         getBuf().append('.');
    227         getBuf().append(name.replace('/', '.'));
    228         mArgumentStack *= 2;
    229     }
    230 
    231     public void visitTypeArgument() {
    232         if (mArgumentStack % 2 == 0) {
    233             ++mArgumentStack;
    234             getBuf().append('<');
    235         } else {
    236             getBuf().append(", ");
    237         }
    238         getBuf().append('*');
    239     }
    240 
    241     public SignatureVisitor visitTypeArgument(final char wildcard) {
    242         if (mArgumentStack % 2 == 0) {
    243             ++mArgumentStack;
    244             getBuf().append('<');
    245         } else {
    246             getBuf().append(", ");
    247         }
    248         if (wildcard != '=') {
    249             if (wildcard == '+') {
    250                 getBuf().append("? extends ");
    251             } else if (wildcard == '-') {
    252                 getBuf().append("? super ");
    253             } else {
    254                 // can this happen?
    255                 getBuf().append(wildcard);
    256             }
    257         }
    258         return this;
    259     }
    260 
    261     public void visitEnd() {
    262         endArguments();
    263     }
    264 
    265     // ------------------------------------------------------------------------
    266     // Utility methods
    267     // ------------------------------------------------------------------------
    268 
    269     /**
    270      * Ends the formal type parameters section of the signature.
    271      */
    272     private void endFormals() {
    273         if (mWritingFormals) {
    274             getBuf().append('>');
    275             mWritingFormals = false;
    276         }
    277     }
    278 
    279     /**
    280      * Ends the type arguments of a class or inner class type.
    281      */
    282     private void endArguments() {
    283         if (mArgumentStack % 2 != 0) {
    284             getBuf().append('>');
    285         }
    286         mArgumentStack /= 2;
    287     }
    288 }
    289