License updated to GPLv3

🧲 New features
Custom user role permissions
Employee edit form updated
Employee daily task list
Attendance and employee distribution charts on dashboard
Improvements to company structure and company assets module
Improved tables for displaying data in several modules
Faster data loading (specially for employee module)
Initials based profile pictures
Re-designed login page
Re-designed user profile page
Improvements to filtering
New REST endpoints for employee qualifications

🐛 Bug fixes
Fixed, issue with managers being able to create performance reviews for employees who are not their direct reports
Fixed, issues related to using full profile image instead of using smaller version of profile image
Changing third gender to other
Improvements and fixes for internal frontend data caching
This commit is contained in:
Thilina Pituwala
2020-10-31 19:02:37 +01:00
parent 86b8345505
commit b1df0037db
29343 changed files with 867614 additions and 2191082 deletions

View File

@@ -0,0 +1,620 @@
pdepend-2.5.2 (2017/12/13)
=
This release contains a single bugfix for missing command options.
- Fix for GH355: Unknown option --jdepend-chart [\#356](https://github.com/pdepend/pdepend/pull/356) ([manuelpichler](https://github.com/manuelpichler))
pdepend-2.5.1 (2017/12/06)
==========================
This release contains many bugfixes, enables Scrutinizer and adds code coverage integration. HHVM support was dropped. Full support for missing language features for PHP <= 7.1 were added.
- Support for "yield from" in PHP 7.0 [\#350](https://github.com/pdepend/pdepend/pull/350) ([emirb](https://github.com/emirb))
- Support for constant visibility in interfaces in PHP 7.1 [\#349](https://github.com/pdepend/pdepend/pull/349) ([KacerCZ](https://github.com/KacerCZ))
- Support catch of multiple exception types in PHP 7.1 [\#348](https://github.com/pdepend/pdepend/pull/348) ([KacerCZ](https://github.com/KacerCZ))
- Added support for PHP 7.1 types - iterable and void [\#342](https://github.com/pdepend/pdepend/pull/342) ([KacerCZ](https://github.com/KacerCZ))
- Add Symfony 4 support [\#340](https://github.com/pdepend/pdepend/pull/340) ([surikman](https://github.com/surikman))
- Fix Scrutinizer config [\#336](https://github.com/pdepend/pdepend/pull/336) ([emirb](https://github.com/emirb))
- Fixed PHPUnit warnings [\#333](https://github.com/pdepend/pdepend/pull/333) ([KacerCZ](https://github.com/KacerCZ))
- Codecov explicit coverage file [\#332](https://github.com/pdepend/pdepend/pull/332) ([emirb](https://github.com/emirb))
- Add codecov.io integration [\#331](https://github.com/pdepend/pdepend/pull/331) ([emirb](https://github.com/emirb))
- Use uniqid\(\) in AbstractASTArtifact::getId\(\) instead of microtime\(\) [\#330](https://github.com/pdepend/pdepend/pull/330) ([KacerCZ](https://github.com/KacerCZ))
- Fix Iterator so it will not return directories [\#329](https://github.com/pdepend/pdepend/pull/329) ([KacerCZ](https://github.com/KacerCZ))
- Fix tests on Windows [\#328](https://github.com/pdepend/pdepend/pull/328) ([KacerCZ](https://github.com/KacerCZ))
- PHP 7.2 fixes [\#326](https://github.com/pdepend/pdepend/pull/326) ([emirb](https://github.com/emirb))
- Capitalize XML word [\#325](https://github.com/pdepend/pdepend/pull/325) ([bocharsky-bw](https://github.com/bocharsky-bw))
- Fix typo [\#321](https://github.com/pdepend/pdepend/pull/321) ([ravage84](https://github.com/ravage84))
- Fixes \#193 regression [\#319](https://github.com/pdepend/pdepend/pull/319) ([mdeboer](https://github.com/mdeboer))
- Remove running of PHP 5.3 build since dropped by Travis. [\#316](https://github.com/pdepend/pdepend/pull/316) ([niconoe-](https://github.com/niconoe-))
- Fix issue \#297 adding support for constant visibility into the parser for PHP 7.1 [\#314](https://github.com/pdepend/pdepend/pull/314) ([mmucklo](https://github.com/mmucklo))
- Remove references to HHVM [\#309](https://github.com/pdepend/pdepend/pull/309) ([ravage84](https://github.com/ravage84))
- fix count\(\): Parameter must be an array or an object that implements ... [\#303](https://github.com/pdepend/pdepend/pull/303) ([remicollet](https://github.com/remicollet))
- "a xml" -\> "an xml" [\#300](https://github.com/pdepend/pdepend/pull/300) ([bocharsky-bw](https://github.com/bocharsky-bw))
pdepend-2.5.0 (2017/01/19)
==========================
This release closes a parsing bug in PDepend 2.4.1, starts with the
implementation of PHP 7.1 support and adds a new attribute for the
fully-qualified-classname to the summary report.
- Fixed #282: Issue with grouped use statements when only a single
level namespace prefix was used. Fixed in commit #3e523f5.
- Implemented #294: Add support for PHP 7.1 optionals. Implemented in
commit #c5c53eb.
- Implemented #88: Fully qualified classname in summary report.
Implemented in commit #13e9cbc.
pdepend-2.4.1 (2017/01/11)
==========================
This release closes a bug within PDepend's parser when keywords are
used as method or constant names in PHP 7.0
- Fixes an issue with methods or constants with keyword identifiers
called/accessed in PHP 7. Fixed in commit #8f07ac7.
pdepend-2.4.0 (2017/01/10)
==========================
This release implements language features like Anonymous Classes,
Group use Declarations, Uniform Variable Syntax or Loosening Reserved
Word Restrictions that were introduced with PHP 7.0, so that PDepend
2.4 is now PHP 7.0 compatible.
- Fixed #281: PHP 7 - Anonymous Class - Internal parser state issues
Fixed in commit #00a61c6.
- Fixed #285: Parse the magic constant __TRAIT__ Fixed in commit
#b76e2b0.
- Fixed #210: Partial Class Namespace is Calculated Twice: in Global
and it's Own Namespace Fixed in commit #e81411f.
- Implemented #280: Refactor SymbolTable Implemented in commit
#1265259.
- Implemented #282: PHP 7 - Group use declarations Implemented in
commit #fd4aaca.
- Implemented #269: Unexpected token: :: (implicit object / method
usage) Implemented in commit #e611915.
- Implemented #204: Support for the ... operator in function calls
Implemented in commit #078e532.
- Implemented #290: Unexpected token: ARRAY (reserved keyword as a
class constant) Implemented in commit #d4bf7bb.
pdepend-2.3.2 (2016/11/23)
==========================
Bugfix release that closes a caching issue that was introduced in
2.3.1.
- Fixed #276: Uncaught Error: Call to a member function type() on null
in Fixed in commit #48d8081.
- Allow list as method name under PHP 7 Fixed in commit #4968ed4.
- Fixed #277: serialize(): "comment" is returned from __sleep multiple
times in store in FileCacheDriver.php Fixed in commit #31cf053.
pdepend-2.3.1 (2016/11/23)
==========================
- Fixed #250: Updating ASTAnonymousClass to implement ASTNode,
retaining class behavior. Fixed in commit #2111906.
pdepend-2.3.0 (2016/11/22)
==========================
This release closes multiple bugs/issue and has merged several
outstanding pull requests. Beside that it is now possible to pipe
source through STDIN into pdepend.
- Fixed #263: Fix NPath calculations for the ternary operator. Fixed
in commit #df0e9c5.
- Fixed #260: Fix typos Fixed in commit #20b36c1.
- Fixed #259: DOMDocument file handling. Fixed in commit #fa2afc6.
- Fixed #247: Fix handling of use declarations with const and function
keywords. Fixed in commit #dc9128b.
- Fixed #240: Fix some typos from the website. Fixed in commit
#332672a.
- Fixed #249: Unexpected token: callable Fixed in commit #.
- Support for PHP's ** pow expression implemented. Implemented in
commit #bce6145.
- Implemented #262: Support stdin implemented. Implemented in commit
#3ef2328.
- Implemented #231: Apply the filter on files as well. Implemented in
commit #62d1406.
pdepend-2.2.6 (2016/10/04)
==========================
Bugfix release.
- Fixed #267: Fix UnexpectedTokenException on null coalesce operator
Fixed in commit #8e80aaa.
pdepend-2.2.4 (2016/03/10)
==========================
This releases closes a bug in PDepend's parsing code for PHP 7 return
types, that caused a invalid state in the internal AST representation.
This bug was issued in PHPMD's issue tracker first by user radmen.
- Cannot create new nodes, when internal state is frozen. #328 Fixed
in commit #ffe9957.
pdepend-2.2.3 (2016/02/22)
==========================
This release includes several pending pull requests from GitHub.
Beside that this release adds support for complex expressions in
property, constant and parameter declarations, introduced with PHP
5.6.
- Fixed #226: Fixed division by zero issue. Fixed in commit #fb46614.
- Fixed #227: Fix support to files filters. Fixed in commit #4e150db.
- Fixed #230: Fix handling cygwin home folder location. Fixed in
commit #126c38a.
- Implemented #221: Add --quiet option. Implemented in commit
#9a710f7.
- Implemented #236: Switch to PSR-4 for autoloading Implemented in
commit #57b54bd.
- Implemented #238: Unexpected token errors for 5.6 "constant
expression" initializers. Implemented in commit #0087c94.
pdepend-2.2.2 (2015/10/16)
==========================
This release adds a new analyzer that can be used to visualize
namespace dependencies.
- Implemented #221: Added line numbers to summary log. Implemented in
commit #a975553.
- Implemented #222: Calculate type dependencies. Implemented in commit
#8a924f6.
pdepend-2.2.1 (2015/09/24)
==========================
With this release we made a dependency downgrade, so that we can
support more environments.
- Implemented #223: Minimum Symfony version downgraded to 2.3.
Implemented in commit #8601cc3.
pdepend-2.2.0 (2015/09/19)
==========================
This release contains beside several contributed additions and
bugfixes better support for PHP 7 language constructs.
- Fixed #119: PDepend doesn't follow any symlinks to directories.
Fixed in commit #b80ae7e.
- Fixed #143: Truncated summary when analyzing ISO-8859-1 input. Fixed
in commit #d979462.
- Fixed #193: Cache conflict when executing pdepend in parallel. Fixed
in commit #a4e20ff.
- Fixed #197: Warning: DOMNode::cloneNode(): ID <id> already defined
in phar. Fixed in commit #2221f74.
- Fixed #201: ShellCheck warnings in scripts/compare.sh Fixed in
commit #.
- Fixed #209: PHP 5.6 constant syntax not supported. Fixed in commit
#1209b0e.
- Fixed #213: PHP 7: T_CHARACTER and T_BAD_CHARACTER are no longer
defined. Fixed in commit #1f5b051.
- Fixed #214: PHP 7: Return types not supported. Fixed in commit
#249932b.
pdepend-2.1.0 (2015/05/21)
==========================
This release introduces an analyzer for the Halstead metrics and the
maintainability index, contributed by Matthias Mullie. Beside that we
have closed several issues and bugs in PDepend's source code.
- Fixed #196: Fix Typo in phpDoc Fixed in commit #2b51fed.
- Fixed #200: Fix annotation-typo in AbstractPHPParser.php Fixed in
commit #776529d.
- Fixed #202: Support for variable arg list implemented Fixed in
commit #dff2547.
- Implemented #177: HHVM support Implemented in commit #48ee5d9.
- Implemented #185: Remove unused imports and order alphabetically
Implemented in commit #46d5fb.
- Implemented #198: Add analyzers for Halstead measures &
maintainability index Implemented in commit #3497862.
pdepend-2.0.6 (2015/03/02)
==========================
Concurrency issue in the file cache garbage collector fixed.
- Suppress exceptions when there are concurrency issues within the
garbage collector. Fixed in commit #3e31cc7.
pdepend-2.0.5 (2015/02/27)
==========================
This release just adds a simple garbage collector for PDepend's file
cache
- Garbage collector for old cache files added. Implemented in commit
#56712b1.
pdepend-2.0.4 (2014/12/04)
==========================
This release closes some minor issues and incorporates several
outstanding pull requests.
- Fixed #187: Unexpected token :?> with broken up switch statement
Fixed in commit #c12ee0e.
- Fixed #180: Unexpected token: <<, line: 5, col: 27 Fixed in commit
#4df5b9d.
- Fixed #179: Fixed display of duration longer than one hour Fixed in
commit #1288292.
- Fixed #176: Typo on website fixed. Fixed in commit #6a8e542.
- Fixed #175: Inconsistent indention in phpunit.dist.xml file fixed.
Fixed in commit #bc758e4.
- Fixed #174: Fix conflicting import: "Extension" is already in use in
the "PDepend\DependencyInjection" namespace. Fixed in commit
#e3e672b.
- Fixed #173: Fixing parsing True/False keywords in namespaces: Usage
of true and false keywords are allowed in namespace declarations in
PHP. Fixed in commit #d96e4e7.
- Fixed #170: invalid xml-report after parsing traits Fixed in commit
#1d1bec0.
- Fixed #167: Fix Invalid argument supplied for foreach() in
FileCacheDriver.php Fixed in commit #73d32f3.
- Fixed #165: Fix FileUtil::getUserHomeDir on Mac Fixed in commit
#4826c3f.
- Fixed #164: Empty yields raise Fatal error: When using empty yields
yield; the parser raises an fatal error. Fixed in commit #7ab0736.
- Fixed #163: File cache concurrency fix: Fixes concurrent run of
pdepend and phpmd. Fixed in commit #3955c07.
- Fixed #154: Invalid trait conflict errors: t is completely valid to
mix traits in PHP that have the same methods declared, as long as
only one of them is concrete (all the others must be abstract).
Fixed in commit #45ab1d3.
- Fixed #128: Problem when I use parent:: in trait Fixed in commit
#a73e6de.
- Implemented #177: HHVM support Implemented in commit #17da34b.
pdepend-2.0.3 (2014/10/08)
==========================
This is a bugfix release which closes some minor issues.
- Fixed #129: Windows+Composer install fails due to "path too long"
Fixed in commit #64f95c1.
- Fixed #172: Outdated news on the website
- Fixed #166: Added support for foreach with list statement (PHP 5.5)
Fixed in commit #a744af1.
- Fixed #171: The list usage in foreach loops reports an invalid token
Fixed in commit #a744af1.
pdepend-2.0.2 (2014/09/16)
==========================
- Fixed #160: include_once PDepend/Util/Coverage/CloverReport.php:
failed to open stream Fixed in commit #4dca605.
- Implemented #105: Support Java style array notations in doc comments
Implemented in commit #2ec5166.
pdepend-2.0.1 (2014/09/09)
==========================
Bug fix release which closes a issue within PDepend's C.R.A.P. index
calculation.
- Handle code surrounded by @codeCoverageIgnore annotations correct.
Fixed in commit #3e67aa2.
pdepend-2.0.0 (2014/05/21)
==========================
New mayor release of PDepend.
- Fixed #126: Allow closure as array element Fixed in commit #b9775ac.
- Fixed #153: Support for new finally keyword implemented. Fixed in
commit #e536e7a.
- Fixed #144: pdepend --version gives me a wrong message.. Fixed in
commit #f6acea9.
- Implemented #113: Specify license, BSD license was missing in
composer.json file. Implemented in commit #3ba9c9e.
- Implemented #117: Adds composer autoload info Implemented in commit
#e624f8e.
pdepend-1.1.1 (2013/07/25)
==========================
Closes several PHP 5.4 issues.
- Fixed #116: Adding a fix for PHP 5.4 style arrays. Fixed in commit
#cbfddaa.
- Fixed #95: PHP 5.4 array syntax is not supported in property
initialization. Fixed in commit #f6ee217.
- Fixed #97: protected property PHP_Depend_Code_Method::$parent Fixed
in commit #87a1b5e.
- Fixed #104: Syntax errors reported when PHP 5.4 short array syntax
is used in method signatures or class variable definitions. Fixed in
commit #d731fa6.
- Fixed #103: Fix syntax error in composer.json example Fixed in
commit #e897a66.
- Implemented #101: Package name for chart svg Implemented in commit
#479aaa5.
pdepend-1.1.0 (2012/09/12)
==========================
This release closes a critical issue in the context of traits
handling.
- Changed type of Node/Trait Fixed in commit #806eaab.
- Changed to PSR1 coding standard. Implemented in commit #.
pdepend-1.0.7 (2012/04/29)
==========================
This release closes a minor bug within the parsing code for doc
comments..
- Fixed: DocComment is sometimes incorrectly set for functions Fixed
in commit #ac71753.
pdepend-1.0.6 (2012/04/22)
==========================
This release closes a bug with traits that were introduced with PHP
5.4. This bug results in an E_FATAL when PHP_Depend performs coupling
analysis on a trait.
- Fixed: E_FATAL when the coupling analyzer processes a trait. Fixed
in commit #ac71753.
- Added: Composer support Implemented in commit #3d98f02.
pdepend-1.0.5 (2012/04/05)
==========================
This release closes a bug introduced with the last release, which
causes PHP_Depend not to flush it's metric cache when a file has
changed.
- Fixed #27588643: PHP_Depend doesn't invalidate the cache. Fixed in
commit #99d5c13.
pdepend-1.0.4 (2012/02/25)
==========================
This release closes an issue introduced with the last release. It
closes one more regression related to PHP's memory_limit and the
Suhosin patch.
- Fixed fatal error due to bug in memory_limit modification code.
Fixed in commit #b869eff.
pdepend-1.0.3 (2012/02/25)
==========================
This release closes a minor issue in PHP_Depend's memory handling when
it is run in a PHP environment that uses the Suhosin patch and the
suhosin.memory_limit setting.
- Fixed #25450915: Alert disable memory_limit Fixed in commit
#0628e7d.
pdepend-1.0.2 (2012/02/15)
==========================
This release contains a huge improvement in PHP_Depend's memory usage.
Due to some changes in the caching behavior we got a memory reduction
of ~ 90%, measured against medium sized code bases like Symfony2 or
FLOW3.
- Fixed #24732243: pdepend fails on 'const' Fixed in commit #4d6a687.
- Fixed #24975343: PHP_Depend doesn't handle nested list expressions.
Fixed in commit #d124ef0.
- Implemented #24702477: Huge memory footprint Implemented in commit
#75c9755.
pdepend-1.0.1 (2012/02/08)
==========================
This release fixes two bugs in PHP_Depend's parser, which resulted in
uncatchable errors.
- Fixed #24635313: _parseOptionalExpression() returning null causes
exception Fixed in commit #97189b0.
- Fixed #24638569: pdepend crashes on vanilia drupal site Fixed in
commit #f20f40a.
pdepend-1.0.0 (2012/02/04)
==========================
Now that we have completed support for all the new language features
introduced with PHP 5.4, we are ready to release version 1.0.0 of
PHP_Depend. PHP_Depend can now handle traits, static closures, binary
numbers, the callable type hint and the new short array syntax. Beside
that, we have spent much effort in improving PHP_Depend's overall
performance and we got an average speed gain of ~ 15% for processing
major frameworks like Symfony2 or FLOW3, when PHP_Depend's file cache
(default setup) is used. Additionally this release closes several
minor issues in PHP_Depend.
- Fixed #18976391: PHP_Depend's file cache implementation does not
work with PHP 5.4. Fixed in commit #06ce51a.
- Fixed #18459091: PDepend task never ends, if there is an incorrect
inheritance Fixed in commit #13b5d12.
- Fixed #19875155: Implement static closures Fixed in commit #1e24a34.
- Implemented #8927307: Add support for traits Implemented in commit
#84f612e.
- Implemented #19874825: Implement the short array syntax introduced
with PHP 5.4 Implemented in commit #338bca2.
- Implemented #9069837: Implement expression lists. Implemented in
commit #bbb06c7.
- Implemented #21435399: Implement PHP 5.4 variable method names
Implemented in commit #911b6ec.
- Implemented #21408469: Implement PHP 5.4 binary number format
Implemented in commit #e3bccf1.
- Implemented #21339411: Implement PHP 5.4 callable type hint
Implemented in commit #ee5caa6.
- Implemented #21271399: Deprecate the --phpunit-xml log option
Implemented in commit #658c25c.
- Implemented #19817309: Implement PHP 5.4 array dereferencing
Implemented in commit #6dba831.
pdepend-0.10.9 (2012/01/25)
===========================
This release fixes a small issue in PHP_Depend's parser, which results
in an exception when heredoc was used as property or constant
initializer.
- Fixed #23951621: PHP_Depend fails on Heredocs and Nowdocs in
property declaration. Fixed in commit #373c478.
pdepend-0.10.8 (2012/01/24)
===========================
This release closes an issue in PHP_Depend's parser that produces
invalid package names when the source file contains a statement before
the class or interface doc comment.
- Fixed #23905939: Package gets lost when prefixed with control
structure Fixed in commit #b62bed7.
pdepend-0.10.7 (2011/12/06)
===========================
This release closes a critical bug in PHP_Depend's parser which
results in an E_FATAL. This can happen when a control structure does
not contain a body or termination token.
- E_FATAL when a control structure like if, for or foreach does not
contain a body or a termination symbol. Fixed in commit #b367a41.
pdepend-0.10.6 (2011/08/21)
===========================
This release closes a critical bug in PHP_Depend's parser that
produced false positiv error messages for classes named like 'True',
'False' or 'Null'
- Fixed #17264279: Unexpected token: True, line: 348, col: 49,
file:... Fixed in commit #5ac3e55.
pdepend-0.10.5 (2011/05/20)
===========================
This release closes two minor bugs in PHP_Depend. One incompatibility
with PHP 5.2.x versions and one bug related to PHP_Depend's log
behavior when PHP_Depend analyzes unstructured source code. This
release was published on May the 20th 2011.
- Fixed #13255437: PHP 5.2 Compatibility Issues. Fixed in commit
#8d4a095.
- Fixed #13405179: PHP Depend report is not generated if all files do
not contain a class nor a function. Fixed in commit #554ade1.
pdepend-0.10.4 (2011/04/09)
===========================
This release contains an improvement in PHP_Depend's memory
consumption. We have optimized the internal data structures in such a
way that the memory footprint was reduced by ~30%. These values were
measured for currently popular frameworks with a medium to large sized
code base. The tests were run under ubuntu with PHP 5.2.17 and PHP
5.3.6.
pdepend-0.10.3 (2011/03/02)
===========================
This release closes a critial bug in PHP_Depend's analyzer locator
code that prevents PHP_Depend from running on windows. This release
was published on March the 02th 2011.
- Fixed #10659085: Analyzer locator code does not work on windows.
Fixed in commit #0101798.
pdepend-0.10.2 (2011/02/28)
===========================
This release of PHP_Depend closes two bugs. One related to the start
and end line properties of object property nodes in the syntax tree.
The second fix closes a bug in PHP_Depend's implementation of the WMCi
metric. Beside these two fixes this release implements three minor
features, one design issue in the syntax tree api and the other two
other features are related to the new metrics CE, CA, CBO and NPM.
Additionally we have restructured PHP_Depend's directory structure
from a custom, freestyle format to a directory layout that is similar
to maven's convention. With this change we have fixed several issues
and workarounds in PHP_Depend's build process.
- Fixed #9936901: WMCi calculation is incorrect for overwritten
methods. Fixed in commit #69d079a.
- Fixed #8927377: Invalid Start/End Line/Column for object property
access. Fixed in commit #fc57264.
- Implemented #9069393: Replace optional NULL argument of setPackage()
with separate method. Implemented in commit #1282cdb.
- Implemented #9069871: Implement efferent- and afferent-coupling for
classes. Implemented in commit #07537c2.
- Implemented #9997915: Implement Number of Public Methods metric.
Implemented in commit #2dd3ebf.
pdepend-0.10.1 (2011/02/06)
===========================
- Fixed #9634613: Notice: Undefined property $___temp___. Fixed in
commit #5fb6900.
pdepend-0.10.0 (2011/02/05)
===========================
This version only contains a small bugfix compared to the last release
canditate. Version 0.10.0 of PHP_Depend was released on February the
05th 2011. The key feature for this release is the overall performance
of PHP_Depend. Therefore we have implemented a new caching layer that
reuses already calculated analyzes-results much more efficient than
older versions of PHP_Depend. With these modifications we have
achieved a performance gain of 100% and more for consecutive
analysis-runs. This final release only fixes a small bug in
PHP_Depend's analyzer class locator that has caused some issues when
PHP_Depend was executed as an external dependency that uses a \*.phar
archive as distribution format.
- Fixed #9623949: Also find analyzers in phar archives in the current
include_path. Fixed in commit #f53dca9.
- Fixed #113: PHP fatal error when an unserialized object graph none
NodeI instances. Fixed in commit #c0f4384.
- Fixed #164: Faulty implementation of the --ignore path filter fixed.
Now this filter only works on the local part of a file or directory
name and not on the complete path. Fixed in commit #f75275e.
- Fixed #176: Calculation of CIS metric is incorrect. Fixed in commit
#1193f4a.
- Fixed #182: Clone is a valid function, method and type name in older
php versions. Fixed with git commit Fixed in commit #b18bf37.
- Fixed #189: Invalid Start/End Line/Column for object method
invocation. Fixed in commit #c6cc9dd.
- Fixed #191: New implementation of --ignore only accepts relative
paths. Fixed in commit #38e6b52.
- Fixed #163: Alternative syntax end tokens can terminate with closing
PHP-tag.
- Fixed #181: No log generated when parsing Typo3 extension
"t3extplorer" (Unexpected token ASCII 39). Indirectly fixed in this
release.
- Implemented #130: Simplify PHP_Depend's ASTCompoundVariable and skip
nested ASTCompoundExpression node instance.
- Implemented #131: Add new method isThis() to PHP_Depend's
ASTVariable class.
- Implemented #132: Housekeeping: Cleanup the PHP_Depend_Input package
test code.
- Implemented #139: Implement Post-/Pre- Increment/Decrement.
- Implemented #143: Support PHP's alternative control structure
syntax.
- Implemented #146: Implement PHP's declare-statement.
- Implemented #148: Implement cast expressions.
- Implemented #170: Rename FunctionNameParserImpl into
FunctionNameParserAllVersions. Task scope changed and complete
refactoring done. Parser moved into a version specific parser class.
- Implemented #178: Provide configuration option for the cache
directory. Implemented in commit #00ed8ec.

View File

@@ -0,0 +1,31 @@
Copyright (c) 2008-2013, Manuel Pichler <mapi@pdepend.org>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Manuel Pichler nor the names of his
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,6 @@
PHP Depend
=======
[![Build Status](https://travis-ci.org/pdepend/pdepend.svg?branch=master)](https://travis-ci.org/pdepend/pdepend)
[![Packagist](https://img.shields.io/packagist/dt/pdepend/pdepend.svg)](https://github.com/pdepend/pdepend)
[![codecov.io](https://codecov.io/gh/pdepend/pdepend/branch/master/graphs/badge.svg?branch=master)](https://codecov.io/github/pdepend/pdepend?branch=master)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/pdepend/pdepend/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/pdepend/pdepend/?branch=master)

View File

@@ -0,0 +1,58 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
$build_script = <<SCRIPT
sudo apt-get update
echo Installing PHP...
sudo apt-get install -y php5 php5-cli php5-curl php5-fpm php5-intl
echo Installing Other deps. ...
sudo apt-get install -y git
SCRIPT
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "ubuntu/trusty64"
# The url from where the 'config.vm.box' box will be fetched if it
# doesn't already exist on the user's system.
# config.vm.box_url = "http://domain.com/path/to/above.box"
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
config.vm.network "public_network"
# If true, then any SSH connections made will enable agent forwarding.
# Default value: false
# config.ssh.forward_agent = true
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
config.vm.synced_folder "./", "/home/vagrant/pdepend/"
config.vm.provider :virtualbox do |vb|
vb.name = "pDepend VM"
vb.customize ["modifyvm", :id, "--memory", "5642"]
vb.customize ["modifyvm", :id, "--cpus", "4"]
vb.customize ["modifyvm", :id, "--hwvirtex", "on"]
vb.customize ["modifyvm", :id, "--nestedpaging", "on"]
end
config.vm.provision :shell, inline: $build_script
end

View File

@@ -0,0 +1,18 @@
project.dir =
project.uri = pdepend.org
project.name = pdepend
project.version = 2.5.2
project.stability = stable
project.pear.uri = pear.example.com
vendor.dir.includes = symfony/**/*,composer/**/*,autoload.php
vendor.dir.excludes = symfony/**/Tests/**/*
codesniffer.standard = PSR2
codesniffer.fail.on.violation = true
project.scm.uri = github.com/${project.name}/${project.name}/commit
phpunit.package.name = phpunit-old

View File

@@ -0,0 +1,19 @@
{
"name": "pdepend/pdepend",
"description": "Official version of pdepend to be handled with Composer",
"license": "BSD-3-Clause",
"require": {
"php": ">=5.3.7",
"symfony/dependency-injection": "^2.3.0|^3|^4",
"symfony/filesystem": "^2.3.0|^3|^4",
"symfony/config": "^2.3.0|^3|^4"
},
"require-dev": {
"phpunit/phpunit": "^4.8|^5.7",
"squizlabs/php_codesniffer": "^2.0.0"
},
"bin": ["src/bin/pdepend"],
"autoload": {
"psr-4": {"PDepend\\": "src/main/php/PDepend"}
}
}

View File

@@ -0,0 +1,13 @@
#!/bin/sh
PHP_BIN=${2:-"php"}
rm -rf ~/.pdepend/*
$PHP_BIN "$(which pdepend)" --jdepend-xml=/tmp/jdpa0.xml --summary-xml=/tmp/suma0.xml "$1"
$PHP_BIN "$(which pdepend)" --jdepend-xml=/tmp/jdpa1.xml --summary-xml=/tmp/suma1.xml "$1"
$PHP_BIN src/bin/pdepend --jdepend-xml=/tmp/jdpb0.xml --summary-xml=/tmp/sumb0.xml "$1"
$PHP_BIN src/bin/pdepend --jdepend-xml=/tmp/jdpb1.xml --summary-xml=/tmp/sumb1.xml "$1"
meld /tmp/suma0.xml /tmp/sumb0.xml /tmp/sumb1.xml
meld /tmp/jdpa0.xml /tmp/jdpb0.xml /tmp/jdpb1.xml

View File

@@ -0,0 +1,169 @@
<?php
$url = 'https://raw.githubusercontent.com/php/php-src/master/Zend/zend_language_scanner.l';
$file = basename($url);
if (isset($argv[1]) && is_numeric($argv[1])) {
$argv[2] = $argv[1];
unset($argv[1]);
}
if (isset($argv[1])) {
if (false === file_exists($argv[1])) {
fwrite(STDERR, "The given zend_language_scanner.l does not exist.\n");
fwrite(STDERR, "Usage:\n~ \$ php-keywords.php <path/to/zend_language_scanner.l> [<phpversion>]\n");
exit(23);
} else {
$file = $argv[1];
}
} else if (false === file_exists($file) || time() - filemtime($file) > 7200) {
shell_exec(sprintf("wget -c '%s'", $url));
touch($file);
}
$data = file_get_contents($file);
$regexp = '(
\s+<ST_IN_SCRIPTING>"([a-z_]+)"\s*\{
\s+RETURN_TOKEN\(([A-Z_]+)\);
\s+\}
)xi';
if (0 === preg_match_all($regexp, $data, $matches)) {
fwrite(STDERR, "No matches found :-(\nUsage:\n~ \$ php-keywords.php <path/to/zend_language_scanner.l>\n");
exit(42);
}
$tokens = [];
foreach ($matches[1] as $i => $keyword) {
$tokens[$matches[2][$i]] = $keyword;
}
ksort($tokens);
$valid = [
'class' => [
'T_NULL',
'T_TRUE',
'T_FALSE',
'T_STRING',
],
'constant' => [
'T_NULL',
'T_SELF',
'T_TRUE',
'T_FALSE',
'T_STRING',
'T_PARENT',
],
'function' => [
'T_NULL',
'T_SELF',
'T_TRUE',
'T_FALSE',
'T_STRING',
'T_PARENT',
],
'namespace' => [
'T_NULL',
'T_SELF',
'T_TRUE',
'T_FALSE',
'T_STRING',
'T_PARENT',
],
];
foreach ($tokens as $constant => $image) {
$valid = test('class', '<?php class %s {}', $image, $constant, $valid);
$valid = test('constant', '<?php class X { const %s = 42; }', $image, $constant, $valid);
$valid = test('function', '<?php class X { public function %s() {} }', $image, $constant, $valid);
$valid = test('namespace', '<?php namespace My\%s { class X { } }', $image, $constant, $valid);
}
$methodCode = dump('class', $valid);
$methodCode .= dump('constant', $valid);
$methodCode .= dump('function', $valid);
$methodCode .= dump('namespace', $valid);
function test($type, $code, $image, $constant, array &$valid)
{
$file = tempnam(sys_get_temp_dir(), 'php-keyword_');
file_put_contents($file, sprintf($code, $image));
exec(sprintf("%s -l '%s'", PHP_BINARY, $file), $output, $retval);
if (0 === $retval) {
$valid[$type][] = $constant;
}
unlink($file);
return $valid;
}
function dump($type, array $valid)
{
$code = sprintf('
/**
* Tests if the give token is a valid %s name in the supported PHP
* version.
*
* @param integer $tokenType
* @return boolean
*/
protected function is%sName($tokenType)
{
switch ($tokenType) {
%s
return true;
}
return false;
}
',
$type,
ucfirst($type),
join(
"\n",
array_map(
function ($token) {
return sprintf(' case Tokens::%s:', $token);
},
$valid[$type]
)
)
);
echo $code;
return $code;
}
if (false === isset($argv[2])) {
exit(0);
}
$parserFile = sprintf(__DIR__ . '/../src/main/php/PDepend/Source/Language/PHP/PHPParserVersion%s.php', $argv[2]);
if (false === file_exists($parserFile)) {
fwrite(STDERR, "The given parser version does not exist.\n");
exit(42);
}
$parserCode = file_get_contents($parserFile);
preg_match(
'(\s+/\* Keyword test methods {{{ \*/\s*([^\s].*[^\s])\s*/\* }}} Keyword test methods \*/)sU',
$parserCode,
$match
);
$parserCode = str_replace(
$match[0],
str_replace(
$match[1],
trim($methodCode),
$match[0]
),
$parserCode
);
echo $parserCode;
file_put_contents($parserFile, $parserCode);

View File

@@ -0,0 +1,188 @@
#!/usr/bin/env php
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2013, Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2013 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend;
/**
* Utility class that we use to recalculate the cache hash/version.
*
* @copyright 2008-2013 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class CacheVersionUpdater
{
/**
* The source directory.
*
* @var string
*/
private $rootDirectory = null;
/**
* The source sub directories that we will process.
*
* @var array(string)
*/
private $localPaths = array(
'/Source',
'/Metrics',
);
/**
* The target file, where this script will persist the new cache version.
*
* @var string
*/
private $targetFile = '/Util/Cache/CacheDriver.php';
/**
* Regular expression used to replace a previous cache version.
*
* @var string
*/
private $targetRegexp = '(@version:[a-f0-9]{32}:@)';
/**
* Constructs a new cache version updater instance.
*/
public function __construct()
{
$this->rootDirectory = realpath(dirname(__FILE__) . '/../src/main/php/PDepend');
}
/**
* Processes all source files and generates a combined version for all files.
* The it replaces the old version key within the project source with the
* newly calculated value.
*
* @return void
*/
public function run()
{
$checksum = '';
foreach ($this->localPaths as $localPath) {
$path = $this->rootDirectory . $localPath;
foreach ($this->readFiles($path) as $file) {
$checksum = $this->hash($file, $checksum);
}
}
$file = $this->rootDirectory . $this->targetFile;
$code = file_get_contents($file);
$code = preg_replace($this->targetRegexp, "@version:{$checksum}:@", $code);
file_put_contents($file, $code);
}
/**
* Generates a hash value for the given <b>$path</b> in combination with a
* previous calculated <b>$checksum</b>.
*
* @param string $path Path to the current context file.
* @param string $checksum Hash/Checksum for all previously parsed files.
* @return string
*/
protected function hash($path, $checksum)
{
return md5($checksum . md5_file($path));
}
/**
* Reads all files below the given <b>$path</b>.
*
* @param string $path The parent directory or a file.
* @return array(string)
*/
protected function readFiles($path)
{
if ($this->accept($path)) {
return array($path);
}
$files = array();
foreach ($this->createFileIterator($path) as $file) {
if ($this->accept($file)) {
$files[] = (string) $file;
}
}
return $files;
}
/**
* Does the given path represent a file that has the expected file extension?
*
* @param string $path Path to a file or directory.
* @return boolean
*/
protected function accept($path)
{
return (is_file($path) && '.php' === substr($path, -4, 4));
}
/**
* Creates an iterator with all files below the given directory.
*
* @param string $path Path to a directory.
* @return \Iterator
*/
protected function createFileIterator($path)
{
return new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path)
);
}
/**
* The main method starts the cache version updater.
*
* @param array $args Cli arguments.
* @return void
*/
public static function main(array $args)
{
$updater = new CacheVersionUpdater();
$updater->run();
}
}
CacheVersionUpdater::main($_SERVER['argv']);

View File

@@ -0,0 +1,72 @@
#!/usr/bin/env php
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
use PDepend\TextUI\Command;
// PEAR/svn workaround
if (strpos('@php_bin@', '@php_bin') === 0) {
set_include_path('.' . PATH_SEPARATOR . dirname(__FILE__) . '/../main/php');
}
// check for pdepend installed as composer package
if (file_exists(__DIR__ . '/../../../../autoload.php')) {
require_once __DIR__ . '/../../../../autoload.php';
} else {
require_once __DIR__ . '/../../vendor/autoload.php';
}
// Allow as much memory as possible by default
if (extension_loaded('suhosin') && is_numeric(ini_get('suhosin.memory_limit'))) {
$limit = ini_get('memory_limit');
if (preg_match('(^(\d+)([BKMGT]))', $limit, $match)) {
$shift = array('B' => 0, 'K' => 10, 'M' => 20, 'G' => 30, 'T' => 40);
$limit = ($match[1] * (1 << $shift[$match[2]]));
}
if (ini_get('suhosin.memory_limit') > $limit && $limit > -1) {
ini_set('memory_limit', ini_get('suhosin.memory_limit'));
}
} else {
ini_set('memory_limit', -1);
}
exit(Command::main());

View File

@@ -0,0 +1,46 @@
@echo off
REM This file is part of PDepend.
REM
REM Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
REM All rights reserved.
REM
REM Redistribution and use in source and binary forms, with or without
REM modification, are permitted provided that the following conditions
REM are met:
REM
REM * Redistributions of source code must retain the above copyright
REM notice, this list of conditions and the following disclaimer.
REM
REM * Redistributions in binary form must reproduce the above copyright
REM notice, this list of conditions and the following disclaimer in
REM the documentation and/or other materials provided with the
REM distribution.
REM
REM * Neither the name of Manuel Pichler nor the names of his
REM contributors may be used to endorse or promote products derived
REM from this software without specific prior written permission.
REM
REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
REM "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
REM LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
REM FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
REM COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
REM INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
REM BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
REM LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
REM LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
REM ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
REM POSSIBILITY OF SUCH DAMAGE.
REM
REM $Id$
REM
if "%PHPBIN%" == "" set PHPBIN=@php_bin@
if not exist "%PHPBIN%" if "%PHP_PEAR_PHP_BIN%" neq "" goto USE_PEAR_PATH
GOTO RUN
:USE_PEAR_PATH
set PHPBIN=%PHP_PEAR_PHP_BIN%
:RUN
"%PHPBIN%" "@bin_dir@\pdepend" %*

View File

@@ -0,0 +1,67 @@
#!/usr/bin/env php
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
use PDepend\TextUI\Command;
// PEAR/svn workaround
if (strpos('@php_bin@', '@php_bin') === 0) {
set_include_path('.' . PATH_SEPARATOR . dirname(__FILE__) . '/../main/php');
}
require_once __DIR__ . '/../../vendor/autoload.php';
// Allow as much memory as possible by default
if (extension_loaded('suhosin') && is_numeric(ini_get('suhosin.memory_limit'))) {
$limit = ini_get('memory_limit');
if (preg_match('(^(\d+)([BKMGT]))', $limit, $match)) {
$shift = array('B' => 0, 'K' => 10, 'M' => 20, 'G' => 30, 'T' => 40);
$limit = ($match[1] * (1 << $shift[$match[2]]));
}
if (ini_get('suhosin.memory_limit') > $limit && $limit > -1) {
ini_set('memory_limit', ini_get('suhosin.memory_limit'));
}
} else {
ini_set('memory_limit', -1);
}
exit(Command::main());

View File

@@ -0,0 +1,61 @@
#!/usr/bin/env php
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
// Map this phar archive
Phar::mapPhar('${archive.alias}');
// Configure include path to use this phar
set_include_path('phar://${archive.alias}/' . PATH_SEPARATOR . get_include_path());
// Run command line interface if this is the called file
if (isset($argv[0]) && realpath($argv[0]) === __FILE__) {
// Set memory limit to max allowed
ini_set('memory_limit', -1);
// Load command line utility
include_once 'phar://${archive.alias}/vendor/autoload.php';
exit(\PDepend\TextUI\Command::main($argv));
}
__HALT_COMPILER();

View File

@@ -0,0 +1,198 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
/**
* PDepend Application
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class Application
{
private $container;
/**
* @var string
*/
private $configurationFile;
/**
* @param string $configurationFile
*/
public function setConfigurationFile($configurationFile)
{
if (!file_exists($configurationFile)) {
throw new \InvalidArgumentException(
sprintf('The configuration file "%s" doesn\'t exist.', $configurationFile)
);
}
$this->configurationFile = $configurationFile;
}
/**
* @return \PDepend\Util\Configuration
*/
public function getConfiguration()
{
return $this->getContainer()->get('pdepend.configuration');
}
/**
* @return \PDepend\Engine
*/
public function getEngine()
{
return $this->getContainer()->get('pdepend.engine');
}
/**
* @return \PDepend\TextUI\Runner
*/
public function getRunner()
{
return $this->getContainer()->get('pdepend.textui.runner'); // TODO: Use standard name? textui is detail.
}
/**
* @return \PDepend\Report\ReportGeneratorFactory
*/
public function getReportGeneratorFactory()
{
return $this->getContainer()->get('pdepend.report_generator_factory');
}
/**
* @return \PDepend\Metrics\AnalyzerFactory
*/
public function getAnalyzerFactory()
{
return $this->getContainer()->get('pdepend.analyzer_factory');
}
private function getContainer()
{
if ($this->container === null) {
$this->container = $this->createContainer();
}
return $this->container;
}
/**
* @return \Symfony\Component\DependencyInjection\ContainerInterface
*/
private function createContainer()
{
$extensions = array(new DependencyInjection\PdependExtension());
$container = new ContainerBuilder(new ParameterBag(array()));
$container->prependExtensionConfig('pdepend', array());
$container->addCompilerPass(new DependencyInjection\Compiler\ProcessListenerPass());
$loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../../../resources'));
foreach ($extensions as $extension) {
$container->registerExtension($extension);
}
if ($this->configurationFile) {
$loader->load($this->configurationFile);
}
$container->compile();
return $container;
}
/**
* Returns available logger options and documentation messages.
*
* @return array(string => string)
*/
public function getAvailableLoggerOptions()
{
return $this->getAvailableOptionsFor('pdepend.logger');
}
/**
* Returns available analyzer options and documentation messages.
*
* @return array(string => string)
*/
public function getAvailableAnalyzerOptions()
{
return $this->getAvailableOptionsFor('pdepend.analyzer');
}
/**
* @return array(string => string)
*/
private function getAvailableOptionsFor($serviceTag)
{
$container = $this->getContainer();
$loggerServices = $container->findTaggedServiceIds($serviceTag);
$options = array();
foreach ($loggerServices as $loggerServiceTags) {
foreach ($loggerServiceTags as $loggerServiceTag) {
if (isset($loggerServiceTag['option']) && isset($loggerServiceTag['message'])) {
$options[$loggerServiceTag['option']] = array(
'message' => $loggerServiceTag['message'],
'value' => isset($loggerServiceTag['value']) ? $loggerServiceTag['value'] : 'file'
);
}
}
}
return $options;
}
}

View File

@@ -0,0 +1,198 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\DbusUI;
// This is just fun and it is not really testable
// @codeCoverageIgnoreStart
use PDepend\Metrics\Analyzer;
use PDepend\ProcessListener;
use PDepend\Source\ASTVisitor\AbstractASTVisitListener;
use PDepend\Source\Builder\Builder;
use PDepend\Source\Tokenizer\Tokenizer;
/**
* Fun result printer that uses dbus to show a notification window.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ResultPrinter extends AbstractASTVisitListener implements ProcessListener
{
/**
* Time when it the process has started.
*
* @var integer
*/
private $startTime = 0;
/**
* Number of parsed/analyzed files.
*
* @var integer
*/
private $parsedFiles = 0;
/**
* Is called when PDepend starts the file parsing process.
*
* @param \PDepend\Source\Builder\Builder $builder The used node builder instance.
* @return void
*/
public function startParseProcess(Builder $builder)
{
$this->startTime = time();
}
/**
* Is called when PDepend has finished the file parsing process.
*
* @param \PDepend\Source\Builder\Builder $builder The used node builder instance.
* @return void
*/
public function endParseProcess(Builder $builder)
{
}
/**
* Is called when PDepend starts parsing of a new file.
*
* @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
* @return void
*/
public function startFileParsing(Tokenizer $tokenizer)
{
}
/**
* Is called when PDepend has finished a file.
*
* @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
* @return void
*/
public function endFileParsing(Tokenizer $tokenizer)
{
++$this->parsedFiles;
}
/**
* Is called when PDepend starts the analyzing process.
*
* @return void
*/
public function startAnalyzeProcess()
{
}
/**
* Is called when PDepend has finished the analyzing process.
*
* @return void
*/
public function endAnalyzeProcess()
{
}
/**
* Is called when PDepend starts the logging process.
*
* @return void
*/
public function startLogProcess()
{
}
/**
* Is called when PDepend has finished the logging process.
*
* @return void
*/
public function endLogProcess()
{
if (extension_loaded('dbus') === false) {
return;
}
$dbus = new Dbus(Dbus::BUS_SESSION);
$proxy = $dbus->createProxy(
"org.freedesktop.Notifications", // connection name
"/org/freedesktop/Notifications", // object
"org.freedesktop.Notifications" // interface
);
$proxy->Notify(
'PDepend',
new DBusUInt32(0),
'pdepend',
'PDepend',
sprintf(
'%d files analyzed in %s minutes...',
$this->parsedFiles,
(date('i:s', time() - $this->startTime))
),
new DBusArray(DBus::STRING, array()),
new DBusDict(DBus::VARIANT, array()),
1000
);
}
/**
* Is called when PDepend starts a new analyzer.
*
* @param \PDepend\Metrics\Analyzer $analyzer The context analyzer instance.
* @return void
*/
public function startAnalyzer(Analyzer $analyzer)
{
}
/**
* Is called when PDepend has finished one analyzing process.
*
* @param \PDepend\Metrics\Analyzer $analyzer The context analyzer instance.
* @return void
*/
public function endAnalyzer(Analyzer $analyzer)
{
}
}
// @codeCoverageIgnoreEnd

View File

@@ -0,0 +1,69 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
/**
* Find Process Listeners of extensions by 'pdepend.process_listener' tag.
*
* Listeners are added to the PDepend\Engine service.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ProcessListenerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$engineDefinition = $container->findDefinition('pdepend.engine');
$processListenerTags = $container->findTaggedServiceIds('pdepend.process_listener');
foreach ($processListenerTags as $id => $tags) {
$engineDefinition->addMethodCall('addProcessListener', array(new Reference($id)));
}
}
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\DependencyInjection;
use PDepend\Util\FileUtil;
use PDepend\Util\Workarounds;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class Configuration implements ConfigurationInterface
{
/**
* @var array(Extension)
*/
private $extensions = array();
public function __construct(array $extensions)
{
$this->extensions = $extensions;
}
/**
* {@inheritDoc}
*/
public function getConfigTreeBuilder()
{
$home = FileUtil::getUserHomeDirOrSysTempDir();
$workarounds = new Workarounds();
$defaultCacheDriver = ($workarounds->hasSerializeReferenceIssue()) ? 'memory' : 'file';
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('pdepend');
$rootNode
->children()
->arrayNode('cache')
->addDefaultsIfNotSet()
->children()
->enumNode('driver')->defaultValue($defaultCacheDriver)->values(array('file', 'memory'))->end()
->scalarNode('location')->defaultValue($home . '/.pdepend')->end()
->end()
->end()
->arrayNode('image_convert')
->addDefaultsIfNotSet()
->children()
->scalarNode('font_size')->defaultValue('11')->end()
->scalarNode('font_family')->defaultValue('Arial')->end()
->end()
->end()
->arrayNode('parser')
->addDefaultsIfNotSet()
->children()
->integerNode('nesting')->defaultValue(65536)->end()
->end()
->end()
->end();
$extensionsNode = $rootNode
->children()
->arrayNode('extensions')
->addDefaultsIfNotSet()
->children();
foreach ($this->extensions as $extension) {
$extensionNode = $extensionsNode->arrayNode($extension->getName());
$extension->getConfig($extensionNode);
}
return $treeBuilder;
}
}

View File

@@ -0,0 +1,136 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\DependencyInjection;
use ReflectionClass;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
/**
* PDepend base extension class.
*
* Copied from Behat
*
* @link https://github.com/Behat/Behat/blob/3.0/src/Behat/Behat/Extension/Extension.php
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
abstract class Extension
{
/**
* Return name of the extension
*
* @return string
*/
abstract public function getName();
/**
* Loads a specific configuration.
*
* @param array $config Extension configuration hash (from behat.yml)
* @param ContainerBuilder $container ContainerBuilder instance
*/
public function load(array $config, ContainerBuilder $container)
{
$path = rtrim($this->getServiceDefinitionsPath(), DIRECTORY_SEPARATOR);
$name = $this->getServiceDefinitionsName();
if (file_exists($path . DIRECTORY_SEPARATOR . ($file = $name . '.xml'))) {
$loader = new XmlFileLoader($container, new FileLocator($path));
$loader->load($file);
}
if (file_exists($path . DIRECTORY_SEPARATOR . ($file = $name . '.yml'))) {
$loader = new YamlFileLoader($container, new FileLocator($path));
$loader->load($file);
}
$container->setParameter($this->getName() . '.parameters', $config);
}
/**
* Setups configuration for current extension.
*
* @param ArrayNodeDefinition $builder
*/
public function getConfig(ArrayNodeDefinition $builder)
{
$builder
->useAttributeAsKey('name')
->prototype('variable');
}
/**
* Returns compiler passes used by this extension.
*
* @return CompilerPassInterface[]
*/
public function getCompilerPasses()
{
return array();
}
/**
* Returns name of the service definition config without extension and path.
*
* @return string
*/
protected function getServiceDefinitionsName()
{
return 'services';
}
/**
* Returns service definition configs path.
*
* @return string
*/
protected function getServiceDefinitionsPath()
{
$reflection = new ReflectionClass($this);
return dirname($reflection->getFileName());
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\DependencyInjection;
/**
* Manage activation and registration of extensions for PDepend.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ExtensionManager
{
private $extensions = array();
/**
* Activate an extension based on a class name.
*
* @throws RuntimeException
* @param string $className
* @return void
*/
public function activateExtension($className)
{
if (!class_exists($className)) {
throw new \RuntimeException(
sprintf(
'Cannot find extension class %s" for PDepend. Maybe the plugin is not installed?',
$className
)
);
}
$extension = new $className;
if (!($extension instanceof Extension)) {
throw new \RuntimeException(
sprintf('Class "%s" is not a valid Extension', $className)
);
}
$this->extensions[$extension->getName()] = $extension;
}
/**
* Return all activated extensions.
*
* @return array(\PDepend\DependencyInjection\Extension)
*/
public function getActivatedExtensions()
{
return $this->extensions;
}
}

View File

@@ -0,0 +1,127 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\DependencyInjection;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension as SymfonyExtension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
/**
* PDepend DependencyInjection Extension for Symfony DIC
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class PdependExtension extends SymfonyExtension
{
/**
* {@inheritDoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$extensionManager = new ExtensionManager();
foreach ($configs as $config) {
if (!isset($config['extensions'])) {
continue;
}
foreach ($config['extensions'] as $config) {
if (!isset($config['class'])) {
continue;
}
$extensionManager->activateExtension($config['class']);
}
}
$configuration = new Configuration($extensionManager->getActivatedExtensions());
$config = $this->processConfiguration($configuration, $configs);
$loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__ . '/../../../resources'));
$loader->load('services.xml');
foreach ($extensionManager->getActivatedExtensions() as $extension) {
$extensionConfig = $config['extensions'][$extension->getName()];
$tempContainer = new ContainerBuilder(new ParameterBag(array()));
$tempContainer->addObjectResource($extension);
// load extension into temporary container
$extension->load($extensionConfig, $tempContainer);
// merge temporary container into normal one
$container->merge($tempContainer);
}
$settings = $this->createSettings($config);
$configurationDefinition = $container->findDefinition('pdepend.configuration');
$configurationDefinition->setArguments(array($settings));
}
private function createSettings($config)
{
$settings = new \stdClass();
$settings->cache = new \stdClass();
$settings->cache->driver = $config['cache']['driver'];
$settings->cache->location = $config['cache']['location'];
$settings->imageConvert = new \stdClass();
$settings->imageConvert->fontSize = $config['image_convert']['font_size'];
$settings->imageConvert->fontFamily = $config['image_convert']['font_family'];
$settings->parser = new \stdClass();
$settings->parser->nesting = $config['parser']['nesting'];
return $settings;
}
public function getNamespace()
{
return 'http://pdepend.org/schema/dic/pdepend';
}
}

View File

@@ -0,0 +1,705 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend;
use PDepend\Input\CompositeFilter;
use PDepend\Input\Filter;
use PDepend\Input\Iterator;
use PDepend\Metrics\AnalyzerCacheAware;
use PDepend\Metrics\AnalyzerClassFileSystemLocator;
use PDepend\Metrics\AnalyzerFactory;
use PDepend\Metrics\AnalyzerFilterAware;
use PDepend\Metrics\AnalyzerLoader;
use PDepend\Report\CodeAwareGenerator;
use PDepend\Source\AST\ASTArtifactList\ArtifactFilter;
use PDepend\Source\AST\ASTArtifactList\CollectionArtifactFilter;
use PDepend\Source\AST\ASTArtifactList\NullArtifactFilter;
use PDepend\Source\ASTVisitor\ASTVisitor;
use PDepend\Source\Builder\Builder;
use PDepend\Source\Language\PHP\PHPBuilder;
use PDepend\Source\Language\PHP\PHPParserGeneric;
use PDepend\Source\Language\PHP\PHPTokenizerInternal;
use PDepend\Source\Tokenizer\Tokenizer;
use PDepend\Util\Cache\CacheFactory;
use PDepend\Util\Configuration;
/**
* PDepend analyzes php class files and generates metrics.
*
* The PDepend is a php port/adaption of the Java class file analyzer
* <a href="http://clarkware.com/software/JDepend.html">JDepend</a>.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class Engine
{
/**
* Marks the storage used for runtime tokens.
*/
const TOKEN_STORAGE = 1;
/**
* Marks the storag engine used for parser artifacts.
*/
const PARSER_STORAGE = 2;
/**
* The system configuration.
*
* @var \PDepend\Util\Configuration
* @since 0.10.0
*/
protected $configuration = null;
/**
* List of source directories.
*
* @var array(string)
*/
private $directories = array();
/**
* List of source code file names.
*
* @var array(string)
*/
private $files = array();
/**
* The used code node builder.
*
* @var \PDepend\Source\Builder\Builder
*/
private $builder = null;
/**
* Generated {@link \PDepend\Source\AST\ASTNamespace} objects.
*
* @var \PDepend\Source\AST\ASTNamespace[]
*/
private $namespaces = null;
/**
* List of all registered {@link \PDepend\Report\ReportGenerator} instances.
*
* @var \PDepend\Report\ReportGenerator[]
*/
private $generators = array();
/**
* A composite filter for input files.
*
* @var \PDepend\Input\CompositeFilter
*/
private $fileFilter = null;
/**
* A filter for namespace.
*
* @var \PDepend\Source\AST\ASTArtifactList\ArtifactFilter
*/
private $codeFilter = null;
/**
* Should the parse ignore doc comment annotations?
*
* @var boolean
*/
private $withoutAnnotations = false;
/**
* List or registered listeners.
*
* @var \PDepend\ProcessListener[]
*/
private $listeners = array();
/**
* List of analyzer options.
*
* @var array(string=>mixed)
*/
private $options = array();
/**
* List of all {@link \PDepend\Source\Parser\ParserException} that were caught during
* the parsing process.
*
* @var \PDepend\Source\Parser\ParserException[]
*/
private $parseExceptions = array();
/**
* The configured cache factory.
*
* @var \PDepend\Util\Cache\CacheFactory
* @since 1.0.0
*/
private $cacheFactory;
/**
* @var \PDepend\Metrics\AnalyzerFactory
*/
private $analyzerFactory;
/**
* Constructs a new php depend facade.
*
* @param \PDepend\Util\Configuration $configuration The system configuration.
* @param \PDepend\Util\Cache\CacheFactory $cacheFactory
* @param \PDepend\Metrics\AnalyzerFactory $analyzerFactory
*/
public function __construct(
Configuration $configuration,
CacheFactory $cacheFactory,
AnalyzerFactory $analyzerFactory
) {
$this->configuration = $configuration;
$this->codeFilter = new NullArtifactFilter();
$this->fileFilter = new CompositeFilter();
$this->cacheFactory = $cacheFactory;
$this->analyzerFactory = $analyzerFactory;
}
/**
* Adds the specified directory to the list of directories to be analyzed.
*
* @param string $directory The php source directory.
* @return void
*/
public function addDirectory($directory)
{
$dir = realpath($directory);
if (!is_dir($dir)) {
throw new \InvalidArgumentException("Invalid directory '{$directory}' added.");
}
$this->directories[] = $dir;
}
/**
* Adds a single source code file to the list of files to be analysed.
*
* @param string $file The source file name.
* @return void
*/
public function addFile($file)
{
if ($file === '-' || $file === 'php://stdin') {
$fileName = 'php://stdin';
} else {
$fileName = realpath($file);
if (!is_file($fileName)) {
throw new \InvalidArgumentException(sprintf('The given file "%s" does not exist.', $file));
}
}
$this->files[] = $fileName;
}
/**
* Adds a logger to the output list.
*
* @param \PDepend\Report\ReportGenerator $generator The logger instance.
* @return void
*/
public function addReportGenerator(\PDepend\Report\ReportGenerator $generator)
{
$this->generators[] = $generator;
}
/**
* Adds a new input/file filter.
*
* @param \PDepend\Input\Filter $filter New input/file filter instance.
* @return void
*/
public function addFileFilter(Filter $filter)
{
$this->fileFilter->append($filter);
}
/**
* Sets an additional code filter. These filters could be used to hide
* external libraries and global stuff from the PDepend output.
*
* @param \PDepend\Source\AST\ASTArtifactList\ArtifactFilter $filter
* @return void
*/
public function setCodeFilter(ArtifactFilter $filter)
{
$this->codeFilter = $filter;
}
/**
* Sets analyzer options.
*
* @param array(string=>mixed) $options The analyzer options.
* @return void
*/
public function setOptions(array $options = array())
{
$this->options = $options;
}
/**
* Should the parse ignore doc comment annotations?
*
* @return void
*/
public function setWithoutAnnotations()
{
$this->withoutAnnotations = true;
}
/**
* Adds a process listener.
*
* @param \PDepend\ProcessListener $listener The listener instance.
* @return void
*/
public function addProcessListener(ProcessListener $listener)
{
if (in_array($listener, $this->listeners, true) === false) {
$this->listeners[] = $listener;
}
}
/**
* Analyzes the registered directories and returns the collection of
* analyzed namespace.
*
* @return \PDepend\Source\AST\ASTNamespace[]
*/
public function analyze()
{
$this->builder = new PHPBuilder();
$this->performParseProcess();
// Get global filter collection
$collection = CollectionArtifactFilter::getInstance();
$collection->setFilter($this->codeFilter);
$collection->setFilter();
$this->performAnalyzeProcess();
// Set global filter for logging
$collection->setFilter($this->codeFilter);
$namespaces = $this->builder->getNamespaces();
$this->fireStartLogProcess();
foreach ($this->generators as $generator) {
// Check for code aware loggers
if ($generator instanceof CodeAwareGenerator) {
$generator->setArtifacts($namespaces);
}
$generator->close();
}
$this->fireEndLogProcess();
return ($this->namespaces = $namespaces);
}
/**
* Returns the number of analyzed php classes and interfaces.
*
* @return integer
*/
public function countClasses()
{
if ($this->namespaces === null) {
$msg = 'countClasses() doesn\'t work before the source was analyzed.';
throw new \RuntimeException($msg);
}
$classes = 0;
foreach ($this->namespaces as $namespace) {
$classes += $namespace->getTypes()->count();
}
return $classes;
}
/**
* Returns an <b>array</b> with all {@link \PDepend\Source\Parser\ParserException}
* that were caught during the parsing process.
*
* @return \PDepend\Source\Parser\ParserException[]
*/
public function getExceptions()
{
return $this->parseExceptions;
}
/**
* Returns the number of analyzed namespaces.
*
* @return integer
*/
public function countNamespaces()
{
if ($this->namespaces === null) {
$msg = 'countNamespaces() doesn\'t work before the source was analyzed.';
throw new \RuntimeException($msg);
}
$count = 0;
foreach ($this->namespaces as $namespace) {
if ($namespace->isUserDefined()) {
++$count;
}
}
return $count;
}
/**
* Returns the analyzed namespace for the given name.
*
* @param string $name
* @return \PDepend\Source\AST\ASTNamespace
* @throws \OutOfBoundsException
* @throws \RuntimeException
*/
public function getNamespace($name)
{
if ($this->namespaces === null) {
$msg = 'getNamespace() doesn\'t work before the source was analyzed.';
throw new \RuntimeException($msg);
}
foreach ($this->namespaces as $namespace) {
if ($namespace->getName() === $name) {
return $namespace;
}
}
throw new \OutOfBoundsException(sprintf('Unknown namespace "%s".', $name));
}
/**
* Returns an array with the analyzed namespace.
*
* @return \PDepend\Source\AST\ASTNamespace[]
* @throws \RuntimeException
*/
public function getNamespaces()
{
if ($this->namespaces === null) {
$msg = 'getNamespaces() doesn\'t work before the source was analyzed.';
throw new \RuntimeException($msg);
}
return $this->namespaces;
}
/**
* Send the start parsing process event.
*
* @param \PDepend\Source\Builder\Builder $builder The used node builder instance.
* @return void
*/
protected function fireStartParseProcess(Builder $builder)
{
foreach ($this->listeners as $listener) {
$listener->startParseProcess($builder);
}
}
/**
* Send the end parsing process event.
*
* @param \PDepend\Source\Builder\Builder $builder The used node builder instance.
* @return void
*/
protected function fireEndParseProcess(Builder $builder)
{
foreach ($this->listeners as $listener) {
$listener->endParseProcess($builder);
}
}
/**
* Sends the start file parsing event.
*
* @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
* @return void
*/
protected function fireStartFileParsing(Tokenizer $tokenizer)
{
foreach ($this->listeners as $listener) {
$listener->startFileParsing($tokenizer);
}
}
/**
* Sends the end file parsing event.
*
* @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
* @return void
*/
protected function fireEndFileParsing(Tokenizer $tokenizer)
{
foreach ($this->listeners as $listener) {
$listener->endFileParsing($tokenizer);
}
}
/**
* Sends the start analyzing process event.
*
* @return void
*/
protected function fireStartAnalyzeProcess()
{
foreach ($this->listeners as $listener) {
$listener->startAnalyzeProcess();
}
}
/**
* Sends the end analyzing process event.
*
* @return void
*/
protected function fireEndAnalyzeProcess()
{
foreach ($this->listeners as $listener) {
$listener->endAnalyzeProcess();
}
}
/**
* Sends the start log process event.
*
* @return void
*/
protected function fireStartLogProcess()
{
foreach ($this->listeners as $listener) {
$listener->startLogProcess();
}
}
/**
* Sends the end log process event.
*
* @return void
*/
protected function fireEndLogProcess()
{
foreach ($this->listeners as $listener) {
$listener->endLogProcess();
}
}
/**
* This method performs the parsing process of all source files. It expects
* that the <b>$_builder</b> property was initialized with a concrete builder
* implementation.
*
* @return void
*/
private function performParseProcess()
{
// Reset list of thrown exceptions
$this->parseExceptions = array();
$tokenizer = new PHPTokenizerInternal();
$this->fireStartParseProcess($this->builder);
foreach ($this->createFileIterator() as $file) {
$tokenizer->setSourceFile($file);
$parser = new PHPParserGeneric(
$tokenizer,
$this->builder,
$this->cacheFactory->create()
);
$parser->setMaxNestingLevel($this->configuration->parser->nesting);
// Disable annotation parsing?
if ($this->withoutAnnotations === true) {
$parser->setIgnoreAnnotations();
}
$this->fireStartFileParsing($tokenizer);
try {
$parser->parse();
} catch (\PDepend\Source\Parser\ParserException $e) {
$this->parseExceptions[] = $e;
}
$this->fireEndFileParsing($tokenizer);
}
$this->fireEndParseProcess($this->builder);
}
/**
* This method performs the analysing process of the parsed source files. It
* creates the required analyzers for the registered listeners and then
* applies them to the source tree.
*
* @return void
*/
private function performAnalyzeProcess()
{
$analyzerLoader = $this->createAnalyzers($this->options);
$collection = CollectionArtifactFilter::getInstance();
$this->fireStartAnalyzeProcess();
ini_set('xdebug.max_nesting_level', $this->configuration->parser->nesting);
foreach ($analyzerLoader as $analyzer) {
// Add filters if this analyzer is filter aware
if ($analyzer instanceof AnalyzerFilterAware) {
$collection->setFilter($this->codeFilter);
}
$analyzer->analyze($this->builder->getNamespaces());
// Remove filters if this analyzer is filter aware
$collection->setFilter();
foreach ($this->generators as $logger) {
$logger->log($analyzer);
}
}
ini_restore('xdebug.max_nesting_level');
$this->fireEndAnalyzeProcess();
}
/**
* This method will create an iterator instance which contains all files
* that are part of the parsing process.
*
* @return \Iterator
*/
private function createFileIterator()
{
if (count($this->directories) === 0 && count($this->files) === 0) {
throw new \RuntimeException('No source directory and file set.');
}
$fileIterator = new \AppendIterator();
foreach ($this->files as $file) {
$fileIterator->append(new Iterator(new \GlobIterator($file), $this->fileFilter));
}
foreach ($this->directories as $directory) {
$fileIterator->append(
new Iterator(
new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator(
$directory . '/',
\RecursiveDirectoryIterator::FOLLOW_SYMLINKS
)
),
$this->fileFilter,
$directory
)
);
}
// TODO: It's important to validate this behavior, imho there is something
// wrong in the iterator code used above.
// Strange: why is the iterator not unique and why does this loop fix it?
$files = array();
foreach ($fileIterator as $file) {
if (is_string($file)) {
$files[$file] = $file;
} else {
$pathname = realpath($file->getPathname());
$files[$pathname] = $pathname;
}
}
foreach ($files as $key => $file) {
if (!$this->fileFilter->accept($file, $file)) {
unset($files[$key]);
}
}
ksort($files);
// END
return new \ArrayIterator(array_values($files));
}
private function createAnalyzers($options)
{
$analyzers = $this->analyzerFactory->createRequiredForGenerators($this->generators);
$cacheKey = md5(serialize($this->files) . serialize($this->directories));
$cache = $this->cacheFactory->create($cacheKey);
foreach ($analyzers as $analyzer) {
if ($analyzer instanceof AnalyzerCacheAware) {
$analyzer->setCache($cache);
}
$analyzer->setOptions($options);
foreach ($this->listeners as $listener) {
$analyzer->addAnalyzeListener($listener);
if ($analyzer instanceof ASTVisitor) {
$analyzer->addVisitListener($listener);
}
}
}
return $analyzers;
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Input;
/**
* Simple composite pattern implementation that allows to bundle multiple
* filter implementations.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class CompositeFilter implements Filter
{
/**
* List of aggregated {@link \PDepend\Input\Filter} objects.
*
* @var \PDepend\Input\Filter[]
*/
protected $filters = array();
/**
* Adds a file filter to this composite.
*
* @param \PDepend\Input\Filter $filter The new filter object.
* @return void
*/
public function append(Filter $filter)
{
$this->filters[] = $filter;
}
/**
* Delegates the given <b>$localPath</b> object to all aggregated filters.
* Returns <b>true</b> if this filter accepts the given path.
*
* @param string $relative The relative path to the specified root.
* @param string $absolute The absolute path to a source file.
* @return boolean
*/
public function accept($relative, $absolute)
{
foreach ($this->filters as $filter) {
if (false === $filter->accept($relative, $absolute)) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,123 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Input;
/**
* Filters a given file path against a blacklist with disallow path fragments.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ExcludePathFilter implements Filter
{
/**
* Regular expression that should not match against the relative file paths.
*
* @var string
* @since 0.10.0
*/
protected $relative = '';
/**
* Regular expression that should not match against the absolute file paths.
*
* @var string
* @since 0.10.0
*/
protected $absolute = '';
/**
* Constructs a new exclude path filter instance and accepts an array of
* exclude pattern as argument.
*
* @param array $patterns List of exclude file path patterns.
*/
public function __construct(array $patterns)
{
$quoted = array_map('preg_quote', $patterns);
$this->relative = '(' . str_replace('\*', '.*', join('|', $quoted)) . ')i';
$this->absolute = '(^(' . str_replace('\*', '.*', join('|', $quoted)) .'))i';
}
/**
* Returns <b>true</b> if this filter accepts the given path.
*
* @param string $relative The relative path to the specified root.
* @param string $absolute The absolute path to a source file.
*
* @return boolean
*/
public function accept($relative, $absolute)
{
return ($this->notRelative($relative) && $this->notAbsolute($absolute));
}
/**
* This method checks if the given <b>$path</b> does not match against the
* exclude patterns as an absolute path.
*
* @param string $path The absolute path to a source file.
*
* @return boolean
* @since 0.10.0
*/
protected function notAbsolute($path)
{
return (preg_match($this->absolute, $path) === 0);
}
/**
* This method checks if the given <b>$path</b> does not match against the
* exclude patterns as an relative path.
*
* @param string $path The relative path to a source file.
*
* @return boolean
* @since 0.10.0
*/
protected function notRelative($path)
{
return (preg_match($this->relative, $path) === 0);
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Input;
/**
* Whitelist filter that accepts files by their file extension.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ExtensionFilter implements Filter
{
/**
* Whitelist of accepted file extensions.
*
* @var array(string)
*/
protected $extensions = array();
/**
* Constructs a new file extension filter instance with the given list of
* allowed file <b>$extensions</b>.
*
* @param array $extensions List of allowed extension.
*/
public function __construct(array $extensions)
{
$this->extensions = $extensions;
}
/**
* Returns <b>true</b> if this filter accepts the given paths.
*
* @param string $relative The relative path to the specified root.
* @param string $absolute The absolute path to a source file.
* @return boolean
*/
public function accept($relative, $absolute)
{
if (strpos($absolute, 'php://') === 0) {
return true;
}
$extension = pathinfo($relative, PATHINFO_EXTENSION);
return in_array($extension, $this->extensions);
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Input;
/**
* Base interface for file filters.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface Filter
{
/**
* Returns <b>true</b> if this filter accepts the given paths.
*
* @param string $relative The relative path to the specified root.
* @param string $absolute The absolute path to a source file.
* @return boolean
*/
public function accept($relative, $absolute);
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Input;
/**
* Simple utility filter iterator for php source files.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class Iterator extends \FilterIterator
{
/**
* The associated filter object.
*
* @var \PDepend\Input\Filter
*/
protected $filter = null;
/**
* Optional root path for the files.
*
* @var string
* @since 0.10.0
*/
protected $rootPath = null;
/**
* Constructs a new file filter iterator.
*
* @param \Iterator $iterator The inner iterator.
* @param \PDepend\Input\Filter $filter The filter object.
* @param string $rootPath Optional root path for the files.
*/
public function __construct(\Iterator $iterator, Filter $filter, $rootPath = null)
{
parent::__construct($iterator);
$this->filter = $filter;
$this->rootPath = $rootPath;
}
/**
* Returns <b>true</b> if the file name ends with '.php'.
*
* @return boolean
*/
public function accept()
{
if ($this->getInnerIterator()->current()->isDir()) {
return false;
}
return $this->filter->accept($this->getLocalPath(), $this->getFullPath());
}
/**
* Returns the full qualified realpath for the currently active file.
*
* @return string
* @since 0.10.0
*/
protected function getFullPath()
{
return $this->getInnerIterator()->current()->getRealpath();
}
/**
* Returns the local path of the current file, if the root path property was
* set. If not, this method returns the absolute file path.
*
* @return string
* @since 0.10.0
*/
protected function getLocalPath()
{
if ($this->rootPath && 0 === strpos($this->getFullPath(), $this->rootPath)) {
return substr($this->getFullPath(), strlen($this->rootPath));
}
return $this->getFullPath();
}
}

View File

@@ -0,0 +1,147 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics;
use PDepend\Source\ASTVisitor\AbstractASTVisitor;
/**
* This abstract class provides a base implementation of an analyzer.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
abstract class AbstractAnalyzer extends AbstractASTVisitor implements Analyzer
{
/**
* Global options array.
*
* @var array(string=>mixed)
*/
protected $options = array();
/**
* List or registered listeners.
*
* @var \PDepend\Metrics\AnalyzerListener[]
*/
private $listeners = array();
/**
* Constructs a new analyzer instance.
*
* @param array(string=>mixed) $options Global option array, every analyzer
* can extract the required options.
*/
public function __construct(array $options = array())
{
$this->options = $options;
}
/**
* Set global options
*
* @param array(string=>mixed) $options Global option array, every analyzer
* can extract the required options.
*/
public function setOptions(array $options = array())
{
$this->options = $options;
}
/**
* Adds a listener to this analyzer.
*
* @param \PDepend\Metrics\AnalyzerListener $listener The listener instance.
* @return void
*/
public function addAnalyzeListener(\PDepend\Metrics\AnalyzerListener $listener)
{
if (in_array($listener, $this->listeners, true) === false) {
$this->listeners[] = $listener;
}
}
/**
* An analyzer that is active must return <b>true</b> to recognized by
* pdepend framework, while an analyzer that does not perform any action
* for any reason should return <b>false</b>.
*
* By default all analyzers are enabled. Overwrite this method to provide
* state based disabling/enabling.
*
* @return boolean
* @since 0.9.10
*/
public function isEnabled()
{
return true;
}
/**
* The analyzer implementation should call this method when it starts the
* code processing. This method will send an analyzer start event to all
* registered listeners.
*
* @return void
*/
protected function fireStartAnalyzer()
{
foreach ($this->listeners as $listener) {
$listener->startAnalyzer($this);
}
}
/**
* The analyzer implementation should call this method when it has finished
* the code processing. This method will send an analyzer end event to all
* registered listeners.
*
* @return void
*/
protected function fireEndAnalyzer()
{
foreach ($this->listeners as $listener) {
$listener->endAnalyzer($this);
}
}
}

View File

@@ -0,0 +1,145 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
namespace PDepend\Metrics;
use PDepend\Source\AST\AbstractASTArtifact;
use PDepend\Util\Cache\CacheDriver;
/**
* This abstract class provides an analyzer that provides the basic infrastructure
* for caching.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
abstract class AbstractCachingAnalyzer extends AbstractAnalyzer implements AnalyzerCacheAware
{
/**
* Collected node metrics
*
* @var array
*/
protected $metrics = null;
/**
* Metrics restored from the cache. This property is only used temporary.
*
* @var array
*/
private $metricsCached = array();
/**
* Injected cache driver.
*
* @var \PDepend\Util\Cache\CacheDriver
*/
private $cache;
/**
* Setter method for the system wide used cache.
*
* @param \PDepend\Util\Cache\CacheDriver $cache
* @return void
*/
public function setCache(CacheDriver $cache)
{
$this->cache = $cache;
}
/**
* Getter method for the system wide used cache.
*
* @return \PDepend\Util\Cache\CacheDriver $cache
*/
public function getCache()
{
return $this->cache;
}
/**
* Tries to restore the metrics for a cached node. If this method has
* restored the metrics it will return <b>TRUE</b>, otherwise the return
* value will be <b>FALSE</b>.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return boolean
*/
protected function restoreFromCache(AbstractASTArtifact $node)
{
$id = $node->getId();
if ($node->isCached() && isset($this->metricsCached[$id])) {
$this->metrics[$id] = $this->metricsCached[$id];
return true;
}
return false;
}
/**
* Initializes the previously calculated metrics from the cache.
*
* @return void
*/
protected function loadCache()
{
$this->metricsCached = (array) $this->cache
->type('metrics')
->restore(get_class($this));
}
/**
* Unloads the metrics cache and stores the current set of metrics in the
* cache.
*
* @return void
*/
protected function unloadCache()
{
$this->cache
->type('metrics')
->store(get_class($this), $this->metrics);
$this->metricsCached = array();
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics;
/**
* This analyzer interface provides a specialized form that allows an analyzer
* to aggregate metrics calculated by other analyzers.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface AggregateAnalyzer extends Analyzer
{
/**
* This method must return an <b>array</b> of class names for required
* analyzers.
*
* @return array(string)
*/
public function getRequiredAnalyzers();
/**
* Adds a required sub analyzer.
*
* @param \PDepend\Metrics\Analyzer $analyzer The sub analyzer instance.
* @return void
*/
public function addAnalyzer(Analyzer $analyzer);
}

View File

@@ -0,0 +1,96 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics;
use PDepend\Source\AST\ASTArtifactList;
/**
* Base interface for all analyzer implementations.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface Analyzer
{
/**
* Constructs a new analyzer instance.
*
* @param array(string=>mixed) $options Global option array, every analyzer
* can extract the required options.
*/
public function __construct(array $options = array());
/**
* Adds a listener to this analyzer.
*
* @param \PDepend\Metrics\AnalyzerListener $listener The listener instance.
* @return void
*/
public function addAnalyzeListener(AnalyzerListener $listener);
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces);
/**
* An analyzer that is active must return <b>true</b> to recognized by
* pdepend framework, while an analyzer that does not perform any action
* for any reason should return <b>false</b>.
*
* @return boolean
* @since 0.9.10
*/
public function isEnabled();
/**
* Set global options
*
* @param array(string=>mixed) $options
* @since 2.0.1
*/
public function setOptions(array $options = array());
}

View File

@@ -0,0 +1,333 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Source\AST\AbstractASTArtifact;
use PDepend\Source\AST\AbstractASTClassOrInterface;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\AST\ASTNamespace;
/**
* This visitor generates the metrics for the analyzed namespaces.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ClassDependencyAnalyzer extends AbstractAnalyzer
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_AFFERENT_COUPLING = 'ca',
M_EFFERENT_COUPLING = 'ce';
/**
* Hash with all calculated node metrics.
*
* <code>
* array(
* '0375e305-885a-4e91-8b5c-e25bda005438' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* ),
* 'e60c22f0-1a63-4c40-893e-ed3b35b84d0b' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* )
* )
* </code>
*
* @var array(string=>array)
*/
private $nodeMetrics = null;
protected $nodeSet = array();
private $efferentNodes = array();
private $afferentNodes = array();
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->nodeMetrics === null) {
$this->fireStartAnalyzer();
$this->nodeMetrics = array();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->postProcess();
$this->fireEndAnalyzer();
}
}
/**
* Returns an array of all afferent nodes.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return \PDepend\Source\AST\AbstractASTArtifact[]
*/
public function getAfferents(AbstractASTArtifact $node)
{
$afferents = array();
if (isset($this->afferentNodes[$node->getId()])) {
$afferents = $this->afferentNodes[$node->getId()];
}
return $afferents;
}
/**
* Returns an array of all efferent nodes.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return \PDepend\Source\AST\AbstractASTArtifact[]
*/
public function getEfferents(AbstractASTArtifact $node)
{
$efferents = array();
if (isset($this->efferentNodes[$node->getId()])) {
$efferents = $this->efferentNodes[$node->getId()];
}
return $efferents;
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
$type = $method->getParent();
foreach ($method->getDependencies() as $dependency) {
$this->collectDependencies($type, $dependency);
}
$this->fireEndMethod($method);
}
/**
* Visits a namespace node.
*
* @param \PDepend\Source\AST\ASTNamespace $namespace
* @return void
*/
public function visitNamespace(ASTNamespace $namespace)
{
$this->fireStartNamespace($namespace);
$this->nodeSet[$namespace->getId()] = $namespace;
foreach ($namespace->getTypes() as $type) {
$type->accept($this);
}
$this->fireEndNamespace($namespace);
}
/**
* Visits a class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
$this->fireStartClass($class);
$this->visitType($class);
$this->fireEndClass($class);
}
/**
* Visits an interface node.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
$this->fireStartInterface($interface);
$this->visitType($interface);
$this->fireEndInterface($interface);
}
/**
* Generic visit method for classes and interfaces. Both visit methods
* delegate calls to this method.
*
* @param \PDepend\Source\AST\AbstractASTClassOrInterface $type
* @return void
*/
protected function visitType(AbstractASTClassOrInterface $type)
{
$id = $type->getId();
foreach ($type->getDependencies() as $dependency) {
$this->collectDependencies($type, $dependency);
}
foreach ($type->getMethods() as $method) {
$method->accept($this);
}
}
/**
* Collects the dependencies between the two given classes.
*
* @param \PDepend\Source\AST\AbstractASTClassOrInterface $typeB
* @param \PDepend\Source\AST\AbstractASTClassOrInterface $typeB
*
* @return void
*/
private function collectDependencies(AbstractASTClassOrInterface $typeA, AbstractASTClassOrInterface $typeB)
{
$idA = $typeA->getId();
$idB = $typeB->getId();
if ($idB === $idA) {
return;
}
// Create a container for this dependency
$this->initTypeMetric($typeA);
$this->initTypeMetric($typeB);
if (!in_array($idB, $this->nodeMetrics[$idA][self::M_EFFERENT_COUPLING])) {
$this->nodeMetrics[$idA][self::M_EFFERENT_COUPLING][] = $idB;
$this->nodeMetrics[$idB][self::M_AFFERENT_COUPLING][] = $idA;
}
}
/**
* Initializes the node metric record for the given <b>$type</b>.
*
* @param \PDepend\Source\AST\AbstractASTClassOrInterface $type
* @return void
*/
protected function initTypeMetric(AbstractASTClassOrInterface $type)
{
$id = $type->getId();
if (!isset($this->nodeMetrics[$id])) {
$this->nodeSet[$id] = $type;
$this->nodeMetrics[$id] = array(
self::M_AFFERENT_COUPLING => array(),
self::M_EFFERENT_COUPLING => array(),
);
}
}
/**
* Post processes all analyzed nodes.
*
* @return void
*/
protected function postProcess()
{
foreach ($this->nodeMetrics as $id => $metrics) {
$this->afferentNodes[$id] = array();
foreach ($metrics[self::M_AFFERENT_COUPLING] as $caId) {
$this->afferentNodes[$id][] = $this->nodeSet[$caId];
}
$this->efferentNodes[$id] = array();
foreach ($metrics[self::M_EFFERENT_COUPLING] as $ceId) {
$this->efferentNodes[$id][] = $this->nodeSet[$ceId];
}
$afferent = count($metrics[self::M_AFFERENT_COUPLING]);
$efferent = count($metrics[self::M_EFFERENT_COUPLING]);
$this->nodeMetrics[$id][self::M_AFFERENT_COUPLING] = $afferent;
$this->nodeMetrics[$id][self::M_EFFERENT_COUPLING] = $efferent;
}
}
/**
* Collects a single cycle that is reachable by this namespace. All namespaces
* that are part of the cylce are stored in the given <b>$list</b> array.
*
* @param \PDepend\Source\AST\AbstractASTArtifact[] &$list
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return boolean If this method detects a cycle the return value is <b>true</b>
* otherwise this method will return <b>false</b>.
*/
protected function collectCycle(array &$list, AbstractASTArtifact $node)
{
if (in_array($node, $list, true)) {
$list[] = $node;
return true;
}
$list[] = $node;
foreach ($this->getEfferents($node) as $efferent) {
if ($this->collectCycle($list, $efferent)) {
return true;
}
}
if (is_int($idx = array_search($node, $list, true))) {
unset($list[$idx]);
}
return false;
}
}

View File

@@ -0,0 +1,409 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Metrics\AggregateAnalyzer;
use PDepend\Metrics\AnalyzerFilterAware;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Source\AST\AbstractASTType;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\AST\ASTProperty;
use PDepend\Source\AST\ASTTrait;
/**
* Generates some class level based metrics. This analyzer is based on the
* metrics specified in the following document.
*
* http://www.aivosto.com/project/help/pm-oo-misc.html
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ClassLevelAnalyzer extends AbstractAnalyzer implements AggregateAnalyzer, AnalyzerFilterAware, AnalyzerNodeAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_IMPLEMENTED_INTERFACES = 'impl',
M_CLASS_INTERFACE_SIZE = 'cis',
M_CLASS_SIZE = 'csz',
M_NUMBER_OF_PUBLIC_METHODS = 'npm',
M_PROPERTIES = 'vars',
M_PROPERTIES_INHERIT = 'varsi',
M_PROPERTIES_NON_PRIVATE = 'varsnp',
M_WEIGHTED_METHODS = 'wmc',
M_WEIGHTED_METHODS_INHERIT = 'wmci',
M_WEIGHTED_METHODS_NON_PRIVATE = 'wmcnp';
/**
* Hash with all calculated node metrics.
*
* <code>
* array(
* '0375e305-885a-4e91-8b5c-e25bda005438' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* ),
* 'e60c22f0-1a63-4c40-893e-ed3b35b84d0b' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* )
* )
* </code>
*
* @var array(string=>array)
*/
private $nodeMetrics = null;
/**
* The internal used cyclomatic complexity analyzer.
*
* @var \PDepend\Metrics\Analyzer\CyclomaticComplexityAnalyzer
*/
private $cyclomaticAnalyzer = null;
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->nodeMetrics === null) {
// First check for the require cc analyzer
if ($this->cyclomaticAnalyzer === null) {
throw new \RuntimeException('Missing required CC analyzer.');
}
$this->fireStartAnalyzer();
$this->cyclomaticAnalyzer->analyze($namespaces);
// Init node metrics
$this->nodeMetrics = array();
// Visit all nodes
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
}
}
/**
* This method must return an <b>array</b> of class names for required
* analyzers.
*
* @return array(string)
*/
public function getRequiredAnalyzers()
{
return array('PDepend\\Metrics\\Analyzer\\CyclomaticComplexityAnalyzer');
}
/**
* Adds a required sub analyzer.
*
* @param \PDepend\Metrics\Analyzer $analyzer The sub analyzer instance.
* @return void
*/
public function addAnalyzer(\PDepend\Metrics\Analyzer $analyzer)
{
if ($analyzer instanceof \PDepend\Metrics\Analyzer\CyclomaticComplexityAnalyzer) {
$this->cyclomaticAnalyzer = $analyzer;
} else {
throw new \InvalidArgumentException('CC Analyzer required.');
}
}
/**
* This method will return an <b>array</b> with all generated metric values
* for the given <b>$node</b>. If there are no metrics for the requested
* node, this method will return an empty <b>array</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array(string=>mixed)
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
$metrics = array();
if (isset($this->nodeMetrics[$artifact->getId()])) {
$metrics = $this->nodeMetrics[$artifact->getId()];
}
return $metrics;
}
/**
* Visits a class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
$this->fireStartClass($class);
$impl = $class->getInterfaces()->count();
$varsi = $this->calculateVarsi($class);
$wmci = $this->calculateWmciForClass($class);
$this->nodeMetrics[$class->getId()] = array(
self::M_IMPLEMENTED_INTERFACES => $impl,
self::M_CLASS_INTERFACE_SIZE => 0,
self::M_CLASS_SIZE => 0,
self::M_NUMBER_OF_PUBLIC_METHODS => 0,
self::M_PROPERTIES => 0,
self::M_PROPERTIES_INHERIT => $varsi,
self::M_PROPERTIES_NON_PRIVATE => 0,
self::M_WEIGHTED_METHODS => 0,
self::M_WEIGHTED_METHODS_INHERIT => $wmci,
self::M_WEIGHTED_METHODS_NON_PRIVATE => 0
);
foreach ($class->getProperties() as $property) {
$property->accept($this);
}
foreach ($class->getMethods() as $method) {
$method->accept($this);
}
$this->fireEndClass($class);
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
// Empty visit method, we don't want interface metrics
}
/**
* Visits a trait node.
*
* @param \PDepend\Source\AST\ASTTrait $trait
* @return void
* @since 1.0.0
*/
public function visitTrait(ASTTrait $trait)
{
$this->fireStartTrait($trait);
$wmci = $this->calculateWmciForTrait($trait);
$this->nodeMetrics[$trait->getId()] = array(
self::M_IMPLEMENTED_INTERFACES => 0,
self::M_CLASS_INTERFACE_SIZE => 0,
self::M_CLASS_SIZE => 0,
self::M_NUMBER_OF_PUBLIC_METHODS => 0,
self::M_PROPERTIES => 0,
self::M_PROPERTIES_INHERIT => 0,
self::M_PROPERTIES_NON_PRIVATE => 0,
self::M_WEIGHTED_METHODS => 0,
self::M_WEIGHTED_METHODS_INHERIT => $wmci,
self::M_WEIGHTED_METHODS_NON_PRIVATE => 0
);
foreach ($trait->getProperties() as $property) {
$property->accept($this);
}
foreach ($trait->getMethods() as $method) {
$method->accept($this);
}
$this->fireEndTrait($trait);
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
$id = $method->getParent()->getId();
$ccn = $this->cyclomaticAnalyzer->getCcn2($method);
// Increment Weighted Methods Per Class(WMC) value
$this->nodeMetrics[$id][self::M_WEIGHTED_METHODS] += $ccn;
// Increment Class Size(CSZ) value
++$this->nodeMetrics[$id][self::M_CLASS_SIZE];
// Increment Non Private values
if ($method->isPublic()) {
++$this->nodeMetrics[$id][self::M_NUMBER_OF_PUBLIC_METHODS];
// Increment Non Private WMC value
$this->nodeMetrics[$id][self::M_WEIGHTED_METHODS_NON_PRIVATE] += $ccn;
// Increment Class Interface Size(CIS) value
++$this->nodeMetrics[$id][self::M_CLASS_INTERFACE_SIZE];
}
$this->fireEndMethod($method);
}
/**
* Visits a property node.
*
* @param \PDepend\Source\AST\ASTProperty $property
* @return void
*/
public function visitProperty(ASTProperty $property)
{
$this->fireStartProperty($property);
$id = $property->getDeclaringClass()->getId();
// Increment VARS value
++$this->nodeMetrics[$id][self::M_PROPERTIES];
// Increment Class Size(CSZ) value
++$this->nodeMetrics[$id][self::M_CLASS_SIZE];
// Increment Non Private values
if ($property->isPublic()) {
// Increment Non Private VARS value
++$this->nodeMetrics[$id][self::M_PROPERTIES_NON_PRIVATE];
// Increment Class Interface Size(CIS) value
++$this->nodeMetrics[$id][self::M_CLASS_INTERFACE_SIZE];
}
$this->fireEndProperty($property);
}
/**
* Calculates the Variables Inheritance of a class metric, this method only
* counts protected and public properties of parent classes.
*
* @param \PDepend\Source\AST\ASTClass $class The context class instance.
* @return integer
*/
private function calculateVarsi(ASTClass $class)
{
// List of properties, this method only counts not overwritten properties
$properties = array();
// Collect all properties of the context class
foreach ($class->getProperties() as $prop) {
$properties[$prop->getName()] = true;
}
foreach ($class->getParentClasses() as $parent) {
foreach ($parent->getProperties() as $prop) {
if (!$prop->isPrivate() && !isset($properties[$prop->getName()])) {
$properties[$prop->getName()] = true;
}
}
}
return count($properties);
}
/**
* Calculates the Weight Method Per Class metric, this method only counts
* protected and public methods of parent classes.
*
* @param \PDepend\Source\AST\ASTClass $class The context class instance.
* @return integer
*/
private function calculateWmciForClass(ASTClass $class)
{
$ccn = $this->calculateWmci($class);
foreach ($class->getParentClasses() as $parent) {
foreach ($parent->getMethods() as $method) {
if ($method->isPrivate()) {
continue;
}
if (isset($ccn[($name = $method->getName())])) {
continue;
}
$ccn[$name] = $this->cyclomaticAnalyzer->getCcn2($method);
}
}
return array_sum($ccn);
}
/**
* Calculates the Weight Method Per Class metric for a trait.
*
* @param \PDepend\Source\AST\ASTTrait $trait
* @return integer
* @since 1.0.6
*/
private function calculateWmciForTrait(ASTTrait $trait)
{
return array_sum($this->calculateWmci($trait));
}
/**
* Calculates the Weight Method Per Class metric.
*
* @param \PDepend\Source\AST\AbstractASTType $type
* @return integer[]
* @since 1.0.6
*/
private function calculateWmci(AbstractASTType $type)
{
$ccn = array();
foreach ($type->getMethods() as $method) {
$ccn[$method->getName()] = $this->cyclomaticAnalyzer->getCcn2($method);
}
return $ccn;
}
}

View File

@@ -0,0 +1,235 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Metrics\Analyzer\CodeRankAnalyzer\StrategyFactory;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
/**
* Calculates the code rank metric for classes and namespaces.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class CodeRankAnalyzer extends AbstractAnalyzer implements AnalyzerNodeAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_CODE_RANK = 'cr',
M_REVERSE_CODE_RANK = 'rcr';
/**
* The used damping factor.
*/
const DAMPING_FACTOR = 0.85;
/**
* Number of loops for the code range calculation.
*/
const ALGORITHM_LOOPS = 25;
/**
* Option key for the code rank mode.
*/
const STRATEGY_OPTION = 'coderank-mode';
/**
* All found nodes.
*
* @var array(string=>array)
*/
private $nodes = array();
/**
* List of node collect strategies.
*
* @var \PDepend\Metrics\Analyzer\CodeRankAnalyzer\CodeRankStrategyI[]
*/
private $strategies = array();
/**
* Hash with all calculated node metrics.
*
* <code>
* array(
* '0375e305-885a-4e91-8b5c-e25bda005438' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* ),
* 'e60c22f0-1a63-4c40-893e-ed3b35b84d0b' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* )
* )
* </code>
*
* @var array(string=>array)
*/
private $nodeMetrics = null;
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->nodeMetrics === null) {
$this->fireStartAnalyzer();
$factory = new StrategyFactory();
if (isset($this->options[self::STRATEGY_OPTION])) {
foreach ($this->options[self::STRATEGY_OPTION] as $identifier) {
$this->strategies[] = $factory->createStrategy($identifier);
}
} else {
$this->strategies[] = $factory->createDefaultStrategy();
}
// Register all listeners
foreach ($this->getVisitListeners() as $listener) {
foreach ($this->strategies as $strategy) {
$strategy->addVisitListener($listener);
}
}
foreach ($namespaces as $namespace) {
// Traverse all strategies
foreach ($this->strategies as $strategy) {
$namespace->accept($strategy);
}
}
// Collect all nodes
foreach ($this->strategies as $strategy) {
$collected = $strategy->getCollectedNodes();
$this->nodes = array_merge_recursive($collected, $this->nodes);
}
// Init node metrics
$this->nodeMetrics = array();
// Calculate code rank metrics
$this->buildCodeRankMetrics();
$this->fireEndAnalyzer();
}
}
/**
* This method will return an <b>array</b> with all generated metric values
* for the given <b>$node</b>. If there are no metrics for the requested
* node, this method will return an empty <b>array</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array(string=>mixed)
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
if (isset($this->nodeMetrics[$artifact->getId()])) {
return $this->nodeMetrics[$artifact->getId()];
}
return array();
}
/**
* Generates the forward and reverse code rank for the given <b>$nodes</b>.
*
* @return void
*/
protected function buildCodeRankMetrics()
{
foreach (array_keys($this->nodes) as $id) {
$this->nodeMetrics[$id] = array(
self::M_CODE_RANK => 0,
self::M_REVERSE_CODE_RANK => 0
);
}
foreach ($this->computeCodeRank('out', 'in') as $id => $rank) {
$this->nodeMetrics[$id][self::M_CODE_RANK] = $rank;
}
foreach ($this->computeCodeRank('in', 'out') as $id => $rank) {
$this->nodeMetrics[$id][self::M_REVERSE_CODE_RANK] = $rank;
}
}
/**
* Calculates the code rank for the given <b>$nodes</b> set.
*
* @param string $id1 Identifier for the incoming edges.
* @param string $id2 Identifier for the outgoing edges.
*
* @return array(string=>float)
*/
protected function computeCodeRank($id1, $id2)
{
$dampingFactory = self::DAMPING_FACTOR;
$ranks = array();
foreach (array_keys($this->nodes) as $name) {
$ranks[$name] = 1;
}
for ($i = 0; $i < self::ALGORITHM_LOOPS; $i++) {
foreach ($this->nodes as $name => $info) {
$rank = 0;
foreach ($info[$id1] as $ref) {
$previousRank = $ranks[$ref];
$refCount = count($this->nodes[$ref][$id2]);
$rank += ($previousRank / $refCount);
}
$ranks[$name] = ((1 - $dampingFactory)) + $dampingFactory * $rank;
}
}
return $ranks;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer\CodeRankAnalyzer;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* The code rank strategy provides an interface for dependency collection.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface CodeRankStrategyI extends ASTVisitor
{
/**
* Returns the collected nodes.
*
* @return array(string=>array)
*/
public function getCollectedNodes();
}

View File

@@ -0,0 +1,150 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer\CodeRankAnalyzer;
use PDepend\Source\AST\AbstractASTArtifact;
use PDepend\Source\AST\AbstractASTClassOrInterface;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\ASTVisitor\AbstractASTVisitor;
/**
* Collects class and namespace metrics based on inheritance.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class InheritanceStrategy extends AbstractASTVisitor implements CodeRankStrategyI
{
/**
* All found nodes.
*
* @var array(string=>array)
*/
private $nodes = array();
/**
* Returns the collected nodes.
*
* @return array(string=>array)
*/
public function getCollectedNodes()
{
return $this->nodes;
}
/**
* Visits a code class object.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
$this->fireStartClass($class);
$this->visitType($class);
$this->fireEndClass($class);
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
$this->fireStartInterface($interface);
$this->visitType($interface);
$this->fireEndInterface($interface);
}
/**
* Generic visitor method for classes and interfaces. Both visit methods
* delegate calls to this method.
*
* @param \PDepend\Source\AST\AbstractASTClassOrInterface $type
* @return void
*/
protected function visitType(AbstractASTClassOrInterface $type)
{
$namespace = $type->getNamespace();
$this->initNode($namespace);
$this->initNode($type);
foreach ($type->getDependencies() as $dependency) {
$depPkg = $dependency->getNamespace();
$this->initNode($dependency);
$this->initNode($depPkg);
$this->nodes[$type->getId()]['in'][] = $dependency->getId();
$this->nodes[$dependency->getId()]['out'][] = $type->getId();
// No self references
if ($namespace !== $depPkg) {
$this->nodes[$namespace->getId()]['in'][] = $depPkg->getId();
$this->nodes[$depPkg->getId()]['out'][] = $namespace->getId();
}
}
}
/**
* Initializes the temporary node container for the given <b>$node</b>.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return void
*/
protected function initNode(AbstractASTArtifact $node)
{
if (!isset($this->nodes[$node->getId()])) {
$this->nodes[$node->getId()] = array(
'in' => array(),
'out' => array(),
'name' => $node->getName(),
'type' => get_class($node)
);
}
}
}

View File

@@ -0,0 +1,148 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer\CodeRankAnalyzer;
use PDepend\Source\AST\AbstractASTArtifact;
use PDepend\Source\AST\AbstractASTClassOrInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\ASTVisitor\AbstractASTVisitor;
/**
* Collects class and namespace metrics based on class and interface methods.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class MethodStrategy extends AbstractASTVisitor implements CodeRankStrategyI
{
/**
* All found nodes.
*
* @var array(string=>array)
*/
private $nodes = array();
/**
* Returns the collected nodes.
*
* @return array(string=>array)
*/
public function getCollectedNodes()
{
return $this->nodes;
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
// Get owner type
$type = $method->getParent();
if (($depType = $method->getReturnClass()) !== null) {
$this->processType($type, $depType);
}
foreach ($method->getExceptionClasses() as $depType) {
$this->processType($type, $depType);
}
foreach ($method->getDependencies() as $depType) {
$this->processType($type, $depType);
}
$this->fireEndMethod($method);
}
/**
* Extracts the coupling information between the two given types and their
* parent namespacess.
*
* @param \PDepend\Source\AST\AbstractASTClassOrInterface $type
* @param \PDepend\Source\AST\AbstractASTClassOrInterface $dependency
* @return void
*/
private function processType(AbstractASTClassOrInterface $type, AbstractASTClassOrInterface $dependency)
{
if ($type !== $dependency) {
$this->initNode($type);
$this->initNode($dependency);
$this->nodes[$type->getId()]['in'][] = $dependency->getId();
$this->nodes[$dependency->getId()]['out'][] = $type->getId();
}
$namespace = $type->getNamespace();
$dependencyNamespace = $dependency->getNamespace();
if ($namespace !== $dependencyNamespace) {
$this->initNode($namespace);
$this->initNode($dependencyNamespace);
$this->nodes[$namespace->getId()]['in'][] = $dependencyNamespace->getId();
$this->nodes[$dependencyNamespace->getId()]['out'][] = $namespace->getId();
}
}
/**
* Initializes the temporary node container for the given <b>$node</b>.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return void
*/
private function initNode(AbstractASTArtifact $node)
{
if (!isset($this->nodes[$node->getId()])) {
$this->nodes[$node->getId()] = array(
'in' => array(),
'out' => array(),
'name' => $node->getName(),
'type' => get_class($node)
);
}
}
}

View File

@@ -0,0 +1,130 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer\CodeRankAnalyzer;
use PDepend\Source\AST\AbstractASTArtifact;
use PDepend\Source\AST\ASTProperty;
use PDepend\Source\ASTVisitor\AbstractASTVisitor;
/**
* Collects class and namespace metrics based on class properties.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class PropertyStrategy extends AbstractASTVisitor implements CodeRankStrategyI
{
/**
* All found nodes.
*
* @var array(string=>array)
*/
private $nodes = array();
/**
* Returns the collected nodes.
*
* @return array(string=>array)
*/
public function getCollectedNodes()
{
return $this->nodes;
}
/**
* Visits a property node.
*
* @param \PDepend\Source\AST\ASTProperty $property
* @return void
*/
public function visitProperty(ASTProperty $property)
{
$this->fireStartProperty($property);
if (($depClass = $property->getClass()) === null) {
$this->fireEndProperty($property);
return;
}
$depNamespace = $depClass->getNamespace();
$class = $property->getDeclaringClass();
$namespace = $class->getNamespace();
if ($depClass !== $class) {
$this->initNode($class);
$this->initNode($depClass);
$this->nodes[$class->getId()]['in'][] = $depClass->getId();
$this->nodes[$depClass->getId()]['out'][] = $class->getId();
}
if ($depNamespace !== $namespace) {
$this->initNode($namespace);
$this->initNode($depNamespace);
$this->nodes[$namespace->getId()]['in'][] = $depNamespace->getId();
$this->nodes[$depNamespace->getId()]['out'][] = $namespace->getId();
}
$this->fireEndProperty($property);
}
/**
* Initializes the temporary node container for the given <b>$node</b>.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return void
*/
protected function initNode(AbstractASTArtifact $node)
{
if (!isset($this->nodes[$node->getId()])) {
$this->nodes[$node->getId()] = array(
'in' => array(),
'out' => array(),
'name' => $node->getName(),
'type' => get_class($node)
);
}
}
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer\CodeRankAnalyzer;
/**
* Factory for the different code rank strategies.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class StrategyFactory
{
/**
* The identifier for the inheritance strategy.
*/
const STRATEGY_INHERITANCE = 'inheritance';
/**
* The identifier for the property strategy.
*/
const STRATEGY_PROPERTY = 'property';
/**
* The identifier for the method strategy.
*/
const STRATEGY_METHOD = 'method';
/**
* The default strategy.
*
* @var string
*/
private $defaultStrategy = self::STRATEGY_INHERITANCE;
/**
* List of all valid properties.
*
* @var array(string)
*/
private $validStrategies = array(
self::STRATEGY_INHERITANCE,
self::STRATEGY_METHOD,
self::STRATEGY_PROPERTY
);
/**
* Creates the default code rank strategy.
*
* @return \PDepend\Metrics\Analyzer\CodeRankAnalyzer\CodeRankStrategyI
*/
public function createDefaultStrategy()
{
return $this->createStrategy($this->defaultStrategy);
}
/**
* Creates a code rank strategy for the given identifier.
*
* @param string $strategyName The strategy identifier.
* @return \PDepend\Metrics\Analyzer\CodeRankAnalyzer\CodeRankStrategyI
* @throws \InvalidArgumentException If the given <b>$id</b> is not valid or
* no matching class declaration exists.
*/
public function createStrategy($strategyName)
{
if (in_array($strategyName, $this->validStrategies) === false) {
throw new \InvalidArgumentException(
sprintf('Cannot load file for identifier "%s".', $strategyName)
);
}
// Prepare identifier
$name = ucfirst(strtolower($strategyName));
$className = "PDepend\\Metrics\\Analyzer\\CodeRankAnalyzer\\{$name}Strategy";
if (false === class_exists($className)) {
$fileName = "PDepend/Metrics/Analyzer/CodeRankAnalyzer/{$name}Strategy.php";
include_once $fileName;
}
return new $className();
}
}

View File

@@ -0,0 +1,155 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
/**
* This analyzer implements several metrics that describe cohesion of classes
* and namespaces.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class CohesionAnalyzer extends AbstractAnalyzer implements AnalyzerNodeAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_LCOM4 = 'lcom4';
/**
* Collected cohesion metrics for classes.
*
* @var array
*/
private $nodeMetrics = array();
/**
* This method will return an <b>array</b> with all generated metric values
* for the node with the given <b>$id</b> identifier. If there are no
* metrics for the requested node, this method will return an empty <b>array</b>.
*
* <code>
* array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* )
* </code>
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array(string=>mixed)
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
if (isset($this->nodeMetrics[$artifact->getId()])) {
return $this->nodeMetrics[$artifact->getId()];
}
return array();
}
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
*
* @return void
*/
public function analyze($namespaces)
{
$this->fireStartAnalyzer();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
}
/*
public function visitProperty(\PDepend\Source\AST\ASTProperty $property)
{
$this->fireStartProperty($property);
echo ltrim($property->getName(), '$'), PHP_EOL;
$this->fireEndProperty($property);
}
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
$prefixes = $method->findChildrenOfType(
'PDepend\\Source\\AST\\ASTMemberPrimaryPrefix'
);
foreach ($prefixes as $prefix) {
$variable = $prefix->getChild(0);
if ($variable instanceof \PDepend\Source\AST\ASTVariable
&& $variable->isThis()
) {
echo "\$this->";
} elseif ($variable instanceof \PDepend\Source\AST\ASTSelfReference) {
echo "self::";
} else {
continue;
}
$next = $prefix->getChild(1);
if ($next instanceof \PDepend\Source\AST\ASTMemberPrimaryPrefix) {
$next = $next->getChild(0);
}
if ($next instanceof \PDepend\Source\AST\ASTPropertyPostfix) {
echo $next->getImage(), PHP_EOL;
} elseif ($next instanceof \PDepend\Source\AST\ASTMethodPostfix) {
echo $next->getImage(), '()', PHP_EOL;
}
}
$this->fireEndMethod($method);
}
*/
}

View File

@@ -0,0 +1,453 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Metrics\AnalyzerProjectAware;
use PDepend\Source\AST\AbstractASTCallable;
use PDepend\Source\AST\AbstractASTType;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\AST\ASTProperty;
/**
* This analyzer collects coupling values for the hole project. It calculates
* all function and method <b>calls</b> and the <b>fanout</b>, that means the
* number of referenced types.
*
* The FANOUT calculation is based on the definition used by the apache maven
* project.
*
* <ul>
* <li>field declarations (Uses doc comment annotations)</li>
* <li>formal parameters and return types (The return type uses doc comment
* annotations)</li>
* <li>throws declarations (Uses doc comment annotations)</li>
* <li>local variables</li>
* </ul>
*
* http://www.jajakarta.org/turbine/en/turbine/maven/reference/metrics.html
*
* The implemented algorithm counts each type only once for a method and function.
* Any type that is either a supertype or a subtype of the class is not counted.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class CouplingAnalyzer extends AbstractAnalyzer implements AnalyzerNodeAware, AnalyzerProjectAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_CALLS = 'calls',
M_FANOUT = 'fanout',
M_CA = 'ca',
M_CBO = 'cbo',
M_CE = 'ce';
/**
* Has this analyzer already processed the source under test?
*
* @var boolean
* @since 0.10.2
*/
private $uninitialized = true;
/**
* The number of method or function calls.
*
* @var integer
*/
private $calls = 0;
/**
* Number of fanouts.
*
* @var integer
*/
private $fanout = 0;
/**
* Temporary map that is used to hold the id combinations of dependee and
* depender.
*
* @var array(string=>array)
* @since 0.10.2
*/
private $dependencyMap = array();
/**
* This array holds a mapping between node identifiers and an array with
* the node's metrics.
*
* @var array(string=>array)
* @since 0.10.2
*/
private $nodeMetrics = array();
/**
* Provides the project summary as an <b>array</b>.
*
* <code>
* array(
* 'calls' => 23,
* 'fanout' => 42
* )
* </code>
*
* @return array(string=>mixed)
*/
public function getProjectMetrics()
{
return array(
self::M_CALLS => $this->calls,
self::M_FANOUT => $this->fanout
);
}
/**
* This method will return an <b>array</b> with all generated metric values
* for the given node instance. If there are no metrics for the given node
* this method will return an empty <b>array</b>.
*
* <code>
* array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* )
* </code>
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array(string=>mixed)
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
if (isset($this->nodeMetrics[$artifact->getId()])) {
return $this->nodeMetrics[$artifact->getId()];
}
return array();
}
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->uninitialized) {
$this->doAnalyze($namespaces);
$this->uninitialized = false;
}
}
/**
* This method traverses all namespaces in the given iterator and calculates
* the coupling metrics for them.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
* @since 0.10.2
*/
private function doAnalyze($namespaces)
{
$this->fireStartAnalyzer();
$this->reset();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->postProcessTemporaryCouplingMap();
$this->fireEndAnalyzer();
}
/**
* This method resets all internal state variables before the analyzer can
* start the object tree traversal.
*
* @return void
* @since 0.10.2
*/
private function reset()
{
$this->calls = 0;
$this->fanout = 0;
$this->nodeMetrics = array();
$this->dependencyMap = array();
}
/**
* This method takes the temporary coupling map with node IDs and calculates
* the concrete node metrics.
*
* @return void
* @since 0.10.2
*/
private function postProcessTemporaryCouplingMap()
{
foreach ($this->dependencyMap as $id => $metrics) {
$afferentCoupling = count($metrics['ca']);
$efferentCoupling = count($metrics['ce']);
$this->nodeMetrics[$id] = array(
self::M_CA => $afferentCoupling,
self::M_CBO => $efferentCoupling,
self::M_CE => $efferentCoupling
);
$this->fanout += $efferentCoupling;
}
$this->dependencyMap = array();
}
/**
* Visits a function node.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$this->fireStartFunction($function);
$fanouts = array();
if (($type = $function->getReturnClass()) !== null) {
$fanouts[] = $type;
++$this->fanout;
}
foreach ($function->getExceptionClasses() as $type) {
if (in_array($type, $fanouts, true) === false) {
$fanouts[] = $type;
++$this->fanout;
}
}
foreach ($function->getDependencies() as $type) {
if (in_array($type, $fanouts, true) === false) {
$fanouts[] = $type;
++$this->fanout;
}
}
foreach ($fanouts as $fanout) {
$this->initDependencyMap($fanout);
$this->dependencyMap[$fanout->getId()]['ca'][$function->getId()] = true;
}
$this->countCalls($function);
$this->fireEndFunction($function);
}
/**
* Visit method for classes that will be called by PDepend during the
* analysis phase with the current context class.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
* @since 0.10.2
*/
public function visitClass(ASTClass $class)
{
$this->initDependencyMap($class);
return parent::visitClass($class);
}
/**
* Visit method for interfaces that will be called by PDepend during the
* analysis phase with the current context interface.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
* @since 0.10.2
*/
public function visitInterface(ASTInterface $interface)
{
$this->initDependencyMap($interface);
return parent::visitInterface($interface);
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
$declaringClass = $method->getParent();
$this->calculateCoupling(
$declaringClass,
$method->getReturnClass()
);
foreach ($method->getExceptionClasses() as $type) {
$this->calculateCoupling($declaringClass, $type);
}
foreach ($method->getDependencies() as $type) {
$this->calculateCoupling($declaringClass, $type);
}
$this->countCalls($method);
$this->fireEndMethod($method);
}
/**
* Visits a property node.
*
* @param \PDepend\Source\AST\ASTProperty $property
* @return void
*/
public function visitProperty(ASTProperty $property)
{
$this->fireStartProperty($property);
$this->calculateCoupling(
$property->getDeclaringClass(),
$property->getClass()
);
$this->fireEndProperty($property);
}
/**
* Calculates the coupling between the given types.
*
* @param \PDepend\Source\AST\AbstractASTType $declaringType
* @param \PDepend\Source\AST\AbstractASTType $coupledType
* @return void
* @since 0.10.2
*/
private function calculateCoupling(
AbstractASTType $declaringType,
AbstractASTType $coupledType = null
) {
$this->initDependencyMap($declaringType);
if (null === $coupledType) {
return;
}
if ($coupledType->isSubtypeOf($declaringType)
|| $declaringType->isSubtypeOf($coupledType)
) {
return;
}
$this->initDependencyMap($coupledType);
$this->dependencyMap[
$declaringType->getId()
]['ce'][
$coupledType->getId()
] = true;
$this->dependencyMap[
$coupledType->getId()
]['ca'][
$declaringType->getId()
] = true;
}
/**
* This method will initialize a temporary coupling container for the given
* given class or interface instance.
*
* @param \PDepend\Source\AST\AbstractASTType $type
* @return void
* @since 0.10.2
*/
private function initDependencyMap(AbstractASTType $type)
{
if (isset($this->dependencyMap[$type->getId()])) {
return;
}
$this->dependencyMap[$type->getId()] = array(
'ce' => array(),
'ca' => array()
);
}
/**
* Counts all calls within the given <b>$callable</b>
*
* @param \PDepend\Source\AST\AbstractASTCallable $callable
* @return void
*/
private function countCalls(AbstractASTCallable $callable)
{
$invocations = $callable->findChildrenOfType('PDepend\\Source\\AST\\ASTInvocation');
$invoked = array();
foreach ($invocations as $invocation) {
$parents = $invocation->getParentsOfType('PDepend\\Source\\AST\\ASTMemberPrimaryPrefix');
$image = '';
foreach ($parents as $parent) {
$child = $parent->getChild(0);
if ($child !== $invocation) {
$image .= $child->getImage() . '.';
}
}
$image .= $invocation->getImage() . '()';
$invoked[$image] = $image;
}
$this->calls += count($invoked);
}
}

View File

@@ -0,0 +1,271 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Metrics\AggregateAnalyzer;
use PDepend\Metrics\Analyzer;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Source\AST\AbstractASTCallable;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTMethod;
/**
* This analyzer calculates the C.R.A.P. index for methods an functions when a
* clover coverage report was supplied. This report can be supplied by using the
* command line option <b>--coverage-report=</b>.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class CrapIndexAnalyzer extends AbstractAnalyzer implements AggregateAnalyzer, AnalyzerNodeAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_CRAP_INDEX = 'crap',
M_COVERAGE = 'cov';
/**
* The report option name.
*/
const REPORT_OPTION = 'coverage-report';
/**
* Calculated crap metrics.
*
* @var array(string=>array)
*/
private $metrics = null;
/**
* The coverage report instance representing the supplied coverage report
* file.
*
* @var \PDepend\Util\Coverage\Report
*/
private $report = null;
/**
*
* @var \PDepend\Metrics\Analyzer\CyclomaticComplexityAnalyzer
*/
private $ccnAnalyzer = array();
/**
* Returns <b>true</b> when this analyzer is enabled.
*
* @return boolean
*/
public function isEnabled()
{
return isset($this->options[self::REPORT_OPTION]);
}
/**
* Returns the calculated metrics for the given node or an empty <b>array</b>
* when no metrics exist for the given node.
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array(string=>float)
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
if (isset($this->metrics[$artifact->getId()])) {
return $this->metrics[$artifact->getId()];
}
return array();
}
/**
* Returns an array with analyzer class names that are required by the crap
* index analyzers.
*
* @return array(string)
*/
public function getRequiredAnalyzers()
{
return array('PDepend\\Metrics\\Analyzer\\CyclomaticComplexityAnalyzer');
}
/**
* Adds an analyzer that this analyzer depends on.
*
* @param \PDepend\Metrics\Analyzer $analyzer
* @return void
*/
public function addAnalyzer(Analyzer $analyzer)
{
$this->ccnAnalyzer = $analyzer;
}
/**
* Performs the crap index analysis.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->isEnabled() && $this->metrics === null) {
$this->doAnalyze($namespaces);
}
}
/**
* Performs the crap index analysis.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
private function doAnalyze($namespaces)
{
$this->metrics = array();
$this->ccnAnalyzer->analyze($namespaces);
$this->fireStartAnalyzer();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
}
/**
* Visits the given method.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
if ($method->isAbstract() === false) {
$this->visitCallable($method);
}
}
/**
* Visits the given function.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$this->visitCallable($function);
}
/**
* Visits the given callable instance.
*
* @param \PDepend\Source\AST\AbstractASTCallable $callable
* @return void
*/
private function visitCallable(AbstractASTCallable $callable)
{
$this->metrics[$callable->getId()] = array(
self::M_CRAP_INDEX => $this->calculateCrapIndex($callable),
self::M_COVERAGE => $this->calculateCoverage($callable)
);
}
/**
* Calculates the crap index for the given callable.
*
* @param \PDepend\Source\AST\AbstractASTCallable $callable
* @return float
*/
private function calculateCrapIndex(AbstractASTCallable $callable)
{
$report = $this->createOrReturnCoverageReport();
$complexity = $this->ccnAnalyzer->getCcn2($callable);
$coverage = $report->getCoverage($callable);
if ($coverage == 0) {
return pow($complexity, 2) + $complexity;
} elseif ($coverage > 99.5) {
return $complexity;
}
return pow($complexity, 2) * pow(1 - $coverage / 100, 3) + $complexity;
}
/**
* Calculates the code coverage for the given callable object.
*
* @param \PDepend\Source\AST\AbstractASTCallable $callable
* @return float
*/
private function calculateCoverage(AbstractASTCallable $callable)
{
return $this->createOrReturnCoverageReport()->getCoverage($callable);
}
/**
* Returns a previously created report instance or creates a new report
* instance.
*
* @return \PDepend\Util\Coverage\Report
*/
private function createOrReturnCoverageReport()
{
if ($this->report === null) {
$this->report = $this->createCoverageReport();
}
return $this->report;
}
/**
* Creates a new coverage report instance.
*
* @return \PDepend\Util\Coverage\Report
*/
private function createCoverageReport()
{
$factory = new \PDepend\Util\Coverage\Factory();
return $factory->create($this->options['coverage-report']);
}
}

View File

@@ -0,0 +1,464 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractCachingAnalyzer;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Metrics\AnalyzerProjectAware;
use PDepend\Source\AST\AbstractASTCallable;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
/**
* This class calculates the Cyclomatic Complexity Number(CCN) for the project,
* methods and functions.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class CyclomaticComplexityAnalyzer extends AbstractCachingAnalyzer implements AnalyzerNodeAware, AnalyzerProjectAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_CYCLOMATIC_COMPLEXITY_1 = 'ccn',
M_CYCLOMATIC_COMPLEXITY_2 = 'ccn2';
/**
* The project Cyclomatic Complexity Number.
*
* @var integer
*/
private $ccn = 0;
/**
* Extended Cyclomatic Complexity Number(CCN2) for the project.
*
* @var integer
*/
private $ccn2 = 0;
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->metrics === null) {
$this->loadCache();
$this->fireStartAnalyzer();
// Init node metrics
$this->metrics = array();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
$this->unloadCache();
}
}
/**
* Returns the cyclomatic complexity for the given <b>$node</b> instance.
*
* @param \PDepend\Source\AST\ASTArtifact $node
* @return integer
*/
public function getCcn(ASTArtifact $node)
{
$metrics = $this->getNodeMetrics($node);
if (isset($metrics[self::M_CYCLOMATIC_COMPLEXITY_1])) {
return $metrics[self::M_CYCLOMATIC_COMPLEXITY_1];
}
return 0;
}
/**
* Returns the extended cyclomatic complexity for the given <b>$node</b>
* instance.
*
* @param \PDepend\Source\AST\ASTArtifact $node
* @return integer
*/
public function getCcn2(ASTArtifact $node)
{
$metrics = $this->getNodeMetrics($node);
if (isset($metrics[self::M_CYCLOMATIC_COMPLEXITY_2])) {
return $metrics[self::M_CYCLOMATIC_COMPLEXITY_2];
}
return 0;
}
/**
* This method will return an <b>array</b> with all generated metric values
* for the given <b>$node</b>. If there are no metrics for the requested
* node, this method will return an empty <b>array</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
if (isset($this->metrics[$artifact->getId()])) {
return $this->metrics[$artifact->getId()];
}
return array();
}
/**
* Provides the project summary metrics as an <b>array</b>.
*
* @return array
*/
public function getProjectMetrics()
{
return array(
self::M_CYCLOMATIC_COMPLEXITY_1 => $this->ccn,
self::M_CYCLOMATIC_COMPLEXITY_2 => $this->ccn2
);
}
/**
* Visits a function node.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$this->fireStartFunction($function);
if (false === $this->restoreFromCache($function)) {
$this->calculateComplexity($function);
}
$this->updateProjectMetrics($function->getId());
$this->fireEndFunction($function);
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
// Empty visit method, we don't want interface metrics
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
if (false === $this->restoreFromCache($method)) {
$this->calculateComplexity($method);
}
$this->updateProjectMetrics($method->getId());
$this->fireEndMethod($method);
}
/**
* Visits methods, functions or closures and calculated their complexity.
*
* @param \PDepend\Source\AST\AbstractASTCallable $callable
* @return void
* @since 0.9.8
*/
public function calculateComplexity(AbstractASTCallable $callable)
{
$data = array(
self::M_CYCLOMATIC_COMPLEXITY_1 => 1,
self::M_CYCLOMATIC_COMPLEXITY_2 => 1
);
foreach ($callable->getChildren() as $child) {
$data = $child->accept($this, $data);
}
$this->metrics[$callable->getId()] = $data;
}
/**
* Stores the complexity of a node and updates the corresponding project
* values.
*
* @param string $nodeId Identifier of the analyzed item.
*
* @return void
* @since 1.0.0
*/
private function updateProjectMetrics($nodeId)
{
$this->ccn += $this->metrics[$nodeId][self::M_CYCLOMATIC_COMPLEXITY_1];
$this->ccn2 += $this->metrics[$nodeId][self::M_CYCLOMATIC_COMPLEXITY_2];
}
/**
* Visits a boolean AND-expression.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitBooleanAndExpression($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits a boolean OR-expression.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitBooleanOrExpression($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits a switch label.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitSwitchLabel($node, $data)
{
if (!$node->isDefault()) {
++$data[self::M_CYCLOMATIC_COMPLEXITY_1];
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
}
return $this->visit($node, $data);
}
/**
* Visits a catch statement.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitCatchStatement($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_1];
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits an elseif statement.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitElseIfStatement($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_1];
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits a for statement.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitForStatement($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_1];
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits a foreach statement.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitForeachStatement($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_1];
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits an if statement.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitIfStatement($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_1];
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits a logical AND expression.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitLogicalAndExpression($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits a logical OR expression.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitLogicalOrExpression($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits a ternary operator.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitConditionalExpression($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_1];
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits a while-statement.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.8
*/
public function visitWhileStatement($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_1];
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
/**
* Visits a do/while-statement.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param array(string=>integer) $data The previously calculated ccn values.
*
* @return array(string=>integer)
* @since 0.9.12
*/
public function visitDoWhileStatement($node, $data)
{
++$data[self::M_CYCLOMATIC_COMPLEXITY_1];
++$data[self::M_CYCLOMATIC_COMPLEXITY_2];
return $this->visit($node, $data);
}
}

View File

@@ -0,0 +1,483 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Source\AST\AbstractASTArtifact;
use PDepend\Source\AST\AbstractASTClassOrInterface;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\AST\ASTNamespace;
/**
* This visitor generates the metrics for the analyzed namespaces.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class DependencyAnalyzer extends AbstractAnalyzer
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_NUMBER_OF_CLASSES = 'tc',
M_NUMBER_OF_CONCRETE_CLASSES = 'cc',
M_NUMBER_OF_ABSTRACT_CLASSES = 'ac',
M_AFFERENT_COUPLING = 'ca',
M_EFFERENT_COUPLING = 'ce',
M_ABSTRACTION = 'a',
M_INSTABILITY = 'i',
M_DISTANCE = 'd';
/**
* Hash with all calculated node metrics.
*
* <code>
* array(
* '0375e305-885a-4e91-8b5c-e25bda005438' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* ),
* 'e60c22f0-1a63-4c40-893e-ed3b35b84d0b' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* )
* )
* </code>
*
* @var array(string=>array)
*/
private $nodeMetrics = null;
protected $nodeSet = array();
private $efferentNodes = array();
private $afferentNodes = array();
/**
* All collected cycles for the input code.
*
* <code>
* array(
* <namespace-id> => array(
* \PDepend\Source\AST\ASTNamespace {},
* \PDepend\Source\AST\ASTNamespace {},
* ),
* <namespace-id> => array(
* \PDepend\Source\AST\ASTNamespace {},
* \PDepend\Source\AST\ASTNamespace {},
* ),
* )
* </code>
*
* @var array(string=>array)
*/
private $collectedCycles = array();
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->nodeMetrics === null) {
$this->fireStartAnalyzer();
$this->nodeMetrics = array();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->postProcess();
$this->calculateAbstractness();
$this->calculateInstability();
$this->calculateDistance();
$this->fireEndAnalyzer();
}
}
/**
* Returns the statistics for the requested node.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return array
*/
public function getStats(AbstractASTArtifact $node)
{
$stats = array();
if (isset($this->nodeMetrics[$node->getId()])) {
$stats = $this->nodeMetrics[$node->getId()];
}
return $stats;
}
/**
* Returns an array of all afferent nodes.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return \PDepend\Source\AST\AbstractASTArtifact[]
*/
public function getAfferents(AbstractASTArtifact $node)
{
$afferents = array();
if (isset($this->afferentNodes[$node->getId()])) {
$afferents = $this->afferentNodes[$node->getId()];
}
ksort($afferents);
return $afferents;
}
/**
* Returns an array of all efferent nodes.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return \PDepend\Source\AST\AbstractASTArtifact[]
*/
public function getEfferents(AbstractASTArtifact $node)
{
$efferents = array();
if (isset($this->efferentNodes[$node->getId()])) {
$efferents = $this->efferentNodes[$node->getId()];
}
ksort($efferents);
return $efferents;
}
/**
* Returns an array of nodes that build a cycle for the requested node or it
* returns <b>null</b> if no cycle exists .
*
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return \PDepend\Source\AST\AbstractASTArtifact[]
*/
public function getCycle(AbstractASTArtifact $node)
{
if (array_key_exists($node->getId(), $this->collectedCycles)) {
return $this->collectedCycles[$node->getId()];
}
$list = array();
if ($this->collectCycle($list, $node)) {
$this->collectedCycles[$node->getId()] = $list;
} else {
$this->collectedCycles[$node->getId()] = null;
}
return $this->collectedCycles[$node->getId()];
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
$namespace = $method->getParent()->getNamespace();
foreach ($method->getDependencies() as $dependency) {
$this->collectDependencies($namespace, $dependency->getNamespace());
}
$this->fireEndMethod($method);
}
/**
* Visits a namespace node.
*
* @param \PDepend\Source\AST\ASTNamespace $namespace
* @return void
*/
public function visitNamespace(ASTNamespace $namespace)
{
$this->fireStartNamespace($namespace);
$this->initNamespaceMetric($namespace);
$this->nodeSet[$namespace->getId()] = $namespace;
foreach ($namespace->getTypes() as $type) {
$type->accept($this);
}
$this->fireEndNamespace($namespace);
}
/**
* Visits a class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
$this->fireStartClass($class);
$this->visitType($class);
$this->fireEndClass($class);
}
/**
* Visits an interface node.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
$this->fireStartInterface($interface);
$this->visitType($interface);
$this->fireEndInterface($interface);
}
/**
* Generic visit method for classes and interfaces. Both visit methods
* delegate calls to this method.
*
* @param \PDepend\Source\AST\AbstractASTClassOrInterface $type
* @return void
*/
protected function visitType(AbstractASTClassOrInterface $type)
{
$id = $type->getNamespace()->getId();
// Increment total classes count
++$this->nodeMetrics[$id][self::M_NUMBER_OF_CLASSES];
// Check for abstract or concrete class
if ($type->isAbstract()) {
++$this->nodeMetrics[$id][self::M_NUMBER_OF_ABSTRACT_CLASSES];
} else {
++$this->nodeMetrics[$id][self::M_NUMBER_OF_CONCRETE_CLASSES];
}
foreach ($type->getDependencies() as $dependency) {
$this->collectDependencies(
$type->getNamespace(),
$dependency->getNamespace()
);
}
foreach ($type->getMethods() as $method) {
$method->accept($this);
}
}
/**
* Collects the dependencies between the two given namespaces.
*
* @param \PDepend\Source\AST\ASTNamespace $namespaceA
* @param \PDepend\Source\AST\ASTNamespace $namespaceB
*
* @return void
*/
private function collectDependencies(ASTNamespace $namespaceA, ASTNamespace $namespaceB)
{
$idA = $namespaceA->getId();
$idB = $namespaceB->getId();
if ($idB === $idA) {
return;
}
// Create a container for this dependency
$this->initNamespaceMetric($namespaceB);
if (!in_array($idB, $this->nodeMetrics[$idA][self::M_EFFERENT_COUPLING])) {
$this->nodeMetrics[$idA][self::M_EFFERENT_COUPLING][] = $idB;
$this->nodeMetrics[$idB][self::M_AFFERENT_COUPLING][] = $idA;
}
}
/**
* Initializes the node metric record for the given <b>$namespace</b>.
*
* @param \PDepend\Source\AST\ASTNamespace $namespace
* @return void
*/
protected function initNamespaceMetric(ASTNamespace $namespace)
{
$id = $namespace->getId();
if (!isset($this->nodeMetrics[$id])) {
$this->nodeSet[$id] = $namespace;
$this->nodeMetrics[$id] = array(
self::M_NUMBER_OF_CLASSES => 0,
self::M_NUMBER_OF_CONCRETE_CLASSES => 0,
self::M_NUMBER_OF_ABSTRACT_CLASSES => 0,
self::M_AFFERENT_COUPLING => array(),
self::M_EFFERENT_COUPLING => array(),
self::M_ABSTRACTION => 0,
self::M_INSTABILITY => 0,
self::M_DISTANCE => 0
);
}
}
/**
* Post processes all analyzed nodes.
*
* @return void
*/
protected function postProcess()
{
foreach ($this->nodeMetrics as $id => $metrics) {
$this->afferentNodes[$id] = array();
foreach ($metrics[self::M_AFFERENT_COUPLING] as $caId) {
$this->afferentNodes[$id][] = $this->nodeSet[$caId];
}
sort($this->afferentNodes[$id]);
$this->efferentNodes[$id] = array();
foreach ($metrics[self::M_EFFERENT_COUPLING] as $ceId) {
$this->efferentNodes[$id][] = $this->nodeSet[$ceId];
}
sort($this->efferentNodes[$id]);
$afferent = count($metrics[self::M_AFFERENT_COUPLING]);
$efferent = count($metrics[self::M_EFFERENT_COUPLING]);
$this->nodeMetrics[$id][self::M_AFFERENT_COUPLING] = $afferent;
$this->nodeMetrics[$id][self::M_EFFERENT_COUPLING] = $efferent;
}
}
/**
* Calculates the abstractness for all analyzed nodes.
*
* @return void
*/
protected function calculateAbstractness()
{
foreach ($this->nodeMetrics as $id => $metrics) {
if ($metrics[self::M_NUMBER_OF_CLASSES] !== 0) {
$this->nodeMetrics[$id][self::M_ABSTRACTION] = (
$metrics[self::M_NUMBER_OF_ABSTRACT_CLASSES] /
$metrics[self::M_NUMBER_OF_CLASSES]
);
}
}
}
/**
* Calculates the instability for all analyzed nodes.
*
* @return void
*/
protected function calculateInstability()
{
foreach ($this->nodeMetrics as $id => $metrics) {
// Count total incoming and outgoing dependencies
$total = (
$metrics[self::M_AFFERENT_COUPLING] +
$metrics[self::M_EFFERENT_COUPLING]
);
if ($total !== 0) {
$this->nodeMetrics[$id][self::M_INSTABILITY] = (
$metrics[self::M_EFFERENT_COUPLING] / $total
);
}
}
}
/**
* Calculates the distance to an optimal value.
*
* @return void
*/
protected function calculateDistance()
{
foreach ($this->nodeMetrics as $id => $metrics) {
$this->nodeMetrics[$id][self::M_DISTANCE] = abs(
($metrics[self::M_ABSTRACTION] + $metrics[self::M_INSTABILITY]) - 1
);
}
}
/**
* Collects a single cycle that is reachable by this namespace. All namespaces
* that are part of the cylce are stored in the given <b>$list</b> array.
*
* @param \PDepend\Source\AST\ASTNamespace[] &$list
* @param \PDepend\Source\AST\ASTNamespace $namespace
* @return boolean If this method detects a cycle the return value is <b>true</b>
* otherwise this method will return <b>false</b>.
*/
protected function collectCycle(array &$list, ASTNamespace $namespace)
{
if (in_array($namespace, $list, true)) {
$list[] = $namespace;
return true;
}
$list[] = $namespace;
foreach ($this->getEfferents($namespace) as $efferent) {
if ($this->collectCycle($list, $efferent)) {
return true;
}
}
if (is_int($idx = array_search($namespace, $list, true))) {
unset($list[$idx]);
}
return false;
}
}

