Real-time PHP code quality analysis powered by PHP Mess Detector
Features β’ Installation β’ Configuration β’ Architecture β’ Contributing
The PHPMD Language Server brings comprehensive code quality analysis to Zed Editor through the Language Server Protocol (LSP). It provides real-time feedback on potential bugs, suboptimal code, overcomplicated expressions, and unused code elements as you write PHP.
- π Instant Feedback - See code quality issues as you type, not after you commit
- β‘ High Performance - Optimized with async processing, LZ4 compression, and smart caching
- π― Zero Configuration - Works out of the box with sensible defaults
- π§ Highly Configurable - Customize rules to match your team's standards
- π¦ Self-Contained - Includes bundled PHPMD binary, no external dependencies required
- Detects code quality issues instantly as you type
- Smart diagnostic ranges that skip leading whitespace for cleaner underlines
- Severity-based highlighting (errors, warnings, info)
- Rule-specific documentation links
- LZ4 Compression - Reduces memory usage by ~85% for large files
- Smart Caching - Avoids re-analyzing unchanged files
- Concurrent Processing - Analyzes up to 4 files simultaneously
- Async Architecture - Non-blocking execution keeps editor responsive
- Timeout Protection - 10-second safeguard prevents hanging on complex files
- Context-Aware Ranges - Different highlighting for class, method, and property issues
- Whitespace Trimming - Underlines start at first code character, not indentation
- Property Detection - Correctly highlights property violations even when PHPMD reports class-level
- Rule Categorization - Automatic severity mapping based on rule priority
- Auto-Discovery - Finds
phpmd.xml,phpmd.xml.dist,.phpmd.xml, or.phpmd.xml.distautomatically - XML Validation - Validates config files before use, skipping invalid XML files
- Smart Fallback - Uses all PHPMD rulesets when no valid config file is found
- Live Reloading - Configuration changes apply instantly without restart
- Multi-Source - Configure via project files, Zed settings, or environment variables
- Auto-Recovery - Gracefully handles deleted or invalid config files
Priority order for finding PHPMD executable:
- Project's
vendor/bin/phpmd(respects composer dependencies) - Custom path from settings
- Bundled PHPMD 2.15+ PHAR (always available fallback)
- System PATH installation
- Process Management - Automatic cleanup of zombie processes
- Memory Monitoring - Tracks and logs memory usage for optimization
- Graceful Degradation - Falls back to defaults when configs fail
- Comprehensive Logging - Detailed debug output for troubleshooting
- Open Zed Editor
- Press
Cmd+Shift+X(macOS) orCtrl+Shift+X(Linux/Windows) - Search for "PHPMD"
- Click Install
# Clone the repository
git clone https://github.com/GeneaLabs/zed-phpmd-lsp.git
cd zed-phpmd-lsp
# Build the extension
cargo build --release
# Build the LSP server
cd lsp-server
cargo build --releaseAdd to your Zed settings.json (open with Cmd+, or Ctrl+,):
{
"languages": {
"PHP": {
"language_servers": ["phpmd", "intelephense"]
}
}
}The extension automatically analyzes PHP files as you open and edit them:
<?php
namespace App\Services;
class UserService
{
private $unused; // π Unused private field
public function complexMethod($a, $b, $c, $d, $e, $f) // π Too many parameters
{
if ($a == true) { // π Use strict comparison
goto end; // π Avoid goto statements
}
eval($userInput); // π Security risk: eval usage
end:
return $result;
}
public function m() { // π Method name too short
// Complex logic here...
}
}The extension uses this priority order (highest to lowest):
- Project Config Files -
phpmd.xml,phpmd.xml.dist,.phpmd.xml - Zed Settings - User or project-specific settings.json
- Environment Variables -
PHPMD_RULESETS,PHPMD_PATH - Defaults - Built-in rulesets: cleancode, codesize, controversial, design, naming, unusedcode
| Ruleset | Description | Key Rules |
|---|---|---|
| cleancode | Clean code practices | BooleanArgumentFlag, ElseExpression, StaticAccess |
| codesize | Complexity and size limits | CyclomaticComplexity, NPathComplexity, ExcessiveMethodLength |
| controversial | Debated best practices | Superglobals, CamelCaseParameterName |
| design | Software design principles | ExitExpression, EvalExpression, GotoStatement |
| naming | Naming conventions | ShortVariable, LongVariable, ShortMethodName |
| unusedcode | Dead code detection | UnusedPrivateField, UnusedLocalVariable, UnusedPrivateMethod |
{
"lsp": {
"phpmd": {
"settings": {
"rulesets": "cleancode,codesize,design"
}
}
}
}Create phpmd.xml in your project root:
<?xml version="1.0"?>
<ruleset name="MyProject"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0
http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Custom rules for MyProject</description>
<!-- Import specific rules -->
<rule ref="rulesets/cleancode.xml">
<exclude name="ElseExpression"/>
</rule>
<rule ref="rulesets/codesize.xml/CyclomaticComplexity">
<properties>
<property name="reportLevel" value="15"/>
</properties>
</rule>
<rule ref="rulesets/naming.xml/ShortVariable">
<properties>
<property name="minimum" value="2"/>
<property name="exceptions" value="id,db,em,i,j,k"/>
</properties>
</rule>
<!-- Exclude patterns -->
<exclude-pattern>*/vendor/*</exclude-pattern>
<exclude-pattern>*/tests/*</exclude-pattern>
<exclude-pattern>*/database/migrations/*</exclude-pattern>
</ruleset>Create .zed/settings.json in your project:
{
"lsp": {
"phpmd": {
"settings": {
"rulesets": "./config/phpmd-strict.xml",
"phpmdPath": "./vendor/bin/phpmd"
}
}
}
}βββββββββββββββββββ LSP Protocol ββββββββββββββββββββ
β β ββββββββββββββββββββΊ β β
β Zed Editor β β PHPMD LSP β
β β β Server β
βββββββββββββββββββ ββββββββββββββββββββ
β β
β β
βΌ βΌ
βββββββββββββββββββ ββββββββββββββββββββ
β PHP Files β β PHPMD Binary β
β in Workspace β β (Analysis) β
βββββββββββββββββββ ββββββββββββββββββββ
- Tower-LSP Framework - Async LSP implementation in Rust
- Tokio Runtime - High-performance async execution
- LZ4 Compression - Memory-efficient document storage
- Semaphore Control - Limits concurrent PHPMD processes
// Document compression reduces memory by ~85%
CompressedDocument {
compressed_data: Vec<u8>, // LZ4 compressed content
original_size: usize, // Original file size
checksum: u64, // Content hash for cache validation
compression_ratio: f32, // Monitoring compression efficiency
}- File Change Detection - Debounced to avoid excessive processing
- Content Compression - LZ4 compression for memory efficiency
- PHPMD Execution - Isolated process with timeout protection
- JSON Parsing - Robust extraction from mixed PHPMD output
- Range Calculation - Smart positioning with whitespace trimming
- Cache Storage - Results cached with content checksums
- Memory Usage: ~15-20MB base + ~0.2MB per open file (compressed)
- Analysis Speed: 50-200ms for typical files (1000 lines)
- Concurrent Files: Up to 4 simultaneous analyses
- Cache Hit Rate: ~70-80% in typical editing sessions
- Compression Ratio: 85-90% size reduction for source files
-
Verify language server is enabled:
{ "languages": { "PHP": { "language_servers": ["phpmd"] } } } -
Check debug output:
- View β Toggle Log Panel
- Look for
PHPMD LSP:prefixed messages
-
Test PHPMD manually:
phpmd path/to/file.php text cleancode
-
Reduce concurrent analyses:
{ "lsp": { "phpmd": { "settings": { "maxConcurrent": 2 } } } } -
Simplify rulesets:
- Start with single ruleset:
"rulesets": "cleancode" - Add more gradually to identify performance impact
- Start with single ruleset:
-
Validate XML syntax:
xmllint --noout phpmd.xml
-
Check file paths:
- Use absolute paths for testing
- Ensure relative paths are from project root
-
Test configuration:
phpmd . text phpmd.xml --verbose
Enable verbose logging in Zed:
{
"lsp": {
"phpmd": {
"settings": {
"logLevel": "debug"
}
}
}
}We welcome contributions! See our Contributing Guide for details.
# Clone and setup
git clone https://github.com/GeneaLabs/zed-phpmd-lsp.git
cd zed-phpmd-lsp
# Install Rust toolchain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build everything
cargo build --release
cd lsp-server && cargo build --release
# Run tests
cargo test- πͺ Windows testing and compatibility
- π§ Linux distribution testing
- π Additional ruleset templates
- π Internationalization support
- π§ͺ Test coverage improvements
- π Documentation translations
This project is licensed under the MIT License - see the LICENSE file for details.
- PHPMD - BSD-3-Clause License (bundled as PHAR)
- Rust Dependencies - Various permissive licenses
See THIRD_PARTY_LICENSES.md for complete attribution.
- Manuel Pichler - Creator of PHPMD
- PHPMD Contributors - For the excellent code quality tool
- Zed Industries - For the blazing-fast editor and extension API
- Tower-LSP Contributors - For the robust LSP framework
- PHP Community - For continuous feedback and support
Made with β€οΈ for the PHP community
Report Bug β’ Request Feature β’ Discussions