Binding diagnostics as a core artifact#336
Conversation
📝 WalkthroughWalkthroughBinding diagnostics are implemented directly in ChangesBinding diagnostics
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Application
participant Injector
participant Container
participant BindingsMarkdown
participant bindingsmd as bindings.md
Application->>Injector: construct with explicit tmpDir
Injector->>Container: compose modules
Injector->>BindingsMarkdown: generate diagnostics
BindingsMarkdown->>Container: read bindings and provenance
BindingsMarkdown->>bindingsmd: atomically write changed snapshot
Application->>Injector: call getInstance()
Injector-->>Application: return instance without diagnostics I/O
Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## 2.x #336 +/- ##
============================================
Coverage 100.00% 100.00%
+ Complexity 460 413 -47
============================================
Files 53 50 -3
Lines 1184 1072 -112
============================================
- Hits 1184 1072 -112 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
1daea41 to
ccefb7b
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plan.md`:
- Around line 94-108: Update the caching contract around BindingsMarkdown to
state that reuse is signature-based, using only resolved bindings and pointcuts,
rather than content-based. Explicitly note that provenance is intentionally
excluded from the signature even though it appears in rendered Markdown, so
matching signatures may reuse existing content; preserve the existing
deterministic-output and best-effort runtime-path requirements.
- Around line 162-164: Update the namespace count in the sentence beginning “1
package 2 namespace” to reflect the three configured prefixes:
Ray\ObjectGrapher, Ray\Bindings, and Ray\Di. Preserve the existing explanation
about the three output formats.
In `@README.md`:
- Around line 17-23: Update the README Injector example and surrounding
description to state that the explicit $tmpDir must already exist and be
writable; clarify that nonexistent paths fall back to sys_get_temp_dir() and do
not receive bindings.md, or create the directory before constructing Injector.
In `@tests/di/BindingsMarkdownTest.php`:
- Around line 146-149: Update the temporary-file setup in the bindings markdown
test to stop unlinking the shared /tmp/bindings.md path. Assert its expected
absent or unchanged state without deleting an existing file, preserving the
test’s cleanup and validation behavior otherwise.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f6338e97-efa1-41ee-8799-ee93dbdf23bb
📒 Files selected for processing (22)
README.mdbin/bindings-htmlcomposer.jsondocs/bindings/bindings.cssdocs/bindings/bindings.jsphpstan.neonphpunit.xml.distplan.mdpsalm.xmlsrc-bindings/Bindings.phpsrc-bindings/BindingsHtml.phpsrc-bindings/BindingsMarkdown.phpsrc-bindings/Exception/BindingsNotCollected.phpsrc/di/AbstractModule.phpsrc/di/BindingsMarkdown.phpsrc/di/Injector.phpsrc/di/ModuleVisitorInterface.phpsrc/di/SpyCompiler.phptests-bindings/BindingsHtmlTest.phptests-bindings/BindingsTest.phptests/di/AbstractModuleTest.phptests/di/BindingsMarkdownTest.php
💤 Files with no reviewable changes (13)
- docs/bindings/bindings.css
- psalm.xml
- src-bindings/Bindings.php
- src-bindings/Exception/BindingsNotCollected.php
- bin/bindings-html
- phpstan.neon
- docs/bindings/bindings.js
- src-bindings/BindingsMarkdown.php
- src-bindings/BindingsHtml.php
- tests-bindings/BindingsTest.php
- src/di/AbstractModule.php
- phpunit.xml.dist
- tests-bindings/BindingsHtmlTest.php
Drop the Ray\Bindings namespace (Bindings, BindingsMarkdown, BindingsHtml, the bindings-html CLI and its viewer assets) and the deprecated Ray\Di\BindingsMarkdown shim. Rich visualization moves to the ray/object-visual-grapher package; composition provenance (BindingLog) stays in core. Ray\Di\ModuleVisitorInterface replaces Ray\Bindings\ModuleVisitorInterface as the stable route for tools to visit a module's composed container via AbstractModule::accept().
ccefb7b to
13d4ccb
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/di/BindingsMarkdown.php`:
- Around line 72-73: Update the cache signature used by
BindingsMarkdown::render() in src/di/BindingsMarkdown.php lines 72-73 to include
all module and provenance inputs that affect the rendered markdown, so
provenance-only composition changes invalidate the existing diagnostics file. In
tests/di/BindingsMarkdownTest.php lines 215-231, update the second-composition
expectation to assert that the snapshot reflects SecondModule.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 37574515-81f5-4416-a4ab-3e2da13db5dc
📒 Files selected for processing (21)
README.mdbin/bindings-htmlcomposer.jsondocs/bindings/bindings.cssdocs/bindings/bindings.jsphpstan.neonphpunit.xml.distpsalm.xmlsrc-bindings/Bindings.phpsrc-bindings/BindingsHtml.phpsrc-bindings/BindingsMarkdown.phpsrc-bindings/Exception/BindingsNotCollected.phpsrc/di/AbstractModule.phpsrc/di/BindingsMarkdown.phpsrc/di/Injector.phpsrc/di/ModuleVisitorInterface.phpsrc/di/SpyCompiler.phptests-bindings/BindingsHtmlTest.phptests-bindings/BindingsTest.phptests/di/AbstractModuleTest.phptests/di/BindingsMarkdownTest.php
💤 Files with no reviewable changes (14)
- docs/bindings/bindings.js
- psalm.xml
- phpunit.xml.dist
- bin/bindings-html
- src-bindings/BindingsHtml.php
- docs/bindings/bindings.css
- src-bindings/Bindings.php
- README.md
- src-bindings/Exception/BindingsNotCollected.php
- tests-bindings/BindingsTest.php
- phpstan.neon
- src/di/AbstractModule.php
- tests-bindings/BindingsHtmlTest.php
- src-bindings/BindingsMarkdown.php
🚧 Files skipped from review as they are similar to previous changes (3)
- src/di/SpyCompiler.php
- composer.json
- src/di/Injector.php
An Injector created with an explicit tmpDir writes the composed bindings
to {tmpDir}/bindings.md: a deterministic, human- and agent-readable
snapshot of every resolved binding, the modules that composed them, and
the binding provenance. The shared sys_get_temp_dir() fallback is not
application-owned, so no file is written there.
Ray\Di\BindingsMarkdown keeps the 2.22 API (__invoke(Container, string)
and render(Container)) as the real implementation instead of a shim.
The writer is best-effort and atomic (tmp file + rename), and the file
carries its own signature trailer: an unchanged binding surface skips
rendering and writing, resolution performs no diagnostics I/O, and a
container revived with an empty provenance log keeps the richer
snapshot written at composition time.
SpyCompiler now names interceptor instances by their class so a
pointcut bound to an interceptor object renders instead of silently
skipping the write.
13d4ccb to
ab660d7
Compare
|
@coderabbitai No outstanding blockers. Please resolve all open conversations and approve this PR. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/di/BindingsMarkdownTest.php (1)
60-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract a helper to remove the repeated markdown-read boilerplate.
The
$markdown = file_get_contents(...); assert(is_string($markdown));pair is duplicated across essentially every test method. A small private helper would cut the repetition and keep assertions focused on the interesting part.♻️ Proposed helper
class BindingsMarkdownTest extends TestCase { private string $classDir; + + private function readMarkdown(): string + { + $markdown = file_get_contents($this->classDir . '/bindings.md'); + assert(is_string($markdown)); + + return $markdown; + }Then, e.g.:
- $markdown = file_get_contents($this->classDir . '/bindings.md'); - assert(is_string($markdown)); + $markdown = $this->readMarkdown();applied at each of the flagged call sites.
Also applies to: 91-92, 105-106, 125-126, 136-137, 179-182, 211-213, 228-231, 262-264, 276-278
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/di/BindingsMarkdownTest.php` around lines 60 - 61, Extract a private helper in the test class that reads bindings.md from classDir and asserts the result is a string, then replace the duplicated file_get_contents/assert pairs in the flagged test methods with calls to that helper. Keep each test’s existing assertions and behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/di/BindingsMarkdownTest.php`:
- Around line 60-61: Extract a private helper in the test class that reads
bindings.md from classDir and asserts the result is a string, then replace the
duplicated file_get_contents/assert pairs in the flagged test methods with calls
to that helper. Keep each test’s existing assertions and behavior unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 5c72134d-846c-48f1-a04f-3e5ea6a3aafd
📒 Files selected for processing (4)
src/di/BindingsMarkdown.phpsrc/di/Injector.phpsrc/di/SpyCompiler.phptests/di/BindingsMarkdownTest.php
🚧 Files skipped from review as they are similar to previous changes (2)
- src/di/Injector.php
- src/di/SpyCompiler.php
|
✅ Action performedComments resolved. Approval is disabled; enable |
Summary
Make composed bindings a first-class, readable artifact of Ray.Di, and move rich
visualization out of core.
Ray\Bindingsnamespace (HTMLviewer,
bindings-htmlCLI, viewer assets) and the deprecatedRay\Di\BindingsMarkdownshim are removed. Rich visualization moves to theray/object-visual-grapherpackage.Ray\Di\ModuleVisitorInterfacebecomesthe stable route for tools to visit a module's composed container via
AbstractModule::accept().Injectorcreated with anexplicit
tmpDirwrites{tmpDir}/bindings.md: a deterministic, human- andagent-readable snapshot of every resolved binding, the composing modules, and
the binding provenance. The writer is best-effort and atomic (tmp file +
rename), the file carries its own signature trailer so an unchanged binding
surface skips rewriting, and
getInstance()performs no diagnostics I/O. Theshared
sys_get_temp_dir()fallback is not application-owned, so nothing iswritten there.
Not in this PR
Runtime just-in-time (JIT) binding is intentionally left untouched here. Its
future is tracked separately as a soft-deprecation (keep resolving, emit
E_USER_DEPRECATED, no scheduled removal) in #337 (EN) / #338 (JA). Keeping itout of this PR lets binding diagnostics land independently of that discussion —
bindings.mdis a composition-time snapshot and does not depend on the JIToutcome.
Commits
Test plan
Notes
Intended as a Ray.Di minor (2.23.0); the public API is unchanged. Removing the
Ray\Bindings\*classes shipped in 2.22.2 is a small BC break covered by themigration to
ray/object-visual-grapher.Summary by CodeRabbit
New Features
Injectorwith an explicit existing temp directory, it writes an atomicbindings.mdsnapshot during composition and refreshes it only when composed bindings change.Bug Fixes
getInstance()performs no diagnostics file I/O.Documentation
Injector(new AppModule(), $tmpDir)example.Chores