Package net.sourceforge.javautil.bytecode.api.type.method

Source Code of net.sourceforge.javautil.bytecode.api.type.method.BytecodeContextMethod

package net.sourceforge.javautil.bytecode.api.type.method;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import net.sourceforge.javautil.bytecode.BytecodeException;
import net.sourceforge.javautil.bytecode.api.IBytecodeAssignable;
import net.sourceforge.javautil.bytecode.api.BytecodeContext;
import net.sourceforge.javautil.bytecode.api.IBytecodeField;
import net.sourceforge.javautil.bytecode.api.BytecodeFieldDeclared;
import net.sourceforge.javautil.bytecode.api.IBytecodeReferenceable;
import net.sourceforge.javautil.bytecode.api.BytecodeResolutionPool;
import net.sourceforge.javautil.bytecode.api.IBytecodeResolvable;
import net.sourceforge.javautil.bytecode.api.LiteralValue;
import net.sourceforge.javautil.bytecode.api.TypeDescriptor;
import net.sourceforge.javautil.bytecode.api.type.AbstractType;
import net.sourceforge.javautil.bytecode.api.type.method.IBytecodeWriterMethod.MathmaticalOperator;
import net.sourceforge.javautil.bytecode.api.type.method.invocation.ArrayConstruction;
import net.sourceforge.javautil.bytecode.api.type.method.invocation.ArrayInitialization;
import net.sourceforge.javautil.bytecode.api.type.method.invocation.CastOperation;
import net.sourceforge.javautil.bytecode.api.type.method.invocation.CoersionOperation;
import net.sourceforge.javautil.bytecode.api.type.method.invocation.ConcatenationOperation;
import net.sourceforge.javautil.bytecode.api.type.method.invocation.MathmaticalOperation;
import net.sourceforge.javautil.bytecode.api.type.method.invocation.MethodInvocation;
import net.sourceforge.javautil.bytecode.api.type.method.invocation.NewInstance;
import net.sourceforge.javautil.bytecode.api.type.method.invocation.TypeLoad;

/**
* The context in which a {@link BytecodeMethodConcrete} or a {@link BytecodeConstructorBase} is written.
*
* @author elponderador
* @author $Author$
* @version $Id$
*/
public class BytecodeContextMethod<W extends IBytecodeWriterMethod> implements BytecodeContext<W> {

  protected final BytecodeContext parent;
  protected final IBytecodeMethod method;
  protected final W writer;
 
  protected List<TypeDescriptor> stack = new ArrayList<TypeDescriptor>();
  protected int maxStack = 0;
 
  protected List<BytecodeScope> scopes = new ArrayList<BytecodeScope>();
  protected List<BytecodeScope> loops = new ArrayList<BytecodeScope>();
 
  protected List<BytecodeLocalVariableDeclaration> localVariables = new ArrayList<BytecodeLocalVariableDeclaration>();
  protected Map<String, BytecodeLocalVariableDeclaration> accessible = new LinkedHashMap<String, BytecodeLocalVariableDeclaration>();
  protected List<BytecodeLocalVariableDeclaration> localVariablesStack = new ArrayList<BytecodeLocalVariableDeclaration>();
  protected int maxLocal = 0;
  protected int currentLocal;
 
  protected List<BytecodeLocalVariableDeclaration> parameters = new ArrayList<BytecodeLocalVariableDeclaration>();
 
  public BytecodeContextMethod(BytecodeContext parent, IBytecodeMethod method, W writer) {
    this.parent = parent;
    this.writer = writer;
    this.method = method;
  }
 
  /**
   * @return The method this context is for
   */
  public IBytecodeMethod getMethod() { return method; }

  /**
   * @return The maximum amount of local variables at a given point
   */
  public int getMaxLocalVariables () { return this.maxLocal; }

  /**
   * @return The local variables in this context
   */
  public List<BytecodeLocalVariableDeclaration> getLocalVariables() {
    return localVariables;
  }

  public BytecodeResolutionPool getResolutionPool() {
    return parent.getResolutionPool();
  }

