PMDASMVisitor.java :  » Code-Analyzer » pmd-4.2rc1 » net » sourceforge » pmd » typeresolution » visitors » Java Open Source

Java Open Source » Code Analyzer » pmd 4.2rc1 
pmd 4.2rc1 » net » sourceforge » pmd » typeresolution » visitors » PMDASMVisitor.java
/**
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 */
package net.sourceforge.pmd.typeresolution.visitors;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;

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

public class PMDASMVisitor implements ClassVisitor {

  private Map<String, String> packages = new HashMap<String, String>();

  private AnnotationVisitor annotationVisitor = new PMDAnnotationVisitor(this);

  private FieldVisitor fieldVisitor = new PMDFieldVisitor(this);

  private SignatureVisitor sigVisitor = new PMDSignatureVisitor(this);

  private MethodVisitor methodVisitor = new PMDMethodVisitor(this);

  public List<String> innerClasses;

  public Map<String, String> getPackages() {
    return packages;
  }

  public List<String> getInnerClasses() {
    return innerClasses;
  }

  private String parseClassName(String name) {
    if (name == null) {
      return null;
    }

    String className = name;
    int n = name.lastIndexOf('/');
    if (n > -1) {
      className = name.substring(n + 1);
    }
    name = name.replace('/', '.');
    packages.put(className, name);
    n = className.indexOf('$');
    if (n > -1) {
      //TODO I don't think the first one, with Class$Inner is needed - come back and check
      packages.put(className.substring(n + 1), name);
      packages.put(className.replace('$', '.'), name);
    }

    return name;
  }

  private void parseClassName(String[] names) {
    if (names != null) {
      for (String s : names) {
        parseClassName(s);
      }
    }
  }

  private void extractSignature(String sig) {
    if (sig != null) {
      new SignatureReader(sig).accept(sigVisitor);
    }
  }

  /* Start ClassVisitor implementations */

  public void visit(int version, int access, String name, String sig, String superName, String[] interfaces) {
    parseClassName(name);
    parseClassName(interfaces);
    if (sig != null) {
      extractSignature(sig);
    }
  }

  public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
    addType(Type.getType(desc));
    return annotationVisitor;
  }

  public FieldVisitor visitField(int access, String name, String desc, String sig, Object value) {
    if (sig != null) {
      extractSignature(sig);
    }

    addType(Type.getType(desc));
    if (value instanceof Type) {
      addType((Type) value);
    }
    return fieldVisitor;
  }

  public MethodVisitor visitMethod(int access, String name, String desc, String sig, String[] exceptions) {
    if (sig != null) {
      extractSignature(sig);
    }
    addMethodDesc(desc);
    parseClassName(exceptions);
    return methodVisitor;
  }

  public void visitSource(String source, String debug) {
  }

  public void visitInnerClass(String name, String outerName, String innerName, int access) {
    if (innerClasses == null) {
      innerClasses = new ArrayList<String>();
    }
    if (!innerClasses.contains(name.replace('/', '.'))) {
      innerClasses.add(name.replace('/', '.'));
    }
    packages.put(innerName, name.replace('/', '.'));
  }

  public void visitOuterClass(String owner, String name, String desc) {
  }

  public void visitEnd() {
  }

  private void addMethodDesc(String desc) {
    addTypes(desc);
    addType(Type.getReturnType(desc));
  }

  private void addTypes(String desc) {
    Type[] types = Type.getArgumentTypes(desc);
    for (Type type : types) {
      addType(type);
    }
  }

  private void addType(Type t) {
    switch (t.getSort()) {
    case Type.ARRAY:
      addType(t.getElementType());
      break;
    case Type.OBJECT:
      parseClassName(t.getClassName().replace('.', '/'));
      break;
    }
  }

  public void visitAttribute(Attribute attr) {
  }

  /*
   * Start visitors
   */

  private static class PMDFieldVisitor implements FieldVisitor {

    private PMDASMVisitor parent;

    public PMDFieldVisitor(PMDASMVisitor visitor) {
      parent = visitor;
    }

    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      parent.addType(Type.getType(desc));
      return parent.annotationVisitor;
    }

    public void visitAttribute(Attribute attr) {
    }

    public void visitEnd() {
    }
  }

  private static class PMDAnnotationVisitor implements AnnotationVisitor {
    private PMDASMVisitor parent;

    public PMDAnnotationVisitor(PMDASMVisitor visitor) {
      parent = visitor;
    }

    public AnnotationVisitor visitAnnotation(String name, String desc) {
      parent.addType(Type.getType(desc));
      return this;
    }

    public void visitEnum(String name, String desc, String value) {
      parent.addType(Type.getType(desc));
    }

    public AnnotationVisitor visitArray(String name) {
      return this;
    }

    public void visitEnd() {
    }

    public void visit(String name, Object value) {
      if (value instanceof Type) {
        parent.addType((Type) value);
      }
    }
  }

  private static class PMDSignatureVisitor implements SignatureVisitor {
    private PMDASMVisitor parent;

    public PMDSignatureVisitor(PMDASMVisitor visitor) {
      this.parent = visitor;
    }

    public void visitFormalTypeParameter(String name) {
    }

    public SignatureVisitor visitClassBound() {
      return this;
    }

    public SignatureVisitor visitInterfaceBound() {
      return this;
    }

    public SignatureVisitor visitSuperclass() {
      return this;
    }

    public SignatureVisitor visitInterface() {
      return this;
    }

    public SignatureVisitor visitParameterType() {
      return this;
    }

    public SignatureVisitor visitReturnType() {
      return this;
    }

    public SignatureVisitor visitExceptionType() {
      return this;
    }

    public void visitBaseType(char descriptor) {
    }

    public void visitTypeVariable(String name) {
    }

    public SignatureVisitor visitArrayType() {
      return this;
    }

    public void visitClassType(String name) {
      parent.parseClassName(name);
    }

    public void visitInnerClassType(String name) {
      parent.parseClassName(name);
    }

    public void visitTypeArgument() {
    }

    public SignatureVisitor visitTypeArgument(char wildcard) {
      return this;
    }

    public void visitEnd() {
    }
  }

  private static class PMDMethodVisitor implements MethodVisitor {
    private PMDASMVisitor parent;

    public PMDMethodVisitor(PMDASMVisitor visitor) {
      parent = visitor;
    }

    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
      parent.addType(Type.getType(desc));
      return parent.annotationVisitor;
    }

    public AnnotationVisitor visitAnnotation(String name, String desc) {
      parent.addType(Type.getType(desc));
      return parent.annotationVisitor;
    }

    public void visitTypeInsn(int opcode, String desc) {
      if (desc.charAt(0) == '[') {
        parent.addType(Type.getType(desc));
      } else {
        parent.parseClassName(desc);
      }
    }

    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
      parent.parseClassName(owner);
      parent.addType(Type.getType(desc));
    }

    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
      parent.parseClassName(owner);
      parent.addMethodDesc(desc);
    }

      /**
       * the constant to be loaded on the stack. This parameter must be a non null
       * Integer, a Float, a Long, a Double a String (or a Type for .class
       * constants, for classes whose version is 49.0 or more).
       *
       * @see org.objectweb.asm.MethodVisitor#visitLdcInsn(java.lang.Object)
       */
      public void visitLdcInsn(Object cst) {
          if (cst instanceof Type) {
            parent.addType((Type) cst);
          } else if (cst instanceof String) {
              parent.parseClassName((String) cst);
          }
      }
    public void visitMultiANewArrayInsn(String desc, int dims) {
      parent.addType(Type.getType(desc));
    }

    public void visitLocalVariable(String name, String desc, String sig, Label start, Label end, int index) {
      parent.extractSignature(sig);
    }

    public void visitCode() {
    }

    public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
    }

    public void visitInsn(int opcode) {
    }

    public void visitIntInsn(int opcode, int operand) {
    }

    public void visitVarInsn(int opcode, int var) {
    }

    public void visitJumpInsn(int opcode, Label label) {
    }

    public void visitLabel(Label label) {
    }

    public void visitIincInsn(int var, int increment) {
    }

    public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
    }

    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
    }

    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
      parent.parseClassName(type);
    }

    public void visitLineNumber(int line, Label start) {
    }

    public void visitMaxs(int maxStack, int maxLocals) {
    }

    public AnnotationVisitor visitAnnotationDefault() {
      return parent.annotationVisitor;
    }

    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      parent.addType(Type.getType(desc));
      return parent.annotationVisitor;
    }

    public void visitEnd() {
    }

    public void visitAttribute(Attribute attr) {
    }

  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.