Home | History | Annotate | Download | only in cst
      1 /*
      2  * Copyright (C) 2007 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.dexgen.rop.cst;
     18 
     19 import com.android.dexgen.rop.type.Prototype;
     20 import com.android.dexgen.rop.type.Type;
     21 import com.android.dexgen.rop.type.TypeBearer;
     22 
     23 /**
     24  * Base class for constants of "methodish" type.
     25  *
     26  * <p><b>Note:</b> As a {@link TypeBearer}, this class bears the return type
     27  * of the method.</p>
     28  */
     29 public abstract class CstBaseMethodRef
     30         extends CstMemberRef {
     31     /** {@code non-null;} the raw prototype for this method */
     32     private final Prototype prototype;
     33 
     34     /**
     35      * {@code null-ok;} the prototype for this method taken to be an instance
     36      * method, or {@code null} if not yet calculated
     37      */
     38     private Prototype instancePrototype;
     39 
     40     /**
     41      * Constructs an instance.
     42      *
     43      * @param definingClass {@code non-null;} the type of the defining class
     44      * @param nat {@code non-null;} the name-and-type
     45      */
     46     /*package*/ CstBaseMethodRef(CstType definingClass, CstNat nat) {
     47         super(definingClass, nat);
     48 
     49         String descriptor = getNat().getDescriptor().getString();
     50         this.prototype = Prototype.intern(descriptor);
     51         this.instancePrototype = null;
     52     }
     53 
     54     /**
     55      * Gets the raw prototype of this method. This doesn't include a
     56      * {@code this} argument.
     57      *
     58      * @return {@code non-null;} the method prototype
     59      */
     60     public final Prototype getPrototype() {
     61         return prototype;
     62     }
     63 
     64     /**
     65      * Gets the prototype of this method as either a
     66      * {@code static} or instance method. In the case of a
     67      * {@code static} method, this is the same as the raw
     68      * prototype. In the case of an instance method, this has an
     69      * appropriately-typed {@code this} argument as the first
     70      * one.
     71      *
     72      * @param isStatic whether the method should be considered static
     73      * @return {@code non-null;} the method prototype
     74      */
     75     public final Prototype getPrototype(boolean isStatic) {
     76         if (isStatic) {
     77             return prototype;
     78         } else {
     79             if (instancePrototype == null) {
     80                 Type thisType = getDefiningClass().getClassType();
     81                 instancePrototype = prototype.withFirstParameter(thisType);
     82             }
     83             return instancePrototype;
     84         }
     85     }
     86 
     87     /** {@inheritDoc} */
     88     @Override
     89     protected final int compareTo0(Constant other) {
     90         int cmp = super.compareTo0(other);
     91 
     92         if (cmp != 0) {
     93             return cmp;
     94         }
     95 
     96         CstBaseMethodRef otherMethod = (CstBaseMethodRef) other;
     97         return prototype.compareTo(otherMethod.prototype);
     98     }
     99 
    100     /**
    101      * {@inheritDoc}
    102      *
    103      * In this case, this method returns the <i>return type</i> of this method.
    104      *
    105      * @return {@code non-null;} the method's return type
    106      */
    107     public final Type getType() {
    108         return prototype.getReturnType();
    109     }
    110 
    111     /**
    112      * Gets the number of words of parameters required by this
    113      * method's descriptor. Since instances of this class have no way
    114      * to know if they will be used in a {@code static} or
    115      * instance context, one has to indicate this explicitly as an
    116      * argument. This method is just a convenient shorthand for
    117      * {@code getPrototype().getParameterTypes().getWordCount()},
    118      * plus {@code 1} if the method is to be treated as an
    119      * instance method.
    120      *
    121      * @param isStatic whether the method should be considered static
    122      * @return {@code >= 0;} the argument word count
    123      */
    124     public final int getParameterWordCount(boolean isStatic) {
    125         return getPrototype(isStatic).getParameterTypes().getWordCount();
    126     }
    127 
    128     /**
    129      * Gets whether this is a reference to an instance initialization
    130      * method. This is just a convenient shorthand for
    131      * {@code getNat().isInstanceInit()}.
    132      *
    133      * @return {@code true} iff this is a reference to an
    134      * instance initialization method
    135      */
    136     public final boolean isInstanceInit() {
    137         return getNat().isInstanceInit();
    138     }
    139 
    140     /**
    141      * Gets whether this is a reference to a class initialization
    142      * method. This is just a convenient shorthand for
    143      * {@code getNat().isClassInit()}.
    144      *
    145      * @return {@code true} iff this is a reference to an
    146      * instance initialization method
    147      */
    148     public final boolean isClassInit() {
    149         return getNat().isClassInit();
    150     }
    151 }
    152