Skip to content

Commit 856a014

Browse files
committed
Add new todo entries
1 parent 86dced4 commit 856a014

1 file changed

Lines changed: 157 additions & 0 deletions

File tree

docs/todo.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,133 @@ long-tail polish.
88

99
---
1010

11+
## Composer Environment Detection & Warnings
12+
13+
### 37. Warn when composer.json is missing or classmap is not optimized
14+
15+
PHPantom relies on Composer artifacts (`vendor/composer/autoload_classmap.php`,
16+
`autoload_psr4.php`, `autoload_files.php`) for class discovery. When these
17+
are missing or incomplete, completions silently degrade. The user should be
18+
told what's wrong and offered help fixing it.
19+
20+
#### Detection (during `initialized`)
21+
22+
| Condition | Severity | Message |
23+
|---|---|---|
24+
| No `composer.json` in workspace root | Warning | "No composer.json found. Class completions will be limited to open files and stubs." |
25+
26+
For the no-composer.json case, offer to generate a minimal one via
27+
`window/showMessageRequest`:
28+
29+
1. **"Generate composer.json"** — create a `composer.json` that maps
30+
the entire project root as a classmap (`"autoload": {"classmap": ["./"]}`).
31+
Then run `composer dump-autoload -o` to build the classmap. This
32+
covers legacy projects and single-directory setups that don't follow
33+
PSR-4 conventions.
34+
2. **"Dismiss"** — do nothing.
35+
36+
| `composer.json` exists but `vendor/` directory is missing | Warning | "No vendor directory found. Run `composer install` to enable full completions." |
37+
| PSR-4 prefixes exist but no user classes in classmap | Info | "Composer classmap does not contain your project classes. Run `composer dump-autoload -o` for full class completions." |
38+
39+
The third condition needs care. The classmap is rarely empty because
40+
vendor packages like PHPUnit use `classmap` autoloading (not PSR-4), so
41+
there will be vendor entries even without `-o`. The real signal is:
42+
the project's `composer.json` declares PSR-4 prefixes (e.g. `App\`,
43+
`Tests\`), but none of the classmap FQNs start with any of those
44+
project prefixes. This means the user's own classes were not dumped
45+
into the classmap, which is exactly what `-o` fixes.
46+
47+
Detection logic:
48+
1. Collect non-vendor PSR-4 prefixes from `psr4_mappings` (already
49+
tagged with `is_vendor`).
50+
2. After loading the classmap, check whether any classmap FQN starts
51+
with one of those prefixes.
52+
3. If there are project PSR-4 prefixes but zero matching classmap
53+
entries, the autoloader is not optimized.
54+
55+
#### Actions (via `window/showMessageRequest`)
56+
57+
For the non-optimized classmap case, offer action buttons:
58+
59+
1. **"Run composer dump-autoload -o"** — spawn the command in the
60+
workspace root, reload the classmap on success, show a progress
61+
notification.
62+
2. **"Add to composer.json & run"** — add
63+
`"config": {"optimize-autoloader": true}` to `composer.json` so
64+
future `composer install` / `composer update` always produce an
65+
optimized classmap, then run `composer dump-autoload`.
66+
3. **"Dismiss"** — do nothing.
67+
68+
#### UX guidelines
69+
70+
- The no-composer.json and no-vendor warnings are safe to show via
71+
`window/showMessage` (informational, no action taken).
72+
- The classmap warning should use `window/showMessageRequest` with
73+
action buttons so the user explicitly opts in before we touch files
74+
or run commands.
75+
- Only show once per session. Do not re-trigger on every `didOpen`.
76+
- Never modify `composer.json` or run commands without explicit user
77+
confirmation via an action button.
78+
- If the spawned `composer` command fails (e.g. PHP not installed
79+
locally, Docker-only setup), catch the error gracefully and show
80+
"Composer command failed. You may need to run it manually."
81+
- Log the detection result to the output panel regardless (already done
82+
for the "Loaded N classmap entries" message, just add context when
83+
zero user classes are found).
84+
85+
---
86+
87+
### 38. File system watching for vendor and project changes
88+
89+
PHPantom loads Composer artifacts (classmap, PSR-4 mappings, autoload
90+
files) once during `initialized` and caches them for the session. If
91+
the user runs `composer update`, `composer require`, or `composer remove`
92+
while the editor is open, the cached data goes stale. The user gets
93+
completions and go-to-definition based on the old package versions
94+
until they restart the editor.
95+
96+
#### What to watch
97+
98+
| Path | Trigger | Action |
99+
|---|---|---|
100+
| `vendor/composer/autoload_classmap.php` | Changed | Reload classmap |
101+
| `vendor/composer/autoload_psr4.php` | Changed | Reload PSR-4 mappings |
102+
| `vendor/composer/autoload_files.php` | Changed | Re-scan autoload files for global functions/constants |
103+
| `composer.json` | Changed | Reload project PSR-4 prefixes, re-check vendor dir |
104+
| `composer.lock` | Changed | Good secondary signal that packages changed |
105+
106+
All three `autoload_*.php` files are rewritten atomically by Composer
107+
on every `install`, `update`, `require`, `remove`, and `dump-autoload`.
108+
Watching these is sufficient to catch any package change.
109+
110+
#### Implementation options
111+
112+
1. **LSP `workspace/didChangeWatchedFiles`** — register file watchers
113+
via `client/registerCapability` during `initialized`. The editor
114+
handles the OS-level watching and sends notifications. This is the
115+
cleanest approach and works cross-platform. Register glob patterns
116+
for the vendor Composer files and `composer.json`.
117+
118+
2. **Server-side `notify` crate** — use the `notify` Rust crate to
119+
watch the file system directly. More control but adds a dependency
120+
and duplicates what the editor already provides.
121+
122+
Option 1 is preferred. The LSP spec's `DidChangeWatchedFilesRegistrationOptions`
123+
supports glob patterns like `**/vendor/composer/autoload_*.php`.
124+
125+
#### Reload strategy
126+
127+
- On change notification, re-run the same parsing logic from
128+
`initialized` for the affected artifact.
129+
- Invalidate `class_index` entries that came from vendor files (their
130+
parsed AST may have changed).
131+
- Clear and re-populate `classmap` from the new `autoload_classmap.php`.
132+
- Log the reload to the output panel so the user knows it happened.
133+
- Debounce rapid changes (Composer writes multiple files in sequence)
134+
with a short delay (e.g. 500ms) to avoid redundant reloads.
135+
136+
---
137+
11138
## Completion & Go-to-Definition Gaps
12139

13140
### Competitive parity (close the gap with PHPStorm / Intelephense)
@@ -26,6 +153,36 @@ large projects with deep namespace hierarchies.
26153

27154
---
28155

156+
#### 39. Conflicting use-import resolution
157+
158+
When auto-importing a class whose short name collides with an existing
159+
`use` statement, the LSP blindly inserts a second `use` with the same
160+
short name. For example, if the file already has `use Cassandra\Exception;`
161+
and the user accepts a completion for PHP's built-in `Exception`, the LSP
162+
inserts `use Exception;` which is a compile error.
163+
164+
The correct behaviour is to detect the conflict and fall back to inserting
165+
a fully-qualified reference (`\Exception`) at the usage site instead of
166+
adding a `use` statement. As stretch behaviour, the LSP could try to
167+
generate a sensible alias (`use MongoDB\Driver\Exception\Exception as
168+
MongoDBException;`). Smart aliasing would be especially useful in the
169+
`use` completion context where the user is explicitly managing imports
170+
and would benefit from a suggested alias rather than a silent fallback
171+
to FQN.
172+
173+
---
174+
175+
#### 40. Insert `use` statements in alphabetical order
176+
177+
Auto-imported `use` statements are currently appended at the bottom of the
178+
existing `use` block. Most PHP coding standards (PSR-12, Symfony, Laravel)
179+
expect `use` statements to be sorted alphabetically. The LSP should scan
180+
the existing imports, find the correct insertion point to maintain
181+
alphabetical order, and place the new statement there instead of at the
182+
end.
183+
184+
---
185+
29186
#### 21. No reverse jump: implementation → interface method declaration
30187

31188
Go-to-implementation lets you jump from an interface method to its concrete

0 commit comments

Comments
 (0)