View File

@@ -0,0 +1,401 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2015, Matthias Mullie <pdepend@mullie.eu>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2015 Matthias Mullie. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractCachingAnalyzer;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Source\AST\AbstractASTCallable;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\Tokenizer\Tokens;
/**
* This class calculates the Halstead Complexity Measures for the project,
* methods and functions.
*
* @copyright 2015 Matthias Mullie. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class HalsteadAnalyzer extends AbstractCachingAnalyzer implements AnalyzerNodeAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_HALSTEAD_LENGTH = 'hnt', // N = N1 + N2 (total operators + operands)
M_HALSTEAD_VOCABULARY = 'hnd', // n = n1 + n2 (distinct operators + operands)
M_HALSTEAD_VOLUME = 'hv', // V = N * log2(n)
M_HALSTEAD_DIFFICULTY = 'hd', // D = (n1 / 2) * (N2 / n2)
M_HALSTEAD_LEVEL = 'hl', // L = 1 / D
M_HALSTEAD_EFFORT = 'he', // E = V * D
M_HALSTEAD_TIME = 'ht', // T = E / 18
M_HALSTEAD_BUGS = 'hb', // B = (E ** (2/3)) / 3000
M_HALSTEAD_CONTENT = 'hi'; // I = (V / D)
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->metrics === null) {
$this->loadCache();
$this->fireStartAnalyzer();
// Init node metrics
$this->metrics = array();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
$this->unloadCache();
}
}
/**
* This method will return an <b>array</b> with all generated basis metrics
* for the given <b>$node</b> (n1, n2, N1, N2). If there are no metrics for
* the requested node, this method will return an empty <b>array</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array
*/
public function getNodeBasisMetrics(ASTArtifact $artifact)
{
if (isset($this->metrics[$artifact->getId()])) {
return $this->metrics[$artifact->getId()];
}
return array();
}
/**
* This method will return an <b>array</b> with all generated metric values
* for the given <b>$node</b>. If there are no metrics for the requested
* node, this method will return an empty <b>array</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
$basis = $this->getNodeBasisMetrics($artifact);
if ($basis) {
return $this->calculateHalsteadMeasures($basis);
}
return array();
}
/**
* Visits a function node.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$this->fireStartFunction($function);
if (false === $this->restoreFromCache($function)) {
$this->calculateHalsteadBasis($function);
}
$this->fireEndFunction($function);
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
// Empty visit method, we don't want interface metrics
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
if (false === $this->restoreFromCache($method)) {
$this->calculateHalsteadBasis($method);
}
$this->fireEndMethod($method);
}
/**
* @see http://www.scribd.com/doc/99533/Halstead-s-Operators-and-Operands-in-C-C-JAVA-by-Indranil-Nandy
*
* @param \PDepend\Source\AST\AbstractASTCallable $callable
* @return void
*/
public function calculateHalsteadBasis(AbstractASTCallable $callable)
{
$operators = array();
$operands = array();
$skipUntil = null;
$tokens = $callable->getTokens();
foreach ($tokens as $i => $token) {
/*
* Some operations should be ignored, e.g. function declarations.
* When we encounter a new function, we'll skip all tokens until we
* find the closing token.
*/
if ($skipUntil !== null) {
if ($token->type === $skipUntil) {
$skipUntil = null;
}
continue;
}
switch ($token->type) {
// A pair of parenthesis is considered a single operator.
case Tokens::T_PARENTHESIS_CLOSE:
case Tokens::T_CURLY_BRACE_CLOSE:
case Tokens::T_SQUARED_BRACKET_CLOSE:
case Tokens::T_ANGLE_BRACKET_CLOSE:
break;
// A label is considered an operator if it is used as the target
// of a GOTO statement.
case Tokens::T_GOTO:
$operators[] = $token->image;
// Ignore next token as operand but count as operator instead.
$skipUntil = $tokens[$i + 1]->type;
$operators[] = $tokens[$i + 1]->image;
break;
/*
* The following control structures case ...: for (...) if (...)
* switch (...) while(...) and try-catch (...) are treated in a
* special way. The colon and the parentheses are considered to
* be a part of the constructs. The case and the colon or the
* “for (...)”, “if (...)”, “switch (...)”, “while(...)”,
* “try-catch( )” are counted together as one operator.
*/
// case Tokens::T_SWITCH: // not followed by ()
// case Tokens::T_TRY: // not followed by ()
// case Tokens::T_DO: // always comes with while, which accounts for () already
case Tokens::T_IF:
case Tokens::T_FOR:
case Tokens::T_FOREACH:
case Tokens::T_WHILE:
case Tokens::T_CATCH:
$operators[] = $token->image;
/*
* These are always followed by parenthesis, which would add
* another operator (only opening parenthesis counts)
* so we'll have to skip that one.
*/
$skipUntil = Tokens::T_PARENTHESIS_OPEN;
break;
/*
* The ternary operator ? followed by : is considered a
* single operator as it is equivalent to “if-else” construct.
*/
case Tokens::T_COLON:
/*
* Colon is used after keyword, where it counts as part of
* that operator, or in ternary operator, where it also
* counts as 1.
*/
break;
// The comments are considered neither an operator nor an operand.
case Tokens::T_DOC_COMMENT:
case Tokens::T_COMMENT:
break;
/*
* `new` is considered same as the function call, mainly because
* it's equivalent to the function call.
*/
case Tokens::T_NEW:
break;
/*
* Like T_IF & co, array(..) needs 3 tokens ("array", "(" and
* ")") for what's essentially just 1 operator.
*/
case Tokens::T_ARRAY:
break;
/*
* Class::method or $object->method both only count as 1
* identifier, even though they consist of 3 tokens.
*/
case Tokens::T_OBJECT_OPERATOR:
case Tokens::T_DOUBLE_COLON:
// Glue ->/:: and before & after parts together.
$image = array_pop($operands).$token->image.$tokens[$i + 1]->image;
$operands[] = $image;
// Skip next part (would be seen as operand)
$skipUntil = $tokens[$i + 1]->type;
break;
// Ignore HEREDOC delimiters.
case Tokens::T_START_HEREDOC:
case Tokens::T_END_HEREDOC:
break;
// Ignore PHP open & close tags and non-PHP content.
case Tokens::T_OPEN_TAG:
case Tokens::T_CLOSE_TAG:
case Tokens::T_NO_PHP:
break;
/*
* The function name is considered a single operator when it
* appears as calling a function, but when it appears in
* declarations or in function definitions it is not counted as
* operator.
* Default parameter assignments are not counted.
*/
case Tokens::T_FUNCTION:
// Because `)` could appear in default argument assignment
// (`$var = array()`), we need to skip until `{`, but that
// one should be included in operators.
$skipUntil = Tokens::T_CURLY_BRACE_OPEN;
$operators[] = '{';
break;
/*
* When variables or constants appear in declaration they are
* not considered as operands, they are considered operands only
* when they appear with operators in expressions.
*/
case Tokens::T_VAR:
case Tokens::T_CONST:
$skipUntil = Tokens::T_SEMICOLON;
break;
case Tokens::T_STRING:
// `define` is T_STRING, just like any other identifier.
if ($token->image === 'define') {
// Undo all of "define", "(", name, ",", value, ")"
$skipUntil = Tokens::T_PARENTHESIS_CLOSE;
} else {
$operands[] = $token->image;
}
break;
// Operands
case Tokens::T_CONSTANT_ENCAPSED_STRING:
case Tokens::T_VARIABLE:
case Tokens::T_LNUMBER:
case Tokens::T_DNUMBER:
case Tokens::T_NUM_STRING:
case Tokens::T_NULL:
case Tokens::T_TRUE:
case Tokens::T_FALSE:
case Tokens::T_CLASS_FQN:
case Tokens::T_LINE:
case Tokens::T_METHOD_C:
case Tokens::T_NS_C:
case Tokens::T_DIR:
case TOKENS::T_ENCAPSED_AND_WHITESPACE: // content of HEREDOC
$operands[] = $token->image;
break;
// Everything else is an operator.
default:
$operators[] = $token->image;
break;
}
}
$this->metrics[$callable->getId()] = array(
'n1' => count($operators),
'n2' => count($operands),
'N1' => count(array_unique($operators)),
'N2' => count(array_unique($operands)),
);
}
/**
* Calculates Halstead measures from n1, n2, N1 & N2.
*
* @see http://www.verifysoft.com/en_halstead_metrics.html
* @see http://www.grammatech.com/codesonar/workflow-features/halstead
*
* @param array $basis [n1, n2, N1, N2]
* @return array
*/
public function calculateHalsteadMeasures(array $basis)
{
$measures = array();
$measures[self::M_HALSTEAD_LENGTH] = $basis['N1'] + $basis['N2'];
$measures[self::M_HALSTEAD_VOCABULARY] = $basis['n1'] + $basis['n2'];
$measures[self::M_HALSTEAD_VOLUME] =
$measures[self::M_HALSTEAD_LENGTH] * log($measures[self::M_HALSTEAD_VOCABULARY], 2);
$measures[self::M_HALSTEAD_DIFFICULTY] = ($basis['n1'] / 2) * ($basis['N1'] / ($basis['n2'] ?: 1));
$measures[self::M_HALSTEAD_LEVEL] = 1 / ($measures[self::M_HALSTEAD_DIFFICULTY] ?: 1);
$measures[self::M_HALSTEAD_EFFORT] =
$measures[self::M_HALSTEAD_VOLUME] * $measures[self::M_HALSTEAD_DIFFICULTY];
$measures[self::M_HALSTEAD_TIME] = $measures[self::M_HALSTEAD_EFFORT] / 18;
$measures[self::M_HALSTEAD_BUGS] = pow($measures[self::M_HALSTEAD_EFFORT], (2/3)) / 3000;
$measures[self::M_HALSTEAD_CONTENT] =
$measures[self::M_HALSTEAD_VOLUME] / ($measures[self::M_HALSTEAD_DIFFICULTY] ?: 1);
return $measures;
}
}

View File

@@ -0,0 +1,317 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Metrics\AnalyzerFilterAware;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Metrics\AnalyzerProjectAware;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\AST\ASTNamespace;
/**
* This analyzer calculates class/namespace hierarchy metrics.
*
* This analyzer expects that a node list filter is set, before it starts the
* analyze process. This filter will suppress PHP internal and external library
* stuff.
*
* This analyzer is based on the following metric set:
* - http://www.aivosto.com/project/help/pm-oo-misc.html
*
* This analyzer is based on the following metric set:
* - http://www.aivosto.com/project/help/pm-oo-misc.html
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class HierarchyAnalyzer extends AbstractAnalyzer implements AnalyzerFilterAware, AnalyzerNodeAware, AnalyzerProjectAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_NUMBER_OF_ABSTRACT_CLASSES = 'clsa',
M_NUMBER_OF_CONCRETE_CLASSES = 'clsc',
M_NUMBER_OF_ROOT_CLASSES = 'roots',
M_NUMBER_OF_LEAF_CLASSES = 'leafs';
/**
* Number of all analyzed functions.
*
* @var integer
*/
private $fcs = 0;
/**
* Number of all analyzer methods.
*
* @var integer
*/
private $mts = 0;
/**
* Number of all analyzed classes.
*
* @var integer
*/
private $cls = 0;
/**
* Number of all analyzed abstract classes.
*
* @var integer
*/
private $clsa = 0;
/**
* Number of all analyzed interfaces.
*
* @var integer
*/
private $interfs = 0;
/**
* Number of all root classes within the analyzed source code.
*
* @var array(string=>boolean)
*/
private $roots = array();
/**
* Number of all none leaf classes within the analyzed source code
*
* @var array(string=>boolean)
*/
private $noneLeafs = array();
/**
* Hash with all calculated node metrics.
*
* <code>
* array(
* '0375e305-885a-4e91-8b5c-e25bda005438' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* ),
* 'e60c22f0-1a63-4c40-893e-ed3b35b84d0b' => array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* )
* )
* </code>
*
* @var array(string=>array)
*/
private $nodeMetrics = null;
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->nodeMetrics === null) {
$this->fireStartAnalyzer();
// Init node metrics
$this->nodeMetrics = array();
// Visit all nodes
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
}
}
/**
* Provides the project summary metrics as an <b>array</b>.
*
* @return array(string=>mixed)
*/
public function getProjectMetrics()
{
// Count none leaf classes
$noneLeafs = count($this->noneLeafs);
return array(
self::M_NUMBER_OF_ABSTRACT_CLASSES => $this->clsa,
self::M_NUMBER_OF_CONCRETE_CLASSES => $this->cls - $this->clsa,
self::M_NUMBER_OF_ROOT_CLASSES => count($this->roots),
self::M_NUMBER_OF_LEAF_CLASSES => $this->cls - $noneLeafs,
);
}
/**
* This method will return an <b>array</b> with all generated metric values
* for the given <b>$node</b> instance. If there are no metrics for the
* requested node, this method will return an empty <b>array</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array(string=>mixed)
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
if (isset($this->nodeMetrics[$artifact->getId()])) {
return $this->nodeMetrics[$artifact->getId()];
}
return array();
}
/**
* Calculates metrics for the given <b>$class</b> instance.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
if (false === $class->isUserDefined()) {
return;
}
$this->fireStartClass($class);
++$this->cls;
if ($class->isAbstract()) {
++$this->clsa;
}
$parentClass = $class->getParentClass();
if ($parentClass !== null) {
if ($parentClass->getParentClass() === null) {
$this->roots[$parentClass->getId()] = true;
}
$this->noneLeafs[$parentClass->getId()] = true;
}
// Store node metric
$this->nodeMetrics[$class->getId()] = array();
foreach ($class->getMethods() as $method) {
$method->accept($this);
}
foreach ($class->getProperties() as $property) {
$property->accept($this);
}
$this->fireEndClass($class);
}
/**
* Calculates metrics for the given <b>$function</b> instance.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$this->fireStartFunction($function);
++$this->fcs;
$this->fireEndFunction($function);
}
/**
* Calculates metrics for the given <b>$interface</b> instance.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
$this->fireStartInterface($interface);
++$this->interfs;
foreach ($interface->getMethods() as $method) {
$method->accept($this);
}
$this->fireEndInterface($interface);
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
++$this->mts;
$this->fireEndMethod($method);
}
/**
* Calculates metrics for the given <b>$namespace</b> instance.
*
* @param \PDepend\Source\AST\ASTNamespace $namespace
* @return void
*/
public function visitNamespace(ASTNamespace $namespace)
{
$this->fireStartNamespace($namespace);
foreach ($namespace->getTypes() as $type) {
$type->accept($this);
}
foreach ($namespace->getFunctions() as $function) {
$function->accept($this);
}
$this->fireEndNamespace($namespace);
}
}

View File

@@ -0,0 +1,355 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Metrics\AnalyzerFilterAware;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Metrics\AnalyzerProjectAware;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTClass;
/**
* This analyzer provides two project related inheritance metrics.
*
* <b>ANDC - Average Number of Derived Classes</b>: The average number of direct
* subclasses of a class. This metric only covers classes in the analyzed system,
* no library or environment classes are covered.
*
* <b>AHH - Average Hierarchy Height</b>: The computed average of all inheritance
* trees within the analyzed system, external classes or interfaces are ignored.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class InheritanceAnalyzer extends AbstractAnalyzer implements
AnalyzerNodeAware,
AnalyzerFilterAware,
AnalyzerProjectAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_AVERAGE_NUMBER_DERIVED_CLASSES = 'andc',
M_AVERAGE_HIERARCHY_HEIGHT = 'ahh',
M_DEPTH_OF_INHERITANCE_TREE = 'dit',
M_NUMBER_OF_ADDED_METHODS = 'noam',
M_NUMBER_OF_OVERWRITTEN_METHODS = 'noom',
M_NUMBER_OF_DERIVED_CLASSES = 'nocc',
M_MAXIMUM_INHERITANCE_DEPTH = 'maxDIT';
/**
* Contains the max inheritance depth for all root classes within the
* analyzed system. The array size is equal to the number of analyzed root
* classes.
*
* @var array(integer)
*/
private $rootClasses = array();
/**
* The maximum depth of inheritance tree value within the analyzed source code.
*
* @var integer
*/
private $maxDIT = 0;
/**
* The average number of derived classes.
*
* @var float
*/
private $andc = 0;
/**
* The average hierarchy height.
*
* @var float
*/
private $ahh = 0;
/**
* Total number of classes.
*
* @var integer
*/
private $numberOfClasses = 0;
/**
* Total number of derived classes.
*
* @var integer
*/
private $numberOfDerivedClasses = 0;
/**
* Metrics calculated for a single source node.
*
* @var array(string=>array)
*/
private $nodeMetrics = null;
/**
* This method will return an <b>array</b> with all generated metric values
* for the given <b>$node</b>. If there are no metrics for the requested
* node, this method will return an empty <b>array</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array(string=>mixed)
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
if (isset($this->nodeMetrics[$artifact->getId()])) {
return $this->nodeMetrics[$artifact->getId()];
}
return array();
}
/**
* Provides the project summary as an <b>array</b>.
*
* <code>
* array(
* 'andc' => 0.73,
* 'ahh' => 0.56
* )
* </code>
*
* @return array(string=>mixed)
*/
public function getProjectMetrics()
{
return array(
self::M_AVERAGE_NUMBER_DERIVED_CLASSES => $this->andc,
self::M_AVERAGE_HIERARCHY_HEIGHT => $this->ahh,
self::M_MAXIMUM_INHERITANCE_DEPTH => $this->maxDIT,
);
}
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->nodeMetrics === null) {
$this->nodeMetrics = array();
$this->fireStartAnalyzer();
$this->doAnalyze($namespaces);
$this->fireEndAnalyzer();
}
}
/**
* Calculates several inheritance related metrics for the given source
* namespaces.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
* @since 0.9.10
*/
private function doAnalyze($namespaces)
{
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
if ($this->numberOfClasses > 0) {
$this->andc = $this->numberOfDerivedClasses / $this->numberOfClasses;
}
if (($count = count($this->rootClasses)) > 0) {
$this->ahh = array_sum($this->rootClasses) / $count;
}
}
/**
* Visits a class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
if (!$class->isUserDefined()) {
return;
}
$this->fireStartClass($class);
$this->initNodeMetricsForClass($class);
$this->calculateNumberOfDerivedClasses($class);
$this->calculateNumberOfAddedAndOverwrittenMethods($class);
$this->calculateDepthOfInheritanceTree($class);
$this->fireEndClass($class);
}
/**
* Calculates the number of derived classes.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
* @since 0.9.5
*/
private function calculateNumberOfDerivedClasses(ASTClass $class)
{
$id = $class->getId();
if (isset($this->derivedClasses[$id]) === false) {
$this->derivedClasses[$id] = 0;
}
$parentClass = $class->getParentClass();
if ($parentClass !== null && $parentClass->isUserDefined()) {
$id = $parentClass->getId();
++$this->numberOfDerivedClasses;
++$this->nodeMetrics[$id][self::M_NUMBER_OF_DERIVED_CLASSES];
}
}
/**
* Calculates the maximum HIT for the given class.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
* @since 0.9.10
*/
private function calculateDepthOfInheritanceTree(ASTClass $class)
{
$dit = 0;
$id = $class->getId();
$root = $class->getId();
foreach ($class->getParentClasses() as $parent) {
if (!$parent->isUserDefined()) {
++$dit;
}
++$dit;
$root = $parent->getId();
}
// Collect max dit value
$this->maxDIT = max($this->maxDIT, $dit);
if (empty($this->rootClasses[$root]) || $this->rootClasses[$root] < $dit) {
$this->rootClasses[$root] = $dit;
}
$this->nodeMetrics[$id][self::M_DEPTH_OF_INHERITANCE_TREE] = $dit;
}
/**
* Calculates two metrics. The number of added methods and the number of
* overwritten methods.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
* @since 0.9.10
*/
private function calculateNumberOfAddedAndOverwrittenMethods(ASTClass $class)
{
$parentClass = $class->getParentClass();
if ($parentClass === null) {
return;
}
$parentMethodNames = array();
foreach ($parentClass->getAllMethods() as $method) {
$parentMethodNames[$method->getName()] = $method->isAbstract();
}
$numberOfAddedMethods = 0;
$numberOfOverwrittenMethods = 0;
foreach ($class->getAllMethods() as $method) {
if ($method->getParent() !== $class) {
continue;
}
if (isset($parentMethodNames[$method->getName()])) {
if (!$parentMethodNames[$method->getName()]) {
++$numberOfOverwrittenMethods;
}
} else {
++$numberOfAddedMethods;
}
}
$id = $class->getId();
$this->nodeMetrics[$id][self::M_NUMBER_OF_ADDED_METHODS] = $numberOfAddedMethods;
$this->nodeMetrics[$id][self::M_NUMBER_OF_OVERWRITTEN_METHODS] = $numberOfOverwrittenMethods;
}
/**
* Initializes a empty metric container for the given class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
* @since 0.9.10
*/
private function initNodeMetricsForClass(ASTClass $class)
{
$id = $class->getId();
if (isset($this->nodeMetrics[$id])) {
return;
}
++$this->numberOfClasses;
$this->nodeMetrics[$id] = array(
self::M_DEPTH_OF_INHERITANCE_TREE => 0,
self::M_NUMBER_OF_ADDED_METHODS => 0,
self::M_NUMBER_OF_DERIVED_CLASSES => 0,
self::M_NUMBER_OF_OVERWRITTEN_METHODS => 0
);
foreach ($class->getParentClasses() as $parent) {
$this->initNodeMetricsForClass($parent);
}
}
}

View File

@@ -0,0 +1,201 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2015, Matthias Mullie <pdepend@mullie.eu>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2015 Matthias Mullie. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractCachingAnalyzer;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Source\AST\AbstractASTCallable;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
/**
* This class calculates the Halstead Complexity Measures for the project,
* methods and functions.
*
* @copyright 2015 Matthias Mullie. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class MaintainabilityIndexAnalyzer extends AbstractCachingAnalyzer implements AnalyzerNodeAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_MAINTAINABILITY_INDEX = 'mi';
/**
* @var AbstractCachingAnalyzer[]
*/
private $analyzers = array();
/**
* Maintainability index is a combination of cyclomatic complexity,
* halstead volume & lines of code, all of which we already have analyzers
* for.
*
* @param array $options
*/
public function __construct(array $options = array())
{
parent::__construct($options);
$this->analyzers['ccn'] = new CyclomaticComplexityAnalyzer();
$this->analyzers['halstead'] = new HalsteadAnalyzer();
$this->analyzers['loc'] = new NodeLocAnalyzer();
}
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace $namespaces
* @return void
*/
public function analyze($namespaces)
{
// Run CCN, Halstead & LOC analyzers first
foreach ($this->analyzers as $analyzer) {
$analyzer->setCache($this->getCache());
$analyzer->analyze($namespaces);
}
if ($this->metrics === null) {
$this->loadCache();
$this->fireStartAnalyzer();
// Init node metrics
$this->metrics = array();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
$this->unloadCache();
}
}
/**
* This method will return an <b>array</b> with all generated metric values
* for the given <b>$node</b>. If there are no metrics for the requested
* node, this method will return an empty <b>array</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
if (isset($this->metrics[$artifact->getId()])) {
return $this->metrics[$artifact->getId()];
}
return array();
}
/**
* Visits a function node.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$this->fireStartFunction($function);
if (false === $this->restoreFromCache($function)) {
$this->calculateMaintainabilityIndex($function);
}
$this->fireEndFunction($function);
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
// Empty visit method, we don't want interface metrics
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
if (false === $this->restoreFromCache($method)) {
$this->calculateMaintainabilityIndex($method);
}
$this->fireEndMethod($method);
}
/**
* @see http://blogs.msdn.com/b/codeanalysis/archive/2007/11/20/maintainability-index-range-and-meaning.aspx
*
* @param \PDepend\Source\AST\AbstractASTCallable $callable
* @return void
*/
public function calculateMaintainabilityIndex(AbstractASTCallable $callable)
{
$cyclomaticComplexity = $this->analyzers['ccn']->getCcn2($callable);
$halstead = $this->analyzers['halstead']->getNodeMetrics($callable);
$halsteadVolume = $halstead[HalsteadAnalyzer::M_HALSTEAD_VOLUME];
$loc = $this->analyzers['loc']->getNodeMetrics($callable);
$eloc = $loc[NodeLocAnalyzer::M_EXECUTABLE_LINES_OF_CODE];
$maintainabilityIndex = 171 - 5.2 * log($halsteadVolume) - 0.23 * $cyclomaticComplexity - 16.2 * log($eloc);
$maintainabilityIndex = min(100, max(0, $maintainabilityIndex * 100 / 171));
$this->metrics[$callable->getId()] = array(self::M_MAINTAINABILITY_INDEX => $maintainabilityIndex);
}
}

View File

@@ -0,0 +1,571 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractCachingAnalyzer;
use PDepend\Metrics\AnalyzerFilterAware;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Source\AST\AbstractASTCallable;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTBooleanAndExpression;
use PDepend\Source\AST\ASTBooleanOrExpression;
use PDepend\Source\AST\ASTConditionalExpression;
use PDepend\Source\AST\ASTExpression;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTLogicalAndExpression;
use PDepend\Source\AST\ASTLogicalOrExpression;
use PDepend\Source\AST\ASTLogicalXorExpression;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\AST\ASTStatement;
use PDepend\Source\AST\ASTSwitchLabel;
use PDepend\Util\MathUtil;
/**
* This analyzer calculates the NPath complexity of functions and methods. The
* NPath complexity metric measures the acyclic execution paths through a method
* or function. See Nejmeh, Communications of the ACM Feb 1988 pp 188-200.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class NPathComplexityAnalyzer extends AbstractCachingAnalyzer implements AnalyzerFilterAware, AnalyzerNodeAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_NPATH_COMPLEXITY = 'npath';
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->metrics === null) {
$this->loadCache();
$this->fireStartAnalyzer();
$this->metrics = array();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
$this->unloadCache();
}
}
/**
* This method will return an <b>array</b> with all generated metric values
* for the node with the given <b>$id</b> identifier. If there are no
* metrics for the requested node, this method will return an empty <b>array</b>.
*
* <code>
* array(
* 'npath' => '17'
* )
* </code>
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
$metric = array();
if (isset($this->metrics[$artifact->getId()])) {
$metric = array(self::M_NPATH_COMPLEXITY => $this->metrics[$artifact->getId()]);
}
return $metric;
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
// Empty visit method, we don't want interface metrics
}
/**
* Visits a function node.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$this->fireStartFunction($function);
if (false === $this->restoreFromCache($function)) {
$this->calculateComplexity($function);
}
$this->fireEndFunction($function);
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
*
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
if (false === $this->restoreFromCache($method)) {
$this->calculateComplexity($method);
}
$this->fireEndMethod($method);
}
/**
* This method will calculate the NPath complexity for the given callable
* instance.
*
* @param \PDepend\Source\AST\AbstractASTCallable $callable
* @return void
* @since 0.9.12
*/
protected function calculateComplexity(AbstractASTCallable $callable)
{
$npath = '1';
foreach ($callable->getChildren() as $child) {
$stmt = $child->accept($this, $npath);
$npath = MathUtil::mul($npath, $stmt);
}
$this->metrics[$callable->getId()] = $npath;
}
/**
* This method calculates the NPath Complexity of a conditional-statement,
* the meassured value is then returned as a string.
*
* <code>
* <expr1> ? <expr2> : <expr3>
*
* -- NP(?) = NP(<expr1>) + NP(<expr2>) + NP(<expr3>) + 2 --
* </code>
*
* @param \PDepend\Source\AST\ASTNode
* @param string $data
* @return string
* @since 0.9.12
*/
public function visitConditionalExpression($node, $data)
{
// Calculate the complexity of the condition
$parent = $node->getParent()->getChild(0);
$npath = $this->sumComplexity($parent);
// New PHP 5.3 ifsetor-operator $x ?: $y
if (count($node->getChildren()) === 1) {
$npath = MathUtil::mul($npath, '2');
}
// The complexity of each child has no minimum
foreach ($node->getChildren() as $child) {
$cn = $this->sumComplexity($child);
$npath = MathUtil::add($npath, $cn);
}
// Add 2 for the branching per the NPath spec
$npath = MathUtil::add($npath, '2');
return MathUtil::mul($npath, $data);
}
/**
* This method calculates the NPath Complexity of a do-while-statement, the
* meassured value is then returned as a string.
*
* <code>
* do
* <do-range>
* while (<expr>)
* S;
*
* -- NP(do) = NP(<do-range>) + NP(<expr>) + 1 --
* </code>
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param string $data The previously calculated npath value.
*
* @return string
* @since 0.9.12
*/
public function visitDoWhileStatement($node, $data)
{
$stmt = $node->getChild(0)->accept($this, 1);
$expr = $this->sumComplexity($node->getChild(1));
$npath = MathUtil::add($expr, $stmt);
$npath = MathUtil::add($npath, '1');
return MathUtil::mul($npath, $data);
}
/**
* This method calculates the NPath Complexity of an elseif-statement, the
* meassured value is then returned as a string.
*
* <code>
* elseif (<expr>)
* <elseif-range>
* S;
*
* -- NP(elseif) = NP(<elseif-range>) + NP(<expr>) + 1 --
*
*
* elseif (<expr>)
* <elseif-range>
* else
* <else-range>
* S;
*
* -- NP(if) = NP(<if-range>) + NP(<expr>) + NP(<else-range> --
* </code>
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param string $data The previously calculated npath value.
*
* @return string
* @since 0.9.12
*/
public function visitElseIfStatement($node, $data)
{
$npath = $this->sumComplexity($node->getChild(0));
foreach ($node->getChildren() as $child) {
if ($child instanceof ASTStatement) {
$expr = $child->accept($this, 1);
$npath = MathUtil::add($npath, $expr);
}
}
if (!$node->hasElse()) {
$npath = MathUtil::add($npath, '1');
}
return MathUtil::mul($npath, $data);
}
/**
* This method calculates the NPath Complexity of a for-statement, the
* meassured value is then returned as a string.
*
* <code>
* for (<expr1>; <expr2>; <expr3>)
* <for-range>
* S;
*
* -- NP(for) = NP(<for-range>) + NP(<expr1>) + NP(<expr2>) + NP(<expr3>) + 1 --
* </code>
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param string $data The previously calculated npath value.
*
* @return string
* @since 0.9.12
*/
public function visitForStatement($node, $data)
{
$npath = '1';
foreach ($node->getChildren() as $child) {
if ($child instanceof ASTStatement) {
$stmt = $child->accept($this, 1);
$npath = MathUtil::add($npath, $stmt);
} elseif ($child instanceof ASTExpression) {
$expr = $this->sumComplexity($child);
$npath = MathUtil::add($npath, $expr);
}
}
return MathUtil::mul($npath, $data);
}
/**
* This method calculates the NPath Complexity of a for-statement, the
* meassured value is then returned as a string.
*
* <code>
* fpreach (<expr>)
* <foreach-range>
* S;
*
* -- NP(foreach) = NP(<foreach-range>) + NP(<expr>) + 1 --
* </code>
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param string $data The previously calculated npath value.
*
* @return string
* @since 0.9.12
*/
public function visitForeachStatement($node, $data)
{
$npath = $this->sumComplexity($node->getChild(0));
$npath = MathUtil::add($npath, '1');
foreach ($node->getChildren() as $child) {
if ($child instanceof ASTStatement) {
$stmt = $child->accept($this, 1);
$npath = MathUtil::add($npath, $stmt);
}
}
return MathUtil::mul($npath, $data);
}
/**
* This method calculates the NPath Complexity of an if-statement, the
* meassured value is then returned as a string.
*
* <code>
* if (<expr>)
* <if-range>
* S;
*
* -- NP(if) = NP(<if-range>) + NP(<expr>) + 1 --
*
*
* if (<expr>)
* <if-range>
* else
* <else-range>
* S;
*
* -- NP(if) = NP(<if-range>) + NP(<expr>) + NP(<else-range> --
* </code>
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param string $data The previously calculated npath value.
*
* @return string
* @since 0.9.12
*/
public function visitIfStatement($node, $data)
{
$npath = $this->sumComplexity($node->getChild(0));
foreach ($node->getChildren() as $child) {
if ($child instanceof ASTStatement) {
$stmt = $child->accept($this, 1);
$npath = MathUtil::add($npath, $stmt);
}
}
if (!$node->hasElse()) {
$npath = MathUtil::add($npath, '1');
}
return MathUtil::mul($npath, $data);
}
/**
* This method calculates the NPath Complexity of a return-statement, the
* meassured value is then returned as a string.
*
* <code>
* return <expr>;
*
* -- NP(return) = NP(<expr>) --
* </code>
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param string $data The previously calculated npath value.
*
* @return string
* @since 0.9.12
*/
public function visitReturnStatement($node, $data)
{
if (($npath = $this->sumComplexity($node)) === '0') {
return $data;
}
return MathUtil::mul($npath, $data);
}
/**
* This method calculates the NPath Complexity of a switch-statement, the
* meassured value is then returned as a string.
*
* <code>
* switch (<expr>)
* <case-range1>
* <case-range2>
* ...
* <default-range>
*
* -- NP(switch) = NP(<expr>) + NP(<default-range>) + NP(<case-range1>) ... --
* </code>
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param string $data The previously calculated npath value.
*
* @return string
* @since 0.9.12
*/
public function visitSwitchStatement($node, $data)
{
$npath = $this->sumComplexity($node->getChild(0));
foreach ($node->getChildren() as $child) {
if ($child instanceof ASTSwitchLabel) {
$label = $child->accept($this, 1);
$npath = MathUtil::add($npath, $label);
}
}
return MathUtil::mul($npath, $data);
}
/**
* This method calculates the NPath Complexity of a try-catch-statement, the
* meassured value is then returned as a string.
*
* <code>
* try
* <try-range>
* catch
* <catch-range>
*
* -- NP(try) = NP(<try-range>) + NP(<catch-range>) --
*
*
* try
* <try-range>
* catch
* <catch-range1>
* catch
* <catch-range2>
* ...
*
* -- NP(try) = NP(<try-range>) + NP(<catch-range1>) + NP(<catch-range2>) ... --
* </code>
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param string $data The previously calculated npath value.
*
* @return string
* @since 0.9.12
*/
public function visitTryStatement($node, $data)
{
$npath = '0';
foreach ($node->getChildren() as $child) {
if ($child instanceof ASTStatement) {
$stmt = $child->accept($this, 1);
$npath = MathUtil::add($npath, $stmt);
}
}
return MathUtil::mul($npath, $data);
}
/**
* This method calculates the NPath Complexity of a while-statement, the
* meassured value is then returned as a string.
*
* <code>
* while (<expr>)
* <while-range>
* S;
*
* -- NP(while) = NP(<while-range>) + NP(<expr>) + 1 --
* </code>
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
* @param string $data The previously calculated npath value.
*
* @return string
* @since 0.9.12
*/
public function visitWhileStatement($node, $data)
{
$expr = $this->sumComplexity($node->getChild(0));
$stmt = $node->getChild(1)->accept($this, 1);
$npath = MathUtil::add($expr, $stmt);
$npath = MathUtil::add($npath, '1');
return MathUtil::mul($npath, $data);
}
/**
* Calculates the expression sum of the given node.
*
* @param \PDepend\Source\AST\ASTNode $node The currently visited node.
*
* @return string
* @since 0.9.12
* @todo I don't like this method implementation, it should be possible to
* implement this method with more visitor behavior for the boolean
* and logical expressions.
*/
public function sumComplexity($node)
{
$sum = '0';
if ($node instanceof ASTConditionalExpression) {
$sum = MathUtil::add($sum, $node->accept($this, 1));
} elseif ($node instanceof ASTBooleanAndExpression
|| $node instanceof ASTBooleanOrExpression
|| $node instanceof ASTLogicalAndExpression
|| $node instanceof ASTLogicalOrExpression
|| $node instanceof ASTLogicalXorExpression
) {
$sum = MathUtil::add($sum, '1');
} else {
foreach ($node->getChildren() as $child) {
$expr = $this->sumComplexity($child);
$sum = MathUtil::add($sum, $expr);
}
}
return $sum;
}
}

View File

@@ -0,0 +1,328 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractAnalyzer;
use PDepend\Metrics\AnalyzerFilterAware;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Metrics\AnalyzerProjectAware;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\AST\ASTNamespace;
/**
* This analyzer collects different count metrics for code artifacts like
* classes, methods, functions or namespaces.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class NodeCountAnalyzer extends AbstractAnalyzer implements AnalyzerFilterAware, AnalyzerNodeAware, AnalyzerProjectAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_NUMBER_OF_PACKAGES = 'nop',
M_NUMBER_OF_CLASSES = 'noc',
M_NUMBER_OF_INTERFACES = 'noi',
M_NUMBER_OF_METHODS = 'nom',
M_NUMBER_OF_FUNCTIONS = 'nof';
/**
* Number Of Packages.
*
* @var integer
*/
private $nop = 0;
/**
* Number Of Classes.
*
* @var integer
*/
private $noc = 0;
/**
* Number Of Interfaces.
*
* @var integer
*/
private $noi = 0;
/**
* Number Of Methods.
*
* @var integer
*/
private $nom = 0;
/**
* Number Of Functions.
*
* @var integer
*/
private $nof = 0;
/**
* Collected node metrics
*
* @var array(string=>array)
*/
private $nodeMetrics = null;
/**
* This method will return an <b>array</b> with all generated metric values
* for the given <b>$node</b> instance. If there are no metrics for the
* requested node, this method will return an empty <b>array</b>.
*
* <code>
* array(
* 'noc' => 23,
* 'nom' => 17,
* 'nof' => 42
* )
* </code>
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array(string=>mixed)
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
$metrics = array();
if (isset($this->nodeMetrics[$artifact->getId()])) {
$metrics = $this->nodeMetrics[$artifact->getId()];
}
return $metrics;
}
/**
* Provides the project summary as an <b>array</b>.
*
* <code>
* array(
* 'nop' => 23,
* 'noc' => 17,
* 'noi' => 23,
* 'nom' => 42,
* 'nof' => 17
* )
* </code>
*
* @return array(string=>mixed)
*/
public function getProjectMetrics()
{
return array(
self::M_NUMBER_OF_PACKAGES => $this->nop,
self::M_NUMBER_OF_CLASSES => $this->noc,
self::M_NUMBER_OF_INTERFACES => $this->noi,
self::M_NUMBER_OF_METHODS => $this->nom,
self::M_NUMBER_OF_FUNCTIONS => $this->nof
);
}
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
// Check for previous run
if ($this->nodeMetrics === null) {
$this->fireStartAnalyzer();
$this->nodeMetrics = array();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
}
}
/**
* Visits a class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
if (false === $class->isUserDefined()) {
return;
}
$this->fireStartClass($class);
// Update global class count
++$this->noc;
$id = $class->getNamespace()->getId();
++$this->nodeMetrics[$id][self::M_NUMBER_OF_CLASSES];
$this->nodeMetrics[$class->getId()] = array(
self::M_NUMBER_OF_METHODS => 0
);
foreach ($class->getMethods() as $method) {
$method->accept($this);
}
$this->fireEndClass($class);
}
/**
* Visits a function node.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$this->fireStartFunction($function);
// Update global function count
++$this->nof;
$id = $function->getNamespace()->getId();
++$this->nodeMetrics[$id][self::M_NUMBER_OF_FUNCTIONS];
$this->fireEndFunction($function);
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
if (false === $interface->isUserDefined()) {
return;
}
$this->fireStartInterface($interface);
// Update global class count
++$this->noi;
$id = $interface->getNamespace()->getId();
++$this->nodeMetrics[$id][self::M_NUMBER_OF_INTERFACES];
$this->nodeMetrics[$interface->getId()] = array(
self::M_NUMBER_OF_METHODS => 0
);
foreach ($interface->getMethods() as $method) {
$method->accept($this);
}
$this->fireEndInterface($interface);
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
// Update global method count
++$this->nom;
$parent = $method->getParent();
// Update parent class or interface
$parentId = $parent->getId();
++$this->nodeMetrics[$parentId][self::M_NUMBER_OF_METHODS];
$id = $parent->getNamespace()->getId();
++$this->nodeMetrics[$id][self::M_NUMBER_OF_METHODS];
$this->fireEndMethod($method);
}
/**
* Visits a namespace node.
*
* @param \PDepend\Source\AST\ASTNamespace $namespace
* @return void
*/
public function visitNamespace(ASTNamespace $namespace)
{
$this->fireStartNamespace($namespace);
++$this->nop;
$this->nodeMetrics[$namespace->getId()] = array(
self::M_NUMBER_OF_CLASSES => 0,
self::M_NUMBER_OF_INTERFACES => 0,
self::M_NUMBER_OF_METHODS => 0,
self::M_NUMBER_OF_FUNCTIONS => 0
);
foreach ($namespace->getClasses() as $class) {
$class->accept($this);
}
foreach ($namespace->getInterfaces() as $interface) {
$interface->accept($this);
}
foreach ($namespace->getFunctions() as $function) {
$function->accept($this);
}
$this->fireEndNamespace($namespace);
}
}

View File

