├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── dependabot-auto-merge.yml │ ├── documentation.yaml │ └── integrate.yaml ├── .gitignore ├── .phive └── phars.xml ├── .phpdoc └── template │ └── base.html.twig ├── .yamllint.yaml ├── LICENSE ├── Makefile ├── README.md ├── composer-require-checker.json ├── composer.json ├── composer.lock ├── docs ├── extending │ ├── index.rst │ └── meta-data.rst ├── getting-started.rst ├── index.rst └── reflection-structure.rst ├── example.php ├── phpbench.json ├── phpcs.xml.dist ├── phpdoc.dist.xml ├── phpstan.neon ├── phpunit.xml.dist ├── psalm-baseline.xml ├── psalm.xml ├── rector.php ├── src ├── php-parser │ └── Modifiers.php └── phpDocumentor │ └── Reflection │ ├── Exception.php │ ├── File │ └── LocalFile.php │ ├── Metadata │ ├── MetaDataContainer.php │ └── Metadata.php │ ├── Middleware │ ├── ChainFactory.php │ ├── Command.php │ └── Middleware.php │ ├── NodeVisitor │ ├── ElementNameResolver.php │ └── FindingVisitor.php │ ├── Php │ ├── Argument.php │ ├── AsymmetricVisibility.php │ ├── Attribute.php │ ├── AttributeContainer.php │ ├── CallArgument.php │ ├── Class_.php │ ├── Constant.php │ ├── EnumCase.php │ ├── Enum_.php │ ├── Factory │ │ ├── AbstractFactory.php │ │ ├── ClassConstant.php │ │ ├── ClassConstantIterator.php │ │ ├── Class_.php │ │ ├── ConstructorPromotion.php │ │ ├── ContextStack.php │ │ ├── Define.php │ │ ├── EnumCase.php │ │ ├── Enum_.php │ │ ├── File.php │ │ ├── File │ │ │ └── CreateCommand.php │ │ ├── Function_.php │ │ ├── GlobalConstant.php │ │ ├── GlobalConstantIterator.php │ │ ├── IfStatement.php │ │ ├── Interface_.php │ │ ├── Method.php │ │ ├── Namespace_.php │ │ ├── Noop.php │ │ ├── Property.php │ │ ├── PropertyBuilder.php │ │ ├── PropertyIterator.php │ │ ├── Reducer │ │ │ ├── Attribute.php │ │ │ ├── Parameter.php │ │ │ └── Reducer.php │ │ ├── TraitUse.php │ │ ├── Trait_.php │ │ └── Type.php │ ├── File.php │ ├── Function_.php │ ├── HasAttributes.php │ ├── Interface_.php │ ├── MetadataContainer.php │ ├── Method.php │ ├── Namespace_.php │ ├── NodesFactory.php │ ├── Project.php │ ├── ProjectFactory.php │ ├── ProjectFactoryStrategies.php │ ├── ProjectFactoryStrategy.php │ ├── Property.php │ ├── PropertyHook.php │ ├── StrategyContainer.php │ ├── Trait_.php │ ├── ValueEvaluator │ │ └── ConstantEvaluator.php │ └── Visibility.php │ └── Types │ └── NamespaceNodeToContext.php └── tests ├── assets └── phpunit_assert.php ├── bench └── ProjectFactoryBench.php ├── coverage-checker.php ├── example.file.php ├── integration ├── AsymmetricAccessorTest.php ├── ClassesTest.php ├── EnumTest.php ├── FileDocblockTest.php ├── Metadata │ ├── Hook.php │ ├── HookStrategy.php │ └── example.php ├── MetadataTest.php ├── PHP8 │ ├── ConstructorPromotionTest.php │ ├── MixedTypeTest.php │ ├── StaticTypeTest.php │ └── UnionTypesTest.php ├── ProjectCreationTest.php ├── ProjectNamespaceTest.php ├── PropertyHookTest.php └── data │ ├── Enums │ ├── EnumConsumer.php │ ├── backedEnum.php │ ├── base.php │ └── enumWithConstant.php │ ├── GlobalFiles │ ├── conditional_function.php │ ├── docblock_followed_by_html.php │ ├── empty.php │ ├── empty_shebang.php │ ├── empty_with_declare.php │ ├── empty_with_html.php │ ├── global_namspaced_function.php │ ├── inline_function.php │ └── psr12.php │ ├── Luigi │ ├── ExampleNestedTrait.php │ ├── Packing.php │ ├── Pizza.php │ ├── StyleFactory.php │ ├── Valued.php │ └── constants.php │ ├── PHP8 │ ├── ConstructorPromotion.php │ ├── MixedType.php │ ├── StaticType.php │ └── UnionTypes.php │ ├── PHP84 │ ├── AsymmetricAccessor.php │ ├── AsymmetricPropertyPromotion.php │ ├── PropertyHook.php │ ├── PropertyHookAsymmetric.php │ ├── PropertyHookPromotion.php │ └── PropertyHookVirtual.php │ ├── Packing.php │ ├── Pizza.php │ └── simpleFunction.php └── unit └── phpDocumentor └── Reflection ├── File └── LocalFileTest.php ├── Middleware └── ChainFactoryTest.php ├── NodeVisitor └── ElementNameResolverTest.php ├── Php ├── ArgumentTest.php ├── Class_Test.php ├── ConstantTest.php ├── EnumCaseTest.php ├── Enum_Test.php ├── Factory │ ├── ClassConstantIteratorTest.php │ ├── ClassConstantTest.php │ ├── Class_Test.php │ ├── ConstructorPromotionTest.php │ ├── ContextStackTest.php │ ├── DefineTest.php │ ├── DummyFactoryStrategy.php │ ├── EnumCaseTest.php │ ├── Enum_Test.php │ ├── File │ │ └── CreateCommandTest.php │ ├── FileTest.php │ ├── Function_Test.php │ ├── GlobalConstantIteratorTest.php │ ├── GlobalConstantTest.php │ ├── Interface_Test.php │ ├── MethodTest.php │ ├── Namespace_Test.php │ ├── PropertyBuilderTest.php │ ├── PropertyIteratorTest.php │ ├── PropertyTest.php │ ├── TestCase.php │ ├── TraitUseTest.php │ ├── Trait_Test.php │ └── TypeTest.php ├── FileTest.php ├── Function_Test.php ├── Interface_Test.php ├── MetadataContainerTestHelper.php ├── MetadataStub.php ├── MethodTest.php ├── Namespace_Test.php ├── NodesFactoryTest.php ├── ProjectFactoryStrategiesTest.php ├── ProjectFactoryTest.php ├── ProjectTest.php ├── PropertyTest.php ├── TestCase.php ├── Trait_Test.php ├── ValueEvaluator │ └── ConstantEvaluatorTest.php └── VisibilityTest.php └── Types └── NamespaceNodeToContextTest.php /.gitattributes: -------------------------------------------------------------------------------- 1 | *.php text eol=lf -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "composer" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | open-pull-requests-limit: 10 8 | 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "weekly" 13 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-auto-merge.yml: -------------------------------------------------------------------------------- 1 | name: "Dependabot auto-merge" 2 | 3 | on: # yamllint disable-line rule:truthy 4 | pull_request_target: null 5 | 6 | permissions: 7 | contents: "write" 8 | 9 | jobs: 10 | dependabot: 11 | runs-on: "ubuntu-latest" 12 | if: "${{ github.actor == 'dependabot[bot]' }}" 13 | steps: 14 | - name: "Dependabot metadata" 15 | id: "metadata" 16 | uses: "dependabot/fetch-metadata@v2.4.0" 17 | with: 18 | github-token: "${{ secrets.GITHUB_TOKEN }}" 19 | - name: "Enable auto-merge for Dependabot PRs" 20 | if: "${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }}" 21 | run: "gh pr merge --auto --merge \"$PR_URL\"" 22 | env: 23 | PR_URL: "${{github.event.pull_request.html_url}}" 24 | GITHUB_TOKEN: "${{secrets.GITHUB_TOKEN}}" 25 | -------------------------------------------------------------------------------- /.github/workflows/documentation.yaml: -------------------------------------------------------------------------------- 1 | name: "Documentation" 2 | 3 | on: # yamllint disable-line rule:truthy 4 | push: 5 | branches: 6 | - "6.x" 7 | pull_request: null 8 | 9 | jobs: 10 | documentation: 11 | name: "Documentation" 12 | runs-on: "ubuntu-latest" 13 | steps: 14 | - name: "Checkout" 15 | uses: "actions/checkout@v4" 16 | 17 | - name: "Build" 18 | uses: "phpDocumentor/phpDocumentor@master" 19 | 20 | - name: "Deploy" 21 | if: "${{ github.event_name == 'push' && github.ref == 'refs/heads/6.x' }}" 22 | uses: "actions/upload-artifact@v4" 23 | with: 24 | name: "documentation" 25 | path: "build/docs" 26 | retention-days: 1 27 | 28 | deploy: 29 | name: "Deploy" 30 | if: "${{ github.event_name == 'push' && github.ref == 'refs/heads/6.x' }}" 31 | runs-on: "ubuntu-latest" 32 | needs: "documentation" 33 | steps: 34 | - name: "Checkout" 35 | uses: "actions/checkout@v4" 36 | with: 37 | repository: "phpDocumentor/docs" 38 | token: "${{ secrets.BOT_TOKEN }}" 39 | path: "docs" 40 | 41 | - name: "Download" 42 | uses: "actions/download-artifact@v4" 43 | with: 44 | name: "documentation" 45 | path: "build/docs" 46 | 47 | - name: "Copy files" 48 | run: "rsync -r --delete build/docs/* docs/docs/components/reflection" 49 | 50 | - name: "Commit" 51 | uses: "stefanzweifel/git-auto-commit-action@v5" 52 | with: 53 | repository: "docs" 54 | commit_message: "Update reflection documentation" 55 | 56 | - name: "Push" 57 | uses: "ad-m/github-push-action@master" 58 | with: 59 | directory: "docs" 60 | github_token: "${{ secrets.BOT_TOKEN }}" 61 | repository: "phpDocumentor/docs" 62 | -------------------------------------------------------------------------------- /.github/workflows/integrate.yaml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/en/actions 2 | 3 | name: "Integrate" 4 | 5 | on: # yamllint disable-line rule:truthy 6 | push: 7 | branches: 8 | - "6.x" 9 | pull_request: null 10 | # Allow manually triggering the workflow. 11 | workflow_dispatch: null 12 | 13 | jobs: 14 | code-coverage: 15 | name: "Code Coverage" 16 | uses: "phpDocumentor/.github/.github/workflows/code-coverage.yml@v0.8" 17 | with: 18 | php-version: "8.2" 19 | 20 | coding-standards: 21 | name: "Coding Standards" 22 | runs-on: "ubuntu-22.04" 23 | steps: 24 | - name: "Checkout" 25 | uses: "actions/checkout@v4" 26 | 27 | - name: "Install PHP" 28 | uses: "shivammathur/setup-php@v2" 29 | with: 30 | coverage: "none" 31 | php-version: "8.2" 32 | tools: "cs2pr" 33 | 34 | - name: "Install dependencies with Composer" 35 | uses: "ramsey/composer-install@v3" 36 | with: 37 | dependency-versions: "locked" 38 | 39 | - name: "Run PHP_CodeSniffer" 40 | run: "vendor/bin/phpcs -q --no-colors --report=checkstyle | cs2pr" 41 | 42 | dependency-analysis: 43 | name: "Dependency analysis" 44 | uses: "phpDocumentor/.github/.github/workflows/dependency-analysis.yml@v0.8" 45 | with: 46 | php-version: "8.2" 47 | 48 | lint-root: 49 | name: "Lint root" 50 | uses: "phpDocumentor/.github/.github/workflows/lint.yml@v0.8" 51 | with: 52 | php-version: "8.2" 53 | composer-options: "--no-check-publish --ansi" 54 | 55 | static-analysis: 56 | name: "Static analysis" 57 | uses: "phpDocumentor/.github/.github/workflows/static-analysis.yml@main" 58 | with: 59 | php-version: "8.2" 60 | php-extensions: "none, ctype, dom, json, mbstring, phar, simplexml, tokenizer, xml, xmlwriter, fileinfo, pcntl, posix" 61 | 62 | unit-tests: 63 | name: "Unit test" 64 | uses: "phpDocumentor/.github/.github/workflows/continuous-integration.yml@v0.8" 65 | 66 | integration-tests: 67 | name: "Integration test" 68 | uses: "phpDocumentor/.github/.github/workflows/continuous-integration.yml@v0.8" 69 | needs: "unit-tests" 70 | with: 71 | test-suite: "integration" 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE Shizzle; it is recommended to use a global .gitignore for this but since this is an OSS project we want to make 2 | # it easy to contribute 3 | .idea 4 | /nbproject/private/ 5 | .buildpath 6 | .project 7 | .settings 8 | 9 | # Build folder and vendor folder are generated code; no need to version this 10 | build/ 11 | tools/ 12 | temp/ 13 | vendor/ 14 | *.phar 15 | 16 | # By default the phpunit.xml.dist is provided; you can override this using a local config file 17 | phpunit.xml 18 | .phpunit.result.cache 19 | .phpunit.cache 20 | 21 | .phpdoc/cache 22 | -------------------------------------------------------------------------------- /.phive/phars.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.phpdoc/template/base.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'layout.html.twig' %} 2 | 3 | {% set topMenu = { 4 | "menu": [ 5 | { "name": "About", "url": "https://phpdoc.org/"}, 6 | { "name": "Components", "url": "https://phpdoc.org/components.html"}, 7 | { "name": "Documentation", "url": "https://docs.phpdoc.org/"}, 8 | ], 9 | "social": [ 10 | { "iconClass": "fab fa-mastodon", "url": "https://phpc.social/@phpdoc"}, 11 | { "iconClass": "fab fa-github", "url": "https://github.com/phpdocumentor/typeresolver"}, 12 | { "iconClass": "fas fa-envelope-open-text", "url": "https://github.com/orgs/phpDocumentor/discussions"} 13 | ] 14 | } 15 | %} 16 | -------------------------------------------------------------------------------- /.yamllint.yaml: -------------------------------------------------------------------------------- 1 | extends: "default" 2 | 3 | ignore: | 4 | .build/ 5 | .notes/ 6 | vendor/ 7 | rules: 8 | braces: 9 | max-spaces-inside-empty: 0 10 | max-spaces-inside: 1 11 | min-spaces-inside-empty: 0 12 | min-spaces-inside: 1 13 | brackets: 14 | max-spaces-inside-empty: 0 15 | max-spaces-inside: 0 16 | min-spaces-inside-empty: 0 17 | min-spaces-inside: 0 18 | colons: 19 | max-spaces-after: 1 20 | max-spaces-before: 0 21 | commas: 22 | max-spaces-after: 1 23 | max-spaces-before: 0 24 | min-spaces-after: 1 25 | comments: 26 | ignore-shebangs: true 27 | min-spaces-from-content: 1 28 | require-starting-space: true 29 | comments-indentation: "enable" 30 | document-end: 31 | present: false 32 | document-start: 33 | present: false 34 | indentation: 35 | check-multi-line-strings: false 36 | indent-sequences: true 37 | spaces: 2 38 | empty-lines: 39 | max-end: 0 40 | max-start: 0 41 | max: 1 42 | empty-values: 43 | forbid-in-block-mappings: true 44 | forbid-in-flow-mappings: true 45 | hyphens: 46 | max-spaces-after: 2 47 | key-duplicates: "enable" 48 | key-ordering: "disable" 49 | line-length: "disable" 50 | new-line-at-end-of-file: "enable" 51 | new-lines: 52 | type: "unix" 53 | octal-values: 54 | forbid-implicit-octal: true 55 | quoted-strings: 56 | quote-type: "double" 57 | trailing-spaces: "enable" 58 | truthy: 59 | allowed-values: 60 | - "false" 61 | - "true" 62 | 63 | yaml-files: 64 | - "*.yaml" 65 | - "*.yml" 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2010 Mike van Riel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: help 2 | help: ## Displays this list of targets with descriptions 3 | @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[32m%-30s\033[0m %s\n", $$1, $$2}' 4 | 5 | .PHONY: code-style 6 | code-style: 7 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/phpcs 8 | 9 | .PHONY: fix-code-style 10 | fix-code-style: 11 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/phpcbf 12 | 13 | .PHONY: static-code-analysis 14 | static-code-analysis: #vendor ## Runs a static code analysis with phpstan/phpstan and vimeo/psalm 15 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.2-cli vendor/bin/phpstan --configuration=phpstan.neon 16 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.2-cli vendor/bin/psalm.phar --show-info=true --threads=4 17 | 18 | .PHONY: test 19 | test: test-unit test-functional ## Runs all test suites with phpunit/phpunit 20 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/phpunit 21 | 22 | .PHONY: test-unit 23 | test-unit: ## Runs unit tests with phpunit/phpunit 24 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/phpunit --testsuite=unit 25 | 26 | .PHONY: test-functional 27 | test-functional: ## Runs unit tests with phpunit/phpunit 28 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/phpunit --testsuite=integration 29 | 30 | .PHONY: dependency-analysis 31 | dependency-analysis: vendor ## Runs a dependency analysis with maglnet/composer-require-checker 32 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli .phive/composer-require-checker check --config-file=/opt/project/composer-require-checker.json 33 | 34 | vendor: composer.json composer.lock 35 | composer validate --no-check-publish 36 | composer install --no-interaction --no-progress 37 | 38 | .PHONY: benchmark 39 | benchmark: 40 | docker run -it --rm -v${CURDIR}:/opt/project -w /opt/project php:8.1-cli tools/phpbench run 41 | 42 | .PHONY: rector 43 | rector: ## Refactor code using rector 44 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project php:8.1-cli vendor/bin/rector process 45 | 46 | .PHONY: pre-commit-test 47 | pre-commit-test: fix-code-style test code-style static-code-analysis 48 | 49 | .PHONY: docs 50 | docs: ## Generate documentation 51 | docker run -it --rm -v${PWD}:/opt/project -w /opt/project phpdoc/phpdoc:3-unstable 52 | -------------------------------------------------------------------------------- /composer-require-checker.json: -------------------------------------------------------------------------------- 1 | { 2 | "symbol-whitelist" : [ 3 | "null", "true", "false", 4 | "static", "self", "parent", 5 | "array", "string", "int", "float", "bool", "iterable", "callable", "void", "object", 6 | "PhpParser\\Node\\Stmt\\PropertyProperty" 7 | ], 8 | "php-core-extensions" : [ 9 | "Core", 10 | "pcre", 11 | "Reflection", 12 | "tokenizer", 13 | "SPL", 14 | "standard" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpdocumentor/reflection", 3 | "description": "Reflection library to do Static Analysis for PHP Projects", 4 | "keywords": ["phpdoc", "phpDocumentor", "reflection", "static analysis"], 5 | "homepage": "http://www.phpdoc.org", 6 | "license": "MIT", 7 | "autoload": { 8 | "files": [ 9 | "src/php-parser/Modifiers.php" 10 | ], 11 | "psr-4": { 12 | "phpDocumentor\\": "src/phpDocumentor" 13 | } 14 | }, 15 | "autoload-dev": { 16 | "psr-4": { 17 | "phpDocumentor\\": [ 18 | "tests/unit/phpDocumentor", 19 | "tests/bench/" 20 | ], 21 | "phpDocumentor\\Reflection\\": [ 22 | "tests/integration" 23 | ] 24 | } 25 | }, 26 | "require": { 27 | "php": "8.1.*|8.2.*|8.3.*|8.4.*", 28 | "composer-runtime-api": "^2", 29 | "nikic/php-parser": "~4.18 || ^5.0", 30 | "phpdocumentor/reflection-common": "^2.1", 31 | "phpdocumentor/reflection-docblock": "^5", 32 | "phpdocumentor/type-resolver": "^1.2", 33 | "symfony/polyfill-php80": "^1.28", 34 | "webmozart/assert": "^1.7" 35 | }, 36 | "require-dev": { 37 | "dealerdirect/phpcodesniffer-composer-installer": "^1.0", 38 | "doctrine/coding-standard": "^13.0", 39 | "eliashaeussler/phpunit-attributes": "^1.7", 40 | "mikey179/vfsstream": "~1.2", 41 | "mockery/mockery": "~1.6.0", 42 | "phpspec/prophecy-phpunit": "^2.0", 43 | "phpstan/extension-installer": "^1.1", 44 | "phpstan/phpstan": "^1.8", 45 | "phpstan/phpstan-webmozart-assert": "^1.2", 46 | "phpunit/phpunit": "^10.0", 47 | "psalm/phar": "^6.0", 48 | "rector/rector": "^1.0.0", 49 | "squizlabs/php_codesniffer": "^3.8" 50 | }, 51 | "config": { 52 | "preferred-install": { 53 | "*": "dist" 54 | }, 55 | "sort-packages": true, 56 | "platform": { 57 | "php": "8.1.0" 58 | }, 59 | "allow-plugins": { 60 | "phpstan/extension-installer": true, 61 | "dealerdirect/phpcodesniffer-composer-installer": true 62 | } 63 | }, 64 | "extra": { 65 | "branch-alias": { 66 | "dev-5.x": "5.3.x-dev", 67 | "dev-6.x": "6.0.x-dev" 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /docs/extending/index.rst: -------------------------------------------------------------------------------- 1 | .. _extending: 2 | 3 | Extend the library 4 | ================== 5 | 6 | The model exposed by this library is closed for inheritance. We did this to ensure the model is stable and does not 7 | change via external factors. The complexity of this project makes it hard to keep all the internal classes stable. 8 | The model is designed to be cached and constructed very carefully to ensure performance and memory usage are optimal. 9 | 10 | Metadata 11 | -------- 12 | 13 | Metadata is a way to extend the model with additional information. We call this metadata, as all first class 14 | elements in the reflected codebase are part of the model. Extra data can be added to these elements using metadata. 15 | 16 | Elements supporting metadata are: 17 | 18 | .. phpdoc:class-list:: [?(@.interfaces contains "\phpDocumentor\Reflection\Metadata\MetaDataContainer")] 19 | 20 | .. phpdoc:name:: 21 | 22 | .. warning:: 23 | 24 | Adding metadata might break the posibilty to cache the model. Be carefull with circular references and large 25 | objects. We do recommend to keep the metadata small and simple. 26 | 27 | Continue reading :doc:`Creating your first metadata `_ to learn how to create your own metadata. 28 | 29 | .. toctree:: 30 | :maxdepth: 1 31 | :titlesonly: 32 | :hidden: 33 | 34 | meta-data 35 | -------------------------------------------------------------------------------- /docs/extending/meta-data.rst: -------------------------------------------------------------------------------- 1 | Metadata 2 | ===== 3 | 4 | The model of this library is as closed as possible. 5 | Main reason is because consumers of the library should rely on cache. 6 | A mutable and flexible interface of the model would most likely break the caching. 7 | However after some time the users to this library started requesting for a more flexible format. 8 | This is why metadata was introduced. 9 | 10 | Create your first metadata 11 | -------------------------- 12 | 13 | First step is to create your own metadata implementation. 14 | 15 | .. code:: php 16 | final class Hook implements \phpDocumentor\Reflection\Metadata\Metadata 17 | { 18 | private string $hook; 19 | 20 | public function __construct(string $hook) 21 | { 22 | $this->hook = $hook; 23 | } 24 | 25 | public function key(): string 26 | { 27 | return "project-metadata"; 28 | } 29 | 30 | public function hook(): string 31 | { 32 | return $this->hook; 33 | } 34 | } 35 | 36 | .. note:: 37 | We do highly recommend to keep your metadata objects small. 38 | When reflecting a large project the number of objects will grow fast. 39 | 40 | Now we have an class that can be used it is time to create a :php:class:`\phpDocumentor\Reflection\Php\ProjectFactoryStrategy`. 41 | Strategies are used to reflect nodes in the AST of `phpparser`_. 42 | 43 | In the example below we are adding the Hook metadata to any functions containing a function call. 44 | 45 | .. code:: php 46 | 47 | use \phpDocumentor\Reflection\Php\Function; 48 | 49 | final class HookStrategy implements \phpDocumentor\Reflection\Php\ProjectFactoryStrategy 50 | { 51 | public function matches(ContextStack $context, object $object): bool 52 | { 53 | return $this->context->peek() instanceof Function_ && 54 | $object instanceof \PhpParser\Node\Expr\FuncCall && 55 | ((string)$object->name) === 'hook' 56 | } 57 | 58 | public function create(ContextStack $context, object $object, StrategyContainer $strategies): void 59 | { 60 | $method = $context->peek(); 61 | $method->addMetadata(new Hook($object->args[0]->value)); 62 | } 63 | } 64 | 65 | .. note:: 66 | To speed up the reflection of your project the default factory instance has a Noop strategy. This strategy will 67 | ignore all statements that are not handled by any strategy. Keep this in mind when implementing your own strategies 68 | especially the statements you are looking for are nested in other statements like a ``while`` loop. 69 | 70 | Finally add your new strategy to the project factory. 71 | 72 | .. code:: php 73 | 74 | $factory = \phpDocumentor\Reflection\Php\ProjectFactory::createInstance(); 75 | $factory->addStrategy(new HookStrategy()); 76 | 77 | .. _phpparser: https://github.com/nikic/PHP-Parser/ 78 | -------------------------------------------------------------------------------- /docs/getting-started.rst: -------------------------------------------------------------------------------- 1 | Getting started 2 | =============== 3 | 4 | This page will give you a quick introduction to the `phpdocumentor/reflection` package and how to get started with it. 5 | 6 | Installation 7 | ------------ 8 | 9 | In order to inspect a codebase you need to tell composer to include the `phpdocumentor/reflection` package. This 10 | can easily be done using the following command in your command line terminal: 11 | 12 | .. code-block:: bash 13 | 14 | composer require phpdocumentor/reflection:~6.0 15 | 16 | In order to use the library you need to include the autoloader of composer in your code. 17 | This can be done by adding the following line to your code: 18 | 19 | .. code-block:: php 20 | 21 | create('My Project', $projectFiles); 43 | 44 | When the process is ready a new object of type :php:class:`phpDocumentor\Reflection\Php\Project` will be returned that 45 | contains a complete hierarchy of all files with their classes, traits and interfaces (and everything in there), but also 46 | all namespaces and packages as a hierarchical tree. 47 | This library does not provide a way to access the structure of the codebase in a searchable way. 48 | This is up to the consumer of the library to implement. 49 | 50 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Reflection 2 | ========== 3 | 4 | Using this library it is possible to statically reflect one or more files and create an object graph representing 5 | your application's structure, including accompanying in-source documentation using DocBlocks. 6 | 7 | The information that this library provides is similar to what the (built-in) Reflection extension of PHP provides; there 8 | are however several advantages to using this library: 9 | 10 | - Due to its Static nature it does not execute procedural code in your reflected files where Dynamic Reflection does. 11 | - Because the none of the code is interpreted by PHP (and executed) Static Reflection uses less memory. 12 | - Can reflect complete files 13 | - Can reflect a whole project by reflecting multiple files. 14 | - Reflects the contents of a DocBlock instead of just mentioning there is one. 15 | - Is capable of analyzing code written for any PHP version (starting at 5.2) up to the lastest version, even if your installed 16 | PHP version is lower than the code you are reflecting. 17 | 18 | .. note:: 19 | As this library focuses on reflecting the structure of the codebase, it does not provide any options to manipulate 20 | the output. If you want to collect more information from the codebase you can read about :ref:`extending the library `. 21 | 22 | .. toctree:: 23 | :hidden: 24 | :maxdepth: 2 25 | 26 | getting-started 27 | reflection-structure 28 | extending/index 29 | -------------------------------------------------------------------------------- /docs/reflection-structure.rst: -------------------------------------------------------------------------------- 1 | Reflection structure 2 | ==================== 3 | 4 | The project created by the :php:class:`\phpDocumentor\Reflection\Php\ProjectFactory` class contains a hierarchy of objects 5 | that represent the structure of your codebase. This hierarchy includes: 6 | 7 | Files 8 | Each file is represented by an object of type :php:class:`\phpDocumentor\Reflection\Php\File` which contains 9 | information about the file such as its name, path, and contents. But also the elements that are defined in the file. 10 | Files can be accessed through the :php:method:`\phpDocumentor\Reflection\Php\Project::getFiles()` method of the project object. 11 | Files are a flat list of all files that were analyzed, regardless of their location in the directory structure. 12 | 13 | Namespaces 14 | Namespaces are represented by objects of type :php:class:`\phpDocumentor\Reflection\Php\Namespace_`. Each namespace 15 | contains a list of classes, interfaces, traits, and functions that are defined within it. Namespaces can be accessed 16 | through the :php:method:`\phpDocumentor\Reflection\Php\Project::getNamespaces()` method of the project object. 17 | Namespaces are hierarchical and can contain sub-namespaces. 18 | 19 | Both namespaces and files do contain the other structural elements that are defined in them, such as classes, interfaces, traits, and functions. 20 | This library does not provide a way to access the structure of the codebase in a searchable way. This is up to the consumer of the library to implement. 21 | -------------------------------------------------------------------------------- /example.php: -------------------------------------------------------------------------------- 1 | create('MyProject', $files); 30 | 31 | // As an example of what you can do, let's list all class names in the file 'tests/example.file.php'. 32 | echo 'List all classes in the example source file: ' . PHP_EOL; 33 | 34 | /** @var \phpDocumentor\Reflection\Php\Class_ $class */ 35 | foreach ($project->getFiles()['tests/example.file.php']->getClasses() as $class) { 36 | echo '- ' . $class->getFqsen() . PHP_EOL; 37 | } 38 | -------------------------------------------------------------------------------- /phpbench.json: -------------------------------------------------------------------------------- 1 | { 2 | "bootstrap": "vendor/autoload.php", 3 | "path": "tests/bench", 4 | "extensions": [ 5 | "PhpBench\\Extensions\\XDebug\\XDebugExtension" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /phpcs.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | The coding standard for this library. 4 | 5 | src 6 | tests/unit 7 | */tests/unit/Types/ContextFactoryTest\.php 8 | 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | packages/guides/src/Setup/QuickStart.php 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | */tests/unit/* 60 | 61 | 62 | 63 | */tests/unit/* 64 | */src/phpDocumentor/Reflection/Php/* 65 | 66 | 67 | -------------------------------------------------------------------------------- /phpdoc.dist.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | Guides 9 | 10 | build/docs 11 | 12 | 13 | latest 14 | 15 | 16 | src/phpDocumentor 17 | 18 | api 19 | 25 | 26 | php 27 | 28 | 29 | template 30 | template-extends 31 | template-implements 32 | extends 33 | implements 34 | 35 | phpDocumentor 36 | 37 | 38 | 39 | docs 40 | 41 | guides 42 | 43 | 44 |