Skip to content

Basic Laravel Blade Template Support#100

Merged
AJenbo merged 5 commits intoAJenbo:mainfrom
MingJen:feat/blade
May 2, 2026
Merged

Basic Laravel Blade Template Support#100
AJenbo merged 5 commits intoAJenbo:mainfrom
MingJen:feat/blade

Conversation

@MingJen
Copy link
Copy Markdown
Contributor

@MingJen MingJen commented May 2, 2026

Overview

This PR introduces initial support for Laravel Blade templates (.blade.php) in PHPantom. It allows developers to enjoy features like Go-to-Definition,
Completion, Hover, and Diagnostics directly inside Blade files by leveraging a Virtual PHP preprocessing strategy.

The implementation is highly modular and designed with Zero-Overhead for non-Laravel developers, as the Blade logic is only triggered for files ending in
.blade.php.

Architecture & Data Flow

To reuse the existing Mago/PHPantom static analysis engine without modifying its core, we use a "Virtual PHP" approach. Here is how a request (e.g.,
"Completion") flows through the system:

  1. Intercept: The LSP layer identifies the file as a .blade.php file via is_blade_file.
  2. Preprocess: The BladePreprocessor transforms the Blade content into valid PHP on-the-fly.
    • Example: @if($user->isAdmin()) becomes if($user->isAdmin()):
    • Invariant: We maintain a 1:1 line mapping to keep coordinate translation simple.
  3. Coordinate Translation (Inbound): The BladeSourceMap translates the editor's cursor position (Blade coordinates) into the corresponding position in the
    Virtual PHP.
  4. Analysis: The translated request is passed to the core PHP analysis engine.
  5. Coordinate Translation (Outbound): The engine returns results (e.g., variable definitions) in PHP coordinates. The BladeSourceMap translates these back
    into original Blade coordinates.
  6. Response: The editor receives accurate positions within the .blade.php file.

Key Features

  • Intelligent Preprocessing: Handles Echo statements ({{ }}), Control Directives (@if, @foreach), and Layout Directives (@extends, @include).
  • Implicit Variables: Injects $errors, $__env, and a dummy blade_directive() function into the virtual scope to prevent false-positive "undefined"
    diagnostics.
  • Performance Optimized:
    • $O(1)$ directive matching using strip_prefix.
    • Consolidated state machine for directive argument parsing.
  • Linter Clean: All code follows idiomatic Rust patterns and passes strict clippy checks.

Core Library Refactoring & Justification