  public AbstractType getEnclosingType() {
    return parent.getEnclosingType();
  }

  public BytecodeContext getParent() { return parent; }

  public W getWriter() { return writer; }
 
  public IBytecodeAssignable resolve(String name) {
    if (this.accessible.containsKey(name)) return this.accessible.get(name);
    return this.parent == null ? null : this.parent.resolve(name);
  }
 
  /**
   * @param idx The index of the current lv stack
   * @return The lv related to the index
   */
  public BytecodeLocalVariableDeclaration getLocalVariable (int idx) {
    return this.localVariablesStack.get(idx);
  }
 
  /**
   * @return The count of parameters formally declared in this context
   */
  public int getDeclaredParameterCount () { return this.parameters.size(); }
 
  /**
   * @param idx The index of the corresponding declared parameter
   * @return The corresponding local variable declaration
   */
  public BytecodeLocalVariableDeclaration getDeclaredParameter (int idx) {
    return this.parameters.get(idx);
  }
 
  /**
   * @return The current parameter types
   */
  public TypeDescriptor[] getParameterTypes () {
    TypeDescriptor[] types = new TypeDescriptor[parameters.size()];
    for (int i=0; i<types.length; i++) {
      types[i] = this.getDeclaredParameter(i).getType();
    }
    return types;
  }
 
  /**
   * This is only for internal use and should not be invoked by third parties.
   *
   * @param name The name of the parameter
   * @param type The type of the parameter
   * @param isFinal True if the parameter value is final, otherwise false
   * @return The local variable declaration
   */
  public BytecodeLocalVariableDeclaration declareParameter (String name, TypeDescriptor type, boolean isFinal) {
    BytecodeLocalVariableDeclaration blvd = this.declareLocalVariable(name, type, isFinal);
    this.parameters.add(blvd);
    return blvd;
  }
 
  public BytecodeLocalVariableDeclaration declareLocalVariable (String name, Class<?> type, boolean isFinal) {
    return this.declareLocalVariable(name, parent.getResolutionPool().resolve(type.getName()), isFinal);
  }
 
  public BytecodeLocalVariableDeclaration declareLocalVariable (String name, IBytecodeResolvable type, boolean isFinal) {
    return this.declareLocalVariable(name, type.getType(), isFinal);
  }

  /**
   * @param name The name of the local variable
   * @param type The type of the local variable
   * @param isFinal True if this variable is final, otherwise false
   */
  public BytecodeLocalVariableDeclaration declareLocalVariable (String name, TypeDescriptor type, boolean isFinal) {
    if (this.accessible.containsKey(name)) throw new BytecodeException("A local variable by this name is accessible: " + name);
   
    BytecodeLocalVariableDeclaration lv = new BytecodeLocalVariableDeclaration(currentLocal++, name, type,
      new BytecodeScope(scopes.get(0), writer.mark(this), scopes.get(0).getEnd()), isFinal
    );
    this.localVariables.add(lv);
    this.localVariablesStack.add(lv);
   
    this.accessible.put(name, lv);
   
    if (this.currentLocal > this.maxLocal) this.maxLocal = currentLocal;
   
    return lv;
  }
 
  public void pushLoop (BytecodeScope scope) {
    this.loops.add(0, scope);
  }
 
  public BytecodeScope popLoop (BytecodeScope scope) {
    this.loops.remove(scope); return scope;
  }
 
  public BytecodeScope popLoop () {
    return this.popLoop(loops.remove(0));
  }
 
  public BytecodeScope getCurrentLoop () {
    return this.loops.get(0);
  }
 
  /**
   * @return The amount of scopes currently on the scope stack
   */
  public int getScopeCount () { return this.scopes.size(); }
 
  /**
   * @param idx The index of the scope
   * @return The corresponding scope, or null if no such scope exists
   */
  public BytecodeScope getScope (int idx) {
    return this.scopes.size() <= idx ? null : this.scopes.get(idx);
  }
 
