001 /* 002 * Cobertura - http://cobertura.sourceforge.net/ 003 * 004 * Copyright (C) 2005 Mark Doliner <thekingant@users.sourceforge.net> 005 * 006 * Cobertura is free software; you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published 008 * by the Free Software Foundation; either version 2 of the License, 009 * or (at your option) any later version. 010 * 011 * Cobertura is distributed in the hope that it will be useful, but 012 * WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Cobertura; if not, write to the Free Software 018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 019 * USA 020 */ 021 022 package net.sourceforge.cobertura.coverage; 023 024 import java.util.regex.Pattern; 025 026 import org.objectweb.asm.Label; 027 import org.objectweb.asm.MethodAdapter; 028 import org.objectweb.asm.MethodVisitor; 029 import org.objectweb.asm.Opcodes; 030 031 /* 032 * TODO: If class is abstract then do not count the "public abstract class bleh" line as a SLOC. 033 * TODO: For branches, only count the branch as covered if both paths are accessed? 034 */ 035 public class MethodInstrumenter extends MethodAdapter implements Opcodes 036 { 037 private final String ownerClass; 038 private String myName; 039 private String myDescriptor; 040 private Pattern ignoreRegexp; 041 private CoverageData coverageData; 042 043 private int currentLine = 0; 044 045 public MethodInstrumenter(final MethodVisitor mv, 046 CoverageData coverageData, final String owner, 047 final String myName, final String myDescriptor, 048 final Pattern ignoreRegexp) 049 { 050 super(mv); 051 this.coverageData = coverageData; 052 this.ownerClass = owner; 053 this.myName = myName; 054 this.myDescriptor = myDescriptor; 055 this.ignoreRegexp = ignoreRegexp; 056 } 057 058 public void visitJumpInsn(int opcode, Label label) 059 { 060 super.visitJumpInsn(opcode, label); 061 062 // Ignore any jump instructions in the "class init" method. 063 // When initializing static variables, the JVM first checks 064 // that the variable is null before attempting to set it. 065 // This check contains an IFNONNULL jump instruction which 066 // would confuse people if it showed up in the reports. 067 if ((opcode != GOTO) && (currentLine != 0) 068 && (!this.myName.equals("<clinit>"))) 069 coverageData.markLineAsConditional(currentLine); 070 } 071 072 public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) 073 { 074 super.visitLookupSwitchInsn(dflt, keys, labels); 075 if (currentLine != 0) 076 coverageData.markLineAsConditional(currentLine); 077 } 078 079 public void visitLineNumber(int line, Label start) 080 { 081 // Record initial information about this line of code 082 currentLine = line; 083 coverageData.addLine(currentLine, myName, myDescriptor); 084 085 // Get an instance of CoverageDataFactory 086 mv.visitMethodInsn(INVOKESTATIC, 087 "net/sourceforge/cobertura/coverage/CoverageDataFactory", 088 "getInstance", 089 "()Lnet/sourceforge/cobertura/coverage/CoverageDataFactory;"); 090 091 // Get the CoverageData object for this class 092 mv.visitLdcInsn(ownerClass); 093 mv 094 .visitMethodInsn( 095 INVOKEVIRTUAL, 096 "net/sourceforge/cobertura/coverage/CoverageDataFactory", 097 "newInstrumentation", 098 "(Ljava/lang/String;)Lnet/sourceforge/cobertura/coverage/CoverageData;"); 099 100 // Call "coverageData.touch(line);" 101 mv.visitIntInsn(SIPUSH, line); 102 mv.visitMethodInsn(INVOKEVIRTUAL, 103 "net/sourceforge/cobertura/coverage/CoverageData", "touch", 104 "(I)V"); 105 106 super.visitLineNumber(line, start); 107 } 108 109 public void visitMethodInsn(int opcode, String owner, String name, 110 String desc) 111 { 112 super.visitMethodInsn(opcode, owner, name, desc); 113 114 if ((ignoreRegexp != null) && (ignoreRegexp.matcher(owner).matches())) 115 coverageData.removeLine(currentLine); 116 } 117 118 }