languages: Add built-in PHP support via intelephense - #31
Merged
Conversation
Adds PHP as a first-class built-in: tree-sitter grammar registered,
.php/.phtml files recognized, syntax highlighting + outline + indents +
injections + runnables on, and intelephense driven for
completion/hover/go-to-def — found on PATH first, otherwise npm-installed
into the language container dir.
- Grammar: canonical tree-sitter-php 0.24.2 (MIT). Same dev-dep-only
tree-sitter ^0.25 constraint as tree-sitter-java; resolves cleanly
against workspace tree-sitter 0.26. Uses LANGUAGE_PHP (mixed-mode PHP
+ inline HTML) since .php files traditionally interleave HTML.
- Queries: pulled from zed-extensions/php (MIT) into
crates/grammars/src/php/. 11 files. Zero patches needed — upstream
queries are written against the same canonical grammar.
- Adapter: new crates/languages/src/php.rs (~150 LOC). Modeled directly
on typescript.rs (single-package variant). $PATH lookup first, then
npm_install_packages("intelephense", latest) into <container>, then
node <container>/node_modules/intelephense/lib/intelephense.js --stdio.
License note in the adapter doc-comment: intelephense is proprietary;
we don't redistribute it, npm fetches at runtime. Users who prefer
OSS can override via the `language_servers` setting (phpactor, phpls).
- Wired into crates/languages/src/lib.rs::init with PaddleBoard tags on
every upstream-shaped edit. Sets `composer.json` as the manifest name
so intelephense can discover package roots.
Final of four planned bake-in PRs (Swift, Kotlin, Java, PHP). Brings the
built-in language count from 13 to 17.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
jasonsmithio
force-pushed
the
feat/lang-php
branch
from
May 16, 2026 16:52
dc4b2eb to
b735172
Compare
jasonsmithio
added a commit
that referenced
this pull request
May 31, 2026
languages: Add built-in PHP support via intelephense
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds PHP as a built-in language — the final PR in the bake-in series (Swift → Kotlin → Java → PHP).
.phpand.phtmlfiles get syntax highlighting, indent rules, outline, runnable tests, debugger query, and completion / hover / go-to-def viaintelephense— found on$PATHfirst, otherwisenpm installed into the language container dir on first open.Built-in language count goes from 13 to 17 once this and the prior three PRs land.
Independent of #28, #29, #30 — all four base on main with no shared touch points beyond
crates/languages/src/lib.rs::init.What's here
tree-sitter-php = "0.24.2"(MIT). Same dev-dep-onlytree-sitter ^0.25constraint astree-sitter-java; resolves cleanly against workspacetree-sitter 0.26. UsesLANGUAGE_PHP(mixed-mode PHP + inline HTML) since.phpfiles traditionally interleave HTML.zed-extensions/php(MIT) intocrates/grammars/src/php/. 11 files:brackets.scm,config.toml,debugger.scm,embedding.scm,highlights.scm,indents.scm,injections.scm,outline.scm,overrides.scm,runnables.scm,textobjects.scm. Zero patches needed — upstream queries are written against the same canonical grammar.crates/languages/src/php.rs(~150 LOC). Modeled directly ontypescript.rs(single-package variant, no separatetypescriptpackage to install alongside the language server).check_if_user_installedcallsdelegate.which("intelephense"); otherwise the adapternpm_install_packages("intelephense", latest)into<container>/node_modules/and invokesnode <container>/node_modules/intelephense/lib/intelephense.js --stdio.npm installfetches it from npmjs.com at runtime. Users who prefer OSS can override via thelanguage_serverssetting to point at phpactor or phpls. This is captured in a doc-comment at the top ofphp.rsso the next reader doesn't have to grep release notes.crates/languages/src/lib.rs::initgains amod php;, anArc::new(php::PhpLspAdapter::new(node.clone()))instantiation, and aLanguageInfo { name: "php", adapters: vec![php_lsp_adapter], manifest_name: Some("composer.json".into()), .. }entry betweenmarkdown-inlineandpython(alphabetical). All four touch points tagged// PaddleBoard:for upstream-merge resolution.Bonus: Tailwind autocomplete in
.phpfiles just worksThe existing
tailwind_languageslist inlib.rs::initalready includes "PHP" as a candidate language for the tailwind LSP. Once this PR lands, tailwind class completion in.phpfiles (Laravel Blade templates, etc.) starts working without any extra wiring on the PHP side.Test plan
cargo check -p grammars --features load-grammarsclean (9.8s, freshtree-sitter-phpcompile)cargo check -p paddleboardclean (6.2s incremental)PaddleBoard.log.phpbuffer triggersnpm install intelephense(~10s on a warm npm cache, ~30s cold) and then the intelephense process spawns. Structurally identical totypescript.rs(verified to work in production); first reviewer can verify by opening any.phpfile in a project.Known limitations
lsp.intelephense.initializationOptions.licenceKeyin settings.Out of scope (follow-ups)
phpactor(composer-distributed) for users avoiding intelephense's licenseRelease Notes:
intelephense. The server is downloaded automatically on first use, or picked up from$PATHif installed system-wide. intelephense is proprietary (free tier; paid features require a license key).