Feat: LSP implementation and vscode extension package - #165
Conversation
add different lsp init processes
…to feat/lsp-implementation
add specific continue on error for incorrect schema
There was a problem hiding this comment.
🟡 Changes recommended
There are confirmed startup/operational issues in the VS Code extension default settings handling and in the LSP transport error handling that can prevent normal use or terminate the server process unexpectedly.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR adds an initial Language Server Protocol (LSP) implementation for eirctl plus a VS Code extension package, and refactors parts of config importing/caching to be more testable and resilient (notably around Git imports and Windows path handling).
Changes:
- Introduces an eirctl LSP server (
cmd/eirctl-lsp) and supporting language/workspace analysis packages (lang/*), with tests. - Adds a VS Code extension package (
vscode-extension/*) plus workspace/launch config to debug the LSP + extension together. - Refactors cache and Git import handling (home-dir injection for cache, more flexible git import parsing, improved SSH known-host handling and Windows-focused test fixes).
File summaries
| File | Description |
|---|---|
| vscode-extension/vsc-extension-quickstart.md | Adds extension quickstart documentation scaffold. |
| vscode-extension/tsconfig.tools.json | Adds build-time TS config for tool scripts (esbuild runner output). |
| vscode-extension/tsconfig.json | Adds base TS config for extension sources/tests. |
| vscode-extension/src/test/extension.test.ts | Adds initial VS Code extension test scaffold. |
| vscode-extension/src/init.ts | Adds language server transport selection (process vs TCP) and connection retry logic. |
| vscode-extension/src/extension.ts | Adds extension activation wiring for vscode-languageclient with YAML selectors/watchers. |
| vscode-extension/README.md | Documents extension features, settings, and local install/testing notes. |
| vscode-extension/package.json | Defines extension manifest, settings contributions, scripts, and dependencies. |
| vscode-extension/eslint.config.mjs | Adds eslint flat config for TypeScript sources. |
| vscode-extension/esbuild.ts | Adds esbuild bundling script for extension build/package pipeline. |
| vscode-extension/CHANGELOG.md | Adds initial changelog scaffold. |
| vscode-extension/.vscodeignore | Defines packaging ignore rules for VSCE output. |
| vscode-extension/.vscode-test.mjs | Configures VS Code test discovery to run compiled tests. |
| scripts/materialize-sonar-source/main_test.go | Adjusts tests for Windows differences (permissions, symlink behavior). |
| lang/workspace/load.go | Adds recursive workspace config loading with import resolution and source tracking. |
| lang/workspace/load_test.go | Adds tests for recursive import loading and error reporting. |
| lang/workspace/imports.go | Adds import classification/resolution (local/url/git) with cache path mapping. |
| lang/workspace/imports_test.go | Adds tests for import resolution across OS path shapes. |
| lang/protocol/types.go | Adds internal protocol types used by analysis/LSP layers. |
| lang/lsp/types.go | Adds JSON-RPC/LSP wire types for server request/response handling. |
| lang/lsp/transport.go | Adds stdio/TCP transport startup for the LSP server. |
| lang/lsp/server.go | Implements core LSP message handling, analysis entry resolution, diagnostics, hover, completion, symbols. |
| lang/lsp/server_test.go | Adds tests for framing, URI/path handling, workspace config discovery, and completions. |
| lang/ast/document.go | Adds YAML document parsing, node location/range mapping, and parse recovery diagnostics. |
| lang/ast/document_test.go | Adds tests for section parsing, range coordinates, and parse recovery behavior. |
| lang/analyze/analyze.go | Adds workspace analysis (definitions/references/diagnostics/completions) including imported configs. |
| lang/analyze/analyze_test.go | Adds tests for analysis indexing, import handling, duplicates, and diagnostics/completions/hover. |
| internal/config/loader.go | Refactors loader to pass explicit home dir into cache; ensures ReadCloser is closed. |
| internal/config/loader_test.go | Simplifies git test repo setup and minor test fixes (resource cleanup, formatting). |
| internal/config/loader_git.go | Updates git import regex parsing (optional ssh user), SSH known-host parsing tweaks. |
| internal/config/loader_git_test.go | Removes unused HOME capture from tests. |
| internal/config/loader_git_hostkey_test.go | Improves known_hosts writing and Windows env setup; adjusts quoting in tests. |
| internal/config/cache.go | Refactors cache to accept homeDir parameter; exports GetCachePath helper. |
| internal/config/cache_test.go | Updates cache tests to use explicit homeDir and path joins. |
| go.sum | Adds zerolog dependency checksums. |
| go.mod | Adds zerolog as a direct dependency. |
| eirctl.yaml | Adds pipelines/tasks to build/package VS Code extension + LSP; updates imports and depends_on shape. |
| eirctl-extension.code-workspace | Adds a VS Code workspace configured for TCP LSP transport. |
| cmd/eirctl-lsp/main.go | Adds LSP server entrypoint with TCP flags and zerolog-based logging. |
| .vscode/launch.json | Adds debug configurations for main binary, LSP server, and extension host (compound). |
| .gitignore | Ignores VS Code extension build artifacts, vsix, and root node_modules while allowing launch.json. |
Review details
Suppressed comments (3)
vscode-extension/src/init.ts:46
languageServer.tcpRetryDelayMsis contributed with a default/minimum of 500ms in package.json, butconfig.get(..., 300)overrides it and can violate the documented minimum. This also makes the extension behavior differ from what settings UI shows.
internal/config/loader_git.go:120- The protocol list in this error message is now inaccurate (the regex accepts
httpas well). Keeping this in sync avoids confusing users when they hit the default branch.
default:
return nil, fmt.Errorf("must specify a protocol (ssh|https|file)\n%w", ErrIncorrectlyFormattedGit)
}
lang/lsp/transport.go:74
- In TCP mode, a per-connection serve error currently calls
log.Fatal(), which terminates the entire language server process due to a single client connection error. This should be logged and the connection should be allowed to close without killing the listener.
if err := server.Serve(); err != nil && !errors.Is(err, io.EOF) {
log.Fatal().Err(err).Msg(name + ": connection terminated")
}
- Files reviewed: 39/42 changed files
- Comments generated: 5
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| func Init(log zerolog.Logger, config TransportConfig) error { | ||
|
|
||
| if config.UseTCP { | ||
| if err := serveTCP(config.Host, config.Port, log); err != nil { | ||
| log.Fatal().Err(err).Msg(name + ": Failed to start TCP server") | ||
| } | ||
| return nil | ||
| } |
| const configuredCwd = config.get<string>('languageServer.cwd'); | ||
| const command = config.get<string>('languageServer.command', ''); | ||
| const args = config.get<string[]>('languageServer.args', []); |
| case "http", "https": | ||
| gs.gcOpts.URL = "https://" + gitImportParts[2] | ||
| gs.gcOpts.URL = "https://" + gitImportParts[3] | ||
| case "file": |
| gitRegexp = regexp.MustCompile(`^git::(ssh|https?|file)://(?:([^/@]+)@)?(.+?)//([^?]+)(?:\?ref=([^&]+))?$`) | ||
| ErrIncorrectlyFormattedGit = errors.New("incorrectly formatted git import, must satisfy this regex `^git::(ssh|https?|file)://(.+?)//([^?]+)(?:\\?ref=([^&]+))?$`") | ||
| ErrGitTagBranchRevisionWrong = errors.New("tag or branch or revision was not found") |
| For local testing you can use the `Debug Extension` | ||
|
|
||
| > There might be a race condition before the tcp server is ready and the extension starts (temp work around) | ||
|
|
📲 What
This pull request introduces several improvements and new features, primarily focused on enhancing the development workflow for the VSCode extension and improving the configuration and testing of cache and Git import handling. The most significant changes include the addition of VSCode debugging and packaging tasks, refactoring cache path handling for better testability, and making the Git import syntax and parsing more robust.
Development workflow and VSCode extension:
.vscode/launch.jsonwith configurations for debugging the main Go program, the LSP server, and the VSCode extension, as well as a compound configuration to debug both the LSP server and extension together.eirctl-extension.code-workspacefile to configure the workspace for the VSCode extension, including settings for the language server's TCP transport.eirctl.yaml, including new pipelines for building, packaging, and scanning.Cache handling improvements:
NewCache(homedir string)), improving testability and removing reliance on environment variables inside the cache logic. Updated related tests and loader construction accordingly. [1] [2] [3]Git import and loader enhancements:
Dependency updates:
github.com/rs/zerologas a dependency for improved logging in the new LSP server entrypoint.Testing and minor fixes:
These changes collectively improve the developer experience, make the codebase more maintainable and testable, and enhance the robustness of configuration and Git import handling.
🤔 Why
🛠 How
👀 Evidence
🕵️ How to test
✅ Acceptance criteria checklist
mainand re-tested where needed.