Skip to content

Make exception PHPDoc consistent and self-documenting#14

Closed
koriym wants to merge 196 commits into
2.xfrom
exception-doc
Closed

Make exception PHPDoc consistent and self-documenting#14
koriym wants to merge 196 commits into
2.xfrom
exception-doc

Conversation

@koriym

@koriym koriym commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Summary

  • make exception PHPDoc consistent across the Ray.Di exception hierarchy
  • document message formats, trigger paths, design constraints, and backward-compatibility status where they add information beyond the class name
  • record the exception documentation convention for future maintenance

Rationale

Exception class names should provide the primary summary of a failure. PHPDoc should add only details the name cannot express, such as message structure, execution context, recovery behavior, or compatibility constraints.

This is a documentation-only change with no runtime behavior changes.

Validation

  • composer test — 269 tests, 459 assertions

koriym and others added 30 commits September 11, 2024 01:23
Add try-catch block to manage missing dependencies during method injection. When a method is annotated with @Inject(optional=true), the code now returns gracefully if no dependency is provided. For methods with @Inject(optional=false), an exception is thrown if the dependency is unbound.
Removed unnecessary type suppression comments and refined type annotations to enhance code clarity across multiple classes. Updated several development dependencies in the composer.lock to their latest versions, ensuring compatibility and consistency. This update primarily affects internal documentation and tooling without altering functionality.
Add a check in the Injector class to verify that the temporary directory is writable before proceeding with the class directory initialization. Introduced a new exception, DirectoryNotWritable, to handle cases where the directory is not writable, enhancing error handling and code robustness.
Handle missing dependencies in setter methods with @Inject(optional=true)
The continuous integration workflow now supports PHP 8.4 as the current stable version. PHP 8.3 has been moved to the old_stable versions list to ensure compatibility continues with earlier versions.
Upgraded PHPStan and PHPStan-PHPUnit to version 2.0 to ensure compatibility with the latest features and improvements. Additionally, Symfony components have been updated to version 7.2.0 to benefit from bug fixes and performance enhancements. This update maintains alignment with the supported PHP versions and related dependencies.
This commit eliminates redundant assert statements to streamline the code and improve readability. Additionally, it uses `@phpstan-ignore-line` annotations to suppress specific warnings, enhancing compatibility with static analysis tools.
Removed unnecessary assertions such as `assert` and `property_exists` to make the tests cleaner and more efficient. Adjusted array handling by casting `bindings` to an array for better compatibility and added necessary code comments to suppress static analysis warnings where applicable. These changes improve the maintainability and readability of the codebase without affecting the functionality.
The PHPUnit version constraint in composer.json has been updated to "^8.5.40 || ^9.5" from "^8.5.24 || ^9.5" to ensure compatibility with recent bug fixes and improvements. This change will help maintain the stability and reliability of the development and testing environment.
This change updates the "ray/aop" package to version 2.16 in the composer.json file. The update aims to incorporate enhancements, bug fixes, or security improvements that come with the new version, ensuring better performance or compliance with the latest standards.
Update CI to support PHP 8.4 and include PHP 8.3 in old_stable
Add @psalm-pure and @psalm-immutable annotations to various classes to improve static analysis and enforce immutability. These changes ensure better code quality and maintainability by providing more explicit type information for tools like Psalm.
Cleaned up code by removing the default value for `Named::$value` and `Inject::$optional`, ensuring they must be explicitly set upon instantiation. The `psalm-pure` annotation was also removed from the `getStringName` function, reflecting the function's possible side effects or method calls. These changes improve code clarity and enforce proper initialization practices.
Corrected the spelling of "LazyInteterface" to "LazyInterface" in all relevant files to ensure consistent naming and prevent potential interface reference errors. This change impacts class implementations and annotations that depended on the misspelled interface name.
Enhance code quality with Psalm annotations
The "baseline" script generates static analysis baselines for PHPStan and Psalm. This simplifies managing analysis results and helps suppress existing issues for future incremental improvements.
Introduced baseline files for PHPStan and Psalm to suppress known issues temporarily, improving focus on new errors. Added references to these baselines in the respective configuration files to aid static analysis setup.
Moved Aspect-Oriented Programming (AOP) binding logic to a new `enableAop` method for better modularity and clarity. Replaced direct assertions with a safer method call (`__setBindings`) to streamline the binding process and improve maintainability.
Switched the Ray/AOP dependency from a stable version to the ^2.x-dev branch. This allows for using the latest development changes while maintaining compatibility with the project.
Added stricter type assertion in `AnnotatedClassMethods` with `assert` to ensure constructor type safety. Removed unnecessary suppression comments and improved type annotations for better code reliability and maintainability.
Upgraded multiple packages to ensure compatibility and receive the latest bug fixes and improvements. Adjusted metadata such as branch aliases and autoload paths where necessary. This helps maintain system stability and prepares for future development.
Disabled the `--show-info` output in the `sa` script for psalm to reduce unnecessary verbosity. This ensures the analysis output remains focused on essential issues.
Added a normalization function to standardize line endings to '\n' in string assertions for consistent behavior across environments. Updated the test to apply this normalization to both expected and actual strings.
Upgraded `vimeo/psalm` to `^6.8` and adjusted `phpmetrics` to support version `^2.7 || v3.0.0rc8`. Removed `psalm/plugin-phpunit` as it is no longer required.
koriym and others added 24 commits July 14, 2026 12:32
- Escape resolved href/data-src values (quotes included) and only link http(s)
  repositories, so composer.lock-derived URLs can't break the anchor markup or
  become a javascript: href.
