VB.NET Language Support - Developer Documentation
Version: 1.0 Last Updated: 2026-02-05
- Prerequisites
- Environment Setup
- Building the Project
- Running Tests
- Debugging
- Code Organization
- Development Workflow
- CI/CD Pipeline
- Release Process
-
.NET 10.0 SDK or later
- Download: https://dotnet.microsoft.com/download
- Verify:
dotnet --version(should be 10.0+)
-
Node.js 18.0 or later
- Download: https://nodejs.org/
- Verify:
node --version(should be 18.0+) - Verify:
npm --version
-
Visual Studio Code 1.80.0 or later
- Download: https://code.visualstudio.com/
- Recommended extensions:
- ESLint
- Prettier
-
Git
- Download: https://git-scm.com/
This repo defines line endings in .gitattributes to avoid local Git warnings and keep checkouts consistent:
- Default text files use LF.
- Windows scripts (
.bat,.cmd) use CRLF.
This policy is local to this repository and does not change machine-wide Git settings.
- netcoredbg (bundled for debugging)
- Included in the VSIX for all supported platforms; users do not need to install it separately.
- Curated binaries are referenced in
src/extension/scripts/netcoredbg-assets.json. - Advanced override: set
NETCOREDBG_PATHto use a custom build during packaging or local dev. - Fork for macOS arm64 investigation: https://github.com/DNAKode/netcoredbg
- Community macOS arm64 builds: https://github.com/Cliffback/netcoredbg-macOS-arm64.nvim
- Emacs with eglot (current harness); lsp-mode optional for future coverage
- Emacs: https://www.gnu.org/software/emacs/
- lsp-mode: https://emacs-lsp.github.io/lsp-mode/
- Helix (manual LSP smoke checks; no headless harness yet)
- Helix: https://helix-editor.com/
git clone https://github.com/DNAKode/vbnet-lsp.git
cd vbnet-lsp# DWSIM test project (git submodule)
git submodule update --init --recursive# Restore .NET dependencies
dotnet restore
# Restore Node.js dependencies for extension
cd src/extension
npm install
cd ../..# Build language server
dotnet build src/VbNet.LanguageServer.Vb
# Build VS Code extension
cd src/extension
npm run compile
cd ../..
# Run tests
dotnet testIMPORTANT: The following directories are gitignored and must be set up locally. These setup steps must be followed exactly to recreate the development environment.
Contains cloned reference repositories for architecture verification and pattern extraction. These are read-only references - we never modify them.
# Create directory (if not exists)
mkdir -p _external
cd _external
# C# for Visual Studio Code - PRIMARY REFERENCE
# Architecture patterns, LSP integration, TypeScript extension structure
git clone https://github.com/dotnet/vscode-csharp.git
# Size: ~200MB, Clone time: 2-5 minutes
# csharp-ls (standalone C# LSP reference)
# CLI surface, stdio startup conventions, and editor-wrapper patterns
# (Neovim/Emacs/VS Code plugin ecosystem)
git clone https://github.com/razzmatazz/csharp-language-server.git
# Size: ~20MB, Clone time: <1 minute
# netcoredbg (DNAKode fork) - Open-source .NET debugger
# DAP protocol reference, debugger integration patterns, macOS arm64 investigation
git clone https://github.com/DNAKode/netcoredbg.git
# Size: ~50MB, Clone time: <1 minute
# netcoredbg macOS arm64 community build (reference + releases)
git clone https://github.com/Cliffback/netcoredbg-macOS-arm64.nvim.git
# Size: ~5MB, Clone time: <1 minute
# (Optional) Roslyn - Deep compiler reference
# Only clone if needed for deep Roslyn API investigation
# git clone https://github.com/dotnet/roslyn.git
# Size: ~2GB, Clone time: 10-20 minutes
# WARNING: Very large repository
cd ..Verification:
ls _external/
# Should show: vscode-csharp/ csharp-language-server/ netcoredbg/Store large test inputs and reference repos under _external/. These are gitignored and can be re-cloned as needed.
# Create directory (if not exists)
mkdir -p _external
cd _external
# DWSIM - Large real-world `VB.NET` codebase
# Performance benchmarking, real-world validation, edge case discovery
git clone https://github.com/DanWBR/dwsim.git
# Size: ~500MB, Clone time: 5-10 minutes
# Note: Contains 100+ `VB.NET` files across multiple projects
cd ..Verification:
ls _external/
# Should show: vscode-csharp/ netcoredbg/ dwsim/
# Verify DWSIM `VB.NET` content
find _external/dwsim -name "*.vb" | head -20IMPORTANT: The test-explore/ directory contains the headless harnesses for VS Code, VB.NET LSP, and Emacs. These are now part of the normal improvement cycle.
Rules for this directory:
- Run tests from here as part of iterative improvement cycles
- Update harnesses when needed to improve reliability and coverage
- Record outcomes in
test-explore/TEST_RESULTS.md - Exclude incidental artifacts (logs, downloaded runtimes) from commits
- Also use test/VbNet.LanguageServer.Tests.Vb/ for unit coverage
What you SHOULD do:
- Run
test-exploreharnesses during fixes and regressions - Capture VS Code logs when needed (
CAPTURE_VSCODE_LOGS=1,CAPTURE_VBNET_TRACE=1) - Update
test-explore/TEST_RESULTS.mdwith test outcomes - Follow
test-explore/README.mdfor log retention and harness conventions
vbnet-lsp/
|-- _external/ # Gitignored - reference repos + large inputs
| |-- vscode-csharp/ # C# extension (primary reference)
| |-- csharp-language-server/ # Standalone C# LSP reference (CLI + editor wrappers)
| |-- netcoredbg/ # netcoredbg fork (macOS arm64 builds)
| |-- netcoredbg-macOS-arm64.nvim/ # netcoredbg macOS arm64 community build
| |-- roslyn/ # Roslyn source (optional)
| `-- dwsim/ # Large `VB.NET` test project
|-- test-explore/ # Tracked - exploratory harnesses (logs excluded)
|-- src/ # Tracked - our source code
|-- test/ # Tracked - our test code (USE THIS!)
|-- integrations/ # Tracked - downstream integration snapshots
`-- docs/ # Tracked - documentation
- Size: Reference repos and inputs are large (vscode-csharp ~200MB, roslyn ~2GB, DWSIM ~500MB)
- External ownership: These repos are maintained by others
- Reproducibility: Clone commands are documented; anyone can recreate
- Cleanliness: Keeps our repo focused on our code
Periodically update to get latest changes:
# Update C# extension reference
cd _external/vscode-csharp && git pull && cd ../..
# Update standalone C# language server reference
cd _external/csharp-language-server && git pull && cd ../..
# Update netcoredbg reference (DNAKode fork)
cd _external/netcoredbg && git pull && cd ../..
# Update netcoredbg macOS arm64 community build reference
cd _external/netcoredbg-macOS-arm64.nvim && git pull && cd ../..
# Update DWSIM test project
cd _external/dwsim && git pull && cd ../..# Debug build
dotnet build src/VbNet.LanguageServer.Vb
# Release build
dotnet build src/VbNet.LanguageServer.Vb -c Release
# Publish for distribution
dotnet publish src/VbNet.LanguageServer.Vb -c Release -o publishcd src/extension
# Compile TypeScript
npm run compile
# Watch mode (for development)
npm run watch
# Package extension (.vsix)
npm run package# Run language server tests
dotnet test test/VbNet.LanguageServer.Tests.Vb/VbNet.LanguageServer.Tests.Vb.vbproj
# Run extension manifest tests (CI-safe, no VS Code required)
dotnet test test/VbNet.Extension.Tests.Vb/VbNet.Extension.Tests.Vb.vbproj
# Run with coverage
dotnet test test/VbNet.LanguageServer.Tests.Vb/VbNet.LanguageServer.Tests.Vb.vbproj --collect:"XPlat Code Coverage"
# Run specific test
dotnet test --filter "FullyQualifiedName~CompletionServiceTests"# Run the DWSIM validation script (optional)
./scripts/test-dwsim.shcd src/extension
# Run extension tests
npm test
# Run tests in watch mode
npm run test:watchThe VS Code harness can exercise netcoredbg-based debug sessions using the bundled debugger (or an override).
# Build debug fixture
dotnet build test/TestProjects/DebugConsole/DebugConsole.vbproj
# Prepare bundled debugger (or set NETCOREDBG_PATH to override)
cd src/extension
npm run bundle-debugger -- --target win32-x64
cd ../../test-explore/clients/vscode
# Run harness (skips debug test if netcoredbg is missing)
$env:FIXTURE_WORKSPACE = "test/TestProjects/DebugConsole"
$env:NETCOREDBG_PATH = "C:\\tools\\netcoredbg\\netcoredbg.exe" # optional override
npm testThe extension bundles netcoredbg via npm run bundle-debugger. If NETCOREDBG_PATH is not set, the script downloads a curated binary listed in src/extension/scripts/netcoredbg-assets.json and copies it into .debugger/ alongside LICENSE.netcoredbg. macOS arm64 uses the Cliffback community build, with an extra notice file copied into .debugger/.
# PowerShell
cd src/extension
npm run bundle-debugger -- --target linux-x64To override the curated binary (for example, a local build), set:
# PowerShell
$env:NETCOREDBG_PATH = "C:\\path\\to\\netcoredbg"
$env:NETCOREDBG_LICENSE = "C:\\path\\to\\LICENSE"
cd src/extension
npm run bundle-debuggerNETCOREDBG_PATH can point to either netcoredbg.exe (Windows) or netcoredbg (Linux/macOS). The file is copied into .debugger/ with the same filename so platform-specific VSIX builds can include the correct binary.
Tip: Build platform-specific VSIX packages on the same OS when possible so file permissions (executable bit) are preserved for netcoredbg.
# Requires Emacs (eglot is built-in)
./test-explore/clients/emacs/run-tests.ps1 -Suite vbnetHelix uses stdio for LSP. Use the project-local languages.toml template and the helper script:
test-explore/clients/helix/run-helix.ps1If hx is not on PATH, pass the path explicitly:
test-explore/clients/helix/run-helix.ps1 -HelixExe C:\Tools\Helix\hx.exe -ServerExe C:\path\to\VbNet.LanguageServer.exeWhen running the VS Code harness inside WSL:
- Ensure Node.js 20, .NET 10 (local install under
~/.dotnetis fine), andxvfbare installed. - Prepare the bundled Linux debugger with
npm run bundle-debugger -- --target linux-x64(or setNETCOREDBG_PATHto a Linux-built netcoredbg binary). - Use
xvfb-run -ato provide a headless display. - VS Code CLI may print a WSL warning prompt; it’s safe to continue in CI-style runs.
Example (WSL):
export PATH="$HOME/.dotnet:$PATH"
export DOTNET_ROOT="$HOME/.dotnet"
cd /mnt/c/Work/vbnet-lsp/src/extension
npm run bundle-debugger -- --target linux-x64
cd /mnt/c/Work/vbnet-lsp/test-explore/clients/vscode
export CODE_DISABLE_WSL=1
export VSCODE_CLI=1
export DONT_PROMPT_WSL_INSTALL=1
export NO_AT_BRIDGE=1
export DBUS_SESSION_BUS_ADDRESS="unix:path=/dev/null"
xvfb-run -a npm test-
Baseline first (Windows + Linux)
- Ensure
test/suites pass on Windows. - Ensure VS Code harness debug tests pass on Windows.
- Ensure WSL/Linux harness debug tests pass (using Linux VSIX).
- Ensure
-
Manual macOS arm64 validation (local machine)
- Use the
package-vsixworkflow to fetch thedarwin-arm64VSIX. - Install VSIX locally on macOS arm64 and run the VS Code harness (debug test included).
- Record results in
test-explore/TEST_RESULTS.md.
- Use the
-
GitHub Actions macOS arm64 pilot
- Create a
workflow_dispatchaction targetingmacos-14runners. - Steps: install Node/.NET, bundle debugger (
npm run bundle-debugger -- --target darwin-arm64), build debug fixture, run VS Code harness tests. - Keep the job gated on green Windows + Linux harness runs to avoid spurious macOS failures.
- Create a
-
Stabilize + expand
- Add debugger-specific assertions/log capture if macOS flakiness appears.
- Promote to a scheduled or PR-triggered workflow only after multiple green runs.
- Consider adding NeoVim coverage for
VB.NETLSP + debugger integration (possibly withneotest), across all supported platforms. - Track Helix automation options; current coverage is manual only (stdio config under
test-explore/clients/helix).
- Open the project in VS Code
- Set breakpoints in VB.NET code
- Press F5 or use "Run > Start Debugging"
- Select ".NET Core Launch (Language Server)" configuration
- Start the language server manually:
dotnet run --project src/VbNet.LanguageServer.Vb
- In VS Code: "Run > Attach to Process"
- Select the
VbNet.LanguageServerprocess
Enable detailed logging by setting environment variable:
export VBNET_LS_LOG_LEVEL=Trace
dotnet run --project src/VbNet.LanguageServer.VbLogs are written to stderr.
- Open
src/extensionin VS Code - Press F5 or use "Run > Start Debugging"
- Select "Extension" launch configuration
- A new VS Code window opens (Extension Development Host)
- Open a
VB.NETproject in the Extension Development Host - Set breakpoints in TypeScript code
View extension logs:
- In Extension Development Host: "View > Output"
- Select "
VB.NETLanguage Support" from dropdown
Enable LSP tracing:
- VS Code Settings:
vbnet.trace.server="verbose" - View LSP messages: "View > Output" > "
VB.NETLanguage Support"
src/VbNet.LanguageServer.Vb/
├── Protocol/ # LSP protocol layer
│ ├── JsonRpcTransport.vb
│ ├── LspMessageHandler.vb
│ └── LspTypes.vb
├── Core/ # Server core
│ ├── LanguageServer.vb
│ ├── RequestRouter.vb
│ └── ServerLifecycle.vb
├── Workspace/ # Workspace management
│ ├── WorkspaceManager.vb
│ ├── DocumentManager.vb
│ ├── ProjectLoader.vb
│ └── FileSystemWatcher.vb
├── Services/ # LSP features
│ ├── DiagnosticsService.vb
│ ├── CompletionService.vb
│ ├── HoverService.vb
│ ├── DefinitionService.vb
│ └── ... (other services)
└── Program.vb # Entry point
src/extension/
├── src/
│ ├── extension.ts # Activation entry point
│ ├── languageClient.ts # LSP client setup
│ ├── commands/ # VS Code commands
│ └── features/ # UI integrations
├── package.json # Extension manifest
└── tsconfig.json # TypeScript config
test/
├── VbNet.LanguageServer.Tests.Vb/ # Unit tests (VB.NET)
│ ├── Services/ # Service tests
│ ├── Workspace/ # Workspace tests
│ └── Protocol/ # Protocol tests
├── VbNet.Extension.Tests.Vb/ # Extension manifest tests (VB.NET)
├── extension.test/ # Extension tests (TS)
└── TestProjects/ # Test projects
├── SmallProject/
├── MediumProject/
└── dwsim/ # Git submodule
-
Create a branch
git checkout -b feature/your-feature-name
-
Make changes following code conventions
-
Write tests for new functionality
-
Run tests to ensure nothing broke
dotnet test cd src/extension && npm test
-
Build and verify
dotnet build -c Release cd src/extension && npm run compile
-
Commit changes
git add . git commit -m "feat: Add feature description"
-
Push and create pull request
git push origin feature/your-feature-name
- Follow standard VB.NET naming conventions (PascalCase for types/methods, camelCase for locals)
- Use
Async/Awaitfor all I/O operations - Always pass
CancellationTokento Roslyn APIs - Document public APIs with XML comments
- Keep methods focused and small (<50 lines typical)
- Use TypeScript strict mode
- Prefer
constoverlet - Use async/await for asynchronous operations
- Follow VS Code extension API patterns
Example:
export async function activate(context: vscode.ExtensionContext) {
const serverOptions: ServerOptions = {
command: 'dotnet',
args: ['run', '--project', 'src/VbNet.LanguageServer.Vb']
};
const clientOptions: LanguageClientOptions = {
documentSelector: [{ scheme: 'file', language: 'vb' }]
};
const client = new LanguageClient(
'vbnetLanguageServer',
'`VB.NET` Language Server',
serverOptions,
clientOptions
);
await client.start();
context.subscriptions.push(client);
}Follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentation changesrefactor: Code refactoringtest: Adding or updating testschore: Build/tooling changesperf: Performance improvements
Examples:
feat(completion): Add keyword completion support
fix(diagnostics): Prevent duplicate diagnostics on file save
docs(architecture): Update LSP feature implementation section
test(integration): Add DWSIM performance benchmarks
Triggers: Push to master/main, all PRs
Current scope: Windows-only (multi-platform planned).
- Run language server unit/integration tests (test/VbNet.LanguageServer.Tests.Vb)
- Run extension manifest checks (test/VbNet.Extension.Tests)
- Bundle Roslyn LSP (win-x64) and validate `.roslyn` + `.roslyn-vb` layout- editor-adapters.yml: Multi-editor smoke validation (Neovim + Emacs harnesses on Windows)
- integration.yml: DWSIM validation
- performance.yml: Nightly performance checks
Workflows available via workflow_dispatch (manual trigger):
- editor-adapters.yml: Run Neovim + Emacs smoke tests against current server build.
- package-vsix.yml: Build a VSIX artifact for a selected target.
- publish-vsix.yml: Build and publish a VSIX to the Marketplace.
- release.yml: Build standalone language server archives + VSIX files and publish a GitHub Release.
- publish-dotnet-tool.yml: Pack and publish the
DNAKode.VbNet.Lspglobal tool package (command:vbnet-ls) to NuGet.
Adapter repo sync/publish guidance:
adapters/scripts/export-adapter-repos.ps1docs/adapter-release-checklist.mdintegrations/scripts/export-integration-repos.ps1docs/downstream-repositories.md
All workflows bundle the curated netcoredbg assets listed in src/extension/scripts/netcoredbg-assets.json,
bundle Roslyn LSP assets via NuGet, and validate that .roslyn + .roslyn-vb are present in the VSIX.
publish-vsix.yml requires the VSCE_PAT secret (Marketplace PAT with publish rights).
publish-dotnet-tool.yml publishes only when NUGET_API_KEY is configured.
CI runs on GitHub Actions have been longer than expected in some recent runs. Track this and investigate if a single test or project dominates runtime (or if the overall duration is acceptable for the coverage). If needed, profile test durations and split the workflow or add test filters.
- Open the GitHub Actions tab.
- Select editor-adapters, package-vsix, publish-vsix, release, or publish-dotnet-tool.
- Click Run workflow and set:
target:win32-x64(default) or one of the listed targets.
- For publish-vsix, ensure the
marketplaceenvironment is approved andVSCE_PATis set. - For release, provide a
tag(for examplev0.1.9) and choosepre_release/draftflags. - For publish-dotnet-tool, provide
versiononly when running manually without av*tag context.
# Install act (GitHub Actions local runner)
# https://github.com/nektos/act
# Run CI workflow
act -j test
# Planned integration workflow (when added)
# act -j integrationFollow Semantic Versioning (SemVer 2.0):
- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes
- Every Marketplace publish must use a new version (no reusing a version number).
- During active development, bump the PATCH version for each preview publish (e.g., 0.1.2, 0.1.3, ...).
- Keep
"preview": trueinsrc/extension/package.jsonfor pre-release channels. - Tag preview publishes with a date-stamped Git tag (example:
v0.1.2-preview.YYYYMMDD). - When a feature set is stable, bump MINOR and keep the same workflow; drop
"preview": trueonly when ready for a non-preview release.
- All tests passing (unit, integration, E2E)
- Documentation updated
- CHANGELOG.md updated (root) and synced into
src/extension/CHANGELOG.md(runnpm run packageornpm run copy-changelog) - Performance targets met
- No P0/P1 bugs open
- Cross-platform testing complete (Windows, macOS, Linux)
- Multi-editor testing complete (VS Code, Emacs)
-
Update version number
# Update version in: # - src/extension/package.json # Dotnet tool package version comes from the git tag (vX.Y.Z -> X.Y.Z)
-
Update CHANGELOG.md
## [1.0.0] - 2026-01-10 ### Added - Feature 1 - Feature 2 ### Fixed - Bug fix 1
Then sync it into the extension bundle:
cd src/extension npm run copy-changelog cd ../..
-
Commit version bump
git add . git commit -m "chore: Bump version to 1.0.0" git tag v1.0.0 git push origin main --tags
-
Run the release workflow
- Push a tag (
v*) to trigger.github/workflows/release.yml, or run it manually viaworkflow_dispatch. - The workflow builds language server archives (
win-x64,linux-x64,osx-x64,osx-arm64) and VSIX packages, then attaches them to a GitHub Release.
- Push a tag (
-
Optional: publish dotnet tool package
- Run
.github/workflows/publish-dotnet-tool.yml, or rely on the samev*tag trigger. - Ensure
NUGET_API_KEYis configured to publish to NuGet.
- Run
-
Optional: publish to Marketplace
- Run
.github/workflows/publish-vsix.ymlfor the target you want to publish. - Ensure the
marketplaceenvironment is approved andVSCE_PATis set.
- Run
-
Announce release
- Update README.md
- Post to discussions/announcements
Solution: Install .NET SDK and ensure dotnet is in PATH
dotnet --version # Verify installationSolution: Check extension logs
- "View > Output" in VS Code
- Select "
VB.NETLanguage Support" from dropdown - Look for error messages
Solution: Restart language server
- VS Code Command Palette (Ctrl+Shift+P)
- "
VB.NET: Restart Language Server"
Or check if server process is running:
ps aux | grep vbnet-ls # Linux/macOS
tasklist | findstr vbnet-ls # WindowsSolution: Set MSBuildPath explicitly
export MSBuildPath=/path/to/dotnet/sdk/10.0.100/MSBuild.dll
dotnet test- Architecture Documentation
- Configuration Guide
- Feature Support Matrix
- Project Plan
- C# Extension Reference
- csharp-ls Reference
- Downstream Repositories
- LSP Specification
- Roslyn API Documentation
Last Updated: 2026-02-05
Maintained by: VB.NET Language Support Contributors