Arbit - project tracking

PHP Depend

Browse source code

File: / PHP/ Depend/ Metrics/ CrapIndex/ Analyzer.php

Type
text/plain text/plain
Last Author
mapi
Version
1063
Line Rev. Author Source
1 1059 mapi <?php
2 1060 mapi /**
3 mapi * This file is part of PHP_Depend.
4 mapi *
5 mapi * PHP Version 5
6 mapi *
7 mapi * Copyright (c) 2008-2010, Manuel Pichler <mapi@pdepend.org>.
8 mapi * All rights reserved.
9 mapi *
10 mapi * Redistribution and use in source and binary forms, with or without
11 mapi * modification, are permitted provided that the following conditions
12 mapi * are met:
13 mapi *
14 mapi * * Redistributions of source code must retain the above copyright
15 mapi * notice, this list of conditions and the following disclaimer.
16 mapi *
17 mapi * * Redistributions in binary form must reproduce the above copyright
18 mapi * notice, this list of conditions and the following disclaimer in
19 mapi * the documentation and/or other materials provided with the
20 mapi * distribution.
21 mapi *
22 mapi * * Neither the name of Manuel Pichler nor the names of his
23 mapi * contributors may be used to endorse or promote products derived
24 mapi * from this software without specific prior written permission.
25 mapi *
26 mapi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 mapi * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 mapi * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 mapi * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 mapi * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 mapi * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 mapi * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 mapi * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34 mapi * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 mapi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36 mapi * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 mapi * POSSIBILITY OF SUCH DAMAGE.
38 mapi *
39 mapi * @category QualityAssurance
40 mapi * @package PHP_Depend
41 mapi * @subpackage Metrics_CrapIndex
42 mapi * @author Manuel Pichler <mapi@pdepend.org>
43 mapi * @copyright 2008-2010 Manuel Pichler. All rights reserved.
44 mapi * @license http://www.opensource.org/licenses/bsd-license.php BSD License
45 mapi * @version SVN: $Id$
46 mapi * @link http://pdepend.org/
47 mapi */
48 1059 mapi
49 mapi require_once 'PHP/Depend/Metrics/NodeAwareI.php';
50 mapi require_once 'PHP/Depend/Metrics/AbstractAnalyzer.php';
51 mapi require_once 'PHP/Depend/Metrics/AggregateAnalyzerI.php';
52 mapi require_once 'PHP/Depend/Metrics/CyclomaticComplexity/Analyzer.php';
53 mapi require_once 'PHP/Depend/Util/Coverage/Factory.php';
54 mapi
55 1060 mapi /**
56 mapi * This analyzer calculates the C.R.A.P. index for methods an functions when a
57 mapi * clover coverage report was supplied. This report can be supplied by using the
58 mapi * command line option <b>--coverage-report=</b>.
59 mapi *
60 mapi * @category QualityAssurance
61 mapi * @package PHP_Depend
62 mapi * @subpackage Metrics_CrapIndex
63 mapi * @author Manuel Pichler <mapi@pdepend.org>
64 mapi * @copyright 2008-2010 Manuel Pichler. All rights reserved.
65 mapi * @license http://www.opensource.org/licenses/bsd-license.php BSD License
66 mapi * @version Release: @package_version@
67 mapi * @link http://pdepend.org/
68 mapi */
69 1059 mapi class PHP_Depend_Metrics_CrapIndex_Analyzer pdepend-warning pdepend-warning pdepend-warning
70 mapi extends PHP_Depend_Metrics_AbstractAnalyzer
71 mapi implements PHP_Depend_Metrics_AggregateAnalyzerI,
72 mapi PHP_Depend_Metrics_NodeAwareI
73 mapi {
74 1060 mapi /**
75 mapi * Type of this analyzer class.
76 mapi */
77 mapi const CLAZZ = __CLASS__;
78 1059 mapi
79 1060 mapi /**
80 mapi * Metrics provided by the analyzer implementation.
81 mapi */
82 mapi const M_CRAP_INDEX = 'crap';
83 1059 mapi
84 mapi /**
85 1060 mapi * The report option name.
86 mapi */
87 mapi const REPORT_OPTION = 'coverage-report';
88 mapi
89 mapi /**
90 mapi * Calculated crap metrics.
91 mapi *
92 mapi * @var array(string=>array)
93 mapi */
94 mapi private $_metrics = null;
95 mapi
96 mapi /**
97 1059 mapi * The coverage report instance representing the supplied coverage report
98 mapi * file.
99 mapi *
100 mapi * @var PHP_Depend_Util_Coverage_Report
101 mapi */
102 mapi private $_report = null;
103 mapi
104 mapi /**
105 mapi *
106 mapi * @var PHP_Depend_Metrics_CyclomaticComplexity_Analyzer
107 mapi */
108 mapi private $_ccnAnalyzer = array();
109 mapi
110 1060 mapi /**
111 mapi * Returns <b>true</b> when this analyzer is enabled.
112 mapi *
113 mapi * @return boolean
114 mapi */
115 1059 mapi public function isEnabled()
116 mapi {
117 1060 mapi return isset($this->options[self::REPORT_OPTION]);
118 1059 mapi }
119 mapi
120 1060 mapi /**
121 mapi * Returns the calculated metrics for the given node or an empty <b>array</b>
122 mapi * when no metrics exist for the given node.
123 mapi *
124 1061 mapi * @param PHP_Depend_Code_NodeI $node The context source node instance.
125 1060 mapi *
126 mapi * @return array(string=>float)
127 mapi */
128 1059 mapi public function getNodeMetrics(PHP_Depend_Code_NodeI $node)
129 mapi {
130 mapi if (isset($this->_metrics[$node->getUUID()])) {
131 mapi return $this->_metrics[$node->getUUID()];
132 mapi }
133 mapi return array();
134 mapi }
135 mapi
136 1061 mapi /**
137 mapi * Returns an array with analyzer class names that are required by the crap
138 mapi * index analyzers.
139 mapi *
140 mapi * @return array(string)
141 mapi */
142 1059 mapi public function getRequiredAnalyzers()
143 mapi {
144 mapi return array(PHP_Depend_Metrics_CyclomaticComplexity_Analyzer::CLAZZ);
145 mapi }
146 mapi
147 1061 mapi /**
148 mapi * Adds an analyzer that this analyzer depends on.
149 mapi *
150 mapi * @param PHP_Depend_Metrics_AnalyzerI $analyzer An analyzer this analyzer
151 mapi * depends on.
152 mapi *
153 mapi * @return void
154 mapi */
155 1059 mapi public function addAnalyzer(PHP_Depend_Metrics_AnalyzerI $analyzer)
156 mapi {
157 mapi $this->_ccnAnalyzer = $analyzer;
158 mapi }
159 mapi
160 1061 mapi /**
161 mapi * Performs the crap index analysis.
162 mapi *
163 mapi * @param PHP_Depend_Code_NodeIterator $packages The context source tree.
164 mapi *
165 mapi * @return void
166 mapi */
167 1059 mapi public function analyze(PHP_Depend_Code_NodeIterator $packages)
168 mapi {
169 1060 mapi if ($this->isEnabled() && $this->_metrics === null) {
170 1059 mapi $this->_analyze($packages);
171 mapi }
172 mapi }
173 mapi
174 1061 mapi /**
175 mapi * Performs the crap index analysis.
176 mapi *
177 mapi * @param PHP_Depend_Code_NodeIterator $packages The context source tree.
178 mapi *
179 mapi * @return void
180 mapi */
181 1059 mapi private function _analyze(PHP_Depend_Code_NodeIterator $packages)
182 mapi {
183 1060 mapi $this->_metrics = array();
184 mapi
185 1059 mapi $this->_ccnAnalyzer->analyze($packages);
186 mapi
187 mapi $this->fireStartAnalyzer();
188 mapi
189 mapi foreach ($packages as $package) {
190 mapi $package->accept($this);
191 mapi }
192 mapi
193 mapi $this->fireEndAnalyzer();
194 mapi }
195 mapi
196 1061 mapi /**
197 mapi * Visits the given method.
198 mapi *
199 mapi * @param PHP_Depend_Code_Method $method The context method.
200 mapi *
201 mapi * @return void
202 mapi */
203 1059 mapi public function visitMethod(PHP_Depend_Code_Method $method)
204 mapi {
205 mapi if ($method->isAbstract() === false) {
206 mapi $this->_visitCallable($method);
207 mapi }
208 mapi }
209 mapi
210 1061 mapi /**
211 mapi * Visits the given function.
212 mapi *
213 mapi * @param PHP_Depend_Code_Function $function The context function.
214 mapi *
215 mapi * @return void
216 mapi */
217 1059 mapi public function visitFunction(PHP_Depend_Code_Function $function)
218 mapi {
219 mapi $this->_visitCallable($function);
220 mapi }
221 mapi
222 1061 mapi /**
223 mapi * Visits the given callable instance.
224 mapi *
225 mapi * @param PHP_Depend_Code_AbstractCallable $callable The context callable.
226 mapi *
227 mapi * @return void
228 mapi */
229 1059 mapi private function _visitCallable(PHP_Depend_Code_AbstractCallable $callable)
230 mapi {
231 1061 mapi $this->_metrics[$callable->getUUID()] = array(
232 mapi self::M_CRAP_INDEX => $this->_calculateCrapIndex($callable)
233 mapi );
234 1059 mapi }
235 mapi
236 1061 mapi /**
237 mapi * Calculates the crap index for the given callable.
238 mapi *
239 mapi * @param PHP_Depend_Code_AbstractCallable $callable The context callable.
240 mapi *
241 mapi * @return float
242 mapi */
243 1059 mapi private function _calculateCrapIndex(PHP_Depend_Code_AbstractCallable $callable)
244 mapi {
245 mapi $report = $this->_createOrReturnCoverageReport();
246 mapi
247 1061 mapi $complexity = $this->_ccnAnalyzer->getCCN2($callable);
248 1063 mapi $coverage = $report->getCoverage($callable);
249 1061 mapi
250 1059 mapi if ($coverage == 0) {
251 1061 mapi return pow($complexity, 2) + $complexity;
252 1059 mapi } else if ($coverage > 99.5) {
253 1061 mapi return $complexity;
254 1059 mapi }
255 1061 mapi return pow($complexity, 2) * pow(1 - $coverage / 100, 3) + $complexity;
256 1059 mapi }
257 mapi
258 1061 mapi /**
259 mapi * Returns a previously created report instance or creates a new report
260 mapi * instance.
261 mapi *
262 mapi * @return PHP_Depend_Util_Coverage_Report
263 mapi */
264 1059 mapi private function _createOrReturnCoverageReport()
265 mapi {
266 mapi if ($this->_report === null) {
267 mapi $this->_report = $this->_createCoverageReport();
268 mapi }
269 mapi return $this->_report;
270 mapi }
271 mapi
272 1061 mapi /**
273 mapi * Creates a new coverage report instance.
274 mapi *
275 mapi * @return PHP_Depend_Util_Coverage_Report
276 mapi */
277 1059 mapi private function _createCoverageReport()
278 mapi {
279 mapi $factory = new PHP_Depend_Util_Coverage_Factory();
280 mapi return $factory->create($this->options['coverage-report']);
281 mapi }
282 mapi }