- Contain the source-map build in try/catch: a malformed composer.lock (bad
  JSON via JSON_THROW_ON_ERROR, or unexpected shapes) omits the map instead of
  crashing the render.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… DI core

BindingsHtml is a pure markdown-to-HTML renderer: it imports no Ray\Di class
and nothing in the core references it, so it doesn't belong in the Ray\Di
namespace next to the DI primitives. The recording classes it sat beside —
BindingLog, BindingEvent, BindingsMarkdown — stay in Ray\Di, because Container
and ContainerFactory depend on them (moving those would cycle: ADP).

- src-bindings/BindingsHtml.php, namespace Ray\Bindings, autoloaded from the
  same ray/di package (vendor/bin/bindings-html stays built-in for every user)
- tests-bindings/BindingsHtmlTest.php, self-contained on a markdown fixture
  (no Injector/fakes), mirroring the source layout
- cs / phpstan / psalm / phpunit configured to cover the new directories

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A binding woven with aspects rendered as one long line that repeated the same
interceptor once per method. The Bindings section now shows each binding as a
ruled row with an indented sub-line that groups the intercepted methods under
each interceptor (by short class name, linked to source):

    Interface- => …Null
      aop  DbQueryInterceptor: listByCustomer, item, put, delete

The markdown is unchanged: this is a viewer-only re-decomposition, keeping the
plain-text record flat for grep/diff while the HTML presents the hierarchy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A toNull() binding resolves to a generated {Interface}{hash}Null class whose
hash is meaningless noise. The viewer now renders such targets as (null object)
— matching the provenance label, dropping the long generated class name (which
also fixes the awkward line wrap on AOP null-object bindings). The exact class
stays in the markdown.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A class bound to itself (bind(X) with no ->to()) renders as X- => (dependency) X.
The provenance already labels this (untargeted) via BindingEvent; the viewer now
does the same in the Bindings section, matching. The markdown is unchanged —
ModuleString still emits the full form (a data-layer change could align it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ModuleString now labels a class bound to itself (X- => (dependency) X) as
(untargeted), mirroring BindingEvent so the Bindings section and the provenance
agree — no benefit to keeping the redundant self-reference. Covered by a new
BindingsMarkdownTest case; ModuleTest::testToString's golden string is updated
to match (FakeDoubleInterceptor is self-bound).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add Ray\Di\BindingsHtml: a shared HTML viewer for bindings.md
- static-analysis: 8.4 -> 8.5
- mutation-testing: 8.4 -> 8.5
- coding-standards: 8.3 -> 8.4
- demo: 8.3 -> 8.4
- prefer-lowest: stays at 8.2 (minimum supported)
- continuous-integration: unchanged (already tests 8.2-8.5)
Each exception leads with its class name stating what went wrong and uses
the phpdoc only for what the name cannot carry: a "Message format:" line
when the message is just variables, plus the path by which execution
reaches the throw and any design reason or recovery behavior.

Class names that already say it all (Unbound, CircularDependency,
RenameTargetAlreadyBound, UncallableSetterMethod, DirectoryNotWritable,
InvalidToConstructorNameParameter) drop the redundant "Thrown when ..."
summary line and open directly with the message format.

No runtime behavior changes; phpdoc only. The convention is also recorded
under Framework Patterns in CLAUDE.md.
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 251 files, which is 101 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e6dd9aca-01b4-4e06-a0fa-e9b5de55104a

📥 Commits

Reviewing files that changed from the base of the PR and between a9e13de and e8a9d25.

⛔ Files ignored due to path filters (1)
  • vendor-bin/tools/composer.lock is excluded by !**/*.lock
📒 Files selected for processing (251)
  • .gitattributes
  • .github/workflows/coding-standards.yml
  • .github/workflows/continuous-integration.yml
  • .github/workflows/demo.yml
  • .github/workflows/mutation-testing.yml
  • .github/workflows/prefer-lowest.yml
  • .github/workflows/static-analysis.yml
  • .github/workflows/update-copyright-years-in-license-file.yml
  • .gitignore
  • .scrutinizer.yml
  • .sonarcloud.properties
  • CHANGELOG.md
  • CLAUDE.md
  • LICENSE
  • bin/bindings-html
  • composer.json
  • demo-php8/01a-linked-binding.php
  • demo-php8/01b-linked-binding-setter-injection.php
  • demo-php8/02-provider-binding.php
  • demo-php8/02a-named-by-qualifier.php
  • demo-php8/02b-named-by-named.php
  • demo-php8/03-injection-point.php
  • demo-php8/04-untarget-binding.php
  • demo-php8/05a-constructor-binding.php
  • demo-php8/05b-constructor-binding-setter-injection.php
  • demo-php8/07-assisted-injection.php
  • demo-php8/10-cache.php
  • demo-php8/11-script-injector.php
  • demo-php8/12-dependency-chain-error-message.php
  • demo-php8/chain-error/A.php
  • demo-php8/chain-error/B.php
  • demo-php8/chain-error/C.php
  • demo-php8/chain-error/D.php
  • demo-php8/chain-error/EInterface.php
  • demo-php8/finder/Db.php
  • demo-php8/finder/DbFinder.php
  • demo-php8/finder/DbInterface.php
  • demo-php8/finder/Finder.php
  • demo-php8/finder/FinderInterface.php
  • demo-php8/finder/FinderModule.php
  • demo-php8/finder/MovieFinder.php
  • demo-php8/finder/MovieLister.php
  • demo-php8/finder/MovieListerInterface.php
  • demo-php8/finder/Sorter.php
  • demo-php8/run.php
  • demo-php8/tmp/.gitkeep
  • demo/01a-linked-binding.php
  • demo/01b-linked-binding-setter-injection.php
  • demo/02-provider-binding.php
  • demo/02a-named-by-qualifier.php
  • demo/02b-named-by-named.php
  • demo/03-injection-point.php
  • demo/05b-constructor-binding-setter-injection.php
  • demo/chain-error/A.php
  • demo/chain-error/B.php
  • demo/chain-error/C.php
  • demo/chain-error/D.php
  • demo/finder/Db.php
  • demo/finder/DbFinder.php
  • demo/finder/MovieFinder.php
  • demo/finder/MovieLister.php
  • demo/run.php
  • docs/bindings/bindings.css
  • docs/bindings/bindings.js
  • infection.json5
  • phpcs.xml
  • phpstan.neon
  • phpunit.xml.dist
  • psalm.xml
  • rector.php
  • src-bindings/BindingsHtml.php
  • src-deprecated/di/BcParameterQualifier.php
  • src-deprecated/di/BcStringParser.php
  • src/di/AbstractModule.php
  • src/di/AnnotatedClass.php
  • src/di/AnnotatedClassMethods.php
  • src/di/Annotation/ScriptDir.php
  • src/di/Argument.php
  • src/di/Arguments.php
  • src/di/AspectBind.php
  • src/di/AssistedInjectInterceptor.php
  • src/di/AssistedInjectModule.php
  • src/di/AssistedInterceptor.php
  • src/di/AssistedModule.php
  • src/di/Bind.php
  • src/di/BindValidator.php
  • src/di/BindingEvent.php
  • src/di/BindingLog.php
  • src/di/BindingsMarkdown.php
  • src/di/CompileNullObject.php
  • src/di/Container.php
  • src/di/ContainerFactory.php
  • src/di/Dependency.php
  • src/di/DependencyFactory.php
  • src/di/DependencyInterface.php
  • src/di/DependencyProvider.php
  • src/di/Di/Assisted.php
  • src/di/Di/Inject.php
  • src/di/Di/Named.php
  • src/di/Di/PostConstruct.php
  • src/di/Di/Qualifier.php
  • src/di/Di/Set.php
  • src/di/Exception.php
  • src/di/Exception/CircularDependency.php
  • src/di/Exception/DirectoryNotWritable.php
  • src/di/Exception/ExceptionInterface.php
  • src/di/Exception/InvalidAssistedInjectMatch.php
  • src/di/Exception/InvalidContext.php
  • src/di/Exception/InvalidProvider.php
  • src/di/Exception/InvalidToConstructorNameParameter.php
  • src/di/Exception/InvalidType.php
  • src/di/Exception/MethodInvocationNotAvailable.php
  • src/di/Exception/NoHint.php
  • src/di/Exception/NotFound.php
  • src/di/Exception/ReadOnlyMapAccess.php
  • src/di/Exception/RenameTargetAlreadyBound.php
  • src/di/Exception/SetNotFound.php
  • src/di/Exception/SpyCompilerNotInstantiable.php
  • src/di/Exception/Unbound.php
  • src/di/Exception/UncallableSetterMethod.php
  • src/di/Exception/Untargeted.php
  • src/di/Grapher.php
  • src/di/InjectionPoint.php
  • src/di/InjectionPointInterface.php
  • src/di/InjectionPoints.php
  • src/di/Injector.php
  • src/di/Instance.php
  • src/di/Matcher/AssistedInjectMatcher.php
  • src/di/MethodInvocationProvider.php
  • src/di/ModuleString.php
  • src/di/MultiBinder.php
  • src/di/MultiBinding/LazyInstance.php
  • src/di/MultiBinding/LazyInterface.php
  • src/di/MultiBinding/LazyProvider.php
  • src/di/MultiBinding/LazyTo.php
  • src/di/MultiBinding/Map.php
  • src/di/MultiBinding/MapProvider.php
  • src/di/MultiBinding/MultiBindingModule.php
  • src/di/MultiBinding/MultiBindings.php
  • src/di/Name.php
  • src/di/NameKeyVarString.php
  • src/di/NewInstance.php
  • src/di/NullDependency.php
  • src/di/NullModule.php
  • src/di/NullObjectDependency.php
  • src/di/ProviderInterface.php
  • src/di/ProviderProvider.php
  • src/di/ProviderSetModule.php
  • src/di/ProviderSetProvider.php
  • src/di/SetterMethod.php
  • src/di/SetterMethods.php
  • src/di/SpyCompiler.php
  • src/di/Types.php
  • src/di/Untarget.php
  • src/di/VisitorInterface.php
  • tests-bindings/BindingsHtmlTest.php
  • tests-php8/AssistedInjectTest.php
  • tests-php8/DualReaderTest.php
  • tests/bootstrap.php
  • tests/deleteFiles.php
  • tests/di/AbstractModuleTest.php
  • tests/di/AnnotatedClassTest.php
  • tests/di/ArgumentTest.php
  • tests/di/ArgumentsTest.php
  • tests/di/AssistedTest.php
  • tests/di/BcParameterQualifierIntegrationTest.php
  • tests/di/BcParameterQualifierTest.php
  • tests/di/BcStringParserTest.php
  • tests/di/BindTest.php
  • tests/di/BindingLogTest.php
  • tests/di/BindingsMarkdownTest.php
  • tests/di/CircularDependencyTest.php
  • tests/di/ContainerTest.php
  • tests/di/DependencyProviderTest.php
  • tests/di/DependencyTest.php
  • tests/di/Fake/Annotation/FakeInjectOne.php
  • tests/di/Fake/Annotation/FakeQualifierOnly.php
  • tests/di/Fake/FakeAnnoClass.php
  • tests/di/Fake/FakeAnnoMethod1.php
  • tests/di/Fake/FakeAnnoMethod2.php
  • tests/di/Fake/FakeAnnoMethod3.php
  • tests/di/Fake/FakeAnnoOrderClass.php
  • tests/di/Fake/FakeAssistedConsumer.php
  • tests/di/Fake/FakeAssistedParamsConsumer.php
  • tests/di/Fake/FakeBcConstructorQualifierClass.php
  • tests/di/Fake/FakeBcParameterQualifierClass.php
  • tests/di/Fake/FakeBcParameterQualifierModule.php
  • tests/di/Fake/FakeBindingLogInnerModule.php
  • tests/di/Fake/FakeBindingLogInstalledModule.php
  • tests/di/Fake/FakeBindingLogModule.php
  • tests/di/Fake/FakeCar.php
  • tests/di/Fake/FakeCarModule.php
  • tests/di/Fake/FakeCircularA.php
  • tests/di/Fake/FakeCircularAInterface.php
  • tests/di/Fake/FakeCircularB.php
  • tests/di/Fake/FakeCircularBInterface.php
  • tests/di/Fake/FakeClassWithBcParameterQualifier.php
  • tests/di/Fake/FakeClosureBindModule.php
  • tests/di/Fake/FakeConstant.php
  • tests/di/Fake/FakeConstantConsumer.php
  • tests/di/Fake/FakeConstructCounter.php
  • tests/di/Fake/FakeCountingMatcher.php
  • tests/di/Fake/FakeDiamondRoot.php
  • tests/di/Fake/FakeDiamondShared.php
  • tests/di/Fake/FakeDiamondSharedInterface.php
  • tests/di/Fake/FakeGearStickInject.php
  • tests/di/Fake/FakeHandleBar.php
  • tests/di/Fake/FakeHandleBarQualifier.php
  • tests/di/Fake/FakeHandleProvider.php
  • tests/di/Fake/FakeIncrementInterceptor.php
  • tests/di/Fake/FakeInjectionPoint.php
  • tests/di/Fake/FakeInternalTypes.php
  • tests/di/Fake/FakeLeft.php
  • tests/di/Fake/FakeMultiBindingAnnotation.php
  • tests/di/Fake/FakeMultiInterceptorModule.php
  • tests/di/Fake/FakeMultiQualifierConsumer.php
  • tests/di/Fake/FakeNoConstructorCallModule.php
  • tests/di/Fake/FakeNullProvider.php
  • tests/di/Fake/FakePdoModule.php
  • tests/di/Fake/FakePhp8Car.php
  • tests/di/Fake/FakePhp8CarModule.php
  • tests/di/Fake/FakePostConstructCounter.php
  • tests/di/Fake/FakeRight.php
  • tests/di/Fake/FakeRobot2.php
  • tests/di/Fake/FakeSelfCircular.php
  • tests/di/Fake/FakeSelfCircularInterface.php
  • tests/di/Fake/FakeUnNamedClass.php
  • tests/di/Fake/FakeUnNamedModule.php
  • tests/di/Fake/FakeVariadicConstructor.php
  • tests/di/Fake/FakeWalkRobot.php
  • tests/di/Fake/FakeWalkRobotLegProviderWithOtherDep.php
  • tests/di/Fake/FakeWalkRobotOtherDepModule.php
  • tests/di/Fake/FakeWarmup.php
  • tests/di/Fake/FakeWarmupDependent.php
  • tests/di/GrapherTest.php
  • tests/di/InjectionPointTest.php
  • tests/di/InjectionPointsTest.php
  • tests/di/InjectorTest.php
  • tests/di/ModuleCompositionTest.php
  • tests/di/ModuleTest.php
  • tests/di/MultiBinding/MultiBinderTest.php
  • tests/di/MultiBinding/MultiBindingModuleTest.php
  • tests/di/NameTest.php
  • tests/di/NewInstanceTest.php
  • tests/di/NoHintTest.php
  • tests/di/README.md
  • tests/di/RenameTest.php
  • tests/di/SetterMethodTest.php
  • tests/di/VisitorTest.php
  • tests/type/InjectorInterfaceTest.php
  • vendor-bin/tools/composer.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch exception-doc

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

koriym commented Jul 15, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@codacy-production

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 5 critical · 38 high · 2 medium · 3 minor

Alerts:
⚠ 48 issues (≤ 0 issues of at least minor severity)

Results:
48 new issues

Category Results
UnusedCode 2 minor
Security 5 critical
38 high
CodeStyle 1 minor
Complexity 2 medium

View in Codacy

🟢 Metrics 158 complexity · 0 duplication

Metric Results
Complexity 158
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (a318795) to head (e8a9d25).
⚠️ Report is 131 commits behind head on 2.x.

Additional details and impacted files
@@             Coverage Diff              @@
##                 2.x       #14    +/-   ##
============================================
  Coverage     100.00%   100.00%            
- Complexity       351       434    +83     
============================================
  Files             47        51     +4     
  Lines            911      1130   +219     
============================================
+ Hits             911      1130   +219     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@koriym koriym closed this Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants