Skip to content
PaskalCPP
Tools

The language server

pcpp --lsp is a Language Server Protocol server: the editor runs it, and so can any LSP client. Every answer comes from the compiler's own analysed tree.

The server

pcpp --lsp speaks LSP over stdin / stdout (Content-Length framing) and names itself PaskalCPP LSP; the editor runs one for its whole lifetime.

  • Positions use the first encoding the client lists that the server knows (utf-16, utf-8, utf-32); a client that lists none gets UTF-16. Buffers sync incrementally.
  • Every language feature is answered from the compiler's own frontend (lexer, parser, semantic pass) run in check mode on the open buffers: nothing is built, an open buffer wins over its file on disk, and an import that is open is read from its buffer.
  • A request the server does not know is answered with an error (method not found); a request whose parameters it cannot read with an invalid-params error.

Diagnostics

Each changed buffer is checked and its reports are published as diagnostics, up to 100 errors per check. The parser recovers from a mistake and checks the rest of the file, so one broken line does not hide the others. The reports are the compiler's own: see Diagnostics.

A check remembers the files on disk its result depends on (directive paths, imported units). A client that can register file watchers gets them, and a change on disk checks every open buffer again.

Reading code

FeatureWhat it gives
Colouringkeywords and builtin types as semantic tokens, from the lexer's own tables
Hoverthe declaration of the name under the cursor in a PaskalCPP code block, and its /// doc comment as Markdown; a name from another file names that file
Go to definitionthe name in the declaration, in another file too; on an overload set, every member
Inlay hintsthe parameter name before each argument of a PaskalCPP routine call
Outlinethe file's imports, declarations, initialize / finalize and tests, a type's members, a routine's local routines and types
Workspace symbolsthe declarations of every open file, narrowed by a case-insensitive substring of the name
Call hierarchya routine's callers and the routines it calls, each with the places of the calls
  • A doc comment's tags are @param, @returns, @raises, @see, @deprecated, @since and @example.
  • Inlay hints are left out for a C/C++ callee, an intrinsic, the variadic tail, and an argument already spelled as its parameter; for an overload set they show only where every member names that parameter alike.
  • The outline leaves out a routine's local variables; selecting an entry selects its name.
  • Call hierarchy works on a routine's name at its declaration or at a call (a forward stands for its full routine), across the modules the open files reach. A call outside every routine (a module's body, initialize / finalize, a test) comes from the module itself.

Writing code

  • Completion, also on . and ->: the names in scope from the analysed tree (innermost first), then intrinsics, the names the module's imports export (bare; a name two units export is one entry per unit, inserting unit.Name), builtin types and keywords; after . / -> the members of the left side's type, then what its embeds promote. PaskalCPP names only.
  • Format Document and Format Selection rewrite only the space between tokens and keep every comment. A file with a syntax error is not formatted, and the client is shown why. The editor's format settings are on Settings.