@@ -0,0 +1,482 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics\Analyzer;
use PDepend\Metrics\AbstractCachingAnalyzer;
use PDepend\Metrics\AnalyzerFilterAware;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Metrics\AnalyzerProjectAware;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTCompilationUnit;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\Tokenizer\Tokens;
/**
* This analyzer collects different lines of code metrics.
*
* It collects the total Lines Of Code(<b>loc</b>), the None Comment Lines Of
* Code(<b>ncloc</b>), the Comment Lines Of Code(<b>cloc</b>) and a approximated
* Executable Lines Of Code(<b>eloc</b>) for files, classes, interfaces,
* methods, properties and function.
*
* The current implementation has a limitation, that affects inline comments.
* The following code will suppress one line of code.
*
* <code>
* function foo() {
* foobar(); // Bad behaviour...
* }
* </code>
*
* The same rule applies to class methods. mapi, <b>PLEASE, FIX THIS ISSUE.</b>
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class NodeLocAnalyzer extends AbstractCachingAnalyzer implements
AnalyzerNodeAware,
AnalyzerFilterAware,
AnalyzerProjectAware
{
/**
* Metrics provided by the analyzer implementation.
*/
const M_LINES_OF_CODE = 'loc',
M_COMMENT_LINES_OF_CODE = 'cloc',
M_EXECUTABLE_LINES_OF_CODE = 'eloc',
M_LOGICAL_LINES_OF_CODE = 'lloc',
M_NON_COMMENT_LINES_OF_CODE = 'ncloc';
/**
* Collected project metrics.
*
* @var array(string=>integer)
*/
private $projectMetrics = array(
self::M_LINES_OF_CODE => 0,
self::M_COMMENT_LINES_OF_CODE => 0,
self::M_EXECUTABLE_LINES_OF_CODE => 0,
self::M_LOGICAL_LINES_OF_CODE => 0,
self::M_NON_COMMENT_LINES_OF_CODE => 0
);
/**
* Executable lines of code in a class. The method calculation increases
* this property with each method's ELOC value.
*
* @var integer
* @since 0.9.12
*/
private $classExecutableLines = 0;
/**
* Logical lines of code in a class. The method calculation increases this
* property with each method's LLOC value.
*
* @var integer
* @since 0.9.13
*/
private $classLogicalLines = 0;
/**
* This method will return an <b>array</b> with all generated metric values
* for the given <b>$node</b> instance. If there are no metrics for the
* requested node, this method will return an empty <b>array</b>.
*
* <code>
* array(
* 'loc' => 23,
* 'cloc' => 17,
* 'eloc' => 17,
* 'ncloc' => 42
* )
* </code>
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array
*/
public function getNodeMetrics(ASTArtifact $artifact)
{
$metrics = array();
if (isset($this->metrics[$artifact->getId()])) {
$metrics = $this->metrics[$artifact->getId()];
}
return $metrics;
}
/**
* Provides the project summary as an <b>array</b>.
*
* <code>
* array(
* 'loc' => 23,
* 'cloc' => 17,
* 'ncloc' => 42
* )
* </code>
*
* @return array
*/
public function getProjectMetrics()
{
return $this->projectMetrics;
}
/**
* Processes all {@link \PDepend\Source\AST\ASTNamespace} code nodes.
*
* @param \PDepend\Source\AST\ASTNamespace[] $namespaces
* @return void
*/
public function analyze($namespaces)
{
if ($this->metrics === null) {
$this->loadCache();
$this->fireStartAnalyzer();
$this->metrics = array();
foreach ($namespaces as $namespace) {
$namespace->accept($this);
}
$this->fireEndAnalyzer();
$this->unloadCache();
}
}
/**
* Visits a class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
$this->fireStartClass($class);
$class->getCompilationUnit()->accept($this);
$this->classExecutableLines = 0;
$this->classLogicalLines = 0;
foreach ($class->getMethods() as $method) {
$method->accept($this);
}
if ($this->restoreFromCache($class)) {
return $this->fireEndClass($class);
}
list($cloc) = $this->linesOfCode($class->getTokens(), true);
$loc = $class->getEndLine() - $class->getStartLine() + 1;
$ncloc = $loc - $cloc;
$this->metrics[$class->getId()] = array(
self::M_LINES_OF_CODE => $loc,
self::M_COMMENT_LINES_OF_CODE => $cloc,
self::M_EXECUTABLE_LINES_OF_CODE => $this->classExecutableLines,
self::M_LOGICAL_LINES_OF_CODE => $this->classLogicalLines,
self::M_NON_COMMENT_LINES_OF_CODE => $ncloc,
);
$this->fireEndClass($class);
}
/**
* Visits a file node.
*
* @param \PDepend\Source\AST\ASTCompilationUnit $compilationUnit
* @return void
*/
public function visitCompilationUnit(ASTCompilationUnit $compilationUnit)
{
// Skip for dummy files
if ($compilationUnit->getFileName() === null) {
return;
}
// Check for initial file
$id = $compilationUnit->getId();
if (isset($this->metrics[$id])) {
return;
}
$this->fireStartFile($compilationUnit);
if ($this->restoreFromCache($compilationUnit)) {
$this->updateProjectMetrics($id);
return $this->fireEndFile($compilationUnit);
}
list($cloc, $eloc, $lloc) = $this->linesOfCode($compilationUnit->getTokens());
$loc = $compilationUnit->getEndLine();
$ncloc = $loc - $cloc;
$this->metrics[$id] = array(
self::M_LINES_OF_CODE => $loc,
self::M_COMMENT_LINES_OF_CODE => $cloc,
self::M_EXECUTABLE_LINES_OF_CODE => $eloc,
self::M_LOGICAL_LINES_OF_CODE => $lloc,
self::M_NON_COMMENT_LINES_OF_CODE => $ncloc
);
$this->updateProjectMetrics($id);
$this->fireEndFile($compilationUnit);
}
/**
* Visits a function node.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$this->fireStartFunction($function);
$function->getCompilationUnit()->accept($this);
if ($this->restoreFromCache($function)) {
return $this->fireEndFunction($function);
}
list($cloc, $eloc, $lloc) = $this->linesOfCode(
$function->getTokens(),
true
);
$loc = $function->getEndLine() - $function->getStartLine() + 1;
$ncloc = $loc - $cloc;
$this->metrics[$function->getId()] = array(
self::M_LINES_OF_CODE => $loc,
self::M_COMMENT_LINES_OF_CODE => $cloc,
self::M_EXECUTABLE_LINES_OF_CODE => $eloc,
self::M_LOGICAL_LINES_OF_CODE => $lloc,
self::M_NON_COMMENT_LINES_OF_CODE => $ncloc
);
$this->fireEndFunction($function);
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
$this->fireStartInterface($interface);
$interface->getCompilationUnit()->accept($this);
foreach ($interface->getMethods() as $method) {
$method->accept($this);
}
if ($this->restoreFromCache($interface)) {
return $this->fireEndInterface($interface);
}
list($cloc) = $this->linesOfCode($interface->getTokens(), true);
$loc = $interface->getEndLine() - $interface->getStartLine() + 1;
$ncloc = $loc - $cloc;
$this->metrics[$interface->getId()] = array(
self::M_LINES_OF_CODE => $loc,
self::M_COMMENT_LINES_OF_CODE => $cloc,
self::M_EXECUTABLE_LINES_OF_CODE => 0,
self::M_LOGICAL_LINES_OF_CODE => 0,
self::M_NON_COMMENT_LINES_OF_CODE => $ncloc
);
$this->fireEndInterface($interface);
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$this->fireStartMethod($method);
if ($this->restoreFromCache($method)) {
return $this->fireEndMethod($method);
}
if ($method->isAbstract()) {
$cloc = 0;
$eloc = 0;
$lloc = 0;
} else {
list($cloc, $eloc, $lloc) = $this->linesOfCode(
$method->getTokens(),
true
);
}
$loc = $method->getEndLine() - $method->getStartLine() + 1;
$ncloc = $loc - $cloc;
$this->metrics[$method->getId()] = array(
self::M_LINES_OF_CODE => $loc,
self::M_COMMENT_LINES_OF_CODE => $cloc,
self::M_EXECUTABLE_LINES_OF_CODE => $eloc,
self::M_LOGICAL_LINES_OF_CODE => $lloc,
self::M_NON_COMMENT_LINES_OF_CODE => $ncloc
);
$this->classExecutableLines += $eloc;
$this->classLogicalLines += $lloc;
$this->fireEndMethod($method);
}
/**
* Updates the project metrics based on the node metrics identifier by the
* given <b>$id</b>.
*
* @param string $id The unique identifier of a node.
* @return void
*/
private function updateProjectMetrics($id)
{
foreach ($this->metrics[$id] as $metric => $value) {
$this->projectMetrics[$metric] += $value;
}
}
/**
* Counts the Comment Lines Of Code (CLOC) and a pseudo Executable Lines Of
* Code (ELOC) values.
*
* ELOC = Non Whitespace Lines + Non Comment Lines
*
* <code>
* array(
* 0 => 23, // Comment Lines Of Code
* 1 => 42 // Executable Lines Of Code
* )
* </code>
*
* @param array $tokens The raw token stream.
* @param boolean $search Optional boolean flag, search start.
* @return array
*/
private function linesOfCode(array $tokens, $search = false)
{
$clines = array();
$elines = array();
$llines = 0;
$count = count($tokens);
if ($search === true) {
for ($i = 0; $i < $count; ++$i) {
$token = $tokens[$i];
if ($token->type === Tokens::T_CURLY_BRACE_OPEN) {
break;
}
}
} else {
$i = 0;
}
for (; $i < $count; ++$i) {
$token = $tokens[$i];
if ($token->type === Tokens::T_COMMENT
|| $token->type === Tokens::T_DOC_COMMENT
) {
$lines =& $clines;
} else {
$lines =& $elines;
}
switch ($token->type) {
// These statement are terminated by a semicolon
//case \PDepend\Source\Tokenizer\Tokens::T_RETURN:
//case \PDepend\Source\Tokenizer\Tokens::T_THROW:
case Tokens::T_IF:
case Tokens::T_TRY:
case Tokens::T_CASE:
case Tokens::T_GOTO:
case Tokens::T_CATCH:
case Tokens::T_WHILE:
case Tokens::T_ELSEIF:
case Tokens::T_SWITCH:
case Tokens::T_DEFAULT:
case Tokens::T_FOREACH:
case Tokens::T_FUNCTION:
case Tokens::T_SEMICOLON:
++$llines;
break;
case Tokens::T_DO:
case Tokens::T_FOR:
// Because statements at least require one semicolon
--$llines;
break;
}
if ($token->startLine === $token->endLine) {
$lines[$token->startLine] = true;
} else {
for ($j = $token->startLine; $j <= $token->endLine; ++$j) {
$lines[$j] = true;
}
}
unset($lines);
}
return array(count($clines), count($elines), $llines);
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
namespace PDepend\Metrics;
use PDepend\Util\Cache\CacheDriver;
/**
* Simple marker interface that is used to mark an analyzer as cache aware. This
* means that the loading infrastructure code will inject an instance of
* {@link \PDepend\Util\Cache\CacheDriver} into this analyzer.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
interface AnalyzerCacheAware extends Analyzer
{
/**
* Setter method for the system wide used cache.
*
* @param \PDepend\Util\Cache\CacheDriver $cache
* @return void
*/
public function setCache(CacheDriver $cache);
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Creates Analyzer instances
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class AnalyzerFactory
{
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
private $container;
/**
* Create a new Analyzer Factory
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* Create and configure all analyzers required for given set of loggers.
*
* @param \PDepend\Report\ReportGenerator[] $generators
* @return \PDepend\Metrics\Analyzer[]
*/
public function createRequiredForGenerators(array $generators)
{
$analyzers = array();
foreach ($generators as $logger) {
foreach ($logger->getAcceptedAnalyzers() as $type) {
$analyzers[$type] = $this->container->get($type);
}
}
return $analyzers;
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics;
/**
* Simple marker interface that is used to mark an analyzer as namespace filter
* aware. This means that a defined namespace filter for external dependencies
* on namespaces an its classes and interfaces must be set before this analyzer
* starts.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface AnalyzerFilterAware extends Analyzer
{
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.10
*/
namespace PDepend\Metrics;
/**
* Filter iterator that only returns enabled {@link \PDepend\Metrics\Analyzer}
* instances.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.10
*/
class AnalyzerIterator extends \FilterIterator
{
/**
* Constructs a new iterator instance.
*
* @param \PDepend\Metrics\Analyzer[] $analyzers
*/
public function __construct(array $analyzers)
{
parent::__construct(new \ArrayIterator($analyzers));
}
/**
* Returns <b>true</b> when the current analyzer instance is enabled.
*
* @return boolean
*/
public function accept()
{
return $this->getInnerIterator()->current()->isEnabled();
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics;
use PDepend\Source\ASTVisitor\ASTVisitListener;
/**
* An implementation of this listener can be used to recieve informations about
* the current metric analyzer.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface AnalyzerListener extends ASTVisitListener
{
/**
* This method is called when the analyzer starts code processing.
*
* @param \PDepend\Metrics\Analyzer $analyzer The context analyzer instance.
* @return void
*/
public function startAnalyzer(Analyzer $analyzer);
/**
* This method is called when the analyzer has finished code processing.
*
* @param \PDepend\Metrics\Analyzer $analyzer The context analyzer instance.
* @return void
*/
public function endAnalyzer(Analyzer $analyzer);
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics;
use PDepend\Source\AST\ASTArtifact;
/**
* Marker interface that marks a result set as node metrics aware.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface AnalyzerNodeAware extends Analyzer
{
/**
* This method will return an <b>array</b> with all generated metric values
* for the node with the given <b>$id</b> identifier. If there are no
* metrics for the requested node, this method will return an empty <b>array</b>.
*
* <code>
* array(
* 'loc' => 42,
* 'ncloc' => 17,
* 'cc' => 12
* )
* </code>
*
* @param \PDepend\Source\AST\ASTArtifact $artifact
* @return array(string=>mixed)
*/
public function getNodeMetrics(ASTArtifact $artifact);
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Metrics;
/**
* This interface is used to mark a result set as project summary aware.
*
* A result set that implements this interface provides overview or calculated
* values for the complete analyzed source code.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface AnalyzerProjectAware extends Analyzer
{
/**
* Provides the project summary as an <b>array</b>.
*
* <code>
* array(
* 'loc' => 1742,
* 'nop' => 23,
* 'noc' => 17
* )
* </code>
*
* @return array(string=>mixed)
*/
public function getProjectMetrics();
}

View File

@@ -0,0 +1,120 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend;
// @codeCoverageIgnoreStart
use PDepend\Metrics\AnalyzerListener;
use PDepend\Source\ASTVisitor\ASTVisitListener;
use PDepend\Source\Builder\Builder;
use PDepend\Source\Tokenizer\Tokenizer;
/**
* This listener can be used to get informations about the current pdepend process.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface ProcessListener extends ASTVisitListener, AnalyzerListener
{
/**
* Is called when PDepend starts the file parsing process.
*
* @param \PDepend\Source\Builder\Builder $builder The used node builder instance.
* @return void
*/
public function startParseProcess(Builder $builder);
/**
* Is called when PDepend has finished the file parsing process.
*
* @param \PDepend\Source\Builder\Builder $builder The used node builder instance.
* @return void
*/
public function endParseProcess(Builder $builder);
/**
* Is called when PDepend starts parsing of a new file.
*
* @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
* @return void
*/
public function startFileParsing(Tokenizer $tokenizer);
/**
* Is called when PDepend has finished a file.
*
* @param \PDepend\Source\Tokenizer\Tokenizer $tokenizer
* @return void
*/
public function endFileParsing(Tokenizer $tokenizer);
/**
* Is called when PDepend starts the analyzing process.
*
* @return void
*/
public function startAnalyzeProcess();
/**
* Is called when PDepend has finished the analyzing process.
*
* @return void
*/
public function endAnalyzeProcess();
/**
* Is called when PDepend starts the logging process.
*
* @return void
*/
public function startLogProcess();
/**
* Is called when PDepend has finished the logging process.
*
* @return void
*/
public function endLogProcess();
}
// @codeCoverageIgnoreEnd

View File

@@ -0,0 +1,62 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report;
use PDepend\Source\AST\ASTArtifactList;
/**
* A logger that implements this interface needs the analyzed code structure.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface CodeAwareGenerator extends ReportGenerator
{
/**
* Sets the context code nodes.
*
* @param \PDepend\Source\AST\ASTArtifactList $artifacts
* @return void
*/
public function setArtifacts(ASTArtifactList $artifacts);
}

View File

@@ -0,0 +1,351 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report\Dependencies;
use PDepend\Metrics\Analyzer;
use PDepend\Metrics\Analyzer\ClassDependencyAnalyzer;
use PDepend\Report\CodeAwareGenerator;
use PDepend\Report\FileAwareGenerator;
use PDepend\Report\NoLogOutputException;
use PDepend\Source\AST\AbstractASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\AbstractASTClassOrInterface;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTCompilationUnit;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\AST\ASTNamespace;
use PDepend\Source\AST\ASTTrait;
use PDepend\Source\ASTVisitor\AbstractASTVisitor;
use PDepend\Util\Utf8Util;
/**
* This logger generates a summary xml document with aggregated project, class,
* method and file dependencies.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class Xml extends AbstractASTVisitor implements CodeAwareGenerator, FileAwareGenerator
{
/**
* The log output file.
*
* @var string
*/
private $logFile = null;
/**
* The raw {@link \PDepend\Source\AST\ASTNamespace} instances.
*
* @var \PDepend\Source\AST\ASTArtifactList
*/
protected $code = null;
/**
* Set of all analyzed files.
*
* @var \PDepend\Source\AST\ASTCompilationUnit[]
*/
protected $fileSet = array();
/**
* @var \PDepend\Metrics\Analyzer\DependencyAnalyzer
*/
private $dependencyAnalyzer;
/**
* The internal used xml stack.
*
* @var DOMElement[]
*/
private $xmlStack = array();
/**
* Sets the output log file.
*
* @param string $logFile The output log file.
*
* @return void
*/
public function setLogFile($logFile)
{
$this->logFile = $logFile;
}
/**
* Returns an <b>array</b> with accepted analyzer types. These types can be
* concrete analyzer classes or one of the descriptive analyzer interfaces.
*
* @return array(string)
*/
public function getAcceptedAnalyzers()
{
return array(
'pdepend.analyzer.class_dependency',
);
}
/**
* Sets the context code nodes.
*
* @param \PDepend\Source\AST\ASTArtifactList $artifacts
* @return void
*/
public function setArtifacts(ASTArtifactList $artifacts)
{
$this->code = $artifacts;
}
/**
* Adds an analyzer to log. If this logger accepts the given analyzer it
* with return <b>true</b>, otherwise the return value is <b>false</b>.
*
* @param \PDepend\dependencies\Analyzer $analyzer The analyzer to log.
* @return boolean
*/
public function log(Analyzer $analyzer)
{
if ($analyzer instanceof ClassDependencyAnalyzer) {
$this->dependencyAnalyzer = $analyzer;
return true;
}
return false;
}
/**
* Closes the logger process and writes the output file.
*
* @return void
* @throws \PDepend\Report\NoLogOutputException If the no log target exists.
*/
public function close()
{
if ($this->logFile === null) {
throw new NoLogOutputException($this);
}
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$dependencies = $dom->createElement('dependencies');
$dependencies->setAttribute('generated', date('Y-m-d\TH:i:s'));
$dependencies->setAttribute('pdepend', '@package_version@');
array_push($this->xmlStack, $dependencies);
foreach ($this->code as $node) {
$node->accept($this);
}
$dom->appendChild($dependencies);
$buffer = $dom->saveXML();
file_put_contents($this->logFile, $buffer);
}
/**
* Visits a class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
$this->generateTypeXml($class, 'class');
}
/**
* Visits a trait node.
*
* @param \PDepend\Source\AST\ASTTrait $trait
* @return void
*/
public function visitTrait(ASTTrait $trait)
{
$this->generateTypeXml($trait, 'trait');
}
/**
* Generates the XML for a class or trait node.
*
* @param \PDepend\Source\AST\ASTClass $type
* @param string $typeIdentifier
* @return void
*/
private function generateTypeXml(AbstractASTClassOrInterface $type, $typeIdentifier)
{
if (!$type->isUserDefined()) {
return;
}
$xml = end($this->xmlStack);
$doc = $xml->ownerDocument;
$typeXml = $doc->createElement($typeIdentifier);
$typeXml->setAttribute('name', Utf8Util::ensureEncoding($type->getName()));
$xml->appendChild($typeXml);
array_push($this->xmlStack, $typeXml);
$this->writeNodeDependencies($typeXml, $type);
$this->writeFileReference($typeXml, $type->getCompilationUnit());
array_pop($this->xmlStack);
}
/**
* Visits a function node.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
// Do not care
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
$this->generateTypeXml($interface, 'interface');
}
/**
* Visits a namespace node.
*
* @param \PDepend\Source\AST\ASTNamespace $namespace
* @return void
*/
public function visitNamespace(ASTNamespace $namespace)
{
$xml = end($this->xmlStack);
$doc = $xml->ownerDocument;
$packageXml = $doc->createElement('package');
$packageXml->setAttribute('name', Utf8Util::ensureEncoding($namespace->getName()));
array_push($this->xmlStack, $packageXml);
foreach ($namespace->getTypes() as $type) {
$type->accept($this);
}
foreach ($namespace->getFunctions() as $function) {
$function->accept($this);
}
array_pop($this->xmlStack);
if ($packageXml->firstChild === null) {
return;
}
$xml->appendChild($packageXml);
}
/**
* Aggregates all dependencies for the given <b>$node</b> instance and adds them
* to the <b>\DOMElement</b>
*
* @param \DOMElement $xml
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return void
*/
protected function writeNodeDependencies(\DOMElement $xml, AbstractASTArtifact $node)
{
if (!$this->dependencyAnalyzer) {
return;
}
$xml = end($this->xmlStack);
$doc = $xml->ownerDocument;
$efferentXml = $doc->createElement('efferent');
$xml->appendChild($efferentXml);
foreach ($this->dependencyAnalyzer->getEfferents($node) as $type) {
$typeXml = $doc->createElement('type');
$typeXml->setAttribute('namespace', Utf8Util::ensureEncoding($type->getNamespaceName()));
$typeXml->setAttribute('name', Utf8Util::ensureEncoding($type->getName()));
$efferentXml->appendChild($typeXml);
}
$afferentXml = $doc->createElement('afferent');
$xml->appendChild($afferentXml);
foreach ($this->dependencyAnalyzer->getAfferents($node) as $type) {
$typeXml = $doc->createElement('type');
$typeXml->setAttribute('namespace', Utf8Util::ensureEncoding($type->getNamespaceName()));
$typeXml->setAttribute('name', Utf8Util::ensureEncoding($type->getName()));
$afferentXml->appendChild($typeXml);
}
}
/**
* Appends a file reference element to the given <b>$xml</b> element.
*
* <code>
* <class name="\PDepend\Engine">
* <file name="PDepend/Engine.php" />
* </class>
* </code>
*
* @param \DOMElement $xml The parent xml element.
* @param \PDepend\Source\AST\ASTCompilationUnit $compilationUnit The code file instance.
* @return void
*/
protected function writeFileReference(\DOMElement $xml, ASTCompilationUnit $compilationUnit = null)
{
if (in_array($compilationUnit, $this->fileSet, true) === false) {
$this->fileSet[] = $compilationUnit;
}
$fileXml = $xml->ownerDocument->createElement('file');
$fileXml->setAttribute('name', Utf8Util::ensureEncoding($compilationUnit->getFileName()));
$xml->appendChild($fileXml);
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report;
/**
* Marker interface for a log file aware logger.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface FileAwareGenerator extends ReportGenerator
{
/**
* Sets the output log file.
*
* @param string $logFile The output log file.
*
* @return void
*/
public function setLogFile($logFile);
}

View File

@@ -0,0 +1,254 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report\Jdepend;
use PDepend\Metrics\Analyzer;
use PDepend\Metrics\Analyzer\DependencyAnalyzer;
use PDepend\Report\CodeAwareGenerator;
use PDepend\Report\FileAwareGenerator;
use PDepend\Report\NoLogOutputException;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\ASTVisitor\AbstractASTVisitor;
use PDepend\Util\Utf8Util;
use PDepend\Util\FileUtil;
use PDepend\Util\ImageConvert;
/**
* Generates a chart with the aggregated metrics.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class Chart extends AbstractASTVisitor implements CodeAwareGenerator, FileAwareGenerator
{
/**
* The output file name.
*
* @var string
*/
private $logFile = null;
/**
* The context source code.
*
* @var \PDepend\Source\AST\ASTArtifactList
*/
private $code = null;
/**
* The context analyzer instance.
*
* @var \PDepend\Metrics\Analyzer\DependencyAnalyzer
*/
private $analyzer = null;
/**
* Sets the output log file.
*
* @param string $logFile The output log file.
*
* @return void
*/
public function setLogFile($logFile)
{
$this->logFile = $logFile;
}
/**
* Returns an <b>array</b> with accepted analyzer types. These types can be
* concrete analyzer classes or one of the descriptive analyzer interfaces.
*
* @return array(string)
*/
public function getAcceptedAnalyzers()
{
return array('pdepend.analyzer.dependency');
}
/**
* Sets the context code nodes.
*
* @param \PDepend\Source\AST\ASTArtifactList $artifacts
* @return void
*/
public function setArtifacts(ASTArtifactList $artifacts)
{
$this->code = $artifacts;
}
/**
* Adds an analyzer to log. If this logger accepts the given analyzer it
* with return <b>true</b>, otherwise the return value is <b>false</b>.
*
* @param \PDepend\Metrics\Analyzer $analyzer The analyzer to log.
* @return boolean
*/
public function log(Analyzer $analyzer)
{
if ($analyzer instanceof DependencyAnalyzer) {
$this->analyzer = $analyzer;
return true;
}
return false;
}
/**
* Closes the logger process and writes the output file.
*
* @return void
* @throws \PDepend\Report\NoLogOutputException If the no log target exists.
*/
public function close()
{
// Check for configured log file
if ($this->logFile === null) {
throw new NoLogOutputException($this);
}
$bias = 0.1;
$svg = new \DOMDocument('1.0', 'UTF-8');
$svg->loadXML(file_get_contents(dirname(__FILE__) . '/chart.svg'));
$layer = $svg->getElementById('jdepend.layer');
$bad = $svg->getElementById('jdepend.bad');
$bad->removeAttribute('xml:id');
$good = $svg->getElementById('jdepend.good');
$good->removeAttribute('xml:id');
$legendTemplate = $svg->getElementById('jdepend.legend');
$legendTemplate->removeAttribute('xml:id');
$max = 0;
$min = 0;
$items = array();
foreach ($this->code as $namespace) {
if (!$namespace->isUserDefined()) {
continue;
}
$metrics = $this->analyzer->getStats($namespace);
if (count($metrics) === 0) {
continue;
}
$size = $metrics['cc'] + $metrics['ac'];
if ($size > $max) {
$max = $size;
} elseif ($min === 0 || $size < $min) {
$min = $size;
}
$items[] = array(
'size' => $size,
'abstraction' => $metrics['a'],
'instability' => $metrics['i'],
'distance' => $metrics['d'],
'name' => Utf8Util::ensureEncoding($namespace->getName())
);
}
$diff = (($max - $min) / 10);
// Sort items by size
usort(
$items,
function ($a, $b) {
return ($a['size'] - $b['size']);
}
);
foreach ($items as $item) {
if ($item['distance'] < $bias) {
$ellipse = $good->cloneNode(true);
} else {
$ellipse = $bad->cloneNode(true);
}
$r = 15;
if ($diff !== 0) {
$r = 5 + (($item['size'] - $min) / $diff);
}
$a = $r / 15;
$e = (50 - $r) + ($item['abstraction'] * 320);
$f = (20 - $r + 190) - ($item['instability'] * 190);
$transform = "matrix({$a}, 0, 0, {$a}, {$e}, {$f})";
$ellipse->setAttribute('id', uniqid('pdepend_'));
$ellipse->setAttribute('title', $item['name']);
$ellipse->setAttribute('transform', $transform);
$layer->appendChild($ellipse);
$result = preg_match('#\\\\([^\\\\]+)$#', $item['name'], $found);
if ($result && count($found)) {
$angle = rand(0, 314) / 100 - 1.57;
$legend = $legendTemplate->cloneNode(true);
$legend->setAttribute('x', $e + $r * (1 + cos($angle)));
$legend->setAttribute('y', $f + $r * (1 + sin($angle)));
$legend->nodeValue = $found[1];
$legendTemplate->parentNode->appendChild($legend);
}
}
$bad->parentNode->removeChild($bad);
$good->parentNode->removeChild($good);
$legendTemplate->parentNode->removeChild($legendTemplate);
$temp = FileUtil::getSysTempDir();
$temp .= '/' . uniqid('pdepend_') . '.svg';
$svg->save($temp);
ImageConvert::convert($temp, $this->logFile);
// Remove temp file
unlink($temp);
}
}

View File

@@ -0,0 +1,373 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report\Jdepend;
use PDepend\Metrics\Analyzer;
use PDepend\Metrics\Analyzer\DependencyAnalyzer;
use PDepend\Report\CodeAwareGenerator;
use PDepend\Report\FileAwareGenerator;
use PDepend\Report\NoLogOutputException;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTNamespace;
use PDepend\Source\ASTVisitor\AbstractASTVisitor;
use PDepend\Util\Utf8Util;
/**
* Generates an xml document with the aggregated metrics. The format is borrowed
* from <a href="http://clarkware.com/software/JDepend.html">JDepend</a>.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class Xml extends AbstractASTVisitor implements CodeAwareGenerator, FileAwareGenerator
{
/**
* The output log file.
*
* @var string
*/
private $logFile = null;
/**
* The raw {@link \PDepend\Source\AST\ASTNamespace} instances.
*
* @var \PDepend\Source\AST\ASTArtifactList
*/
protected $code = null;
/**
* Set of all analyzed files.
*
* @var \PDepend\Source\AST\ASTCompilationUnit[]
*/
protected $fileSet = array();
/**
* List of all generated project metrics.
*
* @var array(string=>mixed)
*/
protected $projectMetrics = array();
/**
* List of all collected node metrics.
*
* @var array(string=>array)
*/
protected $nodeMetrics = array();
/**
* The dependency result set.
*
* @var DependencyAnalyzer
*/
protected $analyzer = null;
/**
* The Packages dom element.
*
* @var \DOMElement
*/
protected $packages = null;
/**
* The Cycles dom element.
*
* @var \DOMElement
*/
protected $cycles = null;
/**
* The concrete classes element for the current package.
*
* @var \DOMElement
*/
protected $concreteClasses = null;
/**
* The abstract classes element for the current package.
*
* @var \DOMElement
*/
protected $abstractClasses = null;
/**
* Sets the output log file.
*
* @param string $logFile The output log file.
*
* @return void
*/
public function setLogFile($logFile)
{
$this->logFile = $logFile;
}
/**
* Returns an <b>array</b> with accepted analyzer types. These types can be
* concrete analyzer classes or one of the descriptive analyzer interfaces.
*
* @return array(string)
*/
public function getAcceptedAnalyzers()
{
return array('pdepend.analyzer.dependency');
}
/**
* Sets the context code nodes.
*
* @param \PDepend\Source\AST\ASTArtifactList $artifacts
* @return void
*/
public function setArtifacts(ASTArtifactList $artifacts)
{
$this->code = $artifacts;
}
/**
* Adds an analyzer to log. If this logger accepts the given analyzer it
* with return <b>true</b>, otherwise the return value is <b>false</b>.
*
* @param \PDepend\Metrics\Analyzer $analyzer The analyzer to log.
* @return boolean
*/
public function log(Analyzer $analyzer)
{
if ($analyzer instanceof DependencyAnalyzer) {
$this->analyzer = $analyzer;
return true;
}
return false;
}
/**
* Closes the logger process and writes the output file.
*
* @return void
* @throws \PDepend\Report\NoLogOutputException If the no log target exists.
*/
public function close()
{
// Check for configured output
if ($this->logFile === null) {
throw new NoLogOutputException($this);
}
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$jdepend = $dom->createElement('PDepend');
$this->packages = $jdepend->appendChild($dom->createElement('Packages'));
$this->cycles = $jdepend->appendChild($dom->createElement('Cycles'));
foreach ($this->code as $node) {
$node->accept($this);
}
$dom->appendChild($jdepend);
$buffer = $dom->saveXML();
file_put_contents($this->logFile, $buffer);
}
/**
* Visits a class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
if (!$class->isUserDefined()) {
return;
}
$doc = $this->packages->ownerDocument;
$classXml = $doc->createElement('Class');
$classXml->setAttribute('sourceFile', (string) $class->getCompilationUnit());
$classXml->appendChild(
$doc->createTextNode(
Utf8Util::ensureEncoding($class->getName())
)
);
if ($class->isAbstract()) {
$this->abstractClasses->appendChild($classXml);
} else {
$this->concreteClasses->appendChild($classXml);
}
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
if (!$interface->isUserDefined()) {
return;
}
$doc = $this->abstractClasses->ownerDocument;
$classXml = $doc->createElement('Class');
$classXml->setAttribute('sourceFile', (string) $interface->getCompilationUnit());
$classXml->appendChild(
$doc->createTextNode(
Utf8Util::ensureEncoding($interface->getName())
)
);
$this->abstractClasses->appendChild($classXml);
}
/**
* Visits a package node.
*
* @param \PDepend\Source\AST\ASTNamespace $namespace
* @return void
*/
public function visitNamespace(ASTNamespace $namespace)
{
if (!$namespace->isUserDefined()) {
return;
}
$stats = $this->analyzer->getStats($namespace);
if (count($stats) === 0) {
return;
}
$doc = $this->packages->ownerDocument;
$this->concreteClasses = $doc->createElement('ConcreteClasses');
$this->abstractClasses = $doc->createElement('AbstractClasses');
$packageXml = $doc->createElement('Package');
$packageXml->setAttribute('name', Utf8Util::ensureEncoding($namespace->getName()));
$statsXml = $doc->createElement('Stats');
$statsXml->appendChild($doc->createElement('TotalClasses'))
->appendChild($doc->createTextNode($stats['tc']));
$statsXml->appendChild($doc->createElement('ConcreteClasses'))
->appendChild($doc->createTextNode($stats['cc']));
$statsXml->appendChild($doc->createElement('AbstractClasses'))
->appendChild($doc->createTextNode($stats['ac']));
$statsXml->appendChild($doc->createElement('Ca'))
->appendChild($doc->createTextNode($stats['ca']));
$statsXml->appendChild($doc->createElement('Ce'))
->appendChild($doc->createTextNode($stats['ce']));
$statsXml->appendChild($doc->createElement('A'))
->appendChild($doc->createTextNode($stats['a']));
$statsXml->appendChild($doc->createElement('I'))
->appendChild($doc->createTextNode($stats['i']));
$statsXml->appendChild($doc->createElement('D'))
->appendChild($doc->createTextNode($stats['d']));
$dependsUpon = $doc->createElement('DependsUpon');
foreach ($this->analyzer->getEfferents($namespace) as $efferent) {
$efferentXml = $doc->createElement('Package');
$efferentXml->appendChild(
$doc->createTextNode(
Utf8Util::ensureEncoding($efferent->getName())
)
);
$dependsUpon->appendChild($efferentXml);
}
$usedBy = $doc->createElement('UsedBy');
foreach ($this->analyzer->getAfferents($namespace) as $afferent) {
$afferentXml = $doc->createElement('Package');
$afferentXml->appendChild(
$doc->createTextNode(
Utf8Util::ensureEncoding($afferent->getName())
)
);
$usedBy->appendChild($afferentXml);
}
$packageXml->appendChild($statsXml);
$packageXml->appendChild($this->concreteClasses);
$packageXml->appendChild($this->abstractClasses);
$packageXml->appendChild($dependsUpon);
$packageXml->appendChild($usedBy);
if (($cycles = $this->analyzer->getCycle($namespace)) !== null) {
$cycleXml = $doc->createElement('Package');
$cycleXml->setAttribute('Name', Utf8Util::ensureEncoding($namespace->getName()));
foreach ($cycles as $cycle) {
$cycleXml->appendChild($doc->createElement('Package'))
->appendChild(
$doc->createTextNode(
Utf8Util::ensureEncoding($cycle->getName())
)
);
}
$this->cycles->appendChild($cycleXml);
}
foreach ($namespace->getTypes() as $type) {
$type->accept($this);
}
if ($this->concreteClasses->firstChild === null
&& $this->abstractClasses->firstChild === null
) {
return;
}
$this->packages->appendChild($packageXml);
}
}

View File

@@ -0,0 +1,587 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="390"
height="250"
id="svg2924"
sodipodi:version="0.32"
inkscape:version="0.46"
version="1.0"
sodipodi:docname="chart.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs2926">
<linearGradient
id="Definition_LinearGradient_76_64_78_66_b3ff4400_619e2400">
<stop
offset="0"
style="stop-color: #b3ff44; stop-opacity: 1.00;"
id="stop24" />
<stop
offset="1"
style="stop-color: #619e24; stop-opacity: 1.00;"
id="stop26" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#Definition_LinearGradient_76_64_78_66_b3ff4400_619e2400"
id="linearGradient2905"
gradientUnits="userSpaceOnUse"
x1="76.3702"
y1="64.2934"
x2="78.8554"
y2="66.7786" />
<linearGradient
id="Definition_LinearGradient_318_84_320_87_ff9d0000_ac550000">
<stop
offset="0"
style="stop-color: #ff9d00; stop-opacity: 1.00;"
id="stop156" />
<stop
offset="1"
style="stop-color: #ac5500; stop-opacity: 1.00;"
id="stop158" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#Definition_LinearGradient_318_84_320_87_ff9d0000_ac550000"
id="jdepend.bad.gradient"
gradientUnits="userSpaceOnUse"
x1="0"
y1="15"
x2="15"
y2="30" />
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2932" />
<linearGradient
inkscape:collect="always"
xlink:href="#Definition_LinearGradient_76_64_78_66_b3ff4400_619e2400"
id="jdepend.good.gradient"
gradientUnits="userSpaceOnUse"
x1="0"
y1="15"
x2="15"
y2="30" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.5"
inkscape:cx="138.95468"
inkscape:cy="125"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1280"
inkscape:window-height="753"
inkscape:window-x="0"
inkscape:window-y="46" />
<metadata
id="metadata2929">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
xml:id="jdepend.layer">
<rect
style="opacity:1;fill:#4e9a06;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4614"
width="373.00024"
height="1.0000018"
x="53.196194"
y="-9.293786"
transform="matrix(0.8604851,0.5094756,-0.5094738,0.8604862,0,0)" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4464"
width="0.99999946"
height="201"
x="82"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4466"
width="0.99999946"
height="201"
x="113.99999"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4468"
width="0.99999946"
height="201"
x="146"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4470"
width="0.99999946"
height="201"
x="177.99998"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4472"
width="0.99999946"
height="201"
x="209.99998"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4474"
width="0.99999946"
height="201"
x="241.99998"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4476"
width="0.99999946"
height="201"
x="274"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4478"
width="0.99999946"
height="201"
x="305.99997"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4480"
width="0.99999946"
height="201"
x="337.99997"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4482"
width="0.99999946"
height="201"
x="369.99997"
y="19.000061"
rx="0"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4484"
width="331"
height="1"
x="40"
y="19.000025" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4486"
width="331"
height="1"
x="40"
y="57.000023" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4488"
width="331"
height="1"
x="40"
y="38.000023" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4490"
width="331"
height="1"
x="40"
y="76.000023" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4492"
width="331"
height="1"
x="40"
y="95.000023" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4494"
width="331"
height="1"
x="40"
y="133.00003" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4496"
width="331"
height="1"
x="40"
y="114.00002" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4498"
width="331"
height="1"
x="40"
y="152.00005" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4500"
width="331"
height="1"
x="40"
y="171.00005" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4502"
width="331"
height="1"
x="40"
y="190.00006" />
<rect
style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4504"
width="331"
height="1"
x="40"
y="209.00006" />
<rect
style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4462"
width="0.99999946"
height="201"
x="49.999996"
y="19.000061"
rx="0"
ry="0" />
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="83.181007"
y="231.87305"
id="text4506"><tspan
sodipodi:role="line"
id="tspan4508"
x="83.181007"
y="231.87305">0.1</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="114.70088"
y="231.87305"
id="text4510"><tspan
sodipodi:role="line"
id="tspan4512"
x="114.70088"
y="231.87305">0.2</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="242.95323"
y="231.87305"
id="text4514"><tspan
sodipodi:role="line"
id="tspan4516"
x="242.95323"
y="231.87305">0.6</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="210.84497"
y="231.87305"
id="text4518"><tspan
sodipodi:role="line"
id="tspan4520"
x="210.84497"
y="231.87305">0.5</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="178.72696"
y="231.87305"
id="text4522"><tspan
sodipodi:role="line"
id="tspan4524"
x="178.72696"
y="231.87305">0.4</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="146.74567"
y="231.87305"
id="text4526"><tspan
sodipodi:role="line"
id="tspan4528"
x="146.74567"
y="231.87305">0.3</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="307.16241"
y="231.87305"
id="text4530"><tspan
sodipodi:role="line"
id="tspan4532"
x="307.16241"
y="231.87305">0.8</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="275.07858"
y="231.87305"
id="text4534"><tspan
sodipodi:role="line"
id="tspan4536"
x="275.07858"
y="231.87305">0.7</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="371.16162"
y="231.87305"
id="text4538"><tspan
sodipodi:role="line"
id="tspan4540"
x="371.16162"
y="231.87305">1.0</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="339.25113"
y="231.87305"
id="text4542"><tspan
sodipodi:role="line"
id="tspan4544"
x="339.25113"
y="231.87305">0.9</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="50.533203"
y="231.87305"
id="text4546"><tspan
sodipodi:role="line"
id="tspan4548"
x="50.533203"
y="231.87305">0.0</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.533201"
y="193.87793"
id="text4550"><tspan
sodipodi:role="line"
id="tspan4552"
x="28.533201"
y="193.87793">0.1</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.533201"
y="174.87793"
id="text4554"><tspan
sodipodi:role="line"
id="tspan4556"
x="28.533201"
y="174.87793">0.2</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.533201"
y="98.87793"
id="text4558"><tspan
sodipodi:role="line"
id="tspan4560"
x="28.533201"
y="98.87793">0.6</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.533201"
y="117.87792"
id="text4562"><tspan
sodipodi:role="line"
id="tspan4564"
x="28.533201"
y="117.87792">0.5</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.533201"
y="136.87793"
id="text4566"><tspan
sodipodi:role="line"
id="tspan4568"
x="28.533201"
y="136.87793">0.4</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.533201"
y="155.87793"
id="text4570"><tspan
sodipodi:role="line"
id="tspan4572"
x="28.533201"
y="155.87793">0.3</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.533201"
y="60.875481"
id="text4574"><tspan
sodipodi:role="line"
id="tspan4576"
x="28.533201"
y="60.875481">0.8</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.533201"
y="79.87793"
id="text4578"><tspan
sodipodi:role="line"
id="tspan4580"
x="28.533201"
y="79.87793">0.7</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.162107"
y="22.87793"
id="text4582"><tspan
sodipodi:role="line"
id="tspan4584"
x="28.162107"
y="22.87793">1.0</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.533201"
y="41.875492"
id="text4586"><tspan
sodipodi:role="line"
id="tspan4588"
x="28.533201"
y="41.875492">0.9</tspan></text>
<text
xml:space="preserve"
style="font-size:10px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="28.939205"
y="212.87793"
id="text4590"><tspan
sodipodi:role="line"
id="tspan4592"
x="28.939205"
y="212.87793">0.0</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="195.05258"
y="247.85966"
id="text4604"
transform="scale(1.0000012,0.9999988)"><tspan
sodipodi:role="line"
id="tspan4606"
x="195.05258"
y="247.85966">Abstraction</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;"
x="-126.09961"
y="10.589844"
id="text4608"
transform="matrix(0,-1,1,0,0,0)"><tspan
sodipodi:role="line"
id="tspan4610"
x="-126.09961"
y="10.589844">Instability</tspan></text>
<text
xml:space="preserve"
style="font-size:9px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Chancery L"
x="313.30417"
y="246.10596"
id="text2692"><tspan
sodipodi:role="line"
id="tspan2694"
x="313.30417"
y="246.10596"
style="font-size:9px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#2e3436;font-family:Arial; Italic">Generated by PDepend</tspan></text>
<ellipse
sodipodi:ry="15"
sodipodi:rx="15"
sodipodi:cy="15"
sodipodi:cx="15"
id="jdepend.bad"
xml:id="jdepend.bad"
style="fill:url(#jdepend.bad.gradient);stroke:none"
ry="15"
rx="15"
cy="15"
cx="15"
transform="translate(163,4)" />
<ellipse
sodipodi:ry="15"
sodipodi:rx="15"
sodipodi:cy="15"
sodipodi:cx="15"
id="jdepend.good"
xml:id="jdepend.good"
style="fill:url(#jdepend.good.gradient);stroke:none"
ry="15"
rx="15"
cy="15"
cx="15"
transform="matrix(0.6,0,0,0.6,41,10)" />
</g>
<g>
<text
xml:space="preserve"
style="font-size:4px;font-family:Arial;fill:#2e3436;"
x="195.05258"
y="120.85966"
xml:id="jdepend.legend">Package</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,66 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report;
/**
* This type of exception is thrown, if a required log target/log file wasn't
* configured for the current logger instance.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class NoLogOutputException extends \LogicException
{
/**
* Creates a new log target exception for the given log instance.
*
* @param \PDepend\Report\ReportGenerator $logger
*/
public function __construct(ReportGenerator $logger)
{
$className = get_class($logger);
$message = "The log target is not configured for '{$className}'.";
parent::__construct($message);
}
}

View File

@@ -0,0 +1,333 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report\Overview;
use PDepend\Metrics\Analyzer;
use PDepend\Metrics\Analyzer\CouplingAnalyzer;
use PDepend\Metrics\Analyzer\CyclomaticComplexityAnalyzer;
use PDepend\Metrics\Analyzer\InheritanceAnalyzer;
use PDepend\Metrics\Analyzer\NodeCountAnalyzer;
use PDepend\Metrics\Analyzer\NodeLocAnalyzer;
use PDepend\Report\FileAwareGenerator;
use PDepend\Report\NoLogOutputException;
use PDepend\Util\FileUtil;
use PDepend\Util\ImageConvert;
/**
* This logger generates a system overview pyramid, as described in the book
* <b>Object-Oriented Metrics in Practice</b>.
*
* http://www.springer.com/computer/programming/book/978-3-540-24429-5
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class Pyramid implements FileAwareGenerator
{
/**
* The output file name.
*
* @var string
*/
private $logFile = null;
/**
* The used coupling analyzer.
*
* @var \PDepend\Metrics\Analyzer\CouplingAnalyzer
*/
private $coupling = null;
/**
* The used cyclomatic complexity analyzer.
*
* @var \PDepend\Metrics\Analyzer\CyclomaticComplexityAnalyzer
*/
private $cyclomaticComplexity = null;
/**
* The used inheritance analyzer.
*
* @var \PDepend\Metrics\Analyzer\InheritanceAnalyzer
*/
private $inheritance = null;
/**
* The used node count analyzer.
*
* @var \PDepend\Metrics\Analyzer\NodeCountAnalyzer
*/
private $nodeCount = null;
/**
* The used node loc analyzer.
*
* @var \PDepend\Metrics\Analyzer\NodeLocAnalyzer
*/
private $nodeLoc = null;
/**
* Holds defined thresholds for the computed proportions. This set is based
* on java thresholds, we should find better values for php projects.
*
* @var array(string => array)
*/
private $thresholds = array(
'cyclo-loc' => array(0.16, 0.20, 0.24),
'loc-nom' => array(7, 10, 13),
'nom-noc' => array(4, 7, 10),
'noc-nop' => array(6, 17, 26),
'calls-nom' => array(2.01, 2.62, 3.2),
'fanout-calls' => array(0.56, 0.62, 0.68),
'andc' => array(0.25, 0.41, 0.57),
'ahh' => array(0.09, 0.21, 0.32)
);
/**
* Sets the output log file.
*
* @param string $logFile The output log file.
*
* @return void
*/
public function setLogFile($logFile)
{
$this->logFile = $logFile;
}
/**
* Returns an <b>array</b> with accepted analyzer types. These types can be
* concrete analyzer classes or one of the descriptive analyzer interfaces.
*
* @return array(string)
*/
public function getAcceptedAnalyzers()
{
return array(
'pdepend.analyzer.coupling',
'pdepend.analyzer.cyclomatic_complexity',
'pdepend.analyzer.inheritance',
'pdepend.analyzer.node_count',
'pdepend.analyzer.node_loc',
);
}
/**
* Adds an analyzer to log. If this logger accepts the given analyzer it
* with return <b>true</b>, otherwise the return value is <b>false</b>.
*
* @param \PDepend\Metrics\Analyzer $analyzer The analyzer to log.
* @return boolean
*/
public function log(Analyzer $analyzer)
{
if ($analyzer instanceof CyclomaticComplexityAnalyzer) {
$this->cyclomaticComplexity = $analyzer;
} elseif ($analyzer instanceof CouplingAnalyzer) {
$this->coupling = $analyzer;
} elseif ($analyzer instanceof InheritanceAnalyzer) {
$this->inheritance = $analyzer;
} elseif ($analyzer instanceof NodeCountAnalyzer) {
$this->nodeCount = $analyzer;
} elseif ($analyzer instanceof NodeLocAnalyzer) {
$this->nodeLoc = $analyzer;
} else {
return false;
}
return true;
}
/**
* Closes the logger process and writes the output file.
*
* @return void
* @throws \PDepend\Report\NoLogOutputException
*/
public function close()
{
// Check for configured log file
if ($this->logFile === null) {
throw new NoLogOutputException($this);
}
$metrics = $this->collectMetrics();
$proportions = $this->computeProportions($metrics);
$svg = new \DOMDocument('1.0', 'UTF-8');
$svg->loadXML(file_get_contents(dirname(__FILE__) . '/pyramid.svg'));
$items = array_merge($metrics, $proportions);
foreach ($items as $name => $value) {
$svg->getElementById("pdepend.{$name}")->nodeValue = $value;
if (($threshold = $this->computeThreshold($name, $value)) === null) {
continue;
}
if (($color = $svg->getElementById("threshold.{$threshold}")) === null) {
continue;
}
if (($rect = $svg->getElementById("rect.{$name}")) === null) {
continue;
}
preg_match('/fill:(#[^;"]+)/', $color->getAttribute('style'), $match);
$style = $rect->getAttribute('style');
$style = preg_replace('/fill:#[^;"]+/', "fill:{$match[1]}", $style);
$rect->setAttribute('style', $style);
}
$temp = FileUtil::getSysTempDir();
$temp .= '/' . uniqid('pdepend_') . '.svg';
$svg->save($temp);
ImageConvert::convert($temp, $this->logFile);
// Remove temp file
unlink($temp);
}
/**
* Computes the threshold (low, average, high) for the given value and metric.
* If no threshold is defined for the given name, this method will return
* <b>null</b>.
*
* @param string $name The metric/field identfier.
* @param mixed $value The metric/field value.
* @return string
*/
private function computeThreshold($name, $value)
{
if (!isset($this->thresholds[$name])) {
return null;
}
$threshold = $this->thresholds[$name];
if ($value <= $threshold[0]) {
return 'low';
} elseif ($value >= $threshold[2]) {
return 'high';
} else {
$low = $value - $threshold[0];
$avg = $threshold[1] - $value;
if ($low < $avg) {
return 'low';
}
}
return 'average';
}
/**
* Computes the proportions between the given metrics.
*
* @param array $metrics The aggregated project metrics.
* @return array(string => float)
*/
private function computeProportions(array $metrics)
{
$orders = array(
array('cyclo', 'loc', 'nom', 'noc', 'nop'),
array('fanout', 'calls', 'nom')
);
$proportions = array();
foreach ($orders as $names) {
for ($i = 1, $c = count($names); $i < $c; ++$i) {
$value1 = $metrics[$names[$i]];
$value2 = $metrics[$names[$i - 1]];
$identifier = "{$names[$i - 1]}-{$names[$i]}";
$proportions[$identifier] = 0;
if ($value1 > 0) {
$proportions[$identifier] = round($value2 / $value1, 3);
}
}
}
return $proportions;
}
/**
* Aggregates the required metrics from the registered analyzers.
*
* @return array(string => mixed)
* @throws \RuntimeException If one of the required analyzers isn't set.
*/
private function collectMetrics()
{
if ($this->coupling === null) {
throw new \RuntimeException('Missing Coupling analyzer.');
}
if ($this->cyclomaticComplexity === null) {
throw new \RuntimeException('Missing Cyclomatic Complexity analyzer.');
}
if ($this->inheritance === null) {
throw new \RuntimeException('Missing Inheritance analyzer.');
}
if ($this->nodeCount === null) {
throw new \RuntimeException('Missing Node Count analyzer.');
}
if ($this->nodeLoc === null) {
throw new \RuntimeException('Missing Node LOC analyzer.');
}
$coupling = $this->coupling->getProjectMetrics();
$cyclomatic = $this->cyclomaticComplexity->getProjectMetrics();
$inheritance = $this->inheritance->getProjectMetrics();
$nodeCount = $this->nodeCount->getProjectMetrics();
$nodeLoc = $this->nodeLoc->getProjectMetrics();
return array(
'cyclo' => $cyclomatic['ccn2'],
'loc' => $nodeLoc['eloc'],
'nom' => ($nodeCount['nom'] + $nodeCount['nof']),
'noc' => $nodeCount['noc'],
'nop' => $nodeCount['nop'],
'ahh' => round($inheritance['ahh'], 3),
'andc' => round($inheritance['andc'], 3),
'fanout' => $coupling['fanout'],
'calls' => $coupling['calls']
);
}
}

View File

@@ -0,0 +1,769 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="390"
height="250"
id="svg5110"
sodipodi:version="0.32"
inkscape:version="0.46"
version="1.0"
sodipodi:docname="pyramid.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs5112">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective5118" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.5"
inkscape:cx="179.96345"
inkscape:cy="96.137457"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1280"
inkscape:window-height="753"
inkscape:window-x="0"
inkscape:window-y="46" />
<metadata
id="metadata5115">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#555753"
width="0"
height="0"
x="0"
y="0"
rx="0"
ry="0"
id="rect8982"
xml:id="threshold.low" />
<rect
style="fill:#73d216"
width="0"
height="0"
x="0"
y="0"
rx="0"
ry="0"
id="rect8983"
xml:id="threshold.average" />
<rect
style="fill:#f57900"
width="0"
height="0"
x="0"
y="0"
rx="0"
ry="0"
id="rect2834"
xml:id="threshold.high" />
<rect
style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4954"
width="118.69567"
height="16.956522"
x="232.7668"
y="185.67191"
rx="2.9780269"
ry="0" />
<rect
style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4956"
width="157.2332"
height="34"
x="232.7668"
y="201"
rx="3.9449191"
ry="0" />
<rect
style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4958"
width="80.158104"
height="33.913044"
x="154.15019"
y="122.47035"
rx="2.0111351"
ry="0" />
<rect
style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4960"
width="234.30832"
height="34"
x="0"
y="201"
rx="5.8787031"
ry="0" />
<rect
style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4962"
width="195.77077"
height="16.956522"
x="38.537552"
y="185.67191"
rx="4.9118109"
ry="0" />
<rect
style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4964"
width="157.2332"
height="16.956522"
x="77.075104"
y="170.25687"
rx="3.9449191"
ry="0" />
<rect
style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4966"
width="118.69567"
height="16.956522"
x="115.61267"
y="154.84189"
rx="2.9780269"
ry="0" />
<rect
style="opacity:1;fill:#d3d7cf;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4968"
width="231.22531"
height="30.83004"
x="1.541504"
y="202.62846"
rx="5.8013515"
ry="0" />
<rect
style="opacity:1;fill:#d3d7cf;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4970"
width="192.68774"
height="15.41502"
x="40.079056"
y="187.21365"
rx="4.8344593"
ry="0" />
<rect
style="opacity:1;fill:#d3d7cf;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4972"
width="154.15019"
height="15.41502"
x="78.616608"
y="171.79837"
rx="3.8675678"
ry="0" />
<rect
style="opacity:1;fill:#d3d7cf;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4974"
width="115.61266"
height="15.41502"
x="117.15414"
y="156.38339"
rx="2.9006755"
ry="0" />
<rect
style="opacity:1;fill:#fcaf3e;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4976"
width="77.075096"
height="30.83004"
x="155.6917"
y="124.01187"
rx="1.9337839"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4978"
width="154.15019"
height="30.83004"
x="234.3083"
y="202.62846"
rx="3.8675678"
ry="0" />
<rect
style="opacity:1;fill:#babdb6;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4980"
width="115.61266"
height="15.41502"
x="234.3083"
y="187.21341"
rx="2.9006755"
ry="0" />
<rect
style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4982"
xml:id="rect.andc"
width="38.537548"
height="15.43004"
x="194.22925"
y="124.01187"
rx="0.96689194"
ry="0" />
<rect
style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect2851"
xml:id="rect.ahh"
width="38.537548"
height="15.4"
x="194.22925"
y="139.41187"
rx="0.96689194"
ry="0" />
<rect
style="opacity:1;fill:#f57900;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4984"
xml:id="rect.noc-nop"
width="38.537548"
height="15.41502"
x="117.15414"
y="156.38339"
rx="0.80574334" />
<rect
style="opacity:1;fill:#f57900;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4986"
xml:id="rect.nom-noc"
width="38.537548"
height="15.41502"
x="78.616608"
y="171.79837"
rx="0.80574334" />
<rect
style="opacity:1;fill:#73d216;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4988"
xml:id="rect.loc-nom"
width="38.537548"
height="15.41502"
x="40.079056"
y="187.21341"
rx="0.80574334" />
<rect
style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4990"
xml:id="rect.cyclo-loc"
width="38.537548"
height="15.41502"
x="1.541504"
y="202.62846"
rx="0.80574334" />
<rect
style="opacity:1;fill:#f57900;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4992"
xml:id="rect.calls-nom"
width="38.537548"
height="15.41502"
x="311.38339"
y="187.21341"
rx="0.80574334" />
<rect
style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4994"
xml:id="rect.fanout-calls"
width="38.537548"
height="15.41502"
x="349.92096"
y="202.62846"
rx="0.80574334" />
<rect
style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4996"
width="231.22531"
height="1"
x="1.541504"
y="217.04344"
rx="5.8013515"
ry="0" />
<rect
style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4998"
width="192.68774"
height="1"
x="40.079056"
y="201.62846"
rx="4.8344593"
ry="0" />
<rect
style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5000"
width="154.15019"
height="1"
x="78.616608"
y="186.21341"
rx="3.8675678"
ry="0" />
<rect
style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5002"
width="115.61266"
height="1"
x="117.15414"
y="170.79837"
rx="2.9006755"
ry="0" />
<rect
style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5004"
width="115.61266"
height="1"
x="234.3083"
y="201.62846"
rx="2.9006755"
ry="0" />
<rect
style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5006"
width="154.15019"
height="1"
x="234.3083"
y="217.04344"
rx="3.8675678"
ry="0" />
<rect
style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect5008"
width="77.075096"
height="1"
x="155.6917"
y="138.42685"
rx="1.9337839"
ry="0" />
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="158"
y="135"
title="Average Number of Derived Classes"
id="text5010"><tspan
sodipodi:role="line"
title="Average Number of Derived Classes"
id="tspan5012"
x="158"
y="135">ANDC</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="158"
y="151"
title="Average Hierarchy Height"
id="text5014"><tspan
sodipodi:role="line"
title="Average Hierarchy Height"
id="tspan5016"
x="158"
y="151">AHH</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="158"
y="168"
title="Number Of Packages"
id="text5018"><tspan
sodipodi:role="line"
title="Number Of Packages"
id="tspan5020"
x="158"
y="168">NOP</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="119"
y="183.00002"
id="text5022"
title="Number Of Classes"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number Of Classes"
id="tspan5024"
x="119"
y="183.00002">NOC</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="81"
y="198.00002"
id="text5026"
title="Number Of Methods (Methods+Functions)"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number Of Methods (Methods+Functions)"
id="tspan5028"
x="81"
y="198.00002">NOM</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="42"
y="213.00002"
id="text5030"
title="Lines Of Code (Non Comment and Non Whitespace Lines)"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Lines Of Code (Non Comment and Non Whitespace Lines)"
id="tspan5032"
x="42"
y="213.00002">LOC</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="3"
y="230.00002"
id="text5034"
title="Cyclomatic Complexity"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Cyclomatic Complexity"
id="tspan5036"
x="3"
y="230.00002">CYCLO</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:end;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="308.85785"
y="198.00043"
id="text5038"
title="Number Of Methods (Methods+Functions)"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number Of Methods (Methods+Functions)"
id="tspan5040"
x="308.85785"
y="198.00043">NOM</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="348"
y="213.00002"
id="text5042"
title="Number of Operation Calls"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number of Operation Calls"
id="tspan5044"
x="348"
y="213.00002">CALLS</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="387"
y="230.00002"
id="text5046"
title="Number of Called Classes"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number of Called Classes"
id="tspan5048"
x="387"
y="230.00002">FANOUT</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Number of Called Classes"
x="236"
y="230.00002"
id="text5050"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number of Called Classes"
id="tspan5052"
xml:id="pdepend.fanout"
x="236"
y="230.00002">8590</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Number of Operation Calls"
x="236"
y="213.00002"
id="text5054"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number of Operation Calls"
id="tspan5056"
xml:id="pdepend.calls"
x="236"
y="213.00002">15128</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Cyclomatic Complexity"
x="232"
y="230.00002"
id="text5058"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Cyclomatic Complexity"
id="tspan5060"
xml:id="pdepend.cyclo"
x="232"
y="230.00002">5579</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Lines Of Code (Non Comment and Non Whitespace Lines)"
x="232"
y="213.00002"
id="text5062"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
xml:id="pdepend.loc"
title="Lines Of Code (Non Comment and Non Whitespace Lines)"
id="tspan5064"
x="232"
y="213.00002">35175</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Number Of Methods (Methods+Functions)"
x="232"
y="198.00002"
id="text5066"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number Of Methods (Methods+Functions)"
id="tspan5068"
xml:id="pdepend.nom"
x="232"
y="198.00002">3618</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Number Of Packages"
x="232"
y="168.00002"
id="text5070"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number Of Packages"
id="tspan5072"
xml:id="pdepend.nop"
x="232"
y="168.00002">19</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Number Of Classes"
x="232"
y="183.00002"
id="text5074"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Number Of Classes"
id="tspan5076"
xml:id="pdepend.noc"
x="232"
y="183.00002">384</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Average Number of Derived Classes"
x="232"
y="135.00002"
id="text5078"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Average Number of Derived Classes"
id="tspan5080"
xml:id="pdepend.andc"
x="232"
y="135.00002">0,31</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Average Hierarchy Height"
x="232"
y="151.00002"
id="text5082"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Average Hierarchy Height"
id="tspan5084"
xml:id="pdepend.ahh"
x="232"
y="151.00002">0,12</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Ratio: Number of Classes / Number of Packages"
x="119"
y="168.00002"
id="text5086"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Ratio: Number of Classes / Number of Packages"
id="tspan5088"
xml:id="pdepend.noc-nop"
x="119"
y="168.00002">20,21</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Ratio: Number of Methods / Number of Classes"
x="81"
y="183.00002"
id="text5090"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Ratio: Number of Methods / Number of Classes"
id="tspan5092"
xml:id="pdepend.nom-noc"
x="81"
y="183.00002">9,42</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Ratio: Lines of Code / Number of Methods"
x="42"
y="198.00002"
id="text5094"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Ratio: Lines of Code / Number of Methods"
id="tspan5096"
xml:id="pdepend.loc-nom"
x="42"
y="198.00002">9,72</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Ratio: Cyclomatic Complexity / Lines of Code"
x="3"
y="213.00002"
id="text5098"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Ratio: Cyclomatic Complexity / Lines of Code"
id="tspan5100"
xml:id="pdepend.cyclo-loc"
x="3"
y="213.00002">0,15</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Ratio: Number of Called Classes(FANOUT) / Number of Operation Calls"
x="388.56299"
y="213.00002"
id="text5102"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Ratio: Number of Called Classes(FANOUT) / Number of Operation Calls"
id="tspan5104"
xml:id="pdepend.fanout-calls"
x="388.56299"
y="213.00002">0,561</tspan></text>
<text
xml:space="preserve"
style="font-size:11px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-anchor:end;fill:#eeeeec;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
title="Ratio: Number of Operation Calls / Number of Methods (Methods+Functions)"
x="348"
y="198.00002"
id="text5106"
transform="scale(0.9999985,1.0000015)"><tspan
sodipodi:role="line"
title="Ratio: Number of Operation Calls / Number of Methods (Methods+Functions)"
id="tspan5108"
xml:id="pdepend.calls-nom"
x="348"
y="198.00002">4,18</tspan></text>
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:end;text-anchor:end;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
x="386.39493"
y="246.10596"
id="text2692"><tspan
sodipodi:role="line"
id="tspan2694"
x="386.39493"
y="246.10596"
style="font-size:9px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;text-anchor:end;fill:#2e3436;font-family:Arial;">Generated by PDepend</tspan></text>
<path
sodipodi:type="arc"
style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3780"
sodipodi:cx="53.333332"
sodipodi:cy="285.66666"
sodipodi:rx="12"
sodipodi:ry="10.333333"
d="M 65.333332,285.66666 A 12,10.333333 0 1 1 41.333332,285.66666 A 12,10.333333 0 1 1 65.333332,285.66666 z"
transform="matrix(0.375,0,0,0.4354839,-5.4999995,119.09677)" />
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:bold;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Chancery L;"
x="32.386719"
y="246.64209"
id="text3782"><tspan
sodipodi:role="line"
id="tspan3784"
x="32.386719"
y="246.64209"
style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#2e3436;font-family:Arial;">Low</tspan></text>
<path
sodipodi:type="arc"
style="opacity:1;fill:#73d216;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3786"
sodipodi:cx="53.333332"
sodipodi:cy="285.66666"
sodipodi:rx="12"
sodipodi:ry="10.333333"
d="M 65.333332,285.66666 A 12,10.333333 0 1 1 41.333332,285.66666 A 12,10.333333 0 1 1 65.333332,285.66666 z"
transform="matrix(0.375,0,0,0.4354839,54.5,119.09677)" />
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:bold;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Chancery L;"
x="102.38672"
y="245.77417"
id="text3788"><tspan
sodipodi:role="line"
id="tspan3790"
x="102.38672"
y="245.77417"
style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#2e3436;font-family:Arial;">Average</tspan></text>
<path
sodipodi:type="arc"
style="opacity:1;fill:#f57900;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3792"
sodipodi:cx="53.333332"
sodipodi:cy="285.66666"
sodipodi:rx="12"
sodipodi:ry="10.333333"
d="M 65.333332,285.66666 A 12,10.333333 0 1 1 41.333332,285.66666 A 12,10.333333 0 1 1 65.333332,285.66666 z"
transform="matrix(0.375,0,0,0.4354839,132.5,119.09677)" />
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:bold;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:URW Chancery L;"
x="170.38672"
y="245.77417"
id="text3794"><tspan
sodipodi:role="line"
id="tspan3796"
x="170.38672"
y="245.77417"
style="font-size:9px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#2e3436;font-family:Arial;">High</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1,79 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report;
use PDepend\Metrics\Analyzer;
/**
* Base interface for all PDepend report generators.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface ReportGenerator
{
/**
* Adds an analyzer to log. If this logger accepts the given analyzer it
* with return <b>true</b>, otherwise the return value is <b>false</b>.
*
* @param \PDepend\Metrics\Analyzer $analyzer The analyzer to log.
* @return boolean
*/
public function log(Analyzer $analyzer);
/**
* Closes the logger process and writes the output file.
*
* @return void
* @throws \PDepend\Report\NoLogOutputException If the no log target exists.
*/
public function close();
/**
* Returns an <b>array</b> with accepted analyzer types. These types can be
* concrete analyzer classes or one of the descriptive analyzer interfaces.
*
* @return array(string)
*/
public function getAcceptedAnalyzers();
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* This factory creates singleton instances of available loggers.
*
* The identifiers are used to find a matching service in the DIC
* that is tagged with 'pdepend.logger' and has an option attribute
* named after the identifier, prefixed with --:
*
* Identifier "my-custom-logger" searchs for:
*
* <tag name="pdepend.logger" option="--my-custom-logger" />
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ReportGeneratorFactory
{
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* Creates a new generator or returns an existing instance for the given
* <b>$identifier</b>.
*
* @param string $identifier The generator identifier.
* @param string $fileName The log output file name.
* @return \PDepend\Report\ReportGenerator
* @throws \RuntimeException
*/
public function createGenerator($identifier, $fileName)
{
if (!isset($this->instances[$identifier])) {
$loggerServices = $this->container->findTaggedServiceIds('pdepend.logger');
$logger = null;
foreach ($loggerServices as $id => $loggerServiceTags) {
foreach ($loggerServiceTags as $loggerServiceTag) {
if ($loggerServiceTag['option'] === '--' . $identifier) {
$logger = $this->container->get($id);
}
}
}
if (!$logger) {
throw new \RuntimeException(sprintf('Unknown generator with identifier "%s".', $identifier));
}
// TODO: Refactor this into an external log configurator or a similar
// concept.
if ($logger instanceof FileAwareGenerator) {
$logger->setLogFile($fileName);
}
$this->instances[$identifier] = $logger;
}
return $this->instances[$identifier];
}
/**
* Set of created logger instances.
*
* @var \PDepend\Report\ReportGenerator[]
*/
protected $instances = array();
}

View File

@@ -0,0 +1,449 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Report\Summary;
use PDepend\Metrics\Analyzer;
use PDepend\Metrics\AnalyzerNodeAware;
use PDepend\Metrics\AnalyzerProjectAware;
use PDepend\Report\CodeAwareGenerator;
use PDepend\Report\FileAwareGenerator;
use PDepend\Report\NoLogOutputException;
use PDepend\Source\AST\AbstractASTArtifact;
use PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTClass;
use PDepend\Source\AST\ASTCompilationUnit;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTInterface;
use PDepend\Source\AST\ASTMethod;
use PDepend\Source\AST\ASTNamespace;
use PDepend\Source\AST\ASTTrait;
use PDepend\Source\ASTVisitor\AbstractASTVisitor;
use PDepend\Util\Utf8Util;
/**
* This logger generates a summary xml document with aggregated project, class,
* method and file metrics.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class Xml extends AbstractASTVisitor implements CodeAwareGenerator, FileAwareGenerator
{
/**
* The log output file.
*
* @var string
*/
private $logFile = null;
/**
* The raw {@link \PDepend\Source\AST\ASTNamespace} instances.
*
* @var \PDepend\Source\AST\ASTArtifactList
*/
protected $code = null;
/**
* Set of all analyzed files.
*
* @var \PDepend\Source\AST\ASTCompilationUnit[]
*/
protected $fileSet = array();
/**
* List of all analyzers that implement the node aware interface
* {@link \PDepend\Metrics\AnalyzerNodeAware}.
*
* @var \PDepend\Metrics\AnalyzerNodeAware[]
*/
private $nodeAwareAnalyzers = array();
/**
* List of all analyzers that implement the node aware interface
* {@link \PDepend\Metrics\AnalyzerProjectAware}.
*
* @var \PDepend\Metrics\AnalyzerProjectAware[]
*/
private $projectAwareAnalyzers = array();
/**
* The internal used xml stack.
*
* @var DOMElement[]
*/
private $xmlStack = array();
/**
* Sets the output log file.
*
* @param string $logFile The output log file.
*
* @return void
*/
public function setLogFile($logFile)
{
$this->logFile = $logFile;
}
/**
* Returns an <b>array</b> with accepted analyzer types. These types can be
* concrete analyzer classes or one of the descriptive analyzer interfaces.
*
* @return array(string)
*/
public function getAcceptedAnalyzers()
{
return array(
'pdepend.analyzer.cyclomatic_complexity',
'pdepend.analyzer.node_loc',
'pdepend.analyzer.npath_complexity',
'pdepend.analyzer.inheritance',
'pdepend.analyzer.node_count',
'pdepend.analyzer.hierarchy',
'pdepend.analyzer.crap_index',
'pdepend.analyzer.code_rank',
'pdepend.analyzer.coupling',
'pdepend.analyzer.class_level',
'pdepend.analyzer.cohesion',
'pdepend.analyzer.halstead',
'pdepend.analyzer.maintainability',
);
}
/**
* Sets the context code nodes.
*
* @param \PDepend\Source\AST\ASTArtifactList $artifacts
* @return void
*/
public function setArtifacts(ASTArtifactList $artifacts)
{
$this->code = $artifacts;
}
/**
* Adds an analyzer to log. If this logger accepts the given analyzer it
* with return <b>true</b>, otherwise the return value is <b>false</b>.
*
* @param \PDepend\Metrics\Analyzer $analyzer The analyzer to log.
* @return boolean
*/
public function log(Analyzer $analyzer)
{
$accepted = false;
if ($analyzer instanceof AnalyzerProjectAware) {
$this->projectAwareAnalyzers[] = $analyzer;
$accepted = true;
}
if ($analyzer instanceof AnalyzerNodeAware) {
$this->nodeAwareAnalyzers[] = $analyzer;
$accepted = true;
}
return $accepted;
}
/**
* Closes the logger process and writes the output file.
*
* @return void
* @throws \PDepend\Report\NoLogOutputException If the no log target exists.
*/
public function close()
{
if ($this->logFile === null) {
throw new NoLogOutputException($this);
}
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->formatOutput = true;
$metrics = $dom->createElement('metrics');
$metrics->setAttribute('generated', date('Y-m-d\TH:i:s'));
$metrics->setAttribute('pdepend', '@package_version@');
foreach ($this->getProjectMetrics() as $name => $value) {
$metrics->setAttribute($name, $value);
}
array_push($this->xmlStack, $metrics);
foreach ($this->code as $node) {
$node->accept($this);
}
if (count($this->fileSet) > 0) {
$filesXml = $dom->createElement('files');
foreach ($this->fileSet as $file) {
$fileXml = $dom->createElement('file');
$fileXml->setAttribute('name', Utf8Util::ensureEncoding($file->getFileName()));
$this->writeNodeMetrics($fileXml, $file);
$filesXml->appendChild($fileXml);
}
$metrics->insertBefore($filesXml, $metrics->firstChild);
}
$dom->appendChild($metrics);
$buffer = $dom->saveXML();
file_put_contents($this->logFile, $buffer);
}
/**
* Returns an array with all collected project metrics.
*
* @return array(string=>mixed)
* @since 0.9.10
*/
private function getProjectMetrics()
{
$projectMetrics = array();
foreach ($this->projectAwareAnalyzers as $analyzer) {
$projectMetrics = array_merge(
$projectMetrics,
$analyzer->getProjectMetrics()
);
}
ksort($projectMetrics);
return $projectMetrics;
}
/**
* Visits a class node.
*
* @param \PDepend\Source\AST\ASTClass $class
* @return void
*/
public function visitClass(ASTClass $class)
{
$this->generateTypeXml($class, 'class');
}
/**
* Visits a trait node.
*
* @param \PDepend\Source\AST\ASTTrait $trait
* @return void
*/
public function visitTrait(ASTTrait $trait)
{
$this->generateTypeXml($trait, 'trait');
}
/**
* Generates the XML for a class or trait node.
*
* @param \PDepend\Source\AST\ASTClass $type
* @param string $typeIdentifier
* @return void
*/
private function generateTypeXml(ASTClass $type, $typeIdentifier)
{
if (!$type->isUserDefined()) {
return;
}
$xml = end($this->xmlStack);
$doc = $xml->ownerDocument;
$typeXml = $doc->createElement($typeIdentifier);
$typeXml->setAttribute('name', Utf8Util::ensureEncoding($type->getName()));
$typeXml->setAttribute('fqname', Utf8Util::ensureEncoding($type->getNamespacedName()));
$typeXml->setAttribute('start', Utf8Util::ensureEncoding($type->getStartLine()));
$typeXml->setAttribute('end', Utf8Util::ensureEncoding($type->getEndLine()));
$this->writeNodeMetrics($typeXml, $type);
$this->writeFileReference($typeXml, $type->getCompilationUnit());
$xml->appendChild($typeXml);
array_push($this->xmlStack, $typeXml);
foreach ($type->getMethods() as $method) {
$method->accept($this);
}
foreach ($type->getProperties() as $property) {
$property->accept($this);
}
array_pop($this->xmlStack);
}
/**
* Visits a function node.
*
* @param \PDepend\Source\AST\ASTFunction $function
* @return void
*/
public function visitFunction(ASTFunction $function)
{
$xml = end($this->xmlStack);
$doc = $xml->ownerDocument;
$functionXml = $doc->createElement('function');
$functionXml->setAttribute('name', Utf8Util::ensureEncoding($function->getName()));
$functionXml->setAttribute('start', Utf8Util::ensureEncoding($function->getStartLine()));
$functionXml->setAttribute('end', Utf8Util::ensureEncoding($function->getEndLine()));
$this->writeNodeMetrics($functionXml, $function);
$this->writeFileReference($functionXml, $function->getCompilationUnit());
$xml->appendChild($functionXml);
}
/**
* Visits a code interface object.
*
* @param \PDepend\Source\AST\ASTInterface $interface
* @return void
*/
public function visitInterface(ASTInterface $interface)
{
// Empty implementation, because we don't want interface methods.
}
/**
* Visits a method node.
*
* @param \PDepend\Source\AST\ASTMethod $method
* @return void
*/
public function visitMethod(ASTMethod $method)
{
$xml = end($this->xmlStack);
$doc = $xml->ownerDocument;
$methodXml = $doc->createElement('method');
$methodXml->setAttribute('name', Utf8Util::ensureEncoding($method->getName()));
$methodXml->setAttribute('start', Utf8Util::ensureEncoding($method->getStartLine()));
$methodXml->setAttribute('end', Utf8Util::ensureEncoding($method->getEndLine()));
$this->writeNodeMetrics($methodXml, $method);
$xml->appendChild($methodXml);
}
/**
* Visits a namespace node.
*
* @param \PDepend\Source\AST\ASTNamespace $namespace
* @return void
*/
public function visitNamespace(ASTNamespace $namespace)
{
$xml = end($this->xmlStack);
$doc = $xml->ownerDocument;
$packageXml = $doc->createElement('package');
$packageXml->setAttribute('name', Utf8Util::ensureEncoding($namespace->getName()));
$this->writeNodeMetrics($packageXml, $namespace);
array_push($this->xmlStack, $packageXml);
foreach ($namespace->getTypes() as $type) {
$type->accept($this);
}
foreach ($namespace->getFunctions() as $function) {
$function->accept($this);
}
array_pop($this->xmlStack);
if ($packageXml->firstChild === null) {
return;
}
$xml->appendChild($packageXml);
}
/**
* Aggregates all metrics for the given <b>$node</b> instance and adds them
* to the <b>\DOMElement</b>
*
* @param \DOMElement $xml
* @param \PDepend\Source\AST\AbstractASTArtifact $node
* @return void
*/
protected function writeNodeMetrics(\DOMElement $xml, AbstractASTArtifact $node)
{
$metrics = array();
foreach ($this->nodeAwareAnalyzers as $analyzer) {
$metrics = array_merge($metrics, $analyzer->getNodeMetrics($node));
}
foreach ($metrics as $name => $value) {
$xml->setAttribute($name, $value);
}
}
/**
* Appends a file reference element to the given <b>$xml</b> element.
*
* <code>
* <class name="\PDepend\Engine">
* <file name="PDepend/Engine.php" />
* </class>
* </code>
*
* @param \DOMElement $xml The parent xml element.
* @param \PDepend\Source\AST\ASTCompilationUnit $compilationUnit The code file instance.
* @return void
*/
protected function writeFileReference(\DOMElement $xml, ASTCompilationUnit $compilationUnit = null)
{
if (in_array($compilationUnit, $this->fileSet, true) === false) {
$this->fileSet[] = $compilationUnit;
}
$fileXml = $xml->ownerDocument->createElement('file');
$fileXml->setAttribute('name', Utf8Util::ensureEncoding($compilationUnit->getFileName()));
$xml->appendChild($fileXml);
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.6
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* An instance of this class represents an object allocation.
*
* <code>
* function foo()
* {
* // -------------
* new bar\Baz();
* // -------------
*
* // ---------
* new Foo();
* // ---------
* }
* </code>
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.6
*/
class ASTAllocationExpression extends AbstractASTNode
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitAllocationExpression($this, $data);
}
}

View File