  /**
   * @param block The block to add to the block stack
   */
  public void push (BytecodeScope scope) { this.scopes.add(0, scope); }
 
  /**
   * @param block The block to pop off the stack
   * @return The popped block if the same as on the stack, otherwise an exception will be thrown
   */
  public BytecodeScope pop (BytecodeScope scope) {
    BytecodeScope removed = this.scopes.remove(0);
    if (removed != scope) throw new BytecodeException("Block pop() out of order");
   
    List<String> toRemove = new ArrayList<String>();
    for (String name : accessible.keySet()) {
      if (accessible.get(name).getScope().getParent() == scope) {
        toRemove.add(name);
      }
    }
   
    for (String name : toRemove) {
      this.localVariablesStack.remove( this.accessible.remove(name) );
     
    }
    this.currentLocal -= toRemove.size();
   
    return removed;
  }
 
  /**
   * @return The popped off scope
   */
  public BytecodeScope popScope () {
    return this.pop(scopes.get(0));
  }
 
  /**
   * @return The maximum amount of items on the stack at any given point
   */
  public int getMaxStackSize () { return this.maxStack; }
 
  /**
   * @return The amount of items currently on the stack
   */
  public int getStackSize () { return this.stack.size(); }
 
  /**
   * @param idx The index of the stack item
   * @return The item or null if no such item is on the stack
   */
  public TypeDescriptor getStack (int idx) {
    return this.stack.size() <= idx ? null : this.stack.get(idx);
  }
 
  /**
   * @param types The types to push onto the stack
   */
  public void push (TypeDescriptor type) {
    this.stack.add(0, type);
    if (this.stack.size() > this.maxStack) this.maxStack = this.stack.size();
  }
 
  /**
   * @param type The type to pop
   * @return The popped type if verified, otherwise throws an exception
   */
  public TypeDescriptor pop (TypeDescriptor type) {
    TypeDescriptor removed = this.stack.remove(0);
    if (!removed.equals(type)) throw new BytecodeException("Type removed from stack inconsistent: " + type.toDescriptorString() + ", expected: " + removed.toDescriptorString());
    return removed;
  }
 
  /**
   * @return The popped off type from the stack
   */
  public TypeDescriptor popStack () {
    return pop(stack.get(0));
  }
 
  /**
   * @param clazz The class to resolve
   * @return The resolvable wrapper
   */
  public IBytecodeResolvable resolve (Class clazz) {
    return this.getResolutionPool().resolve(clazz.getName());
  }
 
  //
  // High Level Bytecode API
  //
 
  public IBytecodeReferenceable[] translate (Object... arguments) {
    IBytecodeReferenceable[] translated = new IBytecodeReferenceable[arguments.length];
   
    for (int i=0; i<arguments.length; i++) {
      if (arguments[i] instanceof IBytecodeReferenceable) {
        translated[i] = (IBytecodeReferenceable) arguments[i];
      } else {
        translated[i] = new LiteralValue(arguments[i]);
      }
    }
   
    return translated;
  }
 
  public void concat (IBytecodeReferenceable... objects) {
    this.createConcat(objects).load(this);
  }
 
  public ConcatenationOperation createConcat (IBytecodeReferenceable... objects) {
    return new ConcatenationOperation(objects);
  }
 
  public IBytecodeReferenceable[] getMethodArguments () {
    return parameters.toArray(new IBytecodeReferenceable[parameters.size()]);
  }
 
  public void returnNull () {
    writer.returnValue(this, null);
  }
 
  public void throwException (IBytecodeReferenceable instance) {
    instance.load(this);
    writer.throwException(this);
  }
 
  public void newInstance (IBytecodeResolvable type, IBytecodeReferenceable... parameters) {
    this.newInstance(type, true, parameters);
  }
 
  public void newInstance (IBytecodeResolvable type, boolean duplicate, IBytecodeReferenceable... parameters) {
    writer.newInstance(this, type.getType());
    if (duplicate) writer.dup(this);
    this.construct(null, type, parameters);
  }
 
  public NewInstance createNewInstanceInvocation (IBytecodeResolvable type, IBytecodeReferenceable... parameters) {
    return new NewInstance(type.getType(), parameters);
  }
 
  public CastOperation createCast (TypeDescriptor target, IBytecodeReferenceable value) {
    return new CastOperation(target, value);
  }
 
  public void cast (TypeDescriptor target, IBytecodeReferenceable value) {
    this.createCast(target, value).load(this);
  }
 
  public CoersionOperation createCoersion (TypeDescriptor target, IBytecodeReferenceable value) {
    return new CoersionOperation(target, value);
  }
 
  public void coerce (TypeDescriptor type, IBytecodeReferenceable value) {
    this.createCoersion(type, value).load(this);
  }
 
  /**
   * @see IBytecodeWriterMethod#jump(BytecodeContextMethod, IBytecodeMarker)
   */
  public void jump (IBytecodeMarker marker) {
    writer.jump(this, marker);
  }
 
  /**
   * @see IBytecodeWriterMethod#jumpIfException(BytecodeContextMethod, IBytecodeMarker, IBytecodeMarker, IBytecodeMarker, TypeDescriptor)
   */
  public void jumpIfException (IBytecodeMarker codeStart, IBytecodeMarker codeEnd, IBytecodeMarker handler, TypeDescriptor type) {
    writer.jumpIfException(this, codeStart, codeEnd, handler, type);
  }
 
  /**
   * @see IBytecodeWriterMethod#jumpFinally(BytecodeContextMethod, IBytecodeMarker, IBytecodeMarker)
   */
  public void jumpFinally (IBytecodeMarker codeStart, IBytecodeMarker finallyMarker) {
    writer.jumpFinally(this, codeStart, finallyMarker);
  }
 
  /**
   * @see IBytecodeWriterMethod#mark(BytecodeContextMethod)
   */
  public IBytecodeMarker mark () { return writer.mark(this); }
 
  /**
   * @see IBytecodeWriterMethod#mark(BytecodeContextMethod, IBytecodeMarker)
   */
  public void mark (IBytecodeMarker marker) { writer.mark(this, marker); }
 
  /**
   * @see IBytecodeWriterMethod#createMarker(BytecodeContextMethod)
   */
  public IBytecodeMarker createMarker () { return writer.createMarker(this); }
 
  /**
   * Load the null value onto the stack
   */
  public void loadNull () { writer.loadNull(this); }
 
  /**
   * @param name The name of a variable
   *
   * @see #get(IBytecodeReferenceable, IBytecodeReferenceable...)
   */
  public void get (String name, IBytecodeReferenceable... indices) {
    this.get(resolve(name), indices);
  }
 
  public void get (String name) {
    IBytecodeReferenceable resolved = resolve(name);
    if (resolved instanceof IBytecodeField && !((IBytecodeField)resolved).getAccess().isStatic()) {
      resolve("this").load(this);
    }
    resolved.load(this);
  }
 
  public void loadType (IBytecodeResolvable type) {
    writer.loadType(this, type);
  }
 
  public FieldInstance getThisField (String name) {
    return new FieldInstance(resolve("this"), getEnclosingType().getField(getResolutionPool(), name));
  }
 
  public IBytecodeField getStaticField (String name) {
    return getEnclosingType().getField(getResolutionPool(), name);
  }

  /**
   * @param array The array from which to load the value
   * @param indices The indices for the matrix point to load
   */
  public void get (IBytecodeReferenceable array, IBytecodeReferenceable... indices) {
    array.load(this);
   
    TypeDescriptor type = array.getType();
   
    for (int i=0; i<indices.length; i++) {
      indices[i].load(this);
      writer.arrayLoad(this, type);
      type = type.getComponentType();
    }
  }
 
  /**
   * @param name The name of an array variable
   *
   * @see #setArrayIndexValue(IBytecodeReferenceable, IBytecodeReferenceable, IBytecodeReferenceable...)
   */
  public void set (String name, IBytecodeReferenceable value, IBytecodeReferenceable... indices) {
    this.setArrayIndexValue(resolve(name), value, indices);
  }

