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}