Repository navigation
Development
Plugin 0.2.2 bundles LSP 0.3.8 from the toolkit 0.5.5 prerelease. CI run 37401363516 passed for source commit c3b6195 on x86, x64 and native ARM64. Each architecture passed all 57 editor assertions in both light and dark modes. Current results and limits are recorded in integration validation.
See the release procedure.
Use Windows 10 or later with Visual Studio 2022 Build Tools and the Desktop development with C++ workload. ARM64 builds also need the MSVC ARM64 build tools. The project uses MSBuild and C++17.
.\build.cmd
.\build\x64\Release\PxToolkitTests.exe
.\test\updater-tests.ps1build.cmd and package.cmd accept x86, x64, or arm64; the default is x64. Packaging verifies the pinned server and runtime archives, checks the DLL and Node architecture, and creates build/PxToolkit-NotepadPlusPlus-0.2.2-win-<arch>.zip. Helper and transport tests and the server version command run when the host can execute the target. ARM64 cross-builds on x64 skip execution; they do not establish ARM64 runtime behavior.
| Argument | MSBuild platform and production directory | Bundled runtime |
|---|---|---|
x86 |
Win32, build/Win32/Release
|
Windows x86 Node 22.23.2 |
x64 |
x64, build/x64/Release
|
Windows x64 Node 24.18.1 |
arm64 |
ARM64, build/ARM64/Release
|
Windows ARM64 Node 22.23.2 |
All current packages contain the same px-lsp 0.3.8 JavaScript and data. Run package commands one at a time because they share the extracted upstream server directory. CI is configured to build all three architectures and run executable checks and native smoke tests in light and dark modes on matching Windows hosts. Updater tests run in the x64 job. These are configured checks; recorded results are listed in the integration document.
The 0.2.1 release validation run passed for source commit 9511952 on x86, x64, and native ARM64. Each architecture passed all 56 editor assertions in both light and dark modes. Wine remains experimental and untested.
The client sets Node's old-space heap ceiling to 1 GiB for x86 and 4 GiB for x64/ARM64. A 4 GiB ceiling causes the bundled 32-bit Node process to fail during startup. Native server initialization is the regression check for this launch requirement.
For native tests, put the official npp.8.9.8.portable.x64.zip archive in build and run package.cmd first. Then run:
.\test\native-smoke.ps1
.\test\native-smoke.ps1 -DarkFor x86, use npp.8.9.8.portable.zip, run package.cmd x86, and add -Architecture x86 to each smoke command. For ARM64, use npp.8.9.8.portable.arm64.zip, run package.cmd arm64, and add -Architecture arm64 on an ARM64 Windows host.
The runner builds a separate test DLL and uses isolated portable Notepad++ instances with fixture mods. Results and screenshots go into build/native-smoke-*. Add -KeepOpen to inspect the fixture after a run. Do not install or ship any build/smoke-dll* DLL. Use the production package.
See Contributing for pull requests and integration validation for recorded results and limits. Wine on Linux and macOS is experimental and untested; a native Windows run does not verify it.
The reliability fixes prepared in 0.2.1 are included in the 0.2.2 release. The existing 0.2.0 archive does not contain them.
An additional rendering fix keeps folding in Notepad++'s folding margin and preserves its change-history margin. This prevents unsaved-change markers from coloring entire lines orange. Native tests check fold controls and change markers after an edit.
Unchanged semantic tokens retain their colors across edits and undo while a new server result is pending. Cached ranges shift with inserted or deleted text; changed tokens fall back to lexical colors. Native regressions check retention before the server can respond.
JSON-RPC validation accepts both object and array parameters. The bundled server sends paradox/indexChanged with [null]; rejecting that valid notification caused false language-server errors. Scalar parameters remain invalid, and feature handlers validate their own payloads.
| Boundary | Corrected behavior |
|---|---|
| Completion | Checks document revision, buffer, server generation, request identity, and caret before display and insertion. Server edit ranges use the shared validator. |
| Text positions | Indexes line starts once per snapshot and advances a cursor for ordered positions. Retains UTF-16 boundary and range checks. |
| Transport writes | Uses a worker and bounded queue; the UI thread does not perform pipe writes. Stopping the server cancels blocked I/O and ends the launcher and its child through a Windows job. |
| Document lifetime | Retains tracked buffer snapshots across restarts. Only documents belonging to the active mod are opened in the new server session. |
| Message dispatch | Validates envelopes and contains payload-decoding exceptions per message. Invalid responses and transport failure do not leave the affected request silently pending. |
| Framing | Rejects negative, signed, fractional, trailing-junk, duplicate, overflowing, and oversized lengths. Missing or oversized headers end the transport session. |
The UI thread still owns editor operations and response callbacks. The reader and writer workers only handle transport I/O. A new session clears queued frames, and callbacks from an older session cannot continue draining into a restarted client.
These limits apply to development builds containing the fixes. They are fixed implementation limits, not user settings.
| Limit | Value |
|---|---|
| Header, including its terminator | 8 KiB |
| Message body | 32 MiB |
| Outbound queued bytes, including the in-flight write | 64 MiB |
| Waiting outbound frames | 1,024 |
| Inbound queued bytes | 64 MiB |
| Inbound queued frames | 4,096 |
The reader allows one 8 KiB read beyond the maximum frame size while reassembling input. Outbound limits apply to serialized JSON, so a document near the body limit can exceed it after JSON escaping. Queue or framing failure ends the session with a logged reason. Restart reconnects after the cause is resolved.
The test executable launches itself as small fixture servers. These tests need no external Node installation. They cover malformed notifications and responses, payload exceptions, subsequent valid messages, a server that never reads stdin, pending-request failure, queue saturation, invalid framing, and successful restart.
Pure helper tests cover fragmented and combined frames, invalid headers and lengths, UTF-16 surrogate boundaries, CRLF positions, backward indexed lookups, edit overlap rejection, token arithmetic overflow, and large semantic responses on many lines and one long line.
Native tests exercise real LSP and Scintilla behavior: completion after caret movement, after typing, and after restart; valid completion and undo; preservation of following text; the visibility of an inactive unsaved declaration after restarting, and isolation and restoration when switching mods. The existing outline, references, rename, localization, folding, signature, and options checks remain.
The semantic-color check targets add_gold, a command annotated by the bundled server. The old check assumed that the declaration at byte 2 always had a semantic token. That assumption depends on indexing state and was not a valid rendering contract. A separate assertion checks lexical punctuation.
A local 620 KB fixture with 20,000 tokens took about 19 seconds before the position-index change and milliseconds afterward. This measures client conversion only. It does not establish server indexing time or whole-editor performance on every mod.