All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.leeyazhou.cobertura.instrument.pass3.InjectCodeClassInstrumenter Maven / Gradle / Ivy

Go to download

Cobertura is a free Java tool that calculates the percentage of code accessed by tests. It can be used to identify which parts of your Java program are lacking test coverage. It is based on jcoverage.

The newest version!
/*
 * 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 com.github.leeyazhou.cobertura.instrument.pass3;

import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.LocalVariablesSorter;

import com.github.leeyazhou.cobertura.instrument.AbstractFindTouchPointsClassInstrumenter;
import com.github.leeyazhou.cobertura.instrument.FindTouchPointsMethodAdapter;
import com.github.leeyazhou.cobertura.instrument.pass1.DetectDuplicatedCodeClassVisitor;
import com.github.leeyazhou.cobertura.instrument.pass2.BuildClassMapClassVisitor;
import com.github.leeyazhou.cobertura.instrument.tp.ClassMap;

/**
 * 

* This class is responsible for real instrumentation of the user's class. *

* *

* It uses information acquired by {@link BuildClassMapClassVisitor} ( * {@link #classMap} ) and {@link DetectDuplicatedCodeClassVisitor} and injects * code snippet provided by {@link CodeProvider} ( {@link #codeProvider} ). *

* * @author [email protected] */ public class InjectCodeClassInstrumenter extends AbstractFindTouchPointsClassInstrumenter { /** * This class is responsible for injecting code inside 'interesting places' of * methods inside instrumented class */ private final InjectCodeTouchPointListener touchPointListener; /** * {@link ClassMap} generated in previous instrumentation pass by * {@link BuildClassMapClassVisitor} */ private final ClassMap classMap; /** * {@link CodeProvider} used to generate pieces of asm code that is injected * into instrumented class. *

* We are strictly recommending here using {@link FastArrayCodeProvider} instead * of {@link AtomicArrayCodeProvider} because of performance. */ private final CodeProvider codeProvider; /** * When we processing the class we want to now if we processed 'static * initialization block' (clinit method). *

* If there is no such a method in the instrumented class - we will need to * generate it at the end *

*/ private boolean wasStaticInitMethodVisited = false; private final Set ignoredMethods; /** * @param cv - a listener for code-instrumentation events * @param ignoreRegexes - list of patters of method calls that should be * ignored from line-coverage-measurement * @param classMap - map of all interesting places in the class. You * should acquire it by * {@link BuildClassMapClassVisitor} and remember to * prepare it using * {@link ClassMap#assignCounterIds()} before using it * with {@link InjectCodeClassInstrumenter} * @param duplicatedLinesMap - map of found duplicates in the class. You should * use {@link DetectDuplicatedCodeClassVisitor} to * find the duplicated lines. * @param threadsafeRigorous threadsafeRigorous * @param ignoredMethods ignoredMethods */ public InjectCodeClassInstrumenter(ClassVisitor cv, Collection ignoreRegexes, boolean threadsafeRigorous, ClassMap classMap, Map> duplicatedLinesMap, Set ignoredMethods) { super(cv, ignoreRegexes, duplicatedLinesMap); this.classMap = classMap; this.ignoredMethods = ignoredMethods; codeProvider = threadsafeRigorous ? new AtomicArrayCodeProvider() : new FastArrayCodeProvider(); touchPointListener = new InjectCodeTouchPointListener(classMap, codeProvider); } @Override public void visit(int version, int access, String name, String signature, String supertype, String[] interfaces) { super.visit(version, access, name, signature, supertype, interfaces); codeProvider.generateCountersField(cv); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); if (ignoredMethods.contains(name + desc)) { return mv; } if (((access & Opcodes.ACC_STATIC) != 0) || "".equals(name)) { mv = new GenerateCallCoberturaInitMethodVisitor(mv, classMap.getClassName()); if ("".equals(name)) { wasStaticInitMethodVisited = true; } } FindTouchPointsMethodAdapter instrumenter = new FindTouchPointsMethodAdapter(mv, classMap.getClassName(), name, desc, eventIdGenerator, duplicatedLinesMap, lineIdGenerator); instrumenter.setTouchPointListener(touchPointListener); instrumenter.setIgnoreRegexp(getIgnoreRegexp()); LocalVariablesSorter sorter = new LocalVariablesSorter(access, desc, instrumenter); int variable = sorter.newLocal(Type.INT_TYPE); touchPointListener.setLastJumpIdVariableIndex(variable); return sorter; // return new ShiftVariableMethodAdapter(instrumenter, access, desc, 1); } /** * Method instrumenter that injects * {@link CodeProvider#generateCINITmethod(MethodVisitor, String, int)} code, * and then forwards the whole previous content of the method. * * @author [email protected] */ private class GenerateCallCoberturaInitMethodVisitor extends MethodVisitor { private String className; public GenerateCallCoberturaInitMethodVisitor(MethodVisitor arg0, String className) { super(Opcodes.ASM5, arg0); this.className = className; } @Override public void visitCode() { codeProvider.generateCallCoberturaInitMethod(mv, className); super.visitCode(); } } /** *

* If there was no 'static initialization block' in the class, the method is * responsible for generating the method.
* It is also responsible for generating method that keeps mapping of counterIds * into source places connected to them *

*/ @Override public void visitEnd() { if (!wasStaticInitMethodVisited) { // We need to generate new method MethodVisitor mv = super.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC, "", "()V", null, null); mv.visitCode(); codeProvider.generateCallCoberturaInitMethod(mv, classMap.getClassName()); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(/* stack */3, /* local */0); mv.visitEnd(); wasStaticInitMethodVisited = true; } codeProvider.generateCoberturaInitMethod(cv, classMap.getClassName(), classMap.getMaxCounterId() + 1); codeProvider.generateCoberturaClassMapMethod(cv, classMap); codeProvider.generateCoberturaGetAndResetCountersMethod(cv, classMap.getClassName()); super.visitEnd(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy