Skip to content

mcpp-language-server v0.0.12

Choose a tag to compare

@github-actions github-actions released this 11 Oct 15:55
· 5 commits to main since this release
5dee2fa

mcpp-language-server 0.0.12

What changed

The bundled clangd is now mcppls-clangd: LLVM 23.1.0 with 25 patches for C++ modules
(mcppls-clangd 0.0.12,
reporting 23.1.0-mcppls.0). Each patch maps to rows of the upstream-defects register (issue #24)
and carries a drop condition. The payload pins the engine by its binary SHA-256 and its source
identity, and the server checks both before it trusts what the engine declares.

Completion on files that import modules

  • Completion answers from the semantic parser, quickly. On the Qt project fixture (12 contexts,
    3 starts × 30 rounds each, Linux x64), warm completion has p95 53–91 ms and completion right after
    an edit 133–168 ms. In the same measurement, completion after an edit is at least twice as fast
    as with stock clangd 23.1. Completion loads from imported modules only the names that can match
    what was typed, shares the draft's verified imports, and lists each constructor overload once. Module importers still answer about 30 ms slower than the same
    project written with headers once warm; that gap is open.
  • Files that include heavy headers and import modules keep their preamble. A file that
    includes Qt or <windows.h> and imports modules (whose own global module fragments include them
    too) used to be parsed in full, headers and all, for every request: about 0.6 s per completion
    for a Qt importer with stock clangd and before this release, and seconds per update with
    <windows.h>. Its headers are now kept in a preamble that is checked against every input it
    read, on Linux, Windows and macOS: 0.05 s per completion on the same Qt file. New conformance
    fixtures ux-modules-qt (Linux) and ux-modules-windows (Windows) hold answers, latency while
    typing, crashes and stalls on such projects.
  • Typing an import, or editing a module the file imports, no longer waits on a rebuild.
    Completion on an import line, or on a blank line among the imports, uses the modules it has. An
    import nothing in the project builds keeps them too. After a dependency is edited, completion
    waits up to 250 ms for its rebuild and otherwise answers from the modules as they were, while
    the rebuild goes on. A cached dependency scan no longer reads every header again.
  • Unsaved edits count. Dependency scans read the request's own buffers. A cached scan or BMI
    verdict is reused only after every input it observed replays unchanged, including __DATE__-like
    builtins and files that did not exist.

Building modules

  • Prerequisite modules build as one bounded, cancellable graph. Independent modules compile in
    parallel within a shared limit. A cycle fails before any BMI is built, and closing a document
    cancels its waits. A module change rebuilds only the modules that depend on it.
  • On Linux, module compilers run in supervised worker processes. They stop when clangd dies,
    are admitted against a shared memory budget, and the files they leave are collected once nothing
    holds them.
  • Malformed module directives recover in place. A missing ; is reported on the directive
    that lacks it, and a directive after a missing BMI no longer derails the rest of the file. The
    product's own relocation of that diagnostic (WA-CLANGD-006) retires for an engine that declares
    the fix.
  • An import of a module nothing provides is reported, and the file keeps answering. A module
    unit whose import resolves to nothing no longer stalls clangd or the files that import it. For
    an engine that declares this (unresolved-import-recovery), the product stops giving such an
    import in a file that provides no module a stand-in, and stops setting a file aside while an
    autosave has such an import on disk (WA-CLANGD-013). Typing an import with autosave on no longer
    rewrites the engine database at each name it passes through. A module unit's own unresolved
    import still gets a stand-in, once the unit has not been edited for a few seconds, so its
    importers keep their features (WA-CLANGD-002).
  • A module built again to the same bytes keeps the modules that import it. A BMI that was
    lost, evicted or damaged is built again, and when its bytes are the same its importers are
    reused instead of being rebuilt one by one (ux-mcpp: 42 importers after one lost module).
    Reusing a cached module no longer looks at every slot of the cache, which made each of a
    request's prerequisites cost about 12 ms, and a file's last prerequisites stay with the engine
    between requests, so typing an import no longer copies every module it needs again (1-2 s for a
    completion right after an autosave).
  • The module cache follows the workspace's cache budget. On Linux, mcppls-clangd's own module
    cache gets three quarters of mcppls.cache.maxBytes (at least 1 GiB; unbounded when the budget
    is) instead of a fixed 1 GiB, past which module builds waited for room: a profile change with
    its modules beside the first profile's stalled the files that needed them.
  • Reusing a dependency scan no longer reads every header again. A header that is on disk with
    the identity, size and modification time the scan saw, and was last modified well before it, is
    taken as unchanged, as clang does for a module's inputs. A hit on the standard library module's
    scan used to read and hash each libc++ header.

mcpp's build programs

  • build.mcpp has the features of target code (#51). From mcpp 2026.10.11.1 the build database
    describes the build programs: build.mcpp, the libraries of [build-dependencies] and mcpp's
    engine interface (import mcpp;), in sets of the build-program configuration. build.mcpp is
    read as C++ with the arguments mcpp compiles it with, so navigation, hover, completion and
    diagnostics reach its libraries and the engine interface. Every editor integration treats .mcpp
    files as C++.
  • The targets and the build programs stay apart. The default context reads a package in both
    [dependencies] and [build-dependencies] as the targets build it, and the context
    <package>:build reads the build programs as mcpp compiles them; build programs with a toolchain
    of their own, as in a cross build, are read there and say so. A target that imports mcpp or a
    library of [build-dependencies], and a build.mcpp that imports a module of the targets, get an
    error at the import, as mcpp refuses them.
  • The engine interface is read-only. Formatting, code actions and renames never edit
    <MCPP_HOME>/engine/<version>/modules, and VS Code opens it read-only.
  • With an mcpp older than 2026.10.11.1, build.mcpp is not read, and a note in it names the mcpp
    that describes it.

Editing

  • Formatting has an mcpp fallback. mcppls.format.fallbackStyle (default auto): a project
    without .clang-format that is an mcpp project formats in the pinned mcpp style. A named style
    overrides it, and a project .clang-format always wins. Other projects keep clangd's default.
  • Compiler extensions complete. Attribute syntax, cleanup functions and, on Windows targets,
    SEH constructs are offered where they are valid.
  • textDocument/semanticTokens/range is answered, and misc-const-correctness no longer suggests
    const for a range a pipeline consumes.

Fixes

  • "preparation-stalled" no longer fires the moment preparation starts again (#49). Preparation
    that had finished a while earlier and was given modules again — a model reloaded, a file opened
    that imports a module nobody had prepared — measured its stall clock from the previous run's
    last progress. It reported "made no progress for a minute (34/39 done)" seconds after starting,
    and wrote a diagnostic bundle.
  • A file mcppls's own engine answers for a while (its module does not compile) is no longer taken
    for one clangd will not finish once it goes back, and a syntax error in a file the editor opened
    outside the workspace is no longer reported as a project issue.

VS Code

  • A server that crashes while starting recovers cleanly. Recovery waits for the failed start
    to settle, then starts a fresh client through the same queue as a manual restart, under the same
    crash budget. A failed protocol write closes the connection instead of leaving an unhandled
    rejection (WA-VSCODE-003, WA-VSCODE-004). A crash report keeps the log path the server announced.

Platforms and compatibility

  • linux-arm64 runs on far more systems. Its clangd is the maintained engine built on an
    Ubuntu 20.04 floor, so it needs glibc 2.31 (Ubuntu 20.04, Debian 11, RHEL 9 and later) instead
    of 2.34 and GCC 12's libstdc++.
  • linux-x64's bundled clangd now needs glibc 2.31. Stock clangd needed 2.18. On an older system
    (Ubuntu 18.04, Debian 10, RHEL 8) the bundled clangd cannot start. mcppls then keeps its own
    module-level features and says why in its status, and mcppls.clangd can point at another
    clangd.
  • macOS needs 12 or later (was 11): the engine is built for macOS 12.
  • An external server or clangd keeps working as before. Intel macOS still has no bundled build.

Files

File What it is How to install it
mcppls-linux-x64.vsix The VS Code extension for one platform, with that platform's payload inside it code --install-extension <file>, or the Extensions view's “Install from VSIX…”
mcppls-linux-arm64.vsix The VS Code extension for one platform, with that platform's payload inside it code --install-extension <file>, or the Extensions view's “Install from VSIX…”
mcppls-darwin-arm64.vsix The VS Code extension for one platform, with that platform's payload inside it code --install-extension <file>, or the Extensions view's “Install from VSIX…”
mcppls-win32-x64.vsix The VS Code extension for one platform, with that platform's payload inside it code --install-extension <file>, or the Extensions view's “Install from VSIX…”
payload-linux-x64.tar.gz The server, the clangd it drives and the semantic kit, as one tree. What every non-VS-Code editor needs Unpack it and put payload/bin/ on PATH; mcppls serve speaks LSP over stdio
payload-linux-arm64.tar.gz The server, the clangd it drives and the semantic kit, as one tree. What every non-VS-Code editor needs Unpack it and put payload/bin/ on PATH; mcppls serve speaks LSP over stdio
payload-darwin-arm64.tar.gz The server, the clangd it drives and the semantic kit, as one tree. What every non-VS-Code editor needs Unpack it and put payload/bin/ on PATH; mcppls serve speaks LSP over stdio
payload-win32-x64.tar.gz The server, the clangd it drives and the semantic kit, as one tree. What every non-VS-Code editor needs Unpack it and put payload/bin/ on PATH; mcppls serve speaks LSP over stdio
mcppls-zed-0.0.12.tar.gz The Zed extension directory mcppls-zed/: extension.toml, the compiled extension.wasm and the crate it was compiled from, which Zed's dev-extension install compiles again. Platform-independent; the server comes from the payload Unpack it, put the payload's payload/bin/ on PATH, then Zed's command palette: zed: install dev extension, and choose mcppls-zed (Zed compiles it, which needs Rust through rustup)
mcppls-clion-0.0.12.zip The IntelliJ-platform plugin archive Gradle produces. Gradle and the JDK it compiles with come from the clion feature (xim:gradle, xim:jdk-temurin), so it does not depend on whatever JDK the machine happens to default to Put the payload's payload/bin/ on PATH, then CLion: Settings → Plugins → the gear menu → Install Plugin from Disk, and restart
SHA256SUMS sha256 of every other file in the release sha256sum -c SHA256SUMS

Not in a release

  • The Claude Code plugin: it is consumed from the repository through its marketplace file, not downloaded as an archive.
  • xlings-res archives and the rendered xim-pkgindex descriptors: the ecosystem publish path is deliberately out of scope for this release, so mcppls-devtools release xlings is not run.
  • The model gateway: a separate package, built and tested on its own, not part of what a user installs.

Generated from packaging/release.manifest.json for 0.0.12.