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: MethodItem.java,v 1.1.1.1.2.1 2004/06/20 20:07:22 vlad_r Exp $
8 */
9package com.vladium.emma.report;
10
11import com.vladium.util.Descriptors;
12import com.vladium.util.IntObjectMap;
13import com.vladium.util.asserts.$assert;
14import com.vladium.emma.data.IMetadataConstants;
15import com.vladium.emma.data.MethodDescriptor;
16
17// ----------------------------------------------------------------------------
18/**
19 * @author Vlad Roubtsov, (C) 2003
20 */
21public
22final class MethodItem extends Item
23{
24    // public: ................................................................
25
26    public MethodItem (final IItem parent, final int ID, final String name, final String descriptor, final int firstLine)
27    {
28        super (parent);
29
30        m_ID = ID;
31        m_name = name;
32        m_descriptor = descriptor;
33        m_firstLine = firstLine;
34    }
35
36    public String getName ()
37    {
38        if (m_userName == null)
39        {
40            m_userName = Descriptors.methodVMNameToJavaName (m_parent.getName (), m_name, m_descriptor, true, true, true);
41        }
42
43        return m_userName;
44    }
45
46    public int getID ()
47    {
48        return m_ID;
49    }
50
51    public int getFirstLine ()
52    {
53        return m_firstLine;
54    }
55
56    public int getAggregate (final int type)
57    {
58        final int [] aggregates = m_aggregates;
59
60        int value = aggregates [type];
61
62        if (value < 0)
63        {
64            final ClassItem parent = ((ClassItem) m_parent);
65
66            final MethodDescriptor method = parent.m_cls.getMethods () [m_ID];
67            final int status = method.getStatus ();
68
69            if ((status & IMetadataConstants.METHOD_NO_BLOCK_DATA) != 0)
70            {
71                if ($assert.ENABLED) $assert.ASSERT (false, "excluded method in report data model");
72
73                for (int i = 0; i < aggregates.length; ++ i) aggregates [i] = 0;
74            }
75            else
76            {
77                final boolean lineInfo = ((status & IMetadataConstants.METHOD_NO_LINE_NUMBER_TABLE) == 0);
78                final boolean [] coverage = parent.m_coverage != null ? parent.m_coverage [m_ID] : null;
79
80                final int totalBlockCount = method.getBlockCount ();
81
82                aggregates [TOTAL_METHOD_COUNT] = 1; // TODO: check that excluded methods are accounted for correctly
83                aggregates [TOTAL_BLOCK_COUNT] = totalBlockCount;
84
85                int totalBlockInstr = 0;
86
87                final int [] blockSizes = method.getBlockSizes ();
88
89                if (coverage != null)
90                {
91                    int coverageBlockCount = 0, coverageLineCount = 0;
92                    int coverageBlockInstr = 0, coverageLineInstr = 0;
93
94                    for (int b = 0; b < totalBlockCount; ++ b)
95                    {
96                        final int instr = blockSizes [b];
97
98                        totalBlockInstr += instr;
99                        if (coverage [b])
100                        {
101                            ++ coverageBlockCount;
102                            coverageBlockInstr += instr;
103                        }
104                    }
105
106                    if (lineInfo)
107                    {
108                        final IntObjectMap lineMap = method.getLineMap (); // TODO: expensive way to get totalLineCount
109                        final int totalLineCount = lineMap.size ();
110
111                        aggregates [TOTAL_LINE_COUNT] = totalLineCount;
112
113                        final int [] lines = lineMap.keys ();
114                        for (int l = 0; l < totalLineCount; ++ l)
115                        {
116                            final int [] blocks = (int []) lineMap.get (lines [l]);
117
118                            int thisLineCoverageCount = 0; final int thisLineTotalCount = blocks.length;
119                            int thisLineCoverageInstr = 0, thisLineTotalInstr = 0;
120
121                            for (int bID = 0; bID < thisLineTotalCount; ++ bID)
122                            {
123                                final int b = blocks [bID];
124
125                                final int instr = blockSizes [b];
126
127                                thisLineTotalInstr += instr;
128                                if (coverage [b])
129                                {
130                                    ++ thisLineCoverageCount;
131                                    thisLineCoverageInstr += instr;
132                                }
133                            }
134
135                            coverageLineCount += (PRECISION * thisLineCoverageCount) / thisLineTotalCount;
136                            coverageLineInstr += (PRECISION * thisLineCoverageInstr) / thisLineTotalInstr;
137                        }
138
139                        aggregates [COVERAGE_LINE_COUNT] = coverageLineCount;
140                        aggregates [COVERAGE_LINE_INSTR] = coverageLineInstr;
141                    }
142
143                    aggregates [TOTAL_BLOCK_INSTR] = totalBlockInstr;
144                    aggregates [COVERAGE_METHOD_COUNT] = coverageBlockCount > 0 ? 1 : 0;
145                    aggregates [COVERAGE_BLOCK_COUNT] = coverageBlockCount;
146                    aggregates [COVERAGE_BLOCK_INSTR] = coverageBlockInstr;
147
148                }
149                else
150                {
151                    for (int b = 0; b < totalBlockCount; ++ b)
152                    {
153                        totalBlockInstr += blockSizes [b];
154                    }
155
156                    aggregates [TOTAL_BLOCK_INSTR] = totalBlockInstr;
157                    aggregates [COVERAGE_METHOD_COUNT] = 0;
158                    aggregates [COVERAGE_BLOCK_COUNT] = 0;
159                    aggregates [COVERAGE_BLOCK_INSTR] = 0;
160
161                    if (lineInfo)
162                    {
163                        final IntObjectMap lineMap = method.getLineMap (); // TODO: expensive way to get totalLineCount
164                        final int totalLineCount = lineMap.size ();
165
166                        aggregates [TOTAL_LINE_COUNT] = totalLineCount;
167                        aggregates [COVERAGE_LINE_COUNT] = 0;
168                        aggregates [COVERAGE_LINE_INSTR] = 0;
169                    }
170                }
171            }
172
173            return aggregates [type];
174        }
175
176        return value;
177    }
178
179    public void accept (final IItemVisitor visitor, final Object ctx)
180    {
181        visitor.visit (this, ctx);
182    }
183
184    public final IItemMetadata getMetadata ()
185    {
186        return METADATA;
187    }
188
189    public static IItemMetadata getTypeMetadata ()
190    {
191        return METADATA;
192    }
193
194    // protected: .............................................................
195
196    // package: ...............................................................
197
198    // private: ...............................................................
199
200
201    private final int m_ID;
202    private final String m_name, m_descriptor;
203    private final int m_firstLine;
204    private transient String m_userName;
205
206    private static final Item.ItemMetadata METADATA; // set in <clinit>
207
208    static
209    {
210        METADATA = new Item.ItemMetadata (IItemMetadata.TYPE_ID_METHOD, "method",
211            1 << IItemAttribute.ATTRIBUTE_NAME_ID |
212            1 << IItemAttribute.ATTRIBUTE_METHOD_COVERAGE_ID |
213            1 << IItemAttribute.ATTRIBUTE_BLOCK_COVERAGE_ID |
214            1 << IItemAttribute.ATTRIBUTE_LINE_COVERAGE_ID);
215    }
216
217} // end of class
218// ----------------------------------------------------------------------------