Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Laravel custom Eloquent builder support.** Models using the `#[UseEloquentBuilder]` attribute now have their custom builder's methods forwarded as static methods on the model. `query()`, `newQuery()`, and `newModelQuery()` return the custom builder type with correct generic model substitution. Contributed by @MingJen in https://github.com/AJenbo/phpantom_lsp/pull/118.
- **Eloquent relation and column string completion.** Typing inside string arguments to `with()`, `load()`, `whereHas()`, and other Eloquent methods that accept relation names now offers relationship method names as completions, with dot-notation traversal for nested relations. Similarly, `where()`, `orderBy()`, `select()`, `pluck()`, and other column-accepting methods offer model column names (from `$casts`, `$fillable`, `@property` tags, timestamps, etc.).
- **Authenticated user resolves to the configured model.** `$request->user()`, `auth()->user()`, and `Auth::user()` now resolve to the Eloquent model declared in `config/auth.php` instead of only the bare `Authenticatable` contract, so completion, hover, and member access work on the concrete model (`$request->user()->email`). Naming a guard selects that guard's model, so `auth('admin')->user()`, `Auth::guard('admin')->user()`, and `$request->user('admin')` resolve to the model configured for the `admin` guard rather than the default one. The config is read statically: only the literal default of `env('AUTH_MODEL', User::class)` is used, never the runtime environment. When a guard, provider, or model could vary at runtime, the result widens to a union of every candidate, and the floor is raised from the abstract contract to the project's own classes that implement it, so a single-model app resolves to just that model while a multi-model app offers each. Members that exist on some candidate resolve; genuinely unknown members still report.
- **Laravel macros are recognized as real methods.** A method registered with `SomeClass::macro('name', fn (...) => ...)`, whether in your own service providers or in an installed package's, now appears in completion on that class, shows the closure's parameters and return type on hover and in signature help, and resolves for member access and chaining. Go-to-definition on a macro call jumps to its `::macro(...)` registration site. Both instance (`$collection->name()`) and static (`SomeClass::name()`) calls work. A macro registered through a facade (`View::macro('extends', ...)`) also attaches to the concrete class the facade resolves to, so an instance call on that class (`$factory->extends()`) resolves as well as the static facade call. Discovery now follows provider-rooted helper classes in both app code and installed packages, including helper classes referenced through `Foo::class`, and also recognizes statically typed variable registrations like `Builder $query` followed by `$query->macro(...)`.
- **Laravel macros are recognized as real methods.** A method registered with `SomeClass::macro('name', fn (...) => ...)`, whether in your own service providers or in an installed package's, now appears in completion on that class, shows the closure's parameters and return type on hover and in signature help, and resolves for member access and chaining. Go-to-definition on a macro call jumps to its `::macro(...)` registration site, landing on the first character of the macro name string. Both instance (`$collection->name()`) and static (`SomeClass::name()`) calls work. A macro registered through a facade (`View::macro('extends', ...)`) also attaches to the concrete class the facade resolves to, so an instance call on that class (`$factory->extends()`) resolves as well as the static facade call. Discovery now follows provider-rooted helper classes in both app code and installed packages, including helper classes referenced through `Foo::class`, and also recognizes statically typed variable registrations like `Builder $query` followed by `$query->macro(...)`. Find-references and rename now link the registration string with macro call sites in both directions, including chained collection-style calls such as `->pluck(...)->macroName()`, and workspace symbol maps are warmed in the background so repeated workspace-wide rename/reference requests avoid reparsing unopened files.
- **Container string aliases and global facades resolve.** `resolve('blade.compiler')` and `app('cache')` resolve to the concrete class Laravel binds the string to, so member access on the result completes, navigates, and type-checks. Bare global facade aliases such as `\App` and `\DB` resolve to their facade class without an explicit import. Both alias tables are read by parsing the framework the project actually has installed (never a version-specific list baked into PHPantom), so a name that only a service provider registers stays unresolved rather than being guessed. A project class whose short name collides with a facade alias (e.g. an app's own `Request` in the current namespace) still wins, since the alias table is only consulted after namespace-aware resolution misses.
- **`model-property<T>` pseudo-type recognition.** The Larastan `model-property<Model>` type no longer triggers "unknown class" diagnostics. It is treated as a string subtype.
- **`compact()` strings are linked to local variables.** A string argument to `compact('user')` is now treated as a reference to the matching local variable. Renaming the variable updates the string (and renaming from the string updates the variable and its other uses), find-references includes the string, and go-to-definition on the string jumps to the variable's assignment. Contributed by @calebdw in https://github.com/PHPantom-dev/phpantom_lsp/pull/159.
Expand Down
2 changes: 1 addition & 1 deletion src/definition/member/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ impl Backend {
(uri.to_string(), offset)
};
let content = self.get_file_content(&uri)?;
let position = crate::util::offset_to_position(&content, offset as usize);
let position = crate::util::offset_to_position(&content, offset as usize + 1);
let parsed_uri = Url::parse(&uri).ok()?;
Some(point_location(parsed_uri, position))
}
Expand Down
5 changes: 5 additions & 0 deletions src/definition/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,11 @@ impl Backend {
if locs.is_empty() { None } else { Some(locs) }
}

SymbolKind::LaravelMacroString { .. } => Some(vec![point_location(
Url::parse(uri).ok()?,
crate::util::offset_to_position(content, cursor_offset as usize),
)]),

SymbolKind::Keyword | SymbolKind::CastType | SymbolKind::Comment => None,
}
}
Expand Down
1 change: 1 addition & 0 deletions src/definition/type_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ impl Backend {
| SymbolKind::ConstantReference { .. }
| SymbolKind::NamespaceDeclaration { .. }
| SymbolKind::LaravelStringKey { .. }
| SymbolKind::LaravelMacroString { .. }
| SymbolKind::Keyword
| SymbolKind::CastType
| SymbolKind::Comment => {
Expand Down
1 change: 1 addition & 0 deletions src/highlight/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ impl Backend {
}
SymbolKind::NamespaceDeclaration { .. }
| SymbolKind::LaravelStringKey { .. }
| SymbolKind::LaravelMacroString { .. }
| SymbolKind::Keyword
| SymbolKind::CastType
| SymbolKind::Comment => Vec::new(),
Expand Down
1 change: 1 addition & 0 deletions src/hover/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,7 @@ impl Backend {
}

SymbolKind::LaravelStringKey { .. }
| SymbolKind::LaravelMacroString { .. }
| SymbolKind::Keyword
| SymbolKind::CastType
| SymbolKind::Comment => None,
Expand Down
Loading
Loading