@@ -0,0 +1,328 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 2.3
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* Represents a php class node.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 2.3
*/
class ASTAnonymousClass extends ASTClass implements ASTNode
{
/**
* The parent node of this node or <b>null</b> when this node is the root
* of a node tree.
*
* @var \PDepend\Source\AST\ASTNode
*/
protected $parent = null;
/**
* Metadata for this node instance, serialized in a string. This string
* contains the start, end line, and the start, end column and the node
* image in a colon separated string.
*
* @var string
* @since 0.10.4
*/
protected $metadata = ':::';
/**
* @param string $image
* @return void
*/
public function setImage($image)
{
$this->setName($image);
}
/**
* Returns the source image of this ast node.
*
* @return string
*/
public function getImage()
{
return $this->getName();
}
/**
* Returns the start line for this ast node.
*
* @return integer
*/
public function getStartLine()
{
return $this->getMetadataInteger(0);
}
/**
* Returns the start column for this ast node.
*
* @return integer
*/
public function getStartColumn()
{
return $this->getMetadataInteger(2);
}
/**
* Returns the end line for this ast node.
*
* @return integer
*/
public function getEndLine()
{
return $this->getMetadataInteger(1);
}
/**
* Returns the end column for this ast node.
*
* @return integer
*/
public function getEndColumn()
{
return $this->getMetadataInteger(3);
}
/**
* For better performance we have moved the single setter methods for the
* node columns and lines into this configure method.
*
* @param integer $startLine
* @param integer $endLine
* @param integer $startColumn
* @param integer $endColumn
* @return void
* @since 0.9.10
*/
public function configureLinesAndColumns($startLine, $endLine, $startColumn, $endColumn)
{
$this->setMetadataInteger(0, $startLine);
$this->setMetadataInteger(1, $endLine);
$this->setMetadataInteger(2, $startColumn);
$this->setMetadataInteger(3, $endColumn);
}
/**
* Returns the parent node of this node or <b>null</b> when this node is
* the root of a node tree.
*
* @return \PDepend\Source\AST\ASTNode
*/
public function getParent()
{
return $this->parent;
}
/**
* Sets the parent node of this node.
*
* @param \PDepend\Source\AST\ASTNode $node
* @return void
*/
public function setParent(ASTNode $node)
{
$this->parent = $node;
}
/**
* Traverses up the node tree and finds all parent nodes that are instances
* of <b>$parentType</b>.
*
* @param string $parentType
* @return \PDepend\Source\AST\ASTNode[]
*/
public function getParentsOfType($parentType)
{
$parents = array();
$parentNode = $this->parent;
while (is_object($parentNode)) {
if ($parentNode instanceof $parentType) {
array_unshift($parents, $parentNode);
}
$parentNode = $parentNode->getParent();
}
return $parents;
}
/**
* This method adds a new child node at the first position of the children.
*
* @param \PDepend\Source\AST\ASTNode $node
* @return void
*/
public function prependChild(ASTNode $node)
{
array_unshift($this->nodes, $node);
$node->setParent($this);
}
/**
* Will return <b>true</b> if this class was declared anonymous in an
* allocation expression.
*
* @return boolean
*/
public function isAnonymous()
{
return true;
}
/**
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @param mixed $data
* @return void
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitAnonymousClass($this, $data);
}
/**
* The magic sleep method will be called by PHP's runtime environment right
* before an instance of this class gets serialized. It should return an
* array with those property names that should be serialized for this class.
*
* @return array
* @since 0.10.0
*/
public function __sleep()
{
return array_merge(array('metadata'), parent::__sleep());
}
/**
* The magic wakeup method will be called by PHP's runtime environment when
* a serialized instance of this class was unserialized. This implementation
* of the wakeup method will register this object in the the global class
* context.
*
* @return void
*/
public function __wakeup()
{
$this->methods = null;
foreach ($this->nodes as $node) {
$node->setParent($this);
}
parent::__wakeup();
}
/**
* Returns an integer value that was stored under the given index.
*
* @param integer $index
* @return integer
* @since 0.10.4
*/
protected function getMetadataInteger($index)
{
return (int) $this->getMetadata($index);
}
/**
* Stores an integer value under the given index in the internally used data
* string.
*
* @param integer $index
* @param integer $value
* @return void
* @since 0.10.4
*/
protected function setMetadataInteger($index, $value)
{
$this->setMetadata($index, $value);
}
/**
* Returns the value that was stored under the given index.
*
* @param integer $index
* @return mixed
* @since 0.10.4
*/
protected function getMetadata($index)
{
$metadata = explode(':', $this->metadata, $this->getMetadataSize());
return $metadata[$index];
}
/**
* Stores the given value under the given index in an internal storage
* container.
*
* @param integer $index
* @param mixed $value
* @return void
* @since 0.10.4
*/
protected function setMetadata($index, $value)
{
$metadata = explode(':', $this->metadata, $this->getMetadataSize());
$metadata[$index] = $value;
$this->metadata = join(':', $metadata);
}
/**
* Returns the total number of the used property bag.
*
* @return integer
* @since 0.10.4
*/
protected function getMetadataSize()
{
return 4;
}
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.6
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* This class represents arguments as they are supplied to functions or
* constructors invocations.
*
* <code>
* // ------------
* Foo::bar($x, $y, $z);
* // ------------
*
* // ------------
* $foo->bar($x, $y, $z);
* // ------------
* </code>
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.6
*/
class ASTArguments extends AbstractASTNode
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitArguments($this, $data);
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
namespace PDepend\Source\AST;
/**
* This class represents an array expression.
*
* <code>
* // -------------------------------------
* $array = array( 1, 2, 3, array( $a, $b, $c ) );
* // -------------------------------------
*
* // ---------------------------
* $array = [ 1, 2, 3, [ $a, $b, $c ] ];
* // ---------------------------
* </code>
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
class ASTArray extends \PDepend\Source\AST\ASTExpression
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(\PDepend\Source\ASTVisitor\ASTVisitor $visitor, $data = null)
{
return $visitor->visitArray($this, $data);
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
namespace PDepend\Source\AST;
/**
* This class represents a single array element expression.
*
* <code>
* // _ ______ __________________________
* // __ ___ __________
* $array = array( 1, 2 => 3, array( $a, &$b, 1 => &$c ) );
*
* // _ ______ _____________________
* // __ ___ ________
* $array = [ 1, 2 => 3, [ $a, &$b, 1 => &$c ] ];
* </code>
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
class ASTArrayElement extends \PDepend\Source\AST\ASTExpression
{
/**
* This method will return <b>true</b> when the element value is passed by
* reference.
*
* @return boolean
*/
public function isByReference()
{
return $this->getMetadataBoolean(5);
}
/**
* This method can be used to mark the element value as passed by reference.
*
* @return void
*/
public function setByReference()
{
return $this->setMetadataBoolean(5, true);
}
/**
* Returns the total number of the used property bag.
*
* @return integer
* @since 0.10.4
* @see \PDepend\Source\AST\ASTNode#getMetadataSize()
*/
protected function getMetadataSize()
{
return 6;
}
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
* @param mixed $data
*
* @return mixed
* @since 0.9.12
*/
public function accept(\PDepend\Source\ASTVisitor\ASTVisitor $visitor, $data = null)
{
return $visitor->visitArrayElement($this, $data);
}
}

View File

@@ -0,0 +1,80 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.12
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* This node class represents a array-expression.
*
* <code>
* ------
* $x[42];
* ------
*
* -----------
* $this->foo[23][42];
* -----------
* </code>
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.12
*/
class ASTArrayIndexExpression extends ASTIndexExpression
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitArrayIndexExpression($this, $data);
}
}

View File

@@ -0,0 +1,77 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* Abstract base class for code item.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface ASTArtifact /* extends ASTNode */
{
/**
* Returns the artifact name.
*
* @return string
* @deprecated Use getImage() inherit from ASTNode class.
*/
public function getName();
/**
* Returns a id for this code node.
*
* @return string
*/
public function getId();
/**
* ASTVisitor method for node tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @return void
*/
public function accept(ASTVisitor $visitor);
}

View File

@@ -0,0 +1,228 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST;
use PDepend\Source\AST\ASTArtifactList\CollectionArtifactFilter;
/**
* Iterator for code nodes.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ASTArtifactList implements \ArrayAccess, \Iterator, \Countable
{
/**
* List of {@link \PDepend\Source\AST\ASTArtifact} objects in
* this iterator.
*
* @var \PDepend\Source\AST\ASTArtifact[]
*/
private $artifacts = array();
/**
* Total number of available nodes.
*
* @var integer
*/
private $count = 0;
/**
* Current internal offset.
*
* @var integer
*/
private $offset = 0;
/**
* Constructs a new node iterator from the given {@link \PDepend\Source\AST\ASTArtifact}
* node array.
*
* @param \PDepend\Source\AST\ASTArtifact[] $artifacts
*/
public function __construct(array $artifacts)
{
$filter = CollectionArtifactFilter::getInstance();
$nodeKeys = array();
foreach ($artifacts as $artifact) {
$id = $artifact->getId();
if (isset($nodeKeys[$id])) {
continue;
}
if ($filter->accept($artifact)) {
$nodeKeys[$id] = $id;
$this->artifacts[] = $artifact;
++$this->count;
}
}
}
/**
* Returns the number of {@link \PDepend\Source\AST\ASTArtifact}
* objects in this iterator.
*
* @return integer
*/
public function count()
{
return count($this->artifacts);
}
/**
* Returns the current node or <b>false</b>
*
* @return \PDepend\Source\AST\ASTArtifact
*/
public function current()
{
if ($this->offset >= $this->count) {
return false;
}
return $this->artifacts[$this->offset];
}
/**
* Returns the name of the current {@link \PDepend\Source\AST\ASTArtifact}.
*
* @return string
*/
public function key()
{
return $this->artifacts[$this->offset]->getName();
}
/**
* Moves the internal pointer to the next {@link \PDepend\Source\AST\ASTArtifact}.
*
* @return void
*/
public function next()
{
++$this->offset;
}
/**
* Rewinds the internal pointer.
*
* @return void
*/
public function rewind()
{
$this->offset = 0;
}
/**
* Returns <b>true</b> while there is a next {@link \PDepend\Source\AST\ASTArtifact}.
*
* @return boolean
*/
public function valid()
{
return ($this->offset < $this->count);
}
/**
* Whether a offset exists
*
* @param mixed $offset An offset to check for.
*
* @return boolean Returns true on success or false on failure. The return
* value will be casted to boolean if non-boolean was returned.
* @since 1.0.0
* @link http://php.net/manual/en/arrayaccess.offsetexists.php
*/
public function offsetExists($offset)
{
return isset($this->artifacts[$offset]);
}
/**
* Offset to retrieve
*
* @param mixed $offset
* @return \PDepend\Source\AST\ASTArtifact Can return all value types.
* @throws \OutOfBoundsException
* @since 1.0.0
* @link http://php.net/manual/en/arrayaccess.offsetget.php
*/
public function offsetGet($offset)
{
if (isset($this->artifacts[$offset])) {
return $this->artifacts[$offset];
}
throw new \OutOfBoundsException("The offset {$offset} does not exist.");
}
/**
* Offset to set
*
* @param mixed $offset
* @param mixed $value
* @return void
* @throws \BadMethodCallException
* @since 1.0.0
* @link http://php.net/manual/en/arrayaccess.offsetset.php
*/
public function offsetSet($offset, $value)
{
throw new \BadMethodCallException('Not supported operation.');
}
/**
* Offset to unset
*
* @param mixed $offset
* @return void
* @throws \BadMethodCallException
* @since 1.0.0
* @link http://php.net/manual/en/arrayaccess.offsetunset.php
*/
public function offsetUnset($offset)
{
throw new \BadMethodCallException('Not supported operation.');
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTArtifact;
/**
* Base interface for {@link \PDepend\Source\AST\ASTArtifactList} filters.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface ArtifactFilter
{
/**
* Returns <b>true</b> if the given node should be part of the node iterator,
* otherwise this method will return <b>false</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $node
* @return boolean
*/
public function accept(ASTArtifact $node);
}

View File

@@ -0,0 +1,120 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTArtifact;
/**
* Static composite filter for code nodes. This class is used for an overall
* filtering.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*
* @fixme Never ever use a singleton!!!
*/
final class CollectionArtifactFilter implements ArtifactFilter
{
/**
* Singleton instance of this filter.
*
* @var \PDepend\Source\AST\ASTArtifactList\CollectionArtifactFilter
*/
private static $instance = null;
/**
* Singleton method for this filter class.
*
* @return \PDepend\Source\AST\ASTArtifactList\CollectionArtifactFilter
*/
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new CollectionArtifactFilter();
}
return self::$instance;
}
/**
* Constructs a new static filter.
*
* @access private
*/
public function __construct()
{
}
/**
* An optional configured filter instance.
*
* @var \PDepend\Source\AST\ASTArtifactList\ArtifactFilter
*/
private $filter = null;
/**
* Sets the used filter instance.
*
* @param \PDepend\Source\AST\ASTArtifactList\ArtifactFilter $filter
* @return void
* @since 0.9.12
*/
public function setFilter(ArtifactFilter $filter = null)
{
$this->filter = $filter;
}
/**
* Returns <b>true</b> if the given node should be part of the node iterator,
* otherwise this method will return <b>false</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $node
* @return boolean
*/
public function accept(ASTArtifact $node)
{
if ($this->filter === null) {
return true;
}
return $this->filter->accept($node);
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\ASTArtifact;
/**
* This is a simple NULL-implementation of the code filter interface.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class NullArtifactFilter implements ArtifactFilter
{
/**
* Returns <b>true</b> if the given node should be part of the node iterator,
* otherwise this method will return <b>false</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $node
* @return boolean
*/
public function accept(ASTArtifact $node)
{
return true;
}
}

View File

@@ -0,0 +1,102 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST\ASTArtifactList;
use PDepend\Source\AST\AbstractASTClassOrInterface;
use PDepend\Source\AST\ASTArtifact;
use PDepend\Source\AST\ASTFunction;
use PDepend\Source\AST\ASTNamespace;
/**
* This class implements a filter that is based on the namespace.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class PackageArtifactFilter implements ArtifactFilter
{
/**
* Regexp with ignorable namespace names and namespace name fragments.
*
* @var string
*/
private $pattern = '';
/**
* Constructs a new namespace filter for the given list of namespace names.
*
* @param array(string) $namespaces
*/
public function __construct(array $namespaces)
{
$patterns = array();
foreach ($namespaces as $namespace) {
$patterns[] = str_replace('\*', '\S*', preg_quote($namespace));
}
$this->pattern = '#^(' . join('|', $patterns) . ')$#D';
}
/**
* Returns <b>true</b> if the given node should be part of the node iterator,
* otherwise this method will return <b>false</b>.
*
* @param \PDepend\Source\AST\ASTArtifact $node
* @return boolean
*/
public function accept(ASTArtifact $node)
{
$namespace = null;
// NOTE: This looks a little bit ugly and it seems better to exclude
// \PDepend\Source\AST\ASTMethod and \PDepend\Source\AST\ASTProperty,
// but when PDepend supports more node types, this could produce errors.
if ($node instanceof AbstractASTClassOrInterface) {
$namespace = $node->getNamespace()->getName();
} elseif ($node instanceof ASTFunction) {
$namespace = $node->getNamespace()->getName();
} elseif ($node instanceof ASTNamespace) {
$namespace = $node->getName();
}
return (preg_match($this->pattern, $namespace) === 0);
}
}

View File

@@ -0,0 +1,68 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* This node class represents any kind of assignment.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ASTAssignmentExpression extends AbstractASTNode
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitAssignmentExpression($this, $data);
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.8
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* This node class represents a boolean and-expression.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.8
*/
class ASTBooleanAndExpression extends AbstractASTNode
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitBooleanAndExpression($this, $data);
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.8
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* This node class represents a boolean or-expression.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.8
*/
class ASTBooleanOrExpression extends AbstractASTNode
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitBooleanOrExpression($this, $data);
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.12
*/
namespace PDepend\Source\AST;
/**
* This node class represents a break-statement.
*
* <code>
* ------
* break;
* ------
*
* ---------
* break 42;
* ---------
*
* ----------------------
* break $this->foobar();
* ----------------------
* </code>
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.12
*/
class ASTBreakStatement extends \PDepend\Source\AST\ASTStatement
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
* @param mixed $data
*
* @return mixed
* @since 0.9.12
*/
public function accept(\PDepend\Source\ASTVisitor\ASTVisitor $visitor, $data = null)
{
return $visitor->visitBreakStatement($this, $data);
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST;
/**
* Base interface for all callables.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
interface ASTCallable
{
/**
* @return \PDepend\Source\AST\ASTType
*/
public function getReturnType();
}

View File

@@ -0,0 +1,181 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.15
*/
namespace PDepend\Source\AST;
/**
* This class represents a cast-expression node.
*
* <code>
* // ----------
* $foo = (int) $bar;
* // ----------
*
* // -----------
* $foo = (bool) $bar;
* // -----------
*
* // ------------
* $foo = (array) $bar;
* // ------------
*
* // ------------
* $foo = (unset) $bar;
* // ------------
*
* // -------------
* $foo = (double) $bar;
* // -------------
*
* // -------------
* $foo = (string) $bar;
* // -------------
*
* // -------------
* $foo = (object) $bar;
* // -------------
* </code>
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.15
*/
class ASTCastExpression extends \PDepend\Source\AST\ASTUnaryExpression
{
/**
* Constructs a new cast-expression node.
*
* @param string $image The original cast image.
*/
public function __construct($image)
{
parent::__construct(preg_replace('(\s+)', '', strtolower($image)));
}
/**
* Returns <b>true</b> when this node represents an array cast-expression.
*
* @return boolean
*/
public function isArray()
{
return ($this->getImage() === '(array)');
}
/**
* Returns <b>true</b> when this node represents an object cast-expression.
*
* @return boolean
*/
public function isObject()
{
return ($this->getImage() === '(object)');
}
/**
* Returns <b>true</b> when this node represents a boolean cast-expression.
*
* @return boolean
*/
public function isBoolean()
{
return ($this->getImage() === '(bool)' || $this->getImage() === '(boolean)');
}
/**
* Returns <b>true</b> when this node represents an integer cast-expression.
*
* @return boolean
*/
public function isInteger()
{
return ($this->getImage() === '(int)' || $this->getImage() === '(integer)');
}
/**
* Returns <b>true</b> when this node represents a float cast-expression.
*
* @return boolean
*/
public function isFloat()
{
return ($this->getImage() === '(real)'
|| $this->getImage() === '(float)'
|| $this->getImage() === '(double)'
);
}
/**
* Returns <b>true</b> when this node represents a string cast-expression.
*
* @return boolean
*/
public function isString()
{
return (strcmp('(string)', $this->getImage()) === 0);
}
/**
* Returns <b>true</b> when this node represents an unset cast-expression.
*
* @return boolean
*/
public function isUnset()
{
return ($this->getImage() === '(unset)');
}
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
* @param mixed $data
*
* @return mixed
*/
public function accept(\PDepend\Source\ASTVisitor\ASTVisitor $visitor, $data = null)
{
return $visitor->visitCastExpression($this, $data);
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST;
/**
* This node class represents a catch-statement.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ASTCatchStatement extends ASTStatement
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
* @param mixed $data
*
* @return mixed
* @since 0.9.12
*/
public function accept(\PDepend\Source\ASTVisitor\ASTVisitor $visitor, $data = null)
{
return $visitor->visitCatchStatement($this, $data);
}
}

View File

@@ -0,0 +1,214 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* Represents a php class node.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ASTClass extends AbstractASTClassOrInterface
{
/**
* List of associated properties.
*
* @var \PDepend\Source\AST\ASTProperty[]
*/
private $properties = null;
/**
* Returns <b>true</b> if this is an abstract class or an interface.
*
* @return boolean
*/
public function isAbstract()
{
return (($this->modifiers & State::IS_EXPLICIT_ABSTRACT) === State::IS_EXPLICIT_ABSTRACT);
}
/**
* This method will return <b>true</b> when this class is declared as final.
*
* @return boolean
*/
public function isFinal()
{
return (($this->modifiers & State::IS_FINAL) === State::IS_FINAL);
}
/**
* Will return <b>true</b> if this class was declared anonymous in an
* allocation expression.
*
* @return boolean
*/
public function isAnonymous()
{
return false;
}
/**
* Returns all properties for this class.
*
* @return \PDepend\Source\AST\ASTProperty[]
*/
public function getProperties()
{
if ($this->properties === null) {
$this->properties = array();
$declarations = $this->findChildrenOfType('PDepend\\Source\\AST\\ASTFieldDeclaration');
foreach ($declarations as $declaration) {
$declarators = $declaration->findChildrenOfType('PDepend\\Source\\AST\\ASTVariableDeclarator');
foreach ($declarators as $declarator) {
$property = new ASTProperty($declaration, $declarator);
$property->setDeclaringClass($this);
$property->setCompilationUnit($this->getCompilationUnit());
$this->properties[] = $property;
}
}
}
return new ASTArtifactList($this->properties);
}
/**
* Checks that this user type is a subtype of the given <b>$type</b> instance.
*
* @param \PDepend\Source\AST\AbstractASTType $type
* @return boolean
*/
public function isSubtypeOf(AbstractASTType $type)
{
if ($type === $this) {
return true;
} elseif ($type instanceof ASTInterface) {
foreach ($this->getInterfaces() as $interface) {
if ($interface === $type) {
return true;
}
}
} elseif (($parent = $this->getParentClass()) !== null) {
if ($parent === $type) {
return true;
}
return $parent->isSubtypeOf($type);
}
return false;
}
/**
* Returns the declared modifiers for this type.
*
* @return integer
* @since 0.9.4
*/
public function getModifiers()
{
return $this->modifiers;
}
/**
* This method sets a OR combined integer of the declared modifiers for this
* node.
*
* This method will throw an exception when the value of given <b>$modifiers</b>
* contains an invalid/unexpected modifier
*
* @param integer $modifiers
* @return void
* @throws \BadMethodCallException
* @throws \InvalidArgumentException
* @since 0.9.4
*/
public function setModifiers($modifiers)
{
if ($this->modifiers !== 0) {
throw new \BadMethodCallException(
'Cannot overwrite previously set class modifiers.'
);
}
$expected = ~State::IS_EXPLICIT_ABSTRACT
& ~State::IS_IMPLICIT_ABSTRACT
& ~State::IS_FINAL;
if (($expected & $modifiers) !== 0) {
throw new \InvalidArgumentException('Invalid class modifier given.');
}
$this->modifiers = $modifiers;
}
/**
* ASTVisitor method for node tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @return void
*/
public function accept(ASTVisitor $visitor)
{
$visitor->visitClass($this);
}
/**
* The magic wakeup method will be called by PHP's runtime environment when
* a serialized instance of this class was unserialized. This implementation
* of the wakeup method will register this object in the the global class
* context.
*
* @return void
* @since 0.10.0
*/
public function __wakeup()
{
parent::__wakeup();
$this->context->registerClass($this);
}
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 2.0.0
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* This class represents the full qualified class name postfix.
*
* <code>
* // -----
* Foo::class
* // -----
*
* // -----
* $bar:: class;
* // -----
* </code>
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 2.0.0
*/
class ASTClassFqnPostfix extends AbstractASTNode
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
* @param mixed $data
*
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitClassFqnPostfix($this, $data);
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
namespace PDepend\Source\AST;
/**
* This type of exception will be thrown when an inheritance hierarchy is
* recursive, so that .
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 1.0.0
*/
class ASTClassOrInterfaceRecursiveInheritanceException extends \RuntimeException
{
/**
* Constructs a new exception instance.
*
* @param \PDepend\Source\AST\AbstractASTClassOrInterface $type
*/
public function __construct(AbstractASTClassOrInterface $type)
{
parent::__construct(
sprintf(
'Type %s\%s is part of an endless inheritance hierarchy.',
preg_replace('(\W+)', '\\', $type->getNamespace()->getName()),
$type->getName()
)
);
}
}

View File

@@ -0,0 +1,126 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.5
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
use PDepend\Source\Builder\BuilderContext;
/**
* This class is used as a placeholder for unknown classes or interfaces. It
* will resolve the concrete type instance on demand.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.5
*/
class ASTClassOrInterfaceReference extends ASTType
{
/**
* The global AST builder context.
*
* @var \PDepend\Source\Builder\BuilderContext
*/
protected $context = null;
/**
* An already loaded type instance.
*
* @var \PDepend\Source\AST\AbstractASTClassOrInterface
*/
protected $typeInstance = null;
/**
* Constructs a new type holder instance.
*
* @param \PDepend\Source\Builder\BuilderContext $context
* @param string $qualifiedName
*/
public function __construct(BuilderContext $context, $qualifiedName)
{
parent::__construct($qualifiedName);
$this->context = $context;
}
/**
* Returns the concrete type instance associated with with this placeholder.
*
* @return \PDepend\Source\AST\AbstractASTClassOrInterface
*/
public function getType()
{
if ($this->typeInstance === null) {
$this->typeInstance = $this->context->getClassOrInterface(
$this->getImage()
);
}
return $this->typeInstance;
}
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitClassOrInterfaceReference($this, $data);
}
/**
* Magic method which returns the names of all those properties that should
* be cached for this node instance.
*
* @return array
* @since 0.10.0
*/
public function __sleep()
{
return array_merge(array('context'), parent::__sleep());
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST;
/**
* This is a special implementation of the node iterator that will translate
* a list of given {@link \PDepend\Source\AST\ASTClassOrInterfaceReference} holders
* into a list of unique {@link \PDepend\Source\AST\AbstractASTClassOrInterface}
* instances.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ASTClassOrInterfaceReferenceIterator extends ASTArtifactList
{
/**
* Constructs a new reference iterator instance.
*
* @param \PDepend\Source\AST\ASTClassOrInterfaceReference[] $references List of
* references to concrete type instances.
*/
public function __construct(array $references)
{
parent::__construct($this->createClassesAndInterfaces($references));
}
/**
* This method creates a set of {@link \PDepend\Source\AST\AbstractASTClassOrInterface}
* objects from the given reference array.
*
* @param \PDepend\Source\AST\ASTClassOrInterfaceReference[] $references
* @return \PDepend\Source\AST\AbstractASTClassOrInterface[]
*/
protected function createClassesAndInterfaces(array $references)
{
$classesAndInterfaces = array();
foreach ($references as $reference) {
$classOrInterface = $reference->getType();
if (isset($classesAndInterfaces[$classOrInterface->getId()])) {
continue;
}
$classesAndInterfaces[$classOrInterface->getId()] = $classOrInterface;
}
return $classesAndInterfaces;
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.5
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* This is a classes only version of the class or interface reference .
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.5
*/
class ASTClassReference extends ASTClassOrInterfaceReference
{
/**
* Returns the concrete type instance associated with with this placeholder.
*
* @return \PDepend\Source\AST\AbstractASTClassOrInterface
*/
public function getType()
{
if ($this->typeInstance === null) {
$this->typeInstance = $this->context->getClass($this->getImage());
}
return $this->typeInstance;
}
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitClassReference($this, $data);
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.12
*/
namespace PDepend\Source\AST;
/**
* This node class represents a clone-expression.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.12
*/
class ASTCloneExpression extends \PDepend\Source\AST\ASTExpression
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
* @param mixed $data
*
* @return mixed
* @since 0.9.12
*/
public function accept(\PDepend\Source\ASTVisitor\ASTVisitor $visitor, $data = null)
{
return $visitor->visitCloneExpression($this, $data);
}
}

View File

@@ -0,0 +1,158 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.12
*/
namespace PDepend\Source\AST;
/**
* This node class represents a closure-expression.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.9.12
*/
class ASTClosure extends AbstractASTNode implements ASTCallable
{
/**
* @return \PDepend\Source\AST\ASTType
*/
public function getReturnType()
{
foreach ($this->nodes as $node) {
if ($node instanceof ASTType) {
return $node;
}
}
return null;
}
/**
* This method will return <b>true</b> when this closure returns by
* reference.
*
* @return boolean
*/
public function returnsByReference()
{
return $this->getMetadataBoolean(5);
}
/**
* This method can be used to flag this closure as returns by reference.
*
* @param boolean $returnsReference Does this closure return by reference?
*
* @return void
*/
public function setReturnsByReference($returnsReference)
{
$this->setMetadataBoolean(5, (boolean) $returnsReference);
}
/**
* Returns whether this closure was defined as static or not.
*
* This method will return <b>TRUE</b> when the closure was declared as
* followed:
*
* <code>
* $closure = static function( $e ) {
* return pow( $e, 2 );
* }
* </code>
*
* And it will return <b>FALSE</b> when we declare the closure as usual:
*
* <code>
* $closure = function( $e ) {
* return pow( $e, 2 );
* }
* </code>
*
* @return boolean
* @since 1.0.0
*/
public function isStatic()
{
return $this->getMetadataBoolean(6);
}
/**
* This method can be used to flag this closure instance as static.
*
* @param boolean $static Whether this closure is static or not.
*
* @return void
* @since 1.0.0
*/
public function setStatic($static)
{
$this->setMetadataBoolean(6, (boolean) $static);
}
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor The calling visitor instance.
* @param mixed $data
*
* @return mixed
* @since 0.9.12
*/
public function accept(\PDepend\Source\ASTVisitor\ASTVisitor $visitor, $data = null)
{
return $visitor->visitClosure($this, $data);
}
/**
* Returns the total number of the used property bag.
*
* @return integer
* @since 1.0.0
* @see \PDepend\Source\AST\ASTNode#getMetadataSize()
*/
protected function getMetadataSize()
{
return 7;
}
}

View File

@@ -0,0 +1,68 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
/**
* This node class represents a comment.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ASTComment extends AbstractASTNode
{
/**
* Accept method of the visitor design pattern. This method will be called
* by a visitor during tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @param mixed $data
* @return mixed
* @since 0.9.12
*/
public function accept(ASTVisitor $visitor, $data = null)
{
return $visitor->visitComment($this, $data);
}
}

View File

@@ -0,0 +1,384 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
namespace PDepend\Source\AST;
use PDepend\Source\ASTVisitor\ASTVisitor;
use PDepend\Util\Cache\CacheDriver;
/**
* This class provides an interface to a single source file.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
*/
class ASTCompilationUnit extends AbstractASTArtifact
{
/**
* The internal used cache instance.
*
* @var \PDepend\Util\Cache\CacheDriver
* @since 0.10.0
*/
protected $cache = null;
/**
* The unique identifier for this function.
*
* @var string
*/
protected $id = null;
/**
* The source file name/path.
*
* @var string
*/
protected $fileName = null;
/**
* The comment for this type.
*
* @var string
*/
protected $comment = null;
/**
* The files start line. This property must always have the value <em>1</em>.
*
* @var integer
* @since 0.10.0
*/
protected $startLine = 0;
/**
* The files end line.
*
* @var integer
* @since 0.10.0
*/
protected $endLine = 0;
/**
* List of classes, interfaces and functions that parsed from this file.
*
* @var \PDepend\Source\AST\AbstractASTArtifact[]
* @since 0.10.0
*/
protected $childNodes = array();
/**
* Was this file instance restored from the cache?
*
* @var boolean
* @since 0.10.0
*/
protected $cached = false;
/**
* Normalized code in this file.
*
* @var string
*/
private $source = null;
/**
* Constructs a new source file instance.
*
* @param string $fileName The source file name/path.
*/
public function __construct($fileName)
{
if (strpos($fileName, 'php://') === 0) {
$this->fileName = $fileName;
} elseif ($fileName !== null) {
$this->fileName = realpath($fileName);
}
}
/**
* Returns the physical file name for this object.
*
* @return string
*/
public function getName()
{
return $this->fileName;
}
/**
* Returns the physical file name for this object.
*
* @return string
*/
public function getFileName()
{
return $this->fileName;
}
/**
* Returns a id for this code node.
*
* @return string
*/
public function getId()
{
return $this->id;
}
/**
* Sets the unique identifier for this file instance.
*
* @param string $id Identifier for this file.
* @return void
* @since 0.9.12
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Setter method for the used parser and token cache.
*
* @param \PDepend\Util\Cache\CacheDriver $cache
* @return \PDepend\Source\AST\ASTCompilationUnit
* @since 0.10.0
*/
public function setCache(CacheDriver $cache)
{
$this->cache = $cache;
return $this;
}
/**
* Returns normalized source code with stripped whitespaces.
*
* @return array(integer=>string)
*/
public function getSource()
{
$this->readSource();
return $this->source;
}
/**
* Returns an <b>array</b> with all tokens within this file.
*
* @return array(array)
*/
public function getTokens()
{
return (array) $this->cache
->type('tokens')
->restore($this->getId());
}
/**
* Sets the tokens for this file.
*
* @param array(array) $tokens The generated tokens.
*
* @return void
*/
public function setTokens(array $tokens)
{
$this->cache
->type('tokens')
->store($this->getId(), $tokens);
}
/**
* Adds a source item that was parsed from this source file.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $artifact
* @return void
* @since 0.10.0
*/
public function addChild(AbstractASTArtifact $artifact)
{
$this->childNodes[$artifact->getId()] = $artifact;
}
/**
* Returns the start line number for this source file. For an existing file
* this value must always be <em>1</em>, while it can be <em>0</em> for a
* not existing dummy file.
*
* @return integer
* @since 0.10.0
*/
public function getStartLine()
{
if ($this->startLine === 0) {
$this->readSource();
}
return $this->startLine;
}
/**
* Returns the start line number for this source file. For an existing file
* this value must always be greater <em>0</em>, while it can be <em>0</em>
* for a not existing dummy file.
*
* @return integer
* @since 0.10.0
*/
public function getEndLine()
{
if ($this->endLine === 0) {
$this->readSource();
}
return $this->endLine;
}
/**
* This method will return <b>true</b> when this file instance was restored
* from the cache and not currently parsed. Otherwise this method will return
* <b>false</b>.
*
* @return boolean
* @since 0.10.0
*/
public function isCached()
{
return $this->cached;
}
/**
* ASTVisitor method for node tree traversal.
*
* @param \PDepend\Source\ASTVisitor\ASTVisitor $visitor
* @return void
*/
public function accept(ASTVisitor $visitor)
{
$visitor->visitCompilationUnit($this);
}
/**
* The magic sleep method will be called by PHP's runtime environment right
* before it serializes an instance of this class. This method returns an
* array with those property names that should be serialized.
*
* @return array(string)
* @since 0.10.0
*/
public function __sleep()
{
return array(
'cache',
'childNodes',
'comment',
'endLine',
'fileName',
'startLine',
'id'
);
}
/**
* The magic wakeup method will is called by PHP's runtime environment when
* a serialized instance of this class was unserialized. This implementation
* of the wakeup method restores the references between all parsed entities
* in this source file and this file instance.
*
* @return void
* @since 0.10.0
* @see \PDepend\Source\AST\ASTCompilationUnit::$childNodes
*/
public function __wakeup()
{
$this->cached = true;
foreach ($this->childNodes as $childNode) {
$childNode->setCompilationUnit($this);
}
}
/**
* Returns the string representation of this class.
*
* @return string
*/
public function __toString()
{
return ($this->fileName === null ? '' : $this->fileName);
}
/**
* Reads the source file if required.
*
* @return void
*/
protected function readSource()
{
if ($this->source === null && (file_exists($this->fileName) || strpos($this->fileName, 'php://') === 0)) {
$source = file_get_contents($this->fileName);
$this->source = str_replace(array("\r\n", "\r"), "\n", $source);
$this->startLine = 1;
$this->endLine = substr_count($this->source, "\n") + 1;
}
}
// Deprecated methods
// @codeCoverageIgnoreStart
/**
* This method can be called by the PDepend runtime environment or a
* utilizing component to free up memory. This methods are required for
* PHP version < 5.3 where cyclic references can not be resolved
* automatically by PHP's garbage collector.
*
* @return void
* @since 0.9.12
* @deprecated Since 0.10.0
*/
public function free()
{
fwrite(STDERR, __METHOD__ . ' is deprecated since version 0.10.0' . PHP_EOL);
}
// @codeCoverageIgnoreEnd
}

View File

@@ -0,0 +1,65 @@
<?php
/**
* This file is part of PDepend.
*
* PHP Version 5
*
* Copyright (c) 2008-2017 Manuel Pichler <mapi@pdepend.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Manuel Pichler nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.10.0
*/
namespace PDepend\Source\AST;
/**
* This type of exception will be thrown when the source file of a code object
* is accessed, but this property is not available.
*
* @copyright 2008-2017 Manuel Pichler. All rights reserved.
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @since 0.10.0
*/
class ASTCompilationUnitNotFoundException extends \RuntimeException
{
/**
* Constructs a new exception instance.
*
* @param \PDepend\Source\AST\AbstractASTArtifact $owner
*/
public function __construct(AbstractASTArtifact $owner)
{
parent::__construct('The mandatory parent was not defined.');
}
}

Some files were not shown because too many files have changed in this diff Show More