This PR introduces Blade template support for diagnostics and coordinate translation. To achieve this, several core library files were refactored. These
changes were necessary to move from a "PHP-only" mindset to a "multi-language/virtual file" architecture.

  1. Context-Aware Coordinate Translation
  • Files affected: src/diagnostics/*.rs (e.g., argument_count.rs, deprecated.rs, implementation_errors.rs)
  • Changes: Refactored the static utility offset_range_to_lsp_range(...) into a Backend method: self.offset_range_to_lsp_range(uri, ...).
  • Justification:
    • Source Mapping Support: Blade files are analyzed as "Virtual PHP" content. To report errors back to the original .blade.php file, the engine must use
      a Source Map.
    • URI-Based Resolution: Since the Backend holds the source maps and virtual content, coordinate translation must be context-aware. Passing the uri
      allows the engine to detect if a file is Blade and automatically apply the correct coordinate transformation, ensuring red lines appear in the correct
      place in the editor.
  1. LSP Type Alignment & CLI Modernization
  • Files affected: src/analyse.rs, src/main.rs
  • Changes:
    • Replaced the custom SeverityFilter enum with the standard tower_lsp::lsp_types::DiagnosticSeverity.
    • Updated AnalyseOptions to use String filters for easier CLI argument passing.
  • Justification:
    • Consistency: Aligning the CLI with the LSP server's internal types reduces boilerplate and ensures that diagnostic severity behaves identically across
      both the "Analyze" command and the live editor experience.
    • Maintainability: Removing redundant internal types simplifies the codebase and leverages the robust type definitions provided by the LSP protocol.
  1. Performance & Structural Optimization
  • Files affected: src/analyse.rs
  • Changes:
    • Removed unnecessary .clone() calls when accessing PSR-4 mappings.
    • Renamed local variables (e.g., psr4 to mappings) to better reflect their role in the updated logic.
  • Justification:
    • Efficiency: Avoiding clones of large mapping vectors reduces memory pressure during full-project scans.
    • Clarity: The term mappings is more inclusive and accurately describes the collection of paths being scanned, especially as the tool evolves to support
      more complex project structures.
  1. Backend Infrastructure for Virtual Files
  • Files affected: src/lib.rs
  • Changes: Added fields to Backend for managing blade_virtual_content and blade_source_maps.
  • Justification: This provides the foundational infrastructure for all LSP features (Hover, Definition, Diagnostics) to support non-PHP files that compile
    down to PHP, ensuring a seamless experience across different file types.

Quality Assurance (Local Validation)

  • Comprehensive Testing: Ran the full test suite via cargo test. All 14 new Blade-specific integration tests passed, alongside existing PHP tests.
  • Static Analysis: Verified that cargo clippy -- -D warnings returns zero warnings, ensuring idiomatic and safe Rust code.
  • Manual Verification: Confirmed in-editor that symbols inside Blade files (like $config-> or $user->) correctly trigger completion and go-to-definition.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 2, 2026

Codecov Report

❌ Patch coverage is 81.93833% with 164 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.60%. Comparing base (8b7ac32) to head (ceb067e).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/blade/mod.rs 4.76% 60 Missing ⚠️
src/blade/source_map.rs 74.41% 22 Missing ⚠️
src/blade/preprocessor.rs 93.05% 20 Missing ⚠️
src/diagnostics/mod.rs 82.50% 14 Missing ⚠️
src/diagnostics/unused_imports.rs 45.00% 11 Missing ⚠️
src/inlay_hints.rs 37.50% 10 Missing ⚠️
src/semantic_tokens.rs 91.26% 9 Missing ⚠️
src/hover/variable_type.rs 61.90% 8 Missing ⚠️
src/analyse.rs 0.00% 3 Missing ⚠️
src/blade/directives.rs 96.77% 3 Missing ⚠️
... and 4 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #100      +/-   ##
==========================================
- Coverage   86.66%   86.60%   -0.07%     
==========================================
  Files         164      168       +4     
  Lines      106572   107553     +981     
==========================================
+ Hits        92360    93145     +785     
- Misses      14212    14408     +196     

☔ 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.

MingJen added 4 commits May 2, 2026 18:46
- Introduce `src/blade` module to handle Blade template compilation into virtual PHP.
- `BladeSourceMap`: Provides `blade_to_php` and `php_to_blade` coordinate translation to accurately map LSP positions.
- `preprocessor`: A state-machine parser that translates Blade directives and echo statements into PHP equivalents while maintaining strict 1:1 line mappings.
- `directives`: Matcher and translator for Blade control structures and view directives.
- Wire the Blade preprocessor into file open and change events.
- Intercept LSP requests (hover, completion, definitions, diagnostics, semantics tokens, inlay hints) and translate incoming Blade coordinates to Virtual PHP coordinates.
- Route the translated requests to the existing Mago/PHPantom static analysis engine.
- Translate the output coordinates back to Blade before responding to the editor.
- Exclude Blade specific dummy elements from diagnostic reporting.
- Add tests to ensure go-to-definition, reference finding, and syntax error resilience work correctly within `.blade.php` files.
- Add test fixtures simulating real-world Blade files and syntax edges (e.g. multi-line directives, mixed HTML/PHP).
Comment thread src/analyse.rs
Comment on lines -5 to -7
//!
//! # Philosophy
//!
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Some of the changes here are a bit destructive

@AJenbo AJenbo merged commit 7bbd33c into AJenbo:main May 2, 2026
6 of 7 checks passed
@AJenbo
Copy link
Copy Markdown
Owner

AJenbo commented May 2, 2026

Thanks, this is a big step on the roadmap!

@AJenbo
Copy link
Copy Markdown
Owner

AJenbo commented May 2, 2026

I added highlighting and compleation on dynamic types which made it feel a bit more well rounded. Other then that really nice work here I think this makes a really solid first level Blade support.

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