  /**
   * @param array The array whose indice will be set
   * @param value The value to set to the specified indice
   * @param indices The set matrix point
   */
  public void setArrayIndexValue (IBytecodeReferenceable array, IBytecodeReferenceable value, IBytecodeReferenceable... indices) {
    array.load(this);
   
    TypeDescriptor type = array.getType();
   
    int load = indices.length - 1;
    for (int i=0; i<load; i++) {
      indices[i].load(this);
      writer.arrayLoad(this, type);
      type = type.getComponentType();
    }
   
    indices[load].load(this);
    if (value == null) loadNull(); else value.load(this);
    writer.arrayStore(this);
  }
 
  public void set (String name, String fieldName, IBytecodeReferenceable value) {
    this.set(resolve(name), fieldName, value);
  }
 
  public void set (IBytecodeReferenceable instance, String fieldName, IBytecodeReferenceable value) {
    instance.load(this);
   
    if (value != null) value.load(this);
    else writer.loadNull(this);
   
    instance.getType(this).getField(this.getResolutionPool(), fieldName).store(this);
  }
 
  /**
   * This will resolve the name to an assignable member.
   *
   * @param name The name of a local variable or class field
   *
   * @see #set(IBytecodeAssignable, IBytecodeReferenceable)
   * @see #resolve(String)
   */
  public void set (String name, IBytecodeReferenceable value) {
    set(resolve(name), value);
  }
 
  /**
   *
   * @param name An assignable member
   * @param value The value to assign
   */
  public void set (IBytecodeAssignable assignable, IBytecodeReferenceable value) {
    value.load(this);
    assignable.store(this);
  }
 
  /**
   * Add arg1 and arg2.
   *
   * @param arg1 The first numerical argument
   * @param arg2 The second numerical argument
   */
  public void add (IBytecodeReferenceable arg1, IBytecodeReferenceable arg2) {
    this.writer.doMath(this, arg1, arg2, MathmaticalOperator.Plus);
  }
 
  /**
   * Minus arg2 from arg1.
   *
   * @param arg1 The first numerical argument
   * @param arg2 The second numerical argument
   */
  public void minus (IBytecodeReferenceable arg1, IBytecodeReferenceable arg2) {
    this.writer.doMath(this, arg1, arg2, MathmaticalOperator.Minus);
  }
 
  /**
   * Multiply arg1 by arg2.
   *
   * @param arg1 The first numerical argument
   * @param arg2 The second numerical argument
   */
  public void multiply (IBytecodeReferenceable arg1, IBytecodeReferenceable arg2) {
    this.writer.doMath(this, arg1, arg2, MathmaticalOperator.Multiply);
  }

  /**
   * Divide arg1 by arg2.
   *
   * @param arg1 The first numerical argument
   * @param arg2 The second numerical argument
   */
  public void divide (IBytecodeReferenceable arg1, IBytecodeReferenceable arg2) {
    this.writer.doMath(this, arg1, arg2, MathmaticalOperator.Divide);
  }
 
  public MathmaticalOperation createDivideOperation (IBytecodeReferenceable arg1, IBytecodeReferenceable arg2) {
    return this.createMathOperation(arg1, arg2, MathmaticalOperator.Divide);
  }
 
  public MathmaticalOperation createMultiplyOperation (IBytecodeReferenceable arg1, IBytecodeReferenceable arg2) {
    return this.createMathOperation(arg1, arg2, MathmaticalOperator.Multiply);
  }
 
  public MathmaticalOperation createMinusOperation (IBytecodeReferenceable arg1, IBytecodeReferenceable arg2) {
    return this.createMathOperation(arg1, arg2, MathmaticalOperator.Minus);
  }
 
  public MathmaticalOperation createAddOperation (IBytecodeReferenceable arg1, IBytecodeReferenceable arg2) {
    return this.createMathOperation(arg1, arg2, MathmaticalOperator.Plus);
  }
 
  public MathmaticalOperation createMathOperation (IBytecodeReferenceable arg1, IBytecodeReferenceable arg2, MathmaticalOperator operator) {
    return new MathmaticalOperation(arg1, arg2, operator);
  }
 
  public void systemPrintLn (IBytecodeReferenceable value) {
    invoke(resolve(System.class).getField(getResolutionPool(), "out"), "println", value);
  }
 
  /**
   * Regular no value return.
   */
  public void returnVoid () { this.writer.returnVoid(this); }
 
  /**
   * @param name The name of the variable to resolve
   *
   * @see #resolve(String)
   */
  public void returnValue (String name) { returnValue(resolve(name)); }
 
  /**
   * @param referenceable The value to return
   */
  public void returnValue (IBytecodeReferenceable expression) {
    TypeDescriptor expectedReturnType = method.getDescriptor().getReturnType();
    if (expectedReturnType == null || expectedReturnType == TypeDescriptor.VOID) {
      if (expression != null) expression.load(this);
      this.returnVoid();
    } else {
      if (expression == null) this.returnNull();
      else {
        this.coerce(expectedReturnType, expression);
        this.writer.returnValue(this, expectedReturnType);
      }
    }
  }
 
  /**
   * @param name The name of a method available to this class
   * @param parameters The parameters to pass to the method invocation
   */
  public void invokeThis (String name, IBytecodeReferenceable... parameters) {
    this.invoke(resolve("this"), name, parameters);
  }
 
  /**
   * @param name The name of the method in the super class
   * @param parameters The parameters to pass to the method invocation
   */
  public void invokeSuper (String name, IBytecodeReferenceable... parameters) {
    this.createSuperInvocation(name, parameters).load(this);
  }
 
  /**
   * @param instance The instance on which to invoke the method
   * @param name The name of the method to invoke
   * @param parameters The parameters to pass to the invocation
   */
  public void invoke (IBytecodeReferenceable instance, String name, IBytecodeReferenceable... parameters) {
    this.createInvocation(instance, name, parameters).load(this);
  }
 
  /**
   * @param type The type to invoke the method on
   * @param name The name of the static method
   * @param parameters The parameters for the method
   */
  public void invoke (IBytecodeResolvable type, String name, IBytecodeReferenceable... parameters) {
    this.createInvocation(type, name, parameters).load(this);
  }
 
  /**
   * @param type The type to create
   * @param indices The indices of the array
   */
  public void newArray (IBytecodeResolvable type, IBytecodeReferenceable... indices) {
    this.createArray(type, indices).load(this);
  }
 
  /**
   * @param type The root component type of the array
   * @param indices The indices of the array
   * @return The array construction
   */
  public ArrayConstruction createArray (IBytecodeResolvable type, IBytecodeReferenceable... indices) {
    return new ArrayConstruction(type.getType(), indices);
  }
 
  /**
   * @param type The root component type of the array
   * @param values The values to load into the array
   * @return The array initialization
   */
  public ArrayInitialization initializeArray (IBytecodeResolvable type, IBytecodeReferenceable... values) {
    return new ArrayInitialization(type.getType(), values);
  }
 
  /**
   * @param parameters The parameters to pass to another constructor
   */
  public void thisConstruct (IBytecodeReferenceable... parameters) {
    this.construct(resolve("this"), getEnclosingType(), parameters);
  }
 
  /**
   * @param parameters The parameters to pass to the super constructor
   */
  public void superConstruct (IBytecodeReferenceable... parameters) {
    IBytecodeResolvable type = this.getEnclosingType().getSuperType();
    if (type == null) type = getResolutionPool().resolve(Object.class.getName());
   
    this.construct(resolve("this"), type, parameters);
  }
 
  /**
   * @param type The type to construct
   * @param parameters The parameters to pass
   */
  public void construct (IBytecodeReferenceable instance, IBytecodeResolvable type, IBytecodeReferenceable... parameters) {
    this.createConstructorInvocation(instance, type, parameters).load(this);
  }
 
  /**
   * Looks up the super method for the specified parameters
   *
   * @see #createInvocation(BytecodeContextMethod, IBytecodeMethod, IBytecodeReferenceable...)
   */
  public MethodInvocation createSuperInvocation (String name, IBytecodeReferenceable... parameters) {
    IBytecodeResolvable st = this.getEnclosingType().getSuperType();
    if (st == null) st = this.getResolutionPool().resolve(Object.class.getName());
   
    IBytecodeMethod method = st.findMethod(this.getResolutionPool(), name, getTypes(parameters));
   
    if (method == null)
      throw new BytecodeException("No such method could be found: " + name + " for " + st.getType().toDescriptorString());
   
    return this.createInvocation(resolve("this"), method, parameters);
  }
 
  /**
   * This will allow any resolvable type to be invoked upon
   *
   * @param type The type to invoke the method on
   *
   * @see #createInvocation(BytecodeContextMethod, IBytecodeMethod, IBytecodeReferenceable...)
   */
  public MethodInvocation createInvocation (IBytecodeReferenceable instance, String name, IBytecodeReferenceable... parameters) {
    IBytecodeMethod method = instance.getType(this).findMethod(this.getResolutionPool(), name, getTypes(parameters));

    if (method == null)
      throw new BytecodeException("No such method could be found: " + name + " for " + instance.getType().toDescriptorString());
   
    return this.createInvocation(instance, method, parameters);
  }
 
  /**
   * @param type The type for method lookup
   * @param name The name of the static method
   * @param parameters The parameters for the method invocation
   * @return The method invocation
   */
  public MethodInvocation createInvocation (IBytecodeResolvable type, String name, IBytecodeReferenceable... parameters) {
    IBytecodeMethod method = type.findMethod(this.getResolutionPool(), name, getTypes(parameters));
   
    if (method == null)
      throw new BytecodeException("No such method could be found: " + name + " for " + type.getType().toDescriptorString());
   
    return this.createInvocation(null, method, parameters);
  }
 
  public TypeLoad createTypeLoad (IBytecodeResolvable type) {
    return new TypeLoad(type);
  }
 
  /**
   * @param context The context in which to invoke the method
   * @param method The method to invoke
   * @param parameters The parameters to pass to the invocation
   * @return The return value
   */
  public MethodInvocation createInvocation (IBytecodeReferenceable instance, IBytecodeMethod method, IBytecodeReferenceable... parameters) {
    return new MethodInvocation(instance, method, parameters);
  }
 
  /**
   * @param parameters The parameters to pass to the this() constructor
   * @return The method invocation
   */
  public MethodInvocation createThisConstructorInvocation (IBytecodeReferenceable... parameters) {
    return this.createConstructorInvocation(resolve("this"), getEnclosingType(), parameters);
  }

  /**
   * @param parameters The parameters to pass to the super constructor
   * @return The method invocation
   */
  public MethodInvocation createSuperConstructorInvocation (IBytecodeReferenceable... parameters) {
    IBytecodeResolvable st = getEnclosingType().getSuperType() == null ?
      getResolutionPool().resolve(Object.class.getName()) : getEnclosingType().getSuperType();
     
    return this.createConstructorInvocation(resolve("this"), st, parameters);
  }
 
  /**
   * @param type The type the constructor is for
   * @param parameters The parameters to pass to the constructor
   * @return The method invocation for the constructor
   */
  public MethodInvocation createConstructorInvocation (IBytecodeReferenceable instance, IBytecodeResolvable type, IBytecodeReferenceable... parameters) {
    return new MethodInvocation(instance, type.findConstructor(this.getResolutionPool(), getTypes(parameters)), parameters);
  }
 
  public TypeDescriptor[] getTypes (IBytecodeReferenceable... arguments) {
    TypeDescriptor[] types = new TypeDescriptor[arguments.length];
    for (int i=0; i<arguments.length; i++) types[i] = arguments[i].getType();
    return types;
  }
 
}
TOP

Related Classes of net.sourceforge.javautil.bytecode.api.type.method.BytecodeContextMethod

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.