Home | History | Annotate | Download | only in report
      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 
     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 
     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 
     54     public String getName ()
     55     {
     56         return m_name;
     57     }
     58 
     59     public String getFullVMName ()
     60     {
     61         return m_fullVMName;
     62     }
     63 
     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 
     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 
     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 
    264     public void accept (final IItemVisitor visitor, final Object ctx)
    265     {
    266         visitor.visit (this, ctx);
    267     }
    268 
    269     public final IItemMetadata getMetadata ()
    270     {
    271         return METADATA;
    272     }
    273 
    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 // ----------------------------------------------------------------------------