Skip to content

Feat: LSP implementation and vscode extension package - #165

Draft
dnitsch wants to merge 21 commits into
mainfrom
feat/lsp-implementation
Draft

Feat: LSP implementation and vscode extension package#165
dnitsch wants to merge 21 commits into
mainfrom
feat/lsp-implementation

Conversation

@dnitsch

@dnitsch dnitsch commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

📲 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:

  • Added .vscode/launch.json with 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.
  • Introduced a new eirctl-extension.code-workspace file to configure the workspace for the VSCode extension, including settings for the language server's TCP transport.
  • Added build and packaging tasks for the VSCode extension and LSP server in eirctl.yaml, including new pipelines for building, packaging, and scanning.

Cache handling improvements:

  • Refactored the cache implementation to accept the home directory as a parameter (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:

  • Improved the Git import regular expression and parsing logic to support optional user fields in SSH URLs and to more robustly handle different protocols and URL formats. Updated the parsing and assignment logic to match the new regex structure. [1] [2]
  • Improved handling of known hosts and SSH command parsing, including safer splitting of SSH config paths and better handling of path backslashes for Windows compatibility. [1] [2] [3]

Dependency updates:

  • Added github.com/rs/zerolog as a dependency for improved logging in the new LSP server entrypoint.

Testing and minor fixes:

  • Updated cache and loader tests to use the new cache constructor and improved path handling, and fixed a minor issue in test helper for writing known hosts. [1] [2] [3]

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

  • Linked the related issue or explained why one is not needed.
  • Added or updated tests, or explained why tests are not applicable.
  • Updated documentation, examples, schemas, or release notes where applicable.
  • Ran the relevant linting, test, and validation checks successfully.
  • Checked that the change does not expose secrets or weaken security controls.
  • Rebased or merged the latest main and re-tested where needed.
  • Confirmed the change meets the repository coding standards.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.tcpRetryDelayMs is contributed with a default/minimum of 500ms in package.json, but config.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 http as 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.

Comment thread lang/lsp/transport.go
Comment on lines +21 to +28
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
}
Comment on lines +10 to +12
const configuredCwd = config.get<string>('languageServer.cwd');
const command = config.get<string>('languageServer.command', '');
const args = config.get<string[]>('languageServer.args', []);
Comment on lines 114 to 116
case "http", "https":
gs.gcOpts.URL = "https://" + gitImportParts[2]
gs.gcOpts.URL = "https://" + gitImportParts[3]
case "file":
Comment thread internal/config/loader_git.go Outdated
Comment on lines 44 to 46
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")
Comment on lines +25 to +28
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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants