feat(lsp) Adds SFTP URI resolution to the runtime provider for LSP workspaces. - #2703
feat(lsp) Adds SFTP URI resolution to the runtime provider for LSP workspaces.#2703gat0sy wants to merge 5 commits into
Conversation
LspToPosition threw range error on format error. We attempt to fix it here with by clamping so we get the correct line count between the client and server. applyTextEdit as also been extracted so both transport and client manager can import it from the helper.
go to def and similar fonction have been added, a new interceptFileLink method has been created to solve an FileUriExposedException you may get if taping the signature link on the hover. if the link is a website, it skips and let the normal behavior occur ( open a web browser page ) if the link is a file, it modifies the uri so the tap behave like a go to instead of crashing the whole app. There are notably also some fixes for code actions, rename...ect, now they use the new lspPostionToOffset that uses clamping
…actions menu Added resolveContentUriForFileUri() to map LSP file:// responses back to content:// and sftp:// URIs via addedFolder matching Refactor editorManager displayFile/openFile to resolve URIs before opening, enabling cross-workspace go-to-definition and references Added SFTP path-aware root URI resolution for remote workspace context Replace selection menu code-actions button with full LSP actions menu (definition, declaration, implementation, type-definition, references, rename, code-actions) with single-item auto-execution
Added sftpRemote.ts runtime provider that translates sftp:// URIs to file:// before sending to LSP servers, stripping host/credentials Register sftpRemoteRuntimeProvider in registerBuiltins.ts Delegate transport to external-websocket provider since SFTP LSP connections are handled via WebSocket tunnel
Greptile SummaryThis PR adds SFTP-aware LSP URI resolution and navigation, expands the selection menu with definition-related actions, handles server-pushed workspace edits, and consolidates custom-server configuration.
Confidence Score: 0/5The PR is not safe to merge until workspace edits are scoped to their originating client and root and SFTP client identity and URI encoding are preserved. Server-pushed edits can target unrelated files and use another client's synchronization state, while distinct SFTP connections can collide in the client cache and valid remote paths can become malformed LSP URIs. Files Needing Attention: src/cm/lsp/transport.ts, src/cm/lsp/runtimes/sftpRemote.ts, src/components/referencesPanel/utils.js
|
| Filename | Overview |
|---|---|
| src/cm/lsp/runtimes/sftpRemote.ts | Adds SFTP runtime delegation, but strips connection identity from cache-key inputs and emits unencoded file URIs. |
| src/cm/lsp/transport.ts | Adds workspace/applyEdit support without workspace scoping and selects plugins without identifying the requesting client. |
| src/cm/lsp/textEditUtils.ts | Centralizes position conversion and text-edit application; correctness depends on receiving the matching client plugin. |
| src/lib/editorManager.js | Adds SFTP root matching and file-URI resolution used by LSP navigation and workspace edits. |
| src/components/referencesPanel/utils.js | Maps file URIs back to available SAF, SFTP, and local roots, with inconsistent SFTP path encoding. |
| src/cm/lsp/definition.ts | Implements definition-family requests and reuses the references panel for multiple destinations. |
| src/settings/lspSettings.js | Consolidates custom LSP server setup into a multi-field transport-aware dialog. |
Sequence Diagram
sequenceDiagram
participant SFTP as SFTP Workspace
participant Runtime as sftpRemote Provider
participant Manager as LspClientManager
participant LSP as WebSocket LSP Server
participant Workspace as AcodeWorkspace
participant Editor as EditorView
SFTP->>Runtime: sftp://authority/path
Runtime->>Manager: file:///path root and document URI
Manager->>LSP: initialize and didOpen
LSP->>Manager: workspace/applyEdit(uri, edits)
Manager->>Workspace: displayFile(uri)
Workspace->>Editor: open and dispatch edits
Reviews (1): Last reviewed commit: "feat(lsp): add SFTP remote runtime provi..." | Re-trigger Greptile
| for (const uri of uris) { | ||
| const edits = changesByUri[uri]; | ||
| if (!edits.length) continue; | ||
|
|
||
| let view = workspace.getFile(uri)?.getView(); | ||
| if (!view) { | ||
| try { | ||
| view = await workspace.displayFile(uri); | ||
| } catch (error) { |
There was a problem hiding this comment.
Workspace edit escapes its root
When an external WebSocket language server sends workspace/applyEdit for an app-accessible URI outside context.rootUri, this handler opens and modifies that unrelated local, SAF, SFTP, or FTP document without checking workspace membership.
How this was verified: The request path reaches workspace.displayFile and the general-purpose file opener without a workspace-root check.
Knowledge Base Used:
| const plugin = LSPPlugin.get(view); | ||
| if (!plugin) { | ||
| failures.push(uri); | ||
| continue; | ||
| } | ||
|
|
||
| const applied = applyTextEdits(plugin, view, edits); |
There was a problem hiding this comment.
Workspace edit uses wrong client
When multiple LSP clients are attached to a document, unfiltered LSPPlugin.get(view) can select a plugin other than the requesting client's. applyTextEdits then maps positions through that client's syncedDoc and unsyncedChanges, causing replacements at incorrect offsets or rejecting a valid edit.
Knowledge Base Used: LSP Integration
| resolveUris(server, context: LspRuntimeUriResolutionContext) { | ||
| const documentUri = sftpUriToFileUri(context.originalDocumentUri); | ||
| const rootUri = context.originalRootUri | ||
| ? sftpUriToFileUri(context.originalRootUri) | ||
| : null; | ||
| return { documentUri, rootUri, scope: "workspace" }; | ||
| }, |
There was a problem hiding this comment.
SFTP client identities collide
When two SFTP connections use the same language server and remote root path but different hosts, ports, or credentials, resolveUris strips their authorities before the workspace-scoped cache key is built. The second workspace therefore reuses the first connection's LSP client, associating diagnostics, navigation, completion, and edits with the wrong remote host.
Knowledge Base Used:
| function sftpUriToFileUri(uri: string): string | null { | ||
| const match = /^sftp:\/\/[^/]*(\/.*)$/.exec(uri); | ||
| if (!match) return null; | ||
| const path = match[1].split("?")[0]; | ||
| if (!path) return null; | ||
| return "file://" + path; | ||
| } |
There was a problem hiding this comment.
SFTP paths become malformed URIs
When an SFTP root or document path contains spaces, Unicode requiring escaping, #, or another URI-significant character, this raw concatenation overrides the encoded URI produced by buildFileUri. The server can then reject the URI, initialize against the wrong root, or treat part of the path as a fragment and fail to locate the document.
Knowledge Base Used:
This PR is based on PR #2702