Package jodd.proxetta.asm

Source Code of jodd.proxetta.asm.MethodSignatureVisitor

// Copyright (c) 2003-2014, Jodd Team (jodd.org). All Rights Reserved.

package jodd.proxetta.asm;

import jodd.asm5.signature.SignatureVisitor;
import jodd.asm5.Opcodes;
import jodd.util.collection.CharArrayList;
import jodd.util.collection.IntArrayList;
import jodd.mutable.MutableInteger;
import jodd.proxetta.MethodInfo;
import jodd.proxetta.ProxettaException;
import jodd.proxetta.ClassInfo;
import jodd.proxetta.AnnotationInfo;
import jodd.asm.TraceSignatureVisitor;

import java.util.List;
import java.util.ArrayList;

/**
* Resolves method signature and holds all information. Uses {@link jodd.asm.TraceSignatureVisitor} from ASM library.
* <pre>
* MethodSignature = ( visitFormalTypeParameter visitClassBound? visitInterfaceBound* )* ( visitParameterType* visitReturnType visitExceptionType* )
* </pre>
*/
public class MethodSignatureVisitor extends TraceSignatureVisitor implements MethodInfo {

  protected int access;
  protected String methodName;
  protected String signature;
  protected int argumentsCount;
  protected int argumentsWords;

  protected MutableInteger returnOpcodeType;
  protected StringBuilder returnTypeName;
  protected String classname;
  protected String description;
  protected String rawSignature;
  protected AnnotationInfo[] annotations;

  protected boolean visitingArgument;
  protected CharArrayList argumentsOpcodeType;
  protected IntArrayList argumentsOffset;
  protected List<String> argumentsTypeNames;
  protected AnnotationInfo[][] argumentsAnnotation;

  protected String declaredClassName;

  protected ClassInfo targetClassInfo;
  protected int hierarchyLevel;
  protected boolean isStatic;

  // ---------------------------------------------------------------- ctors

/*  public MethodSignatureVisitor(String description) {
    this();
    this.description = description;
  }
*/
  public MethodSignatureVisitor(String methodName, final int access, String classname, String description, String signature, ClassInfo targetClassInfo) {
    this();
    this.isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
    this.isStatic = (access & Opcodes.ACC_STATIC) != 0;
    this.methodName = methodName;
    this.access = access;
    this.classname = classname;
    this.description = description;
    this.targetClassInfo = targetClassInfo;
    this.rawSignature = signature;
  }

  private MethodSignatureVisitor() {
        super(new StringBuilder());
    }

  private MethodSignatureVisitor(final StringBuilder declaration) {
        super(declaration);
    }

  private MethodSignatureVisitor(final StringBuilder buf, MutableInteger returnOpcodeType, StringBuilder returnTypeName) {
    this(buf);
    this.returnOpcodeType = returnOpcodeType;
    this.returnTypeName = returnTypeName;
  }

  // ---------------------------------------------------------------- code

  @Override
  public SignatureVisitor visitParameterType() {
    super.visitParameterType();
    visitingArgument = true;
    if (argumentsOpcodeType == null) {
      argumentsOpcodeType = new CharArrayList();
      argumentsOffset = new IntArrayList();
      argumentsTypeNames = new ArrayList<String>();

      argumentsOpcodeType.add('L');
      argumentsOffset.add(0);
      argumentsTypeNames.add(null);
    }
    return this;
  }


  @Override
  public SignatureVisitor visitReturnType() {
    super.visitReturnType();
    returnOpcodeType = new MutableInteger();
    returnTypeName = new StringBuilder();
    return new MethodSignatureVisitor(returnType, returnOpcodeType, returnTypeName);
  }

  @Override
  public SignatureVisitor visitExceptionType() {
    super.visitExceptionType();
    return new MethodSignatureVisitor(exceptions);
  }


  @Override
  public void visitBaseType(final char descriptor) {
    String name = null;
    char type = descriptor;
    if (isArray()) {
      type = '[';
      name = getArrayDepthString() + descriptor;
    }
    super.visitBaseType(descriptor);
    maybeUseType(type,  name);
  }

  /**
   * Visits a signature corresponding to a type variable.
   */
  @Override
  public void visitTypeVariable(final String name) {
    super.visitTypeVariable(name);
    maybeUseType('L', name);    // toask what is this?
  }

  /**
   * Visits a signature corresponding to an array type.
   */
  @Override
  public SignatureVisitor visitArrayType() {
    super.visitArrayType();
    return this;
  }

  /**
   * Starts the visit of a signature corresponding to a class or interface type.
   */
  @Override
  public void visitClassType(final String name) {
    super.visitClassType(name);
    maybeUseType('L', 'L' + name + ';');
  }

  // ---------------------------------------------------------------- method signature

  /**
   * Returns signature.
   */
  public String getSignature() {
    if (signature == null) {
      signature = createSignature();
    }
    return signature;
  }

  private String createSignature() {
    StringBuilder methodDeclaration = new StringBuilder(30);
    methodDeclaration.append(getReturnType()).append(' ').append(methodName).append(getDeclaration());
    String genericExceptions = getExceptions();
    if (genericExceptions != null) {
      methodDeclaration.append(" throws ").append(genericExceptions);
    }
    return methodDeclaration.toString();
  }

  public String getRawSignature() {
    return rawSignature;
  }

  public String getMethodName() {
    return methodName;
  }

  public int getArgumentsCount() {
    return argumentsCount;
  }

  /**
   * @param index 1-base index
   */
  public char getArgumentOpcodeType(int index) {
    return argumentsOpcodeType.get(index);
  }

  public String getArgumentTypeName(int i) {
    return argumentsTypeNames.get(i);
  }

  public int getArgumentOffset(int index) {
    return argumentsOffset.get(index);
  }

  public AnnotationInfo[] getArgumentAnnotations(int index) {
    return argumentsAnnotation[index];
  }

  public int getAllArgumentsSize() {
    return argumentsWords;
  }

  public char getReturnOpcodeType() {
    return (char) returnOpcodeType.value;
  }

  public String getReturnTypeName() {
    return returnTypeName.toString();
  }

  public int getAccessFlags() {
    return access;
  }

  public String getClassname() {
    return classname;
  }

  public String getDescription() {
    return description;
  }

  public AnnotationInfo[] getAnnotations() {
    return annotations;
  }

  public String getDeclaredClassName() {
    if (declaredClassName == null) {
      return classname;
    }
    return declaredClassName;
  }

  public void setDeclaredClassName(String declaredClassName) {
    this.declaredClassName = declaredClassName;
  }

  public boolean isTopLevelMethod() {
    return declaredClassName == null;
  }

  public ClassInfo getClassInfo() {
    return targetClassInfo;
  }

  public int getHierarchyLevel() {
    return hierarchyLevel;
  }


  // ---------------------------------------------------------------- utilities

  /**
   * Returns <code>true</code> if we are currently visiting an array.
   */
  private boolean isArray() {
    return arrayStack != 0;
  }

  /**
   * Add '[' for current array depth.
   */
  private String getArrayDepthString() {
    int aStack = arrayStack;    // copy value
    StringBuilder ads = new StringBuilder();
    while (aStack % 2 != 0) {
      aStack /= 2;
      ads.append('[');
    }
    return ads.toString();
  }

  /**
   * Saves argument type if parameter is currently visiting, otherwise
   * saves return type. When saving arguments data, stores also current argument offset.
   */
  private void maybeUseType(char type, String typeName) {
    if (visitingArgument == true) {
      if (isArray() == true) {
        type = '[';
        typeName = getArrayDepthString() + typeName;
      }
      if (type == 'V') {
        throw new ProxettaException("Method argument can't be void");
      }
      argumentsCount++;
      argumentsOpcodeType.add(type);
      argumentsOffset.add(argumentsWords + 1);
      argumentsTypeNames.add(typeName);
      if ((type == 'D') || (type == 'J')) {
        argumentsWords += 2;
      } else {
        argumentsWords++;
      }
      visitingArgument = false;
    } else if (returnOpcodeType != null) {
      if (isArray() == true) {
        type = '[';
        typeName = getArrayDepthString() + typeName;
      }
      returnOpcodeType.value = type;

      returnTypeName.setLength(0);

      if (typeName != null) {
        returnTypeName.append(typeName);
      }
    }
  }

  // ---------------------------------------------------------------- toString

/*
  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    MethodSignatureVisitor that = (MethodSignatureVisitor) o;
    return getSignature().equals(that.getSignature());
  }

  @Override
  public int hashCode() {
    return getSignature().hashCode();
  }

*/
  @Override
  public String toString() {
    return getDeclaredClassName() + '#' + getMethodName() + getDescription();
  }

}
TOP

Related Classes of jodd.proxetta.asm.MethodSignatureVisitor

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.