/* * Cobertura - http://cobertura.sourceforge.net/ * * Copyright (C) 2011 Piotr Tabor * * Note: This file is dual licensed under the GPL and the Apache * Source License (so that it can be used from both the main * Cobertura classes and the ant tasks). * * Cobertura is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2 of the License, * or (at your option) any later version. * * Cobertura is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cobertura; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ package net.sourceforge.cobertura.instrument.pass3; import net.sourceforge.cobertura.instrument.tp.ClassMap; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; /** * Universal API for all methods that are responsible for generating any JASM code that have * to be injected into real classes. * <p/> * The general idea is that injected code is responsible for incrementing counters. The realization of counters * is implementation dependent. * * @author piotr.tabor@gmail.com */ public interface CodeProvider { /** * Name of a field that have to be injected into instrumented class that is responsible for storing counters */ public static final String COBERTURA_COUNTERS_FIELD_NAME = "__cobertura_counters"; /** * Name of a method that will to be injected into instrumented class that is responsible for storing * class-map (information on mapping of counter identifiers into lines, jumps and switch-touches). */ public static final String COBERTURA_CLASSMAP_METHOD_NAME = "__cobertura_classmap"; /** * Name of method that will initialize internal counters variable. */ public static final String COBERTURA_INIT_METHOD_NAME = "__cobertura_init"; /** * Name of a method that have to be injected into instrumented class that is responsible for reading * value of given counter. * <p/> * Signature of this method is: int[] __cobertura_counter(int counterId); */ public static final String COBERTURA_GET_AND_RESET_COUNTERS_METHOD_NAME = "__cobertura_get_and_reset_counters"; /** * Generates fields injected into instrumented class by cobertura. * * @param cv - ClassVisitor that is listener of code-generation events */ public abstract void generateCountersField(ClassVisitor cv); /** * Injects code that increments counter given by parameter. * * @param nextMethodVisitor - {@link MethodVisitor} that is listener of code-generation events * @param counterId - counterId of counter that have to be incremented * @param className - internal name (asm) of class being instrumented */ public abstract void generateCodeThatIncrementsCoberturaCounter( MethodVisitor nextMethodVisitor, Integer counterId, String className); /** * Injects code that increments counter given by internal variable. * The id of the variable is identified by lastJumpIdVariableIndex. The variable is in most cases set (by {@link #generateCodeThatSetsJumpCounterIdVariable(MethodVisitor, int, int)} * to some counterId and in the target label, the counter identified by the variable is incremented. * long * * @param nextMethodVisitor - {@link MethodVisitor} that is listener of code-generation events * @param lastJumpIdVariableIndex - id of the variable used to store counterId that have to be incremented * @param className - internal name (asm) of class being instrumented */ public abstract void generateCodeThatIncrementsCoberturaCounterFromInternalVariable( MethodVisitor nextMethodVisitor, int lastJumpIdVariableIndex, String className); /** * Injects code that sets internal variable (identified by lastJumpIdVariableIndex) to given value. * * @param nextMethodVisitor - {@link MethodVisitor} that is listener of code-generation events * @param new_value - value to set the variable to * @param lastJumpIdVariableIndex - index of variable that have to be set */ public abstract void generateCodeThatSetsJumpCounterIdVariable( MethodVisitor nextMethodVisitor, int new_value, int lastJumpIdVariableIndex); /** * Injects code that sets internal variable (identified by lastJumpIdVariableIndex) to zero. * * @param nextMethodVisitor - {@link MethodVisitor} that is listener of code-generation events * @param lastJumpIdVariableIndex - index of variable that have to be set */ public abstract void generateCodeThatZeroJumpCounterIdVariable( MethodVisitor nextMethodVisitor, int lastJumpIdVariableIndex); /** * Injects code that behaves the same as such a code snippet: * <pre> * if (value('lastJumpIdVariableIndex')==neededJumpCounterIdVariableValue){ * cobertura_counters.increment(counterIdToIncrement); * } * </pre> * <p/> * This snippet is used in switch case of switch statement. We have a label and we want to ensure that * we are executing the label in effect of switch statement-jump, and not other JUMP or fall-throught. */ public abstract void generateCodeThatIncrementsCoberturaCounterIfVariableEqualsAndCleanVariable( MethodVisitor nextMethodVisitor, Integer neededJumpCounterIdVariableValue, Integer counterIdToIncrement, int lastJumpIdVariableIndex, String className); /** * The version of cobertura prior to 1.10 used *.ser file to store information of lines, jumps, switches and other * constructions used in the class. It was difficult to user to transfer the files after instrumentation into * 'production' directory. To avoid that we are now creating the class-map as a special injected method that is responsible * for keeping such a informations. * * @param cv - listener used to inject the code * @param classMap - structure that is keeping all collected information about the class. The information from the structure will be stored as * method body. */ public void generateCoberturaClassMapMethod(ClassVisitor cv, ClassMap classMap); /** * Generate method {@value #COBERTURA_GET_AND_RESET_COUNTERS_METHOD_NAME} that is accessor to couters. * Signature of this method is: static int __cobertura_counter(int counterId); * * @param cv - listener used to inject the code */ public abstract void generateCoberturaGetAndResetCountersMethod( ClassVisitor cv, String className); public void generateCoberturaInitMethod(ClassVisitor cv, String className, int countersCnt); public abstract void generateCallCoberturaInitMethod(MethodVisitor mv, String className); }