Skip to content

feat(catalog): keep editor features working after DO, CALL and unparsable statements; resolve CALL - #914

Open
psteinroe wants to merge 1 commit into
feat/editor-features-refresh-settingsfrom
feat/editor-best-effort-call
Open

psteinroe wants to merge 1 commit into
feat/editor-features-refresh-settingsfrom
feat/editor-best-effort-call

Conversation

@psteinroe

@psteinroe psteinroe commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #911.

One DO block, CALL, EXECUTE, or half-typed DDL statement turned off function hints, function tokens, enum tokens and resolved overloads for the rest of the file, and CALL itself got nothing.

create table broken (id int,);          -- e.g. while typing
do $$ begin raise notice 'x'; end $$;
call do_it(1, 'a');
-- before: no hints, no token, empty hover on do_it
-- after:  do_it(a: 1, b: 'a'), do_it is a function token, hover shows the procedure
select make_point(1, 2) from users where current = 'happy';
-- before: no x:/y: hints, no function token for make_point, 'happy' not an enum member
-- after:  as if the statements above weren't there

Best-effort catalog for editor features

Catalog::apply taints the catalog on statements it can't model, and walk_statements taints it on statements that don't parse. From then on nothing is missing, function and operator candidates are incomplete, and casts are unknown, so no Function or EnumLiteral reference is recorded. That is right for the linter, which only reports what is certain, but too strict for hints, tokens and hover, and it made hints below the cursor flicker while typing.

Catalog::best_effort() returns a catalog whose lookups ignore the taint: it keeps answering from the database and the statements it could follow, and still only finds objects that exist there. Only walk_statements (hover, inlay hints, semantic tokens) uses it. The linter's catalog is unchanged, the Postgres regression suite and the analyser specs pass, and references_are_only_collected_on_request still checks that findings don't depend on collecting references. The trade-off: an object a DO block creates is unknown and one it drops is still found, which the docs now say.

CALL

The resolver now handles CallStmt, only when references are collected: the arguments are typed (so nested calls, casts and enum literals get references), and the call goes through select_function. A reference is recorded when the match is a procedure without output parameters, because CALL passes an argument for OUT parameters too, so they wouldn't line up with the signature. The findings of the arguments are dropped: Postgres' checks of CALL (transformCallStmt) aren't ported, and the linter output must not change.

Hover: the editor grammar doesn't classify the name in CALL, so hover found no node and returned nothing. When there is no hovered node, hover now shows the function of a Function reference at the cursor.

Tests

  • pgls_catalog: procedure_call_references (named arguments, nested calls, procedures with OUT parameters and non-procedures skipped), best_effort_catalogs_ignore_unmodelled_statements (the same statement after DO with a strict and a best-effort catalog), and CALL in references_are_only_collected_on_request.
  • pgls_workspace: hints, tokens and hover after a broken create table, a DO block and a CALL.
  • pgls_hover: snapshot for hovering a procedure in CALL (only the matching overload).

Not covered

  • Hovering the schema in call public.proc() shows the procedure too, since the fallback has no hovered node to tell the parts apart.
  • CALL of procedures with OUT or INOUT parameters.

Follow-ups: CALL of procedures with OUT/INOUT parameters is added in #937.

…able statements; resolve CALL

Editor features walk the file with a best-effort catalog, which ignores
statements whose effects it can't follow instead of treating every
lookup after them as unknown. The linter keeps the strict catalog.

CALL records a reference to the procedure it calls, so it gets inlay
hints, a semantic token and hover. Its arguments' findings are dropped,
since Postgres' checks of CALL are not ported.

This branch has not been deployed

No deployments
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.

1 participant