BlockClassAdapter.java

    1/*******************************************************************************
    2 * Copyright (c) 2009 Mountainminds GmbH & Co. KG and others
    3 * All rights reserved. This program and the accompanying materials
    4 * are made available under the terms of the Eclipse Public License v1.0
    5 * which accompanies this distribution, and is available at
    6 * http://www.eclipse.org/legal/epl-v10.html
    7 *
    8 * Contributors:
    9 *    Marc R. Hoffmann - initial API and implementation
   10 *    
   11 * $Id: $
   12 *******************************************************************************/
   13package org.jacoco.core.instr;
   14
   15import org.objectweb.asm.ClassVisitor;
   16import org.objectweb.asm.MethodVisitor;
   17import org.objectweb.asm.Opcodes;
   18import org.objectweb.asm.Type;
   19import org.objectweb.asm.commons.EmptyVisitor;
   20
   21/**
   22 * A {@link ClassVisitor} that drives {@link IBlockMethodVisitor} for each
   23 * non-abstract method.
   24 * 
   25 * @author Marc R. Hoffmann
   26 * @version $Revision: $
   27 */
   28
   29public abstract class BlockClassAdapter implements ClassVisitor,
   30        IProbeIdGenerator {
   31
   32    private static class EmptyBlockMethodVisitor extends EmptyVisitor implements
   33            IBlockMethodVisitor {
   34
   35        public void visitBlockEndBeforeJump(final int id) {
   36        }
   37
   38        public void visitBlockEnd(final int id) {
   39        }
   40    }
   41
   42    private int counter = 0;
   43
   44    public final MethodVisitor visitMethod(final int access, final String name,
   45            final String desc, final String signature, final String[] exceptions) {
   46        if ((access & Opcodes.ACC_ABSTRACT) == 0) {
   47            IBlockMethodVisitor mv = visitNonAbstractMethod(access, name, desc,
   48                    signature, exceptions);
   49            if (mv == null) {
   50                // We need to visit the method in any case, otherwise probe ids
   51                // are not reproducible
   52                mv = new EmptyBlockMethodVisitor();
   53            }
   54            return new BlockMethodAdapter(mv, this, access, name, desc,
   55                    signature, exceptions);
   56        } else {
   57            return visitAbstractMethod(access, name, desc, signature,
   58                    exceptions);
   59        }
   60    }
   61
   62    /**
   63     * This method is called for every non-abstract method.
   64     * 
   65     * @param access
   66     *            the method's access flags (see {@link Opcodes}). This
   67     *            parameter also indicates if the method is synthetic and/or
   68     *            deprecated.
   69     * @param name
   70     *            the method's name.
   71     * @param desc
   72     *            the method's descriptor (see {@link Type Type}).
   73     * @param signature
   74     *            the method's signature. May be <tt>null</tt> if the method
   75     *            parameters, return type and exceptions do not use generic
   76     *            types.
   77     * @param exceptions
   78     *            the internal names of the method's exception classes (see
   79     *            {@link Type#getInternalName() getInternalName}). May be
   80     *            <tt>null</tt>.
   81     * @return an object to visit the byte code of the method, or <tt>null</tt>
   82     *         if this class visitor is not interested in visiting the code of
   83     *         this method.
   84     */
   85    protected abstract IBlockMethodVisitor visitNonAbstractMethod(
   86            final int access, final String name, final String desc,
   87            final String signature, final String[] exceptions);
   88
   89    /**
   90     * This method is called for every abstract method.
   91     * 
   92     * @param access
   93     *            the method's access flags (see {@link Opcodes}). This
   94     *            parameter also indicates if the method is synthetic and/or
   95     *            deprecated.
   96     * @param name
   97     *            the method's name.
   98     * @param desc
   99     *            the method's descriptor (see {@link Type Type}).
  100     * @param signature
  101     *            the method's signature. May be <tt>null</tt> if the method
  102     *            parameters, return type and exceptions do not use generic
  103     *            types.
  104     * @param exceptions
  105     *            the internal names of the method's exception classes (see
  106     *            {@link Type#getInternalName() getInternalName}). May be
  107     *            <tt>null</tt>.
  108     * @return an object to visit the byte code of the method, or <tt>null</tt>
  109     *         if this class visitor is not interested in visiting the code of
  110     *         this method.
  111     */
  112    protected abstract MethodVisitor visitAbstractMethod(final int access,
  113            final String name, final String desc, final String signature,
  114            final String[] exceptions);
  115
  116    /**
  117     * Returns the total number of probes of the processed class.
  118     * 
  119     * @return number of probes
  120     */
  121    protected final int getProbeCount() {
  122        return counter;
  123    }
  124
  125    // === IProbeIdGenerator ===
  126
  127    public int nextId() {
  128        return counter++;
  129    }
  130
  131}