Description
PHPantom cannot resolve/parse classes that live under a symlinked directory inside the workspace. Many real-world projects do not use Composer and instead link their in-house framework into the project via a symlink (for example a framework directory pointing to a shared framework checkout elsewhere on disk). Because PHPantom's workspace walk does not follow symlinks, every class under that directory — in our case a whole set of framework namespace prefixes — is missing from the index, so goto-definition / hover / diagnostics fail on those symbols.
Use case
Our project (a PHP 8.3 app) has no composer.json. The framework lives outside the repo and is linked into the project root:
my_project/ <- workspace root (LSP opened here)
├── .phpantom.toml
├── src/ <- application code (indexed fine)
└── framework -> /absolute/path/to/shared-framework <- symlink, NOT followed
├── core/ <- framework core classes
└── shared/ -> /absolute/path/to/another/shared-module <- nested symlink
With [indexing] strategy = "self" (scan every PHP file in the workspace), all framework classes are unresolved. The .gitignore does not exclude the symlinked directory, so the only reason they're missing is that symlinked directories are skipped during the walk.
Proposed solution
Ideally, one (or both) of:
- Follow symlinks in the workspace walk — call
.follow_links(true) on the ignore::WalkBuilder in src/classmap_scanner/discovery.rs (walk_roots), with cycle protection (the ignore crate handles symlink loops when following is enabled). This would index the linked framework transparently.
- A configurable list of extra index roots / include paths in
.phpantom.toml (e.g. [indexing] roots = ["/absolute/path/to/shared-framework"]), so projects can explicitly point PHPantom at framework sources outside (or linked into) the workspace without changing directory layout.
A follow_links(true) option flag under [indexing] (default false, opt-in) would also be a safe middle ground.
Alternatives considered
[indexing] strategy = "self" — already used; still does not follow symlinks.
- Removing the symlink and copying the framework into the repo — undesirable: breaks the shared-framework layout (the same framework tree is shared across multiple projects) and risks affecting runtime autoloading.
- Opening the framework directory as a separate workspace — cross-workspace references still resolve poorly.
.gitignore negation (e.g. !framework) — has no effect, since the walk skips symlinks regardless of gitignore status.
Code example
<?php
// src/Service/SomeService.php
namespace app\Service;
use Vendor\Framework\Core\DB; // <-- unresolved under the symlinked framework dir
use Vendor\Framework\Shared\Foo; // <-- unresolved
class SomeService
{
public function run(): void
{
$db = DB::connect('db'); // goto-definition / hover do not work
}
}
---
*Context: PHPantom 0.10.0. Confirmed in source that `walk_roots` in `src/classmap_scanner/discovery.rs` builds the `ignore::WalkBuilder` without `.follow_links(true)`.*
Description
PHPantom cannot resolve/parse classes that live under a symlinked directory inside the workspace. Many real-world projects do not use Composer and instead link their in-house framework into the project via a symlink (for example a framework directory pointing to a shared framework checkout elsewhere on disk). Because PHPantom's workspace walk does not follow symlinks, every class under that directory — in our case a whole set of framework namespace prefixes — is missing from the index, so goto-definition / hover / diagnostics fail on those symbols.
Use case
Our project (a PHP 8.3 app) has no
composer.json. The framework lives outside the repo and is linked into the project root:With
[indexing] strategy = "self"(scan every PHP file in the workspace), all framework classes are unresolved. The.gitignoredoes not exclude the symlinked directory, so the only reason they're missing is that symlinked directories are skipped during the walk.Proposed solution
Ideally, one (or both) of:
.follow_links(true)on theignore::WalkBuilderinsrc/classmap_scanner/discovery.rs(walk_roots), with cycle protection (theignorecrate handles symlink loops when following is enabled). This would index the linked framework transparently..phpantom.toml(e.g.[indexing] roots = ["/absolute/path/to/shared-framework"]), so projects can explicitly point PHPantom at framework sources outside (or linked into) the workspace without changing directory layout.A
follow_links(true)option flag under[indexing](defaultfalse, opt-in) would also be a safe middle ground.Alternatives considered
[indexing] strategy = "self"— already used; still does not follow symlinks..gitignorenegation (e.g.!framework) — has no effect, since the walk skips symlinks regardless of gitignore status.Code example