• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // ----------------------------------------------------------------------------