1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. 2 * 3 * This program and the accompanying materials are made available under 4 * the terms of the Common Public License v1.0 which accompanies this distribution, 5 * and is available at http://www.eclipse.org/legal/cpl-v10.html 6 * 7 * $Id: SrcFileItem.java,v 1.1.1.1.2.1 2004/06/20 20:07:22 vlad_r Exp $ 8 */ 9 package com.vladium.emma.report; 10 11 import java.util.Iterator; 12 13 import com.vladium.util.IntObjectMap; 14 import com.vladium.util.asserts.$assert; 15 import com.vladium.emma.data.ClassDescriptor; 16 import com.vladium.emma.data.MethodDescriptor; 17 18 // ---------------------------------------------------------------------------- 19 /** 20 * @author Vlad Roubtsov, (C) 2003 21 */ 22 public 23 final class SrcFileItem extends Item 24 { 25 // public: ................................................................ 26 27 28 public final class LineCoverageData 29 { 30 public static final int LINE_COVERAGE_ZERO = 0; 31 public static final int LINE_COVERAGE_PARTIAL = 1; 32 public static final int LINE_COVERAGE_COMPLETE = 2; 33 34 public final int m_coverageStatus; 35 public final int [/* units mode */][/* total, coverage */] m_coverageRatio; // not null in LINE_COVERAGE_PARTIAL status only] 36 LineCoverageData(final int coverageStatus, final int [][] coverageRatio)37 LineCoverageData (final int coverageStatus, final int [][] coverageRatio) 38 { 39 m_coverageStatus = coverageStatus; 40 m_coverageRatio = coverageRatio; 41 } 42 43 } // end of nested class 44 45 SrcFileItem(final IItem parent, final String name, final String fullVMName)46 public SrcFileItem (final IItem parent, final String name, final String fullVMName) 47 { 48 super (parent); 49 50 m_name = name; 51 m_fullVMName = fullVMName; 52 } 53 getName()54 public String getName () 55 { 56 return m_name; 57 } 58 getFullVMName()59 public String getFullVMName () 60 { 61 return m_fullVMName; 62 } 63 getFirstLine()64 public int getFirstLine () 65 { 66 // TODO: state validation 67 68 if (m_firstLine == 0) 69 { 70 getAggregate (TOTAL_LINE_COUNT); // fault line coverage calculation 71 } 72 73 return m_firstLine; 74 } 75 76 77 78 getLineCoverage()79 public IntObjectMap /* line_no:int -> LineCoverageData */ getLineCoverage () 80 { 81 if (m_lineCoverage == null) 82 { 83 getAggregate (TOTAL_LINE_COUNT); // fault line coverage calculation 84 } 85 86 return m_lineCoverage; 87 } 88 89 getAggregate(final int type)90 public int getAggregate (final int type) 91 { 92 final int [] aggregates = m_aggregates; 93 94 int value = aggregates [type]; 95 96 if (value < 0) 97 { 98 switch (type) 99 { 100 case COVERAGE_CLASS_COUNT: 101 case TOTAL_CLASS_COUNT: 102 { 103 aggregates [TOTAL_CLASS_COUNT] = getChildCount (); 104 105 value = 0; 106 for (Iterator children = getChildren (); children.hasNext (); ) 107 { 108 // SF BUG 972725: this was incorrectly using 'type' instead 109 // of the COVERAGE_CLASS_COUNT aggregate type, making class 110 // coverage computation dependent on the order of how item 111 // nodes were traversed in report generators 112 value += ((IItem) children.next ()).getAggregate (COVERAGE_CLASS_COUNT); 113 } 114 aggregates [COVERAGE_CLASS_COUNT] = value; 115 116 return aggregates [type]; 117 } 118 //break; 119 120 121 case TOTAL_SRCFILE_COUNT: 122 { 123 return aggregates [TOTAL_SRCFILE_COUNT] = 1; 124 } 125 //break; 126 127 128 case COVERAGE_LINE_COUNT: 129 case TOTAL_LINE_COUNT: 130 131 case COVERAGE_LINE_INSTR: 132 { 133 // line aggregate types are special when used on srcfile items: 134 // unlike all others, they do not simply add up when the line 135 // info is available; instead, lines from all classes belonging 136 // to the same srcfile parent are set-merged 137 138 final IntObjectMap /* line -> int[2] */ fldata = new IntObjectMap (); 139 140 for (Iterator classes = getChildren (); classes.hasNext (); ) 141 { 142 final ClassItem cls = (ClassItem) classes.next (); 143 144 final boolean [][] ccoverage = cls.getCoverage (); // this can be null 145 final ClassDescriptor clsdesc = cls.getClassDescriptor (); 146 final MethodDescriptor [] methoddescs = clsdesc.getMethods (); 147 148 for (Iterator methods = cls.getChildren (); methods.hasNext (); ) 149 { 150 final MethodItem method = (MethodItem) methods.next (); 151 final int methodID = method.getID (); 152 153 final boolean [] mcoverage = ccoverage == null ? null : ccoverage [methodID]; 154 155 final MethodDescriptor methoddesc = methoddescs [methodID]; 156 final int [] mbsizes = methoddesc.getBlockSizes (); 157 final IntObjectMap mlineMap = methoddesc.getLineMap (); 158 if ($assert.ENABLED) $assert.ASSERT (mlineMap != null); 159 160 final int [] mlines = mlineMap.keys (); 161 for (int ml = 0, mlLimit = mlines.length; ml < mlLimit; ++ ml) 162 { 163 final int mline = mlines [ml]; 164 165 int [] data = (int []) fldata.get (mline); 166 if (data == null) 167 { 168 data = new int [4]; // { totalcount, totalinstr, coveragecount, coverageinstr } 169 fldata.put (mline, data); 170 } 171 172 final int [] lblocks = (int []) mlineMap.get (mline); 173 174 final int bCount = lblocks.length; 175 data [0] += bCount; 176 177 for (int bID = 0; bID < bCount; ++ bID) 178 { 179 final int block = lblocks [bID]; 180 181 final boolean bcovered = mcoverage != null && mcoverage [block]; 182 final int instr = mbsizes [block]; 183 184 data [1] += instr; 185 if (bcovered) 186 { 187 ++ data [2]; 188 data [3] += instr; 189 } 190 } 191 } 192 } 193 } 194 195 final int lineCount = fldata.size (); 196 197 aggregates [TOTAL_LINE_COUNT] = lineCount; 198 199 int coverageLineCount = 0; 200 int coverageLineInstr = 0; 201 202 final IntObjectMap /* line_no:int -> LineCoverageData */ lineCoverage = new IntObjectMap (lineCount); 203 int firstLine = Integer.MAX_VALUE; 204 205 final int [] clines = fldata.keys (); 206 207 for (int cl = 0; cl < lineCount; ++ cl) 208 { 209 final int cline = clines [cl]; 210 final int [] data = (int []) fldata.get (cline); 211 212 final int ltotalCount = data [0]; 213 final int ltotalInstr = data [1]; 214 final int lcoverageCount = data [2]; 215 final int lcoverageInstr = data [3]; 216 217 if (lcoverageInstr > 0) 218 { 219 coverageLineCount += (PRECISION * lcoverageCount) / ltotalCount; 220 coverageLineInstr += (PRECISION * lcoverageInstr) / ltotalInstr; 221 } 222 223 // side effect: populate line coverage data map [used by getLineCoverage()] 224 225 final int lcoverageStatus; 226 int [][] lcoverageRatio = null; 227 228 if (lcoverageInstr == 0) 229 lcoverageStatus = LineCoverageData.LINE_COVERAGE_ZERO; 230 else if (lcoverageInstr == ltotalInstr) 231 lcoverageStatus = LineCoverageData.LINE_COVERAGE_COMPLETE; 232 else 233 { 234 lcoverageStatus = LineCoverageData.LINE_COVERAGE_PARTIAL; 235 lcoverageRatio = new int [][] {{ltotalCount, lcoverageCount}, {ltotalInstr, lcoverageInstr}}; // note: ordering depends on IItemAttribute.UNITS_xxx 236 } 237 238 lineCoverage.put (cline, new LineCoverageData (lcoverageStatus, lcoverageRatio)); 239 240 // side effect: compute m_firstLine 241 242 if (cline < firstLine) firstLine = cline; 243 } 244 245 m_lineCoverage = lineCoverage; // side effect 246 m_firstLine = firstLine; // side effect 247 248 aggregates [COVERAGE_LINE_COUNT] = coverageLineCount; 249 aggregates [COVERAGE_LINE_INSTR] = coverageLineInstr; 250 251 return aggregates [type]; 252 } 253 //break; 254 255 256 default: return super.getAggregate (type); 257 } 258 } 259 260 return value; 261 } 262 263 accept(final IItemVisitor visitor, final Object ctx)264 public void accept (final IItemVisitor visitor, final Object ctx) 265 { 266 visitor.visit (this, ctx); 267 } 268 getMetadata()269 public final IItemMetadata getMetadata () 270 { 271 return METADATA; 272 } 273 getTypeMetadata()274 public static IItemMetadata getTypeMetadata () 275 { 276 return METADATA; 277 } 278 279 // protected: ............................................................. 280 281 // package: ............................................................... 282 283 // private: ............................................................... 284 285 286 private final String m_name, m_fullVMName; 287 private IntObjectMap /* line_no:int -> LineCoverageData */ m_lineCoverage; 288 private int m_firstLine; 289 290 private static final Item.ItemMetadata METADATA; // set in <clinit> 291 292 static 293 { 294 METADATA = new Item.ItemMetadata (IItemMetadata.TYPE_ID_SRCFILE, "srcfile", 295 1 << IItemAttribute.ATTRIBUTE_NAME_ID | 296 1 << IItemAttribute.ATTRIBUTE_CLASS_COVERAGE_ID | 297 1 << IItemAttribute.ATTRIBUTE_METHOD_COVERAGE_ID | 298 1 << IItemAttribute.ATTRIBUTE_BLOCK_COVERAGE_ID | 299 1 << IItemAttribute.ATTRIBUTE_LINE_COVERAGE_ID); 300 } 301 302 } // end of class 303 // ----------------------------------------------------------------------------