Skip to content

Add function signature help #20

Description

@Seddryck

Goal

Add LSP signature help for Expressif function calls so that users can see the function signature and the currently active parameter while entering arguments.

This is the fourth feature in the initial LSP roadmap. It should build directly on the shared function metadata used by completion (#16) and hover (#19), not introduce a new model of functions or parameters.

Expected behavior

Given:

text-to-pad-right(@myCount, "*")
                  ^

or while typing:

text-to-pad-right(@myCount, 
                            ^

the client should be able to display:

text-to-pad-right(length, character)
                  ^^^^^^

and, after the comma, identify character as the active parameter.

Scope

Implement an LSP signature-help handler that:

  • identifies the innermost function call containing the cursor;
  • resolves that call to function metadata through the shared function catalog;
  • returns one or more LSP SignatureInformation entries as appropriate;
  • identifies the active signature and active parameter;
  • exposes parameter labels and, where available, concise parameter documentation;
  • updates correctly while the user edits arguments;
  • behaves correctly for nested calls;
  • returns no signature help when the cursor is not inside a supported function argument list.

The implementation should use parsed syntax and source positions wherever possible. It should not determine the active argument by naively counting commas in raw text because commas may occur in nested calls, arrays, records, strings, or other syntax constructs.

Shared metadata

Signature help must reuse the same function metadata abstraction as #16 and #19.

The shared metadata should provide at least:

  • canonical function name;
  • aliases when applicable;
  • ordered parameters;
  • parameter names;
  • optionality;
  • function summary;
  • parameter summaries when available.

Conceptually:

Document + cursor
      │
      ▼
Expressif.Syntax
      │
      ▼
function call + active argument
      │
      ▼
FunctionCatalog
      │
      ▼
SignatureHelpHandler

No second parameter catalog should be maintained in the language server.

Active parameter detection

Correct active-parameter detection is the central behavior of this feature.

Tests should cover at least:

foo(|)
foo(a|)
foo(a, |)
foo(a, b|)
foo(bar(a, b), |)
foo("a,b", |)

where | represents the cursor.

Nested function calls must select the innermost applicable function. For example:

outer(inner(a, |), b)

should show signature help for inner, not outer.

Once the cursor moves outside the inner call but remains in outer, signature help should switch back to outer.

Optional and excess arguments

Optional parameters should be represented consistently with hover.

If the cursor is beyond the number of declared parameters, the server should remain stable and deterministic. It may keep the last valid parameter active or return no active parameter, depending on the LSP library's model, but the behavior must be tested and documented.

Malformed/incomplete expressions are expected while typing. Signature help should therefore work on recoverable/incomplete syntax when the parser provides enough structure to identify the function call and active argument.

Trigger characters

The server should advertise sensible signature-help trigger characters, normally including:

  • ( to start signature help;
  • , to move to the next parameter.

Retrigger behavior should also support cursor movement or continued editing where the LSP client requests signature help explicitly.

Trigger characters are protocol hints only; the handler must still validate that the cursor is actually in a function-call context.

Signature rendering

The signature label should follow the same rendering convention as hover, for example:

token(index, separator?)

Parameter labels supplied in ParameterInformation must map accurately to the corresponding portion of the displayed signature so clients can highlight the active parameter correctly.

Acceptance criteria

  • The language server advertises and handles LSP signature-help requests.
  • ( and , are exposed as appropriate signature-help trigger characters.
  • Signature help shows the resolved Expressif function signature while the cursor is inside its argument list.
  • The active parameter is correct before the first argument, within an argument, and after commas.
  • Nested function calls select the innermost applicable call.
  • Commas inside nested syntax or string literals do not incorrectly advance the active parameter.
  • Optional parameters are represented consistently with function hover.
  • Function and parameter information comes from the same shared function catalog used by Add function-name completion #16 and Add function hover documentation #19.
  • Parameter documentation is included when readily available from the authoritative metadata source.
  • Incomplete but recoverable calls can still provide signature help where parser information permits.
  • Requests outside function argument lists return no misleading signature help.
  • Tests cover nested calls, cursor boundaries, optional parameters, incomplete calls, and negative contexts.
  • The feature remains editor-agnostic and works through standard LSP clients, including the thin VS Code client from Add VS Code extension as thin LSP client #13.

Out of scope

  • Type-based overload resolution.
  • Inferring parameter values or suggesting argument values.
  • Completion of fields, variables, literals, or argument values.
  • Runtime validation of argument values.
  • Function hover; covered by Add function hover documentation #19.
  • Semantic highlighting; handled separately by the next roadmap feature.
  • VS Code-specific parameter UI.

Metadata

Metadata

Assignees

No one assigned

    Labels

    new-featureRequest for a new feature in the tool

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions