@@ -7,6 +7,64 @@ pipeline so it produces correct data. Downstream consumers
77(diagnostics, hover, completion, definition) should never need
88to second-guess upstream output.
99
10+ ## B116. Renaming a constructor-promoted property parameter doesn't cascade to ` $this->prop ` usages
11+
12+ ** Severity: Low-Medium (rename only updates the parameter declaration
13+ itself; every ` $this->field ` reference elsewhere in the class is left
14+ stale, silently producing a broken rename) · Discovered while
15+ investigating a user-reported GitHub Q&A about rename support for
16+ promoted properties**
17+
18+ ``` php
19+ final class SomeService {
20+ public function __construct(
21+ private int $someField, // renaming this parameter...
22+ ) {}
23+
24+ public function handle(): void {
25+ $this->someField; // ...doesn't rename this usage
26+ }
27+ }
28+ ```
29+
30+ The symbol-map extraction for constructor parameters
31+ (` src/symbol_map/extraction/class_like.rs:605-642 ` ) unconditionally
32+ tags every parameter's ` VarDefSite ` /` SymbolSpan ` with
33+ ` kind: VarDefKind::Parameter ` (line 633), with no check for
34+ ` param.is_promoted_property() ` . This is the symbol map that
35+ ` find_references ` /rename consult, and it's a separate structure from
36+ the properties list the type engine builds in
37+ ` src/parser/classes.rs:1040-1049 ` , which * does* special-case
38+ ` is_promoted_property() ` to synthesize a property for hover/completion/
39+ type-inference of ` $this->someField ` — but that data isn't wired back
40+ into the symbol map's ` VarDefKind ` .
41+
42+ Because of this, ` lookup_var_def_kind_at ` (` src/definition/resolve.rs:130 ` )
43+ reports ` VarDefKind::Parameter ` for a promoted property, so
44+ ` src/references/dispatch.rs:136-172 ` routes the rename to
45+ ` find_variable_references ` (` src/references/variables.rs:22 ` ) instead
46+ of the cross-file, member-access-aware ` find_member_references ` .
47+ ` find_variable_references ` is explicitly file-local/scope-local and
48+ never looks at ` $this->foo ` sites, so it only renames the parameter's
49+ own token(s). The same ` VarDefKind::Property ` check gates
50+ ` is_property_rename ` in ` src/rename/prepare.rs:302-306 ` , so the rename
51+ is also misclassified as a plain-variable rename rather than a
52+ property rename, which skips the ` $this->foo ` prefix-fixup logic
53+ ` src/rename/mod.rs ` documents for property renames.
54+
55+ Fix by making the symbol-map extraction in ` class_like.rs ` emit
56+ ` VarDefKind::Property ` (or an equivalent alias treated like ` Property `
57+ everywhere) for parameters where ` param.is_promoted_property() ` is
58+ true, and register the declaration wherever
59+ ` find_member_references ` /the declaration-hierarchy resolvers expect
60+ property declarations to live. Audit the other call sites that branch
61+ on ` VarDefKind::Parameter ` vs ` Property ` for promoted params for their
62+ own reasons (semantic tokens at ` semantic_tokens.rs:757-770 ` , hover at
63+ ` hover/mod.rs:152-158 ` ) so they keep working once the kind changes.
64+ There is no existing test coverage for promoted-property rename or
65+ references (` src/rename/tests.rs ` and ` tests/integration/references.rs `
66+ have no ` __construct ` /promoted-property cases).
67+
1068## B115. Closure-parameter inference uses call-position instead of the declared parameter index, so named arguments that reorder a call break it
1169
1270** Severity: Low-Medium (closure/arrow-function parameters silently lose
0 commit comments