Skip to content

Fix #894: hover for locals, ctor params, and members inside init() bodies#899

Merged
DavidObando merged 1 commit into
mainfrom
fix/issue-894-hover-in-constructor-body
Jun 20, 2026
Merged

Fix #894: hover for locals, ctor params, and members inside init() bodies#899
DavidObando merged 1 commit into
mainfrom
fix/issue-894-hover-in-constructor-body

Conversation

@DavidObando

Copy link
Copy Markdown
Owner

Fixes #894

Problem

Hovering over a local variable, a constructor parameter, or a class member referenced inside an init(...) constructor body produced no hover result, while the identical reference inside a normal method body worked correctly.

Root cause

The language server's SemanticModel local-scope machinery (SemanticLookup.cs) was keyed exclusively on FunctionDeclarationSyntax. G# constructors are ConstructorDeclarationSyntax, and their synthesized FunctionSymbol has a null Declaration. As a result the hover/semantic-lookup pipeline never descended into constructor bodies:

  • Constructor parameters and the implicit this were never registered in the scope maps.
  • Constructor body locals were skipped in MapLocalVariables because the bound function's Declaration was null.
  • Resolve's by-name local fallback (FindContainingFunction) and the implicit-this member resolution (ResolveImplicitThisMember) only considered method declarations, so bare local/member references inside init never resolved.

Fix

Generalized the local-declarations scope key from FunctionDeclarationSyntax to SyntaxNode and threaded constructors through the same pipeline that already powers method bodies:

  • Map constructor parameters and the implicit this in the struct member loop (alongside methods).
  • Match constructor body locals against the constructor's body syntax in MapLocalVariables, using a FunctionSymbol -> ConstructorDeclarationSyntax reverse map to recover the declaring syntax.
  • Collect ConstructorDeclarationSyntax into per-file buckets and add FindContainingConstructor, so Resolve's by-name fallback covers constructor scopes.
  • Extend ResolveImplicitThisMember to treat init(...) bodies as having an implicit this receiver, so bare member references (e.g. Area = product) resolve to the class member.

Hover for locals, constructor parameters, and class members inside init now matches method-body behavior exactly.

Tests

Added test/LanguageServer.Tests/Issue894ConstructorHoverTests.cs with regression coverage for:

  • hover over a local variable declared in init -> (local variable) product int32
  • hover over a constructor parameter -> (parameter) w int32
  • hover over a class member referenced in init -> Area int32 + its doc comment

All three failed (null hover) before the fix and pass after.

Validation

  • dotnet build GSharp.sln --configuration Release --no-restore -graph -> succeeded, 0 warnings/errors.
  • dotnet test GSharp.sln --configuration Release --no-build -> 5490 passed, 1 skipped, 0 failed (Core 3340 +1 skipped, Compiler 1360, LanguageServer 340, Interpreter 308, Extensions 104, Sdk 38).

…) bodies

Hover/semantic lookup walked function and method bodies but never descended
into user-defined `init(...)` constructor bodies, so hovering a local
variable, a constructor parameter, or a class member referenced inside a
constructor returned no result — even though the same reference inside a
method body worked.

Root cause: the SemanticModel's local-scope machinery was keyed exclusively
on FunctionDeclarationSyntax. Constructors are ConstructorDeclarationSyntax
whose synthesized FunctionSymbol has a null Declaration, so:
- constructor parameters and the implicit `this` were never registered,
- constructor body locals were skipped in MapLocalVariables (the bound
  function's Declaration was null),
- Resolve's by-name local fallback (FindContainingFunction) and the
  implicit-`this` member resolution only considered methods.

Fix: generalize the local-declarations scope key from FunctionDeclarationSyntax
to SyntaxNode and thread constructors through the same pipeline:
- map ctor parameters and the implicit `this` in the struct member loop,
- match ctor body locals against the constructor's body syntax in
  MapLocalVariables via a FunctionSymbol -> ConstructorDeclarationSyntax map,
- collect ConstructorDeclarationSyntax into per-file buckets and add
  FindContainingConstructor so Resolve's by-name fallback covers ctor scopes,
- extend ResolveImplicitThisMember to treat ctor bodies as having `this`.

Adds regression tests covering hover over a local var, a ctor parameter, and
a class member inside an init() body.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@DavidObando DavidObando merged commit a4ef3f1 into main Jun 20, 2026
7 checks passed
@DavidObando DavidObando deleted the fix/issue-894-hover-in-constructor-body branch June 20, 2026 02:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hovering over local var or class member inside init() .ctor body doesn't produce expected result

1 participant