Skip to content

Add demo for Ray.Compiler usage#130

Merged
koriym merged 2 commits into1.xfrom
demo
Nov 18, 2025
Merged

Add demo for Ray.Compiler usage#130
koriym merged 2 commits into1.xfrom
demo

Conversation

@koriym
Copy link
Member

@koriym koriym commented Nov 18, 2025

Summary

  • Add working demo demonstrating Ray.Compiler's two-phase architecture
  • Includes complete example: interface, implementation, module, compile script, and run script
  • Comprehensive README with technical documentation

Demo Structure

Files:

  • GreeterInterface.php - Service interface
  • Greeter.php - Service implementation with constructor injection
  • AppModule.php - Ray.Di module defining bindings
  • compile.php - Build-time compilation script
  • run.php - Runtime execution script using CompiledInjector
  • README.md - Complete documentation with architecture explanation

Usage:

# Compile (build time)
php demo/compile.php

# Run (production)
php demo/run.php

Documentation Highlights

The README explains:

  • Two-phase architecture (compile-time vs runtime)
  • Generated script inspection
  • Performance benefits (no reflection, no dependency resolution at runtime)
  • Visual architecture diagram
  • Next steps for exploration

Test Plan

  • Run compilation script successfully
  • Verify generated scripts in .compiled/ directory
  • Execute runtime script and verify output
  • Confirm .compiled/ directory is gitignored
  • Validate autoload configuration in composer.json

🤖 Generated with Claude Code

Summary by Sourcery

Provide a working example of Ray.Compiler's two-phase dependency injection process, showcasing compile-time container generation and lightweight runtime execution.

New Features:

  • Add a complete Ray.Compiler demo with service interface, implementation, DI module, and compile/run scripts

Build:

  • Configure composer.json to autoload the demo namespace
  • Ignore demo/.compiled directory in .gitignore

Documentation:

  • Add a comprehensive demo README with architecture overview, usage steps, and performance benefits

Summary by CodeRabbit

  • New Features

    • Added a demo app with a simple greeter, plus scripts to compile and run a pre-compiled runtime for faster startup.
  • Documentation

    • Added a comprehensive demo README with architecture overview, usage steps, and inspection guidance for generated outputs.
  • Chores

    • Updated project config to include demo resources, ignored generated artifacts, and extended CI to run the demo compile/run steps.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

Warning

Rate limit exceeded

@koriym has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 17 minutes and 1 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between d7717c5 and dee40a5.

📒 Files selected for processing (9)
  • .github/workflows/continuous-integration.yml (1 hunks)
  • .gitignore (1 hunks)
  • composer.json (1 hunks)
  • demo/AppModule.php (1 hunks)
  • demo/Greeter.php (1 hunks)
  • demo/GreeterInterface.php (1 hunks)
  • demo/README.md (1 hunks)
  • demo/compile.php (1 hunks)
  • demo/run.php (1 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a demo for Ray\Compiler: new demo namespace, Greeter interface and implementation, a DI AppModule, compile/run scripts, generated compiled artifacts under demo/.compiled, README documentation, composer autoload-dev mapping, .gitignore update, and CI step to run the demo scripts.

Changes

Cohort / File(s) Summary
Build config
\.gitignore``, composer.json
Added /demo/.compiled to .gitignore. Added autoload-dev PSR-4 mapping "Ray\\Compiler\\Demo\\": "demo" in composer.json.
Demo API & DI module
demo/GreeterInterface.php, demo/Greeter.php, demo/AppModule.php
Added GreeterInterface::greet(string): string. Implemented Greeter (readonly $greeting, constructor, greet) and AppModule binding GreeterInterfaceGreeter.
Demo scripts
demo/compile.php, demo/run.php
Added compile.php to compile the DI container into demo/.compiled/. Added run.php to load the compiled injector and invoke the greeter at runtime.
Documentation
demo/README.md
Added README describing compile-time vs runtime workflow, usage steps, generated artifacts location, and inspection guidance.
CI workflow
.github/workflows/continuous-integration.yml
Added execution of demo/compile.php && php demo/run.php to the reusable workflow invocation.
Generated compiled artifacts
demo/.compiled/*
Added multiple generated PHP artifacts under demo/.compiled/ (e.g., -Ray_Compiler_Annotation_Compile.php, Ray_Compiler_Demo_GreeterInterface-.php, Ray_Di_*.php, etc.) representing pre-compiled providers, singletons, and injector bootstrap code.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant compile.php
    participant Compiler
    participant FileSystem as ".compiled/"
    participant run.php
    participant CompiledInjector
    participant Greeter

    rect rgb(220,235,255)
    Note over User,FileSystem: Compile-time
    User->>compile.php: php demo/compile.php
    compile.php->>Compiler: compile AppModule
    Compiler->>FileSystem: write generated PHP into .compiled/
    FileSystem-->>compile.php: path written
    compile.php-->>User: show confirmation
    end

    rect rgb(235,255,220)
    Note over User,Greeter: Runtime
    User->>run.php: php demo/run.php
    run.php->>CompiledInjector: load compiled container from .compiled/
    CompiledInjector->>Greeter: instantiate Greeter (no reflection)
    run.php->>Greeter: call greet("World")
    Greeter-->>run.php: "Hello World"
    run.php-->>User: print result
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review focus:
    • demo/compile.php and demo/run.php for correct Compiler/CompiledInjector usage and paths.
    • Composer autoload-dev mapping and .gitignore entry.
    • Generated artifacts in demo/.compiled/ only require sanity checks (consistency, path correctness).
    • README and CI workflow step for accuracy.

Poem

🐇 In a burrow of code I hop and compile,
Greeter bundled up, all neat and agile.
Build-time magic, runtime so spry,
No reflection needed — just blink and reply.
Hooray — compiled rabbits leap sky-high! 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add demo for Ray.Compiler usage' directly and clearly describes the primary change: introducing a complete demo showcasing Ray.Compiler's two-phase architecture with supporting files, documentation, and CI integration.

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 and usage tips.

@sourcery-ai
Copy link

sourcery-ai bot commented Nov 18, 2025

Reviewer's Guide

Introduce a complete Ray.Compiler demo by registering the demo namespace, adding the service interface and implementation with DI module, build-time compilation and runtime scripts, and comprehensive documentation.

Sequence diagram for build-time compilation and runtime injection (Ray.Compiler Demo)

sequenceDiagram
    participant Dev as "Developer (actor)"
    participant CompileScript as "compile.php"
    participant AppModule
    participant Compiler
    participant ScriptDir as ".compiled/"
    participant RunScript as "run.php"
    participant CompiledInjector
    participant GreeterInterface
    participant Greeter

    Dev->>CompileScript: Run compile.php
    CompileScript->>AppModule: Instantiate AppModule
    CompileScript->>Compiler: Pass AppModule to Compiler
    Compiler->>ScriptDir: Generate compiled scripts
    Dev->>RunScript: Run run.php
    RunScript->>CompiledInjector: Instantiate with .compiled/
    CompiledInjector->>GreeterInterface: getInstance(GreeterInterface)
    GreeterInterface->>Greeter: greet('World')
    GreeterInterface->>Greeter: greet('Ray.Compiler')
Loading

Class diagram for Greeter service and DI module (Ray.Compiler Demo)

classDiagram
    class GreeterInterface {
        +greet(string $name): string
    }
    class Greeter {
        +__construct(string $greeting = 'Hello')
        +greet(string $name): string
    }
    GreeterInterface <|.. Greeter
    class AppModule {
        +configure(): void
    }
    AppModule --|> AbstractModule
    AppModule ..> GreeterInterface : binds to
    GreeterInterface <.. AppModule : binding
    Greeter <.. AppModule : binding
Loading

File-Level Changes

Change Details Files
Register demo namespace in autoload
  • Add PSR-4 mapping for Ray\Compiler\Demo in autoload-dev
composer.json
Add service interface, implementation, and DI module
  • Define GreeterInterface
  • Implement Greeter with constructor injection
  • Configure DI binding in AppModule
demo/GreeterInterface.php
demo/Greeter.php
demo/AppModule.php
Add build-time compilation and runtime scripts
  • Create compile.php to generate optimized scripts
  • Create run.php using CompiledInjector for execution
demo/compile.php
demo/run.php
Add comprehensive demo documentation
  • Document two-phase architecture and usage
  • Include code inspection steps, benefits, and architecture diagram
demo/README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@codecov
Copy link

codecov bot commented Nov 18, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (78492de) to head (dee40a5).
⚠️ Report is 3 commits behind head on 1.x.

Additional details and impacted files
@@             Coverage Diff             @@
##                 1.x      #130   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
  Complexity        93        93           
===========================================
  Files             11        11           
  Lines            232       232           
===========================================
  Hits             232       232           

☔ View full report in Codecov by Sentry.
📢 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.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Add demo/.compiled/ to .gitignore so generated scripts aren’t accidentally committed.
  • In compile.php, create the .compiled directory if it doesn’t exist to avoid manual setup errors.
  • In README, note the PHP version requirement (e.g. PHP 8.1+ for readonly properties) in the prerequisites section.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Add demo/.compiled/ to .gitignore so generated scripts aren’t accidentally committed.
- In compile.php, create the .compiled directory if it doesn’t exist to avoid manual setup errors.
- In README, note the PHP version requirement (e.g. PHP 8.1+ for readonly properties) in the prerequisites section.

## Individual Comments

### Comment 1
<location> `demo/run.php:10-15` </location>
<code_context>
+$scriptDir = __DIR__ . '/.compiled';
+
+// Use the compiled injector (no Ray.Di runtime overhead)
+$injector = new CompiledInjector($scriptDir);
+
+/** @var GreeterInterface $greeter */
</code_context>

<issue_to_address>
**suggestion:** Consider handling injector instantiation errors for robustness.

If CompiledInjector fails due to missing or corrupted scripts, exceptions may occur. Adding validation or error handling here will make the code more robust.

```suggestion
$scriptDir = __DIR__ . '/.compiled';

// Use the compiled injector (no Ray.Di runtime overhead) with error handling
try {
    $injector = new CompiledInjector($scriptDir);
} catch (\Throwable $e) {
    fwrite(STDERR, "Failed to instantiate CompiledInjector: " . $e->getMessage() . "\n");
    exit(1);
}

/** @var GreeterInterface $greeter */
```
</issue_to_address>

### Comment 2
<location> `demo/compile.php:15` </location>
<code_context>
+
+// Compile the dependency injection container
+$compiler = new Compiler();
+$compiler->compile($module, $scriptDir);
+
+echo "✓ Compilation complete! Scripts saved to: {$scriptDir}\n";
</code_context>

<issue_to_address>
**suggestion:** Consider handling compilation errors to improve user feedback.

Wrap the compile call in a try-catch block and display any errors to ensure users receive clear feedback if compilation fails.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +10 to +15
$scriptDir = __DIR__ . '/.compiled';

// Use the compiled injector (no Ray.Di runtime overhead)
$injector = new CompiledInjector($scriptDir);

/** @var GreeterInterface $greeter */
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Consider handling injector instantiation errors for robustness.

If CompiledInjector fails due to missing or corrupted scripts, exceptions may occur. Adding validation or error handling here will make the code more robust.

Suggested change
$scriptDir = __DIR__ . '/.compiled';
// Use the compiled injector (no Ray.Di runtime overhead)
$injector = new CompiledInjector($scriptDir);
/** @var GreeterInterface $greeter */
$scriptDir = __DIR__ . '/.compiled';
// Use the compiled injector (no Ray.Di runtime overhead) with error handling
try {
$injector = new CompiledInjector($scriptDir);
} catch (\Throwable $e) {
fwrite(STDERR, "Failed to instantiate CompiledInjector: " . $e->getMessage() . "\n");
exit(1);
}
/** @var GreeterInterface $greeter */

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
demo/README.md (2)

46-53: Add language identifier to the output code block.

The code block showing expected output should specify a language identifier for proper syntax highlighting.

Apply this diff:

-```
+```text
 Hello, World!
 Hello, Ray.Compiler!

74-91: Add language identifier to the ASCII diagram code block.

The ASCII diagram should specify a language identifier (e.g., text) to satisfy markdown linting rules.

Apply this diff:

-```
+```text
 ┌─────────────────┐         ┌──────────────┐
 │  Ray.Di Module  │────────▶│   Compiler   │
demo/run.php (1)

10-16: Consider adding error handling for better user experience.

If the .compiled directory or bindings are missing (e.g., user forgets to run compile.php first), the script will throw an exception. Consider wrapping the injector creation and getInstance calls in a try-catch with a friendly error message directing users to run compile.php first.

Example enhancement:

try {
    $injector = new CompiledInjector($scriptDir);
    $greeter = $injector->getInstance(GreeterInterface::class);
} catch (\Exception $e) {
    echo "Error: Failed to load compiled scripts.\n";
    echo "Please run 'php demo/compile.php' first to generate the compiled scripts.\n";
    echo "Details: {$e->getMessage()}\n";
    exit(1);
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 78492de and cc676a9.

📒 Files selected for processing (8)
  • .gitignore (1 hunks)
  • composer.json (1 hunks)
  • demo/AppModule.php (1 hunks)
  • demo/Greeter.php (1 hunks)
  • demo/GreeterInterface.php (1 hunks)
  • demo/README.md (1 hunks)
  • demo/compile.php (1 hunks)
  • demo/run.php (1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: tests/Fake/CompileVisitor/FakeQux.php:7-23
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `InjectorInterface` in the `Ray\Di` namespace may not be directly visible in static analysis due to dynamic inclusion or being part of external dependencies. This was inferred from the user's assertion and the fact that related tests are passing.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: README.md:13-14
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `CompileInjector` class now uses `Compiler` to compile modules and initializes `AirInjector`. This change should be documented in the README.md.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:27-118
Timestamp: 2025-01-12T05:02:54.169Z
Learning: Dynamic script loading using `require` with variable paths is a necessary feature in Ray.Compiler's dependency injection system, similar to PHP's autoloading mechanism. The security concerns are mitigated by controlling the script directory and constructing file paths using internal class names rather than user input.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: src/CompileInjector.php:14-18
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `CompileInjector` class now uses `Compiler` to compile modules and initializes `AirInjector`. This change should be documented in the README.md.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:113-115
Timestamp: 2025-01-12T16:45:45.701Z
Learning: In Ray.Compiler's AirInjector, using require_once is preferred over require for safety, despite a minor performance impact. The performance difference is negligible in the context of dependency injection.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: composer-require-checker.json:7-15
Timestamp: 2025-01-14T06:24:56.336Z
Learning: The ray-di organization's reusable workflow installs composer-require-checker during CI and supports running with or without a config file via the has_crc_config input parameter.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: tests/Fake/FakeInvalidDependency.php:30-32
Timestamp: 2025-01-12T06:30:48.288Z
Learning: Test doubles in the Ray.Compiler codebase that are designed to test invalid scenarios (like FakeInvalidDependency) can have empty method implementations, as they are intentionally incomplete to facilitate testing error cases.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: composer-require-checker.json:7-15
Timestamp: 2025-01-14T06:24:56.336Z
Learning: The ray-di organization uses reusable GitHub Actions workflows from ray-di/.github repository for static analysis, including composer-require-checker configuration.
📚 Learning: 2024-11-27T01:37:48.101Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 114
File: src/DiCompiler.php:51-58
Timestamp: 2024-11-27T01:37:48.101Z
Learning: In `src/DiCompiler.php`, modifications to the type handling of `$scriptDir` in the `__construct` method have been previously discussed and do not need further changes.

Applied to files:

  • demo/compile.php
  • demo/run.php
📚 Learning: 2024-07-28T07:10:50.356Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: README.md:13-14
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `CompileInjector` class now uses `Compiler` to compile modules and initializes `AirInjector`. This change should be documented in the README.md.

Applied to files:

  • demo/compile.php
  • demo/README.md
  • demo/run.php
📚 Learning: 2025-01-12T04:53:17.265Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: tests/AirInjectorTest.php:106-115
Timestamp: 2025-01-12T04:53:17.265Z
Learning: In Ray.Compiler test classes, temporary test directories should use the class's $this->scriptDir property which is automatically cleaned up by the tearDown method, rather than creating separate directories.

Applied to files:

  • demo/compile.php
  • composer.json
📚 Learning: 2025-01-12T16:15:56.591Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src-function/prototype.php:0-0
Timestamp: 2025-01-12T16:15:56.591Z
Learning: In Ray.Compiler, the $scriptDir parameter is sanitized using realpath() in the AirInjector class before being passed to lower-level functions like prototype() and singleton().

Applied to files:

  • demo/compile.php
  • demo/run.php
📚 Learning: 2025-01-12T05:02:54.169Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:27-118
Timestamp: 2025-01-12T05:02:54.169Z
Learning: Dynamic script loading using `require` with variable paths is a necessary feature in Ray.Compiler's dependency injection system, similar to PHP's autoloading mechanism. The security concerns are mitigated by controlling the script directory and constructing file paths using internal class names rather than user input.

Applied to files:

  • demo/compile.php
  • demo/README.md
📚 Learning: 2025-01-12T16:45:45.701Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:113-115
Timestamp: 2025-01-12T16:45:45.701Z
Learning: In Ray.Compiler's AirInjector, using require_once is preferred over require for safety, despite a minor performance impact. The performance difference is negligible in the context of dependency injection.

Applied to files:

  • demo/README.md
  • demo/run.php
📚 Learning: 2024-07-28T07:10:50.356Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: tests/Fake/CompileVisitor/FakeQux.php:7-23
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `InjectorInterface` in the `Ray\Di` namespace may not be directly visible in static analysis due to dynamic inclusion or being part of external dependencies. This was inferred from the user's assertion and the fact that related tests are passing.

Applied to files:

  • demo/README.md
  • demo/run.php
🧬 Code graph analysis (5)
demo/AppModule.php (2)
src/Compiler.php (1)
  • Compiler (34-78)
demo/Greeter.php (1)
  • Greeter (7-17)
demo/GreeterInterface.php (1)
demo/Greeter.php (1)
  • greet (13-16)
demo/compile.php (2)
src/Compiler.php (1)
  • Compiler (34-78)
demo/AppModule.php (1)
  • AppModule (9-15)
demo/run.php (2)
src/CompiledInjector.php (1)
  • CompiledInjector (33-132)
demo/GreeterInterface.php (1)
  • greet (9-9)
demo/Greeter.php (1)
demo/GreeterInterface.php (1)
  • greet (9-9)
🪛 markdownlint-cli2 (0.18.1)
demo/README.md

46-46: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


74-74: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review
🔇 Additional comments (6)
.gitignore (1)

13-13: LGTM!

The gitignore entry correctly excludes the compiled artifacts directory generated by the demo.

demo/GreeterInterface.php (1)

1-10: LGTM!

Clean interface definition following PHP best practices. The method signature is clear and type-safe.

composer.json (1)

42-42: LGTM!

The autoload-dev mapping is correctly configured for the demo namespace. Appropriate placement in autoload-dev rather than production autoload.

demo/AppModule.php (1)

9-15: LGTM!

Clean DI module configuration following Ray.Di conventions. The binding is straightforward and correct.

demo/Greeter.php (1)

7-17: LGTM!

Clean implementation using modern PHP features (constructor property promotion and readonly properties). The implementation correctly fulfills the interface contract.

demo/compile.php (1)

10-15: Add directory creation before attempting to open the compile lock file.

The Compiler::compile() method attempts to open a lock file at $scriptDir . '/compile.lock' without first ensuring the directory exists. The fopen() call will fail if the directory doesn't exist. While FilePutContents eventually creates the directory during container setup, this happens too late.

Add explicit directory creation at the beginning of the compile() method in src/Compiler.php, before the fopen() call:

if (! is_dir($scriptDir) && ! mkdir($scriptDir, 0777, true)) {
    throw new RuntimeException("Failed to create script directory: $scriptDir");
}

This follows the pattern already used in src/InjectorFactory.php:32 and ensures the directory exists before attempting file operations.

⛔ Skipped due to learnings
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 114
File: src/DiCompiler.php:51-58
Timestamp: 2024-11-27T01:37:48.101Z
Learning: In `src/DiCompiler.php`, modifications to the type handling of `$scriptDir` in the `__construct` method have been previously discussed and do not need further changes.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: tests/AirInjectorTest.php:106-115
Timestamp: 2025-01-12T04:53:17.265Z
Learning: In Ray.Compiler test classes, temporary test directories should use the class's $this->scriptDir property which is automatically cleaned up by the tearDown method, rather than creating separate directories.

@koriym
Copy link
Member Author

koriym commented Nov 18, 2025

@coderabbitai review demo/README.md

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 18, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the demo/README.md file
cat demo/README.md

Length of output: 2631


@koriym: I've reviewed the demo/README.md file. Overall, it's well-written and provides a clear introduction to Ray.Compiler! Here's my feedback:

Strengths ✅

  1. Clear structure - Logical flow from architecture to usage to benefits
  2. Two-phase architecture explanation - Well articulated with distinct compile-time vs runtime phases
  3. Practical examples - Includes actual commands and expected output
  4. Visual aid - ASCII diagram effectively illustrates the compilation flow
  5. Next steps - Guides users on what to explore further

Suggestions for Enhancement 🔧

1. Add Prerequisites Section

Consider adding before "Usage":

## Prerequisites

- PHP 8.1 or higher
- Composer installed
- Run `composer install` before using the demo

2. Clarify Generated Filenames

The example Ray_Compiler_Demo_GreeterInterface-.php has a trailing dash. If this is the actual format, consider adding a note explaining the naming convention. If it's a placeholder, update with the actual pattern.

3. Enhance "Inspecting Generated Code" Section

Add more guidance on what to look for:

You'll see plain PHP code that instantiates objects - no complex DI logic!

Look for:
- Direct `new Greeter()` instantiation
- Constructor arguments resolved at compile-time
- Simple `return` statements

4. Add Troubleshooting/Notes

Consider adding:

## Notes

- Recompile whenever you modify `AppModule.php` or add new bindings
- The `.compiled/` directory is gitignored (see `.gitignore`)
- Generated scripts are version-controlled safe but regenerated on deployment

5. Link to Main Documentation

Add a reference to the main Ray.Compiler docs or repository for deeper dives.

6. Typo/Clarity Check

In the diagram, consider adding arrows labels like "compiles to" or "uses" for additional clarity.

The README effectively demonstrates Ray.Compiler's value proposition. These enhancements would make it even more user-friendly! 🚀

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
demo/README.md (3)

46-53: Specify language for fenced code block output.

The output example block is missing a language identifier, which is flagged by markdown linting standards (MD040). While the content is readable, specifying the language improves consistency and enables syntax highlighting in documentation viewers.

Apply this diff to add a language identifier:

-Output:
-```
+Output:
+```text
 Hello, World!
 Hello, Ray.Compiler!
 
 ✓ Using pre-compiled dependency injection!
 ✓ No reflection, no dependency resolution at runtime
 ✓ Check demo/.compiled/ for generated PHP scripts
-```
+```

74-91: Specify language for the ASCII diagram block.

The workflow diagram block lacks a language identifier (MD040). For ASCII art, using text as the language is a markdown best practice that enables proper rendering in documentation viewers.

Apply this diff to add the language identifier:

 ## How It Works
 
-```
+```text
 ┌─────────────────┐         ┌──────────────┐
 │  Ray.Di Module  │────────▶│   Compiler   │
 │  (Bindings)     │         │              │
 └─────────────────┘         └──────┬───────┘
                                    │
                                    ▼
                             ┌──────────────┐
                             │  PHP Scripts │
                             │ (Optimized)  │
                             └──────┬───────┘
                                    │
                                    ▼
                             ┌──────────────────┐
                             │ CompiledInjector │
                             │  (Lightweight)   │
                             └──────────────────┘
-```
+```

27-44: Consider adding a Prerequisites section.

First-time users benefit from knowing upfront what's required (PHP version, Composer, dependencies). Adding a brief Prerequisites section before "Usage" would improve clarity and reduce friction for newcomers, especially since the README doesn't mention required PHP version or that composer install must be run first.

Consider adding a Prerequisites section like:

## Prerequisites

- PHP 8.1 or higher
- Composer installed
- Run `composer install` before compiling

## Usage

This aligns with the prior reviewer feedback and improves the documentation's usability.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc676a9 and 60aaa13.

📒 Files selected for processing (1)
  • demo/README.md (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2024-07-28T07:10:50.356Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: src/CompileInjector.php:14-18
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `CompileInjector` class now uses `Compiler` to compile modules and initializes `AirInjector`. This change should be documented in the README.md.

Applied to files:

  • demo/README.md
📚 Learning: 2025-01-12T05:02:54.169Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:27-118
Timestamp: 2025-01-12T05:02:54.169Z
Learning: Dynamic script loading using `require` with variable paths is a necessary feature in Ray.Compiler's dependency injection system, similar to PHP's autoloading mechanism. The security concerns are mitigated by controlling the script directory and constructing file paths using internal class names rather than user input.

Applied to files:

  • demo/README.md
📚 Learning: 2025-01-12T16:45:45.701Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:113-115
Timestamp: 2025-01-12T16:45:45.701Z
Learning: In Ray.Compiler's AirInjector, using require_once is preferred over require for safety, despite a minor performance impact. The performance difference is negligible in the context of dependency injection.

Applied to files:

  • demo/README.md
📚 Learning: 2024-07-28T07:10:50.356Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: tests/Fake/CompileVisitor/FakeQux.php:7-23
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `InjectorInterface` in the `Ray\Di` namespace may not be directly visible in static analysis due to dynamic inclusion or being part of external dependencies. This was inferred from the user's assertion and the fact that related tests are passing.

Applied to files:

  • demo/README.md
🪛 markdownlint-cli2 (0.18.1)
demo/README.md

46-46: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


74-74: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
demo/README.md (3)

46-53: Add language identifiers to fenced code blocks.

The code/diagram blocks are missing language specifications. While the README is clear, this helps with syntax highlighting and follows Markdown best practices.

Apply this diff to add language identifiers:

 Output:
-```
+```text
 Hello, World!
 Hello, Ray.Compiler!

 ✓ Using pre-compiled dependency injection!
 ✓ No reflection, no dependency resolution at runtime
 ✓ Check demo/.compiled/ for generated PHP scripts
-```
+```

 ## How It Works
 
-```
+```text
 ┌─────────────────┐         ┌──────────────┐

Also applies to: 74-91


27-27: Consider adding a Prerequisites section.

Users new to Ray.Compiler may benefit from explicit prerequisites before diving into usage. This would clarify baseline requirements without cluttering the main flow.

Example addition (can insert after "## Files" and before "## Usage"):

## Prerequisites

- PHP 8.1 or higher
- Composer installed
- Dependencies installed: `composer install`

93-98: Consider adding Troubleshooting and important notes.

A brief section addressing common scenarios would improve usability, especially for first-time users who might wonder when recompilation is needed or how to clear cached compiled scripts.

Example section to append before or after "## Next Steps":

## Notes & Troubleshooting

- **Recompile after changes**: Modify `AppModule.php` or service definitions? Run `php demo/compile.php` again to regenerate scripts.
- **Clearing cache**: Remove `demo/.compiled/` manually; it will be regenerated on next compilation.
- **.compiled/ is gitignored**: Generated scripts are not committed; each deployment regenerates them from source bindings.
- **Performance**: The generated PHP scripts execute with zero dependency resolution overhead—ideal for production.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60aaa13 and 59caff9.

📒 Files selected for processing (1)
  • demo/README.md (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2024-07-28T07:10:50.356Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: src/CompileInjector.php:14-18
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `CompileInjector` class now uses `Compiler` to compile modules and initializes `AirInjector`. This change should be documented in the README.md.

Applied to files:

  • demo/README.md
📚 Learning: 2025-01-12T05:02:54.169Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:27-118
Timestamp: 2025-01-12T05:02:54.169Z
Learning: Dynamic script loading using `require` with variable paths is a necessary feature in Ray.Compiler's dependency injection system, similar to PHP's autoloading mechanism. The security concerns are mitigated by controlling the script directory and constructing file paths using internal class names rather than user input.

Applied to files:

  • demo/README.md
📚 Learning: 2025-01-12T16:45:45.701Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:113-115
Timestamp: 2025-01-12T16:45:45.701Z
Learning: In Ray.Compiler's AirInjector, using require_once is preferred over require for safety, despite a minor performance impact. The performance difference is negligible in the context of dependency injection.

Applied to files:

  • demo/README.md
📚 Learning: 2024-07-28T07:10:50.356Z
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: tests/Fake/CompileVisitor/FakeQux.php:7-23
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `InjectorInterface` in the `Ray\Di` namespace may not be directly visible in static analysis due to dynamic inclusion or being part of external dependencies. This was inferred from the user's assertion and the fact that related tests are passing.

Applied to files:

  • demo/README.md
🪛 markdownlint-cli2 (0.18.1)
demo/README.md

46-46: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


74-74: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review
🔇 Additional comments (1)
demo/README.md (1)

1-98: Overall structure and content are excellent.

The README clearly explains the two-phase architecture, provides practical commands, and demonstrates the generated output. The ASCII diagram effectively visualizes the workflow, and the "Inspecting Generated Code" section (lines 55–63) gives readers actionable guidance on what to look for in the compiled output.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59caff9 and d7717c5.

📒 Files selected for processing (1)
  • .github/workflows/continuous-integration.yml (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: tests/Fake/CompileVisitor/FakeQux.php:7-23
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `InjectorInterface` in the `Ray\Di` namespace may not be directly visible in static analysis due to dynamic inclusion or being part of external dependencies. This was inferred from the user's assertion and the fact that related tests are passing.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: README.md:13-14
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `CompileInjector` class now uses `Compiler` to compile modules and initializes `AirInjector`. This change should be documented in the README.md.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 112
File: src/CompileInjector.php:14-18
Timestamp: 2024-07-28T07:10:50.356Z
Learning: The `CompileInjector` class now uses `Compiler` to compile modules and initializes `AirInjector`. This change should be documented in the README.md.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:27-118
Timestamp: 2025-01-12T05:02:54.169Z
Learning: Dynamic script loading using `require` with variable paths is a necessary feature in Ray.Compiler's dependency injection system, similar to PHP's autoloading mechanism. The security concerns are mitigated by controlling the script directory and constructing file paths using internal class names rather than user input.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: composer-require-checker.json:7-15
Timestamp: 2025-01-14T06:24:56.336Z
Learning: The ray-di organization's reusable workflow installs composer-require-checker during CI and supports running with or without a config file via the has_crc_config input parameter.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: src/AirInjector.php:113-115
Timestamp: 2025-01-12T16:45:45.701Z
Learning: In Ray.Compiler's AirInjector, using require_once is preferred over require for safety, despite a minor performance impact. The performance difference is negligible in the context of dependency injection.
Learnt from: koriym
Repo: ray-di/Ray.Compiler PR: 115
File: composer-require-checker.json:7-15
Timestamp: 2025-01-14T06:24:56.336Z
Learning: The ray-di organization uses reusable GitHub Actions workflows from ray-di/.github repository for static analysis, including composer-require-checker configuration.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review

koriym and others added 2 commits November 18, 2025 14:18
- Add GreeterInterface, Greeter implementation
- Add AppModule for DI bindings
- Add compile.php and run.php scripts
- Add comprehensive README with architecture explanation
- Update .gitignore to exclude demo/.compiled
- Update composer.json autoload-dev for demo namespace

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Run demo/compile.php to generate compiled scripts
- Run demo/run.php to verify demo execution
- Ensures .compiled/ directory exists before running

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@koriym koriym merged commit b265687 into 1.x Nov 18, 2025
34 checks passed
@koriym koriym deleted the demo branch November 18, 2025 05:24
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.

1 participant