Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **ServerCancelled retry** — `LspClient::request()` now retries up to 3 times with exponential backoff (500 ms → 1 s → 2 s) when an LSP server returns error code -32802 with `data.retriggerRequest: true`, instead of propagating the error immediately to the MCP caller (#128)
- **Integration test readiness gate** — Replaced `publishDiagnostics`-based readiness signal with hover-probe polling (3 consecutive successful hover responses required), matching the ra_e2e approach; fixes 3 of 5 integration tests that failed consistently in isolation after PR #123 (#127)
- **LSP server requests** — Handle server-to-client requests such as `client/registerCapability`, fixing tsgo timeouts.
- **Pull diagnostics** — Omit absent `identifier` and `previousResultId` fields from `textDocument/diagnostic` requests, fixing tsgo `InvalidParams` errors.
- **Integration tests** — Add `[workspace]` table to `tests/fixtures/rust_workspace/Cargo.toml` so cargo treats the fixture as a standalone workspace; fixes 8 rust-analyzer integration tests that failed with "Failed to load workspaces." (#118)
- **e2e coverage** — Add ra_e2e sub-cases for `get_signature_help`, `go_to_implementation`, `go_to_type_definition`, `get_inlay_hints` (4 LSP 3.17 tools from #124 had no coverage); add `list_resources`, `read_resource`, `subscribe_resource`, `unsubscribe_resource` to `McpClient` and ra_e2e_suite (MCP resources path was entirely untested) (#129, #130)

Expand Down
43 changes: 36 additions & 7 deletions crates/mcpls-core/src/bridge/translator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,30 @@ impl Default for Translator {
}
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct DiagnosticRequestParams {
text_document: TextDocumentIdentifier,
#[serde(skip_serializing_if = "Option::is_none")]
identifier: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
previous_result_id: Option<String>,
#[serde(flatten)]
work_done_progress_params: WorkDoneProgressParams,
#[serde(flatten)]
partial_result_params: PartialResultParams,
}

fn diagnostic_request_params(text_document: TextDocumentIdentifier) -> DiagnosticRequestParams {
DiagnosticRequestParams {
text_document,
identifier: None,
previous_result_id: None,
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
}
}

/// Position in a document (1-based for MCP).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Position2D {
Expand Down Expand Up @@ -750,13 +774,7 @@ impl Translator {
.ensure_open(&validated_path, &client)
.await?;

let params = lsp_types::DocumentDiagnosticParams {
text_document: TextDocumentIdentifier { uri },
identifier: None,
previous_result_id: None,
work_done_progress_params: WorkDoneProgressParams::default(),
partial_result_params: PartialResultParams::default(),
};
let params = diagnostic_request_params(TextDocumentIdentifier { uri });

let timeout_duration = Duration::from_secs(30);
let response: lsp_types::DocumentDiagnosticReportResult = client
Expand Down Expand Up @@ -2074,6 +2092,17 @@ mod tests {
// This test verifies the data structure is properly initialized.
}

#[test]
fn test_diagnostic_request_params_omit_optional_null_fields() {
let uri = "file:///test.ts".parse().unwrap();
let params = diagnostic_request_params(TextDocumentIdentifier { uri });
let value = serde_json::to_value(params).unwrap();

assert_eq!(value["textDocument"]["uri"], "file:///test.ts");
assert!(value.get("identifier").is_none());
assert!(value.get("previousResultId").is_none());
}

#[test]
fn test_validate_path_no_workspace_roots() {
let translator = Translator::new();
Expand Down
Loading