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}