BlockClassAdapter.java

    1/*******************************************************************************
    2 * Copyright (c) 2009, 2010 Mountainminds GmbH & Co. KG and Contributors
    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 *******************************************************************************/
   12package org.jacoco.core.instr;
   13
   14import org.objectweb.asm.ClassAdapter;
   15import org.objectweb.asm.ClassVisitor;
   16import org.objectweb.asm.MethodVisitor;
   17import org.objectweb.asm.commons.EmptyVisitor;
   18
   19/**
   20 * A {@link ClassVisitor} that calculates block boundaries for every
   21 * method.
   22 * 
   23 * @author Marc R. Hoffmann
   24 * @version 0.4.1.20101007204400
   25 */
   26
   27class BlockClassAdapter extends ClassAdapter implements IProbeIdGenerator {
   28
   29    private static final IBlockMethodVisitor EMPTY_BLOCK_METHOD_VISITOR;
   30
   31    static {
   32        class Impl extends EmptyVisitor implements IBlockMethodVisitor {
   33            public void visitBlockEndBeforeJump(final int id) {
   34            }
   35
   36            public void visitBlockEnd(final int id) {
   37            }
   38        }
   39        EMPTY_BLOCK_METHOD_VISITOR = new Impl();
   40    }
   41
   42    private final IBlockClassVisitor cv;
   43
   44    private int counter = 0;
   45
   46    /**
   47     * Creates a new adapter that delegates to the given visitor.
   48     * 
   49     * @param cv
   50     *            instance to delegate to
   51     */
   52    public BlockClassAdapter(final IBlockClassVisitor cv) {
   53        super(cv);
   54        this.cv = cv;
   55    }
   56
   57    @Override
   58    public final MethodVisitor visitMethod(final int access, final String name,
   59            final String desc, final String signature, final String[] exceptions) {
   60        IBlockMethodVisitor mv = cv.visitMethod(access, name, desc, signature,
   61                exceptions);
   62        if (mv == null) {
   63            // We need to visit the method in any case, otherwise probe ids
   64            // are not reproducible
   65            mv = EMPTY_BLOCK_METHOD_VISITOR;
   66        }
   67        return new BlockMethodAdapter(mv, this, access, name, desc, signature,
   68                exceptions);
   69    }
   70
   71    @Override
   72    public void visitEnd() {
   73        cv.visitTotalProbeCount(counter);
   74        super.visitEnd();
   75    }
   76
   77    // === IProbeIdGenerator ===
   78
   79    public int nextId() {
   80        return counter++;
   81    }
   82
   83}