Raven VS Code Extension
The Raven VS Code extension wires the editor to the Raven.LanguageServer LSP process so .rvn files, with legacy .rav compatibility, can surface diagnostics, completions, and inlay hints. The language server publishes syntax diagnostics immediately after edits and keeps previous semantic diagnostics and inlays visible for unchanged ranges while newer snapshot results are pending. It auto-discovers the language server build output and starts it with dotnet when the extension activates.
Accepting identifier completion preserves surrounding indentation and comments.
When editing inside an identifier, suggestions use the prefix before the caret
and acceptance replaces the entire identifier. Method completion adds parentheses
and places the caret inside them when starting a new call. If an argument list
already exists, completion preserves it and leaves the caret after the method name.
On an indented blank line, completion offers visible values and statement keywords.
A completed member expression on the previous line does not restrict these
suggestions; an unfinished access such as Console. still offers members when
continued on the next line.
Ordinary code suggestions are suppressed inside comments and literal text,
including unfinished strings. Embedded expressions such as ${Console.} retain
code completion. Parentheses, quotes, and newlines are not automatic completion
trigger characters.
The Explorer also contains an opt-in Raven Syntax Tree debugging view. It
renders nodes, tokens, trivia, syntax property roles, raw kinds, spans, missing
elements, and diagnostics from the machine-readable rvn dev syntax json
output. The toolbar switches between the authored syntax tree and the fully
macro-expanded tree, and can open the complete expanded source in a read-only
virtual Raven document. Tree selections reveal the corresponding authored or
expanded source range.
The view is always available from the Explorer's Views menu. Run Raven: Show Authored Syntax Tree or Raven: Show Expanded Syntax Tree from the Command Palette to open Explorer, focus the view, and select its mode.
Embedded macro language tooling
When a token-tree macro exposes an IMacroEmbeddedLanguageProvider projection,
the extension can reuse an installed VS Code language provider without copying
that language's catalog into Raven. For markup!, the language server returns
the position-preserving html projection that owns the cursor. The extension
opens it as an invisible virtual HTML document, invokes VS Code's standard HTML
completion and hover providers, and maps their ranges back to the Raven body.
Completion items are merged after Raven's semantic completions; hover content
is merged after Raven's semantic hover when both providers contribute.
| Cursor location | Raven contribution | Projected HTML contribution |
|---|---|---|
| Standard element or attribute | Macro classifications and structural diagnostics | Catalog completion and HTML documentation hover |
| Blazor component tag or parameter | Symbol hover, definition, and compiler-backed component completion | HTML results may supplement but do not replace Raven symbols |
Embedded { RavenExpression } |
Native Raven diagnostics, completion, hover, definition, and inlays | None; reported Raven fragments take precedence over the projection |
Nested markup! in component! |
Component parameters and surrounding lexical scope remain visible | The nested position-preserving HTML document supplies completion and hover |
This gives standard HTML elements, attributes, and closing-tag suggestions in
markup!, including a nested invocation inside a component! block. Blazor
component tags and [Parameter] properties still come from Raven's compiler
completion provider. Embedded Raven expressions are masked in the HTML view and
continue to use native Raven tooling. The bridge currently covers completion
and hover. HTML formatting, linked editing, and diagnostics are later slices.
Prerequisites
- .NET SDK available on your
PATHso the client can start the language server. - The Raven SDK for build, run, and debug commands. The packaged extension can provide editor features from its bundled language server without the SDK.
- Node.js 18+ only when building the extension from source.
Installing the preview
Download and install the VSIX from the matching GitHub release:
curl -fLO https://github.com/marinasundstrom/raven/releases/download/v0.1.16/raven-vscode.vsix
code --install-extension raven-vscode.vsix --force
Restart VS Code after installing. If VS Code cannot discover rvn, set
raven.sdkPath to the versioned directory printed by rvn sdk path.
Building the extension
Install dependencies and compile the client bundle from the repository root:
cd src/Raven.VSCode
npm install
npm run compile
The production JavaScript bundle emits to dist/extension.js and is referenced
by the extension manifest.
Running inside VS Code
The repository provides three deliberately separate development environments:
# Child terminal using the repository SDK and commands.
scripts/development-shell.sh
# Installed extension using repository SDK/compiler/language-server paths.
scripts/code-development.sh .
# Build and run the repository extension in an isolated Extension Development Host.
scripts/code-extension-development.sh .
The extension-development launcher runs
scripts/build-development-environment.sh first, so it does not depend on a
previous terminal or VS Code development session. Pass --no-build only when
the repository outputs are already current. From an existing repository
window, select Raven: Test Repository Extension in Run and Debug. That
configuration performs the same complete build and supplies the repository SDK,
compiler, and language-server paths to its Extension Development Host.
Configuration
The extension exposes settings to control language-server resolution and debug compilation:
raven.sdkPath(string): Override the Raven SDK root directory. An explicit path selects that SDK's language server and command-line tools. When this is unset, the extension runsrvn sdk pathto discover an installed SDK for build, run, and debug commands, but keeps using its matching bundled language server for editor features.raven.languageServerPath(string): Override the resolvedRaven.LanguageServer.dllpath. Use this when working with custom build outputs or packaged bits.raven.autoBuildLanguageServerOnActivate(boolean): Opt-in source-development setting that buildssrc/Raven.LanguageServer/Raven.LanguageServer.csprojbefore activation if it can find the project in the current workspace or extension ancestors. It can substantially delay startup and is ignored whenraven.languageServerPathis set.raven.compilerProjectPath(string): Override the path used to locate a prebuiltrvnc.dllundersrc/Raven.Compiler/bin/Debug/<tfm>when no bundled compiler driver is available.raven.targetFramework(string): Optional target framework (for example,net10.0) passed to debug compile invocations.raven.inlayHints.enabled(boolean): Master switch for Raven inlay hints.raven.inlayHints.inferredTypes.enabled(boolean): Show inferred type annotation hints when Raven inlay hints are enabled.raven.inlayHints.names.enabled(boolean): Show name hints for positional invocation arguments and deconstruction elements when Raven inlay hints are enabled.raven.inlayHints.requestDebounceMilliseconds(number): Delay inlay requests after document edits so typing can settle before semantic inlay work runs.
The repository launchers set RAVEN_SDK_ROOT and
RAVEN_LANGUAGE_SERVER_PATH for the child VS Code process. The extension uses
those paths when the corresponding explicit setting is absent. This keeps the
development selection scoped to that process; it does not modify user settings
or the installed Raven SDK.
When the extension discovers a workspace-built language server, it stages that build into an extension-owned directory before launch. The staged copy runs with the repository root as its working directory so repo-relative assets like Raven.Core.dll continue to resolve while the workspace build outputs remain free of language-server file locks.
Toolchain provenance
Use Raven: Show Toolchain Information to make the active toolchain explicit. The command opens the Raven output channel and reports:
- whether VS Code loaded a repository development extension or an installed extension, including its version and path;
- whether the language server came from an explicit override, an explicit SDK, a repository build, the installed extension bundle, or the discovered SDK fallback, including its exact path;
- the discovered or explicitly configured SDK version and path used by Raven commands; and
- the
Raven.Sdkversion selected by the nearestglobal.jsonfor every workspace folder.
These identities need not be the same. In the normal installed configuration,
editor features come from the server bundled with the installed VSIX, Raven
commands use the installed SDK, and dotnet build resolves the project SDK
selected by global.json. A repository extension host instead prefers the
repository-built language server so local compiler and language-service changes
are visible.
F5 compile + debug
The extension contributes a Raven debug type:
Raven: Compile and Debugcompiles the active.rvnfile or.rvnprojtarget using thervnccompiler driver. Legacy.ravsource files remain supported for compatibility.- Build artifacts are emitted to
${workspaceFolder}/.raven-debug. - After compile succeeds, the extension starts a
coreclrdebug session withdotnet <compiled-output.dll>.
You can start it by pressing F5 in a Raven file, or by running Raven: Compile and Debug Active File from the command palette.
Running a file or project
Raven: Run Active File/Project uses the rvn frontend. Selecting a .rvn
or legacy .rav source that belongs to a Raven project runs its owning project
through rvn run; selecting a .rvnproj file also runs that project. A source
without an owning project runs as an isolated file-based application. The
command opens an interactive terminal rooted beside the resolved project or
source file so application input and output behave like an ordinary script or
console application.
Language features follow evaluated project membership. A source included by a project receives that project's semantic context; a source outside project items receives an isolated file-application context even when a project file exists elsewhere in the workspace.
Packaging
scripts/package-vscode.sh publishes a framework-dependent language server into a server/ directory next to package.json and creates the VSIX. The compiler remains in the separately installed Raven SDK. A direct raven.languageServerPath override has highest precedence, followed by an explicit raven.sdkPath, workspace development builds, and the server packaged with the extension. A server from an automatically discovered SDK is only a final fallback when no matching packaged or workspace server is available. This prevents a newly installed extension from silently running an older SDK's language server.
When no SDK is discovered, the bundled server still provides editor features and the extension offers a link to the SDK installation instructions. The prompt can be permanently dismissed for syntax-only installations.
Inlay request concurrency
Inlay requests are tracked by document version and range. Separate visible ranges may complete independently; a newer request for the same range supersedes the older request. Results for edited or closed documents and cancelled requests are discarded. Completed request tracking is released, so scrolling does not retain range entries.
Run scripts/vscode-inlay-acceptance.cjs through VS Code's --extensionTestsPath
against an isolated Raven project containing Main.rvn. It temporarily changes
that buffer, restores it, and writes vscode-inlay-acceptance.json beside the
project. It covers unchanged declarations across comment edits and concurrent
visible ranges; run against the actual extension build under review. The
2026-10-14 regression reproduced a missing first-range response before the fix
and passed all 12 post-edit samples and eight concurrent range responses after it.
Imported project configuration changes
The client file watcher includes .props and .targets alongside project and
source files. Restoring an invalid imported configuration must trigger a reload
without requiring another source edit. The native packaged editor acceptance
checks invalidation and recovery of its imported class-library props file. This
is editor synchronization only; no Runtime Contract or compiler semantics change.