Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
92e0dc1
feat(php): Add scalable reference CodeLens
sidux Aug 26, 2026
0ccf3f5
fix(indexing): Reuse workspace index for annotations
sidux Aug 27, 2026
be8c516
fix(indexing): Batch member reference counts
sidux Aug 27, 2026
4176e9e
fix(indexing): Reuse forward scopes for member counts
sidux Aug 27, 2026
5757191
fix(indexing): Coalesce member count refreshes
sidux Aug 27, 2026
e1daa32
fix(indexing): Cache semantic member targets
sidux Aug 27, 2026
f4bea42
fix(references): keep member batching framework-neutral
sidux Aug 27, 2026
d06fdfe
feat(navigation): Navigate PHP symbols in YAML and XML
sidux Aug 25, 2026
66ef462
feat(navigation): Index YAML and XML PHP references
sidux Aug 26, 2026
dc6652f
feat(frameworks): Add Symfony and Doctrine resource navigation
sidux Jul 6, 2026
63cd4fa
fix(symfony): Preserve framework CodeLens destinations
sidux Aug 5, 2026
1f54594
fix(doctrine): Bound reverse relationship CodeLens
sidux Aug 27, 2026
5354811
fix(navigation): Preserve Symfony resource fallbacks
sidux Aug 27, 2026
7c90214
fix(doctrine): Cache repository mapping index
sidux Aug 27, 2026
2c60084
fix(indexing): Index framework reference lookups
sidux Aug 27, 2026
6106c78
test(frameworks): avoid redundant URI allocations
sidux Aug 27, 2026
af3df00
feat(symfony): Index PHP configuration resources
sidux Jul 29, 2026
ff40130
feat(symfony): Add service container intelligence
sidux Jul 29, 2026
fd29607
fix(symfony): Handle Unicode in PHP resource scans
sidux Jul 29, 2026
086d08a
feat(symfony): Add route intelligence
sidux Jul 29, 2026
46ca1b9
feat(symfony): Add Twig template intelligence
sidux Jul 29, 2026
0995004
feat(symfony): Add translation intelligence
sidux Jul 29, 2026
ba8db30
feat(php): Map transparent proxies to real classes
sidux Aug 25, 2026
58a0ac0
feat(php): add call hierarchy
sidux Aug 30, 2026
b15472c
feat(symfony): Navigate event publishers and listeners
sidux Aug 25, 2026
22e6a6b
feat(symfony): Add events and Messenger intelligence
sidux Jul 29, 2026
845866b
perf(symfony): index Messenger CodeLens mappings
sidux Aug 27, 2026
596c503
feat(symfony): expose events in call hierarchy
sidux Aug 30, 2026
8894f02
feat(symfony): Resolve configured ExpressionLanguage strings
sidux Aug 25, 2026
303a6cb
Merge upstream main into feat/framework-resource-navigation
sidux Sep 28, 2026
72b1e68
Merge feat/framework-resource-navigation into feat/symfony-service-co…
sidux Sep 28, 2026
9ef7894
Merge feat/symfony-service-container-intelligence into feat/symfony-r…
sidux Sep 28, 2026
532080a
Merge feat/symfony-route-intelligence into feat/symfony-twig-template…
sidux Sep 28, 2026
7bcd44c
Merge feat/symfony-twig-template-intelligence into feat/symfony-trans…
sidux Sep 28, 2026
baf2265
Merge feat/symfony-translation-intelligence into feat/symfony-events-…
sidux Sep 28, 2026
5926823
Merge feat/symfony-events-messenger-intelligence into feat/symfony-ex…
sidux Sep 28, 2026
12e8dc6
refactor(symfony): drop transparent proxy mapping
sidux Sep 28, 2026
d7e18fc
Merge feat/symfony-events-messenger-intelligence into feat/symfony-ex…
sidux Sep 28, 2026
f765e3c
Merge upstream main into feat/framework-resource-navigation
sidux Sep 28, 2026
ac744cd
Merge feat/framework-resource-navigation into feat/symfony-service-co…
sidux Sep 28, 2026
451e216
Merge feat/symfony-service-container-intelligence into feat/symfony-r…
sidux Sep 28, 2026
e304ce2
Merge feat/symfony-route-intelligence into feat/symfony-twig-template…
sidux Sep 28, 2026
90f27df
Merge feat/symfony-twig-template-intelligence into feat/symfony-trans…
sidux Sep 28, 2026
94d5979
Merge feat/symfony-translation-intelligence into feat/symfony-events-…
sidux Sep 28, 2026
c33e815
Merge feat/symfony-events-messenger-intelligence into feat/symfony-ex…
sidux Sep 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
261 changes: 261 additions & 0 deletions config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,267 @@
}
}
},
"symfony": {
"type": "object",
"description": "Symfony runtime metadata recovered statically from compiled containers and configured PHP attributes.",
"properties": {
"container": {
"type": "object",
"description": "Controls static compiled-container discovery. Container PHP is read as text and is never executed.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Read Symfony compiled-container metadata.",
"default": true
},
"environment": {
"type": "string",
"description": "Cache environment used by automatic var/cache/<environment> discovery.",
"default": "dev"
},
"paths": {
"type": "array",
"description": "Optional workspace-relative compiled-container files, directories, or glob patterns. The newest useful match wins.",
"items": {
"type": "string"
}
}
}
},
"events": {
"type": "object",
"description": "Configures event-name matching and attribute adapters. Exact listener wiring comes from the compiled container.",
"properties": {
"ignored-prefixes": {
"type": "array",
"description": "Prefixes removed before event names are compared.",
"items": {
"type": "string"
}
},
"ignored-suffixes": {
"type": "array",
"description": "Suffixes removed before event names are compared.",
"items": {
"type": "string"
}
},
"publishers": {
"type": "array",
"description": "Rules that derive Symfony event publishers from PHP method attributes.",
"items": {
"type": "object",
"properties": {
"attribute": {
"type": "string",
"description": "Fully-qualified publisher attribute class."
},
"name-argument": {
"type": "string",
"description": "Named argument containing an explicit event name."
},
"name-position": {
"type": "integer",
"description": "Zero-based positional fallback for the explicit event-name argument.",
"minimum": 0
},
"dispatch-argument": {
"type": "string",
"description": "Named argument containing dispatch enum cases."
},
"dispatch-position": {
"type": "integer",
"description": "Zero-based positional fallback for the dispatch argument.",
"minimum": 0
},
"default-dispatch": {
"type": "array",
"description": "Dispatch names used when the attribute omits its dispatch argument.",
"items": {
"type": "string"
}
},
"dispatch-cases": {
"type": "object",
"description": "Map from PHP enum case name to the event-name dispatch segment.",
"additionalProperties": {
"type": "string"
}
},
"name-template": {
"type": "string",
"description": "Derived event-name template. Supports {dispatch}, {class}, {class_snake}, {method}, {method_snake}, {method_suffix}, and {method_suffix_snake}."
},
"explicit-name-template": {
"type": "string",
"description": "Template used for explicit names. Supports the same placeholders plus {name}.",
"default": "{name}"
},
"default-methods": {
"type": "array",
"description": "Method names that omit the method suffix.",
"items": {
"type": "string"
}
},
"skip": {
"type": "array",
"description": "Conditions that omit one derived dispatch when another attribute argument is set.",
"items": {
"type": "object",
"properties": {
"dispatch": {
"type": "string"
},
"argument": {
"type": "string"
},
"position": {
"type": "integer",
"minimum": 0
}
},
"required": [
"dispatch",
"argument"
]
}
}
},
"required": [
"attribute",
"name-template"
]
}
},
"subscribers": {
"type": "array",
"description": "Optional rules that expose event names written in subscriber method attributes before or without a compiled container.",
"items": {
"type": "object",
"properties": {
"attribute": {
"type": "string",
"description": "Fully-qualified subscriber attribute class."
},
"name-argument": {
"type": "string"
},
"name-position": {
"type": "integer",
"minimum": 0
},
"transport-argument": {
"type": "string"
},
"transport-position": {
"type": "integer",
"minimum": 0
},
"transport-cases": {
"type": "object",
"description": "Map from PHP enum case name to an event-name suffix.",
"additionalProperties": {
"type": "string"
}
}
},
"required": [
"attribute"
]
}
}
}
},
"expression-language": {
"type": "object",
"description": "Maps configured PHP attribute and constructor arguments to Symfony ExpressionLanguage strings and their PHP type contracts.",
"properties": {
"attributes": {
"type": "array",
"description": "Method-attribute arguments that contain an expression string or an array of expression strings.",
"items": {
"type": "object",
"properties": {
"attribute": {
"type": "string",
"description": "Fully-qualified PHP method attribute class."
},
"argument": {
"type": "string",
"description": "Named argument containing expressions."
},
"position": {
"type": "integer",
"description": "Zero-based positional fallback for the expression argument.",
"minimum": 0
},
"method-parameters": {
"type": "boolean",
"description": "Bind expression roots to method parameters with the same name.",
"default": false
},
"bindings": {
"type": "object",
"description": "Map expression roots to return, parameter:<name-or-index>, or class:<FQN> type sources.",
"additionalProperties": {
"type": "string"
}
}
},
"required": [
"attribute"
]
}
},
"constructors": {
"type": "array",
"description": "Expression object constructors nested inside PHP method attributes.",
"items": {
"type": "object",
"properties": {
"class": {
"type": "string",
"description": "Fully-qualified expression object class."
},
"argument": {
"type": "string",
"description": "Named constructor argument containing the expression."
},
"position": {
"type": "integer",
"description": "Zero-based positional fallback for the constructor argument.",
"minimum": 0
},
"inside-attribute-prefixes": {
"type": "array",
"description": "Only match constructors nested in attributes whose FQN starts with one of these prefixes. An empty list matches any attribute.",
"items": {
"type": "string"
}
},
"method-parameters": {
"type": "boolean",
"description": "Bind expression roots to method parameters with the same name.",
"default": false
},
"bindings": {
"type": "object",
"description": "Map expression roots to return, parameter:<name-or-index>, or class:<FQN> type sources.",
"additionalProperties": {
"type": "string"
}
}
},
"required": [
"class"
]
}
}
}
}
}
},
"formatting": {
"type": "object",
"description": "Controls the formatting strategy. PHPantom ships a built-in formatter (PER-CS 2.0 style). Projects with php-cs-fixer or PHP_CodeSniffer in composer.json require-dev automatically use those tools instead. Explicit configuration here always takes priority.",
Expand Down
14 changes: 14 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ src/
│
│ # Class & type resolution
├── resolution.rs # Multi-phase class/function lookup across files (find_or_load_class)
├── symfony/ # Compiled-container, event, and ExpressionLanguage adapters
├── class_lookup.rs # Subtype checks (is_subtype_of_typed) and class-lookup helpers
├── inheritance/ # Parent/trait/mixin member merging, generics substitution
├── virtual_members/ # Synthesized members: phpdoc.rs (@method/@property/@mixin) + laravel/ (one file per Eloquent/framework feature)
Expand Down Expand Up @@ -143,6 +144,19 @@ diagnostics, hover, go-to-definition, and signature help, not just completion
below). Do not build a second type-resolution path: extend the engine here so
every consumer benefits.

### Framework Runtime Metadata

Framework-generated files feed small metadata adapters instead of creating a
second symbol resolver. `symfony/container.rs` reads compiled containers as text and exposes
listener registrations and proxied service candidates; it never includes PHP.
`symfony/events.rs` combines that exact runtime wiring with configured
attribute rules, then serves go-to-definition, references, and code lenses.
`symfony/expressions.rs` maps configured attribute and constructor arguments to
method parameter, return, or fixed-class types, then delegates member chains to
the shared PHP type engine for navigation and diagnostics.
Both inputs name the real classes: a compiled container records the class it
hands to a proxy factory, not the generated subclass.

## External Crates

PHPantom uses several crates from the [Mago](https://github.com/carthage-software/mago)
Expand Down
Loading
Loading