Skip to content

feat(workspace): resolve E'...' function bodies and locate PL/pgSQL bodies by token - #941

Open
psteinroe wants to merge 1 commit into
feat/sql-function-bodiesfrom
feat/escape-string-bodies
Open

psteinroe wants to merge 1 commit into
feat/sql-function-bodiesfrom
feat/escape-string-bodies

Conversation

@psteinroe

Copy link
Copy Markdown
Collaborator

Stacked on #918.

Two cases #918 left out: function bodies written as escape strings, and the PL/pgSQL body range, which still used content.find.

create function escaped_fn() returns text language sql
as E'select \'é\' || name from users where gone = 1';
-- before: no tokens, hints, hover, or diagnostics in the body
-- after:  name and users get tokens, and unknownColumn is on `gone`

create function f() returns void language plpgsql
as 'begin raise notice ''x''; ende';
-- before: no PL/pgSQL syntax error at all (the body text wasn't found in the source)
-- after:  the syntax error covers the body

What changed

  • StatementOffsets (pgls_analyser) maps escapes of any length instead of only '': each escape records the bytes it stands for in the statement and its bytes in the document. Offsets inside an escape map to its start in both directions.
  • sql_function::string_body unescapes '...' and E'...' constants after AS, following the xe rules of Postgres' lexer (scan.l#L262 at REL_18_6): \b \f \n \r \t \v, octal, \x hex, \u/\U, '', and \ before any other character. A value that isn't valid UTF-8 (e.g. \xff), a \u without four digits, a surrogate pair, or a constant continued on a new line is not matched, and the body gets no statements like before. U&'...' bodies are still not supported.
  • PgQueryStore::get_or_cache_plpgsql_parse uses string_body for the range of PL/pgSQL syntax errors. If the body can't be located, the error now covers the whole statement instead of the check being skipped.

Tests

  • unescape unit tests: every escape kind, multi-byte UTF-8 from \x pairs, and the cases that aren't matched.
  • StatementOffsets: an escape that is longer than the bytes it stands for.
  • sql_function: an E'...' body with '', \', \\, \n and é, mapped back to the document.
  • pg_query: PL/pgSQL syntax error spans for a body with '' and for a body whose text also appears earlier, in a parameter default.
  • Workspace: tokens and an unknownColumn diagnostic in an E'...' body.

Not covered

U&'...' bodies; PL/pgSQL bodies still get no editor features (only the syntax check).

…odies by token

Function bodies written as escape strings are unescaped like Postgres'
lexer does, with a map of where each escape is, so their statements get
tokens, hover, hints and diagnostics at the right place. The offset map
now handles escapes of any length.

The PL/pgSQL syntax check found the body with a substring search, which
failed for bodies with doubled quotes (skipping the check) and could
match an earlier occurrence. It now uses the string constant after AS,
and reports on the whole statement if the body can't be found.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant