summaryrefslogtreecommitdiff
path: root/tests/integration/lsp_tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/integration/lsp_tests.rs')
-rw-r--r--tests/integration/lsp_tests.rs129
1 files changed, 129 insertions, 0 deletions
diff --git a/tests/integration/lsp_tests.rs b/tests/integration/lsp_tests.rs
index f5d09bc77..9d82e0afd 100644
--- a/tests/integration/lsp_tests.rs
+++ b/tests/integration/lsp_tests.rs
@@ -9,6 +9,7 @@ use deno_core::url::Url;
use pretty_assertions::assert_eq;
use std::fs;
use test_util::assert_starts_with;
+use test_util::assertions::assert_json_subset;
use test_util::deno_cmd_with_deno_dir;
use test_util::env_vars_for_npm_tests;
use test_util::lsp::LspClient;
@@ -16,6 +17,65 @@ use test_util::testdata_path;
use test_util::TestContextBuilder;
use tower_lsp::lsp_types as lsp;
+/// Helper to get the `lsp::Range` of the `n`th occurrence of
+/// `text` in `src`. `n` is zero-based, like most indexes.
+fn range_of_nth(
+ n: usize,
+ text: impl AsRef<str>,
+ src: impl AsRef<str>,
+) -> lsp::Range {
+ let text = text.as_ref();
+
+ let src = src.as_ref();
+
+ let start = src
+ .match_indices(text)
+ .nth(n)
+ .map(|(i, _)| i)
+ .unwrap_or_else(|| panic!("couldn't find text {text} in source {src}"));
+ let end = start + text.len();
+ let mut line = 0;
+ let mut col = 0;
+ let mut byte_idx = 0;
+
+ let pos = |line, col| lsp::Position {
+ line,
+ character: col,
+ };
+
+ let mut start_pos = None;
+ let mut end_pos = None;
+ for c in src.chars() {
+ if byte_idx == start {
+ start_pos = Some(pos(line, col));
+ }
+ if byte_idx == end {
+ end_pos = Some(pos(line, col));
+ break;
+ }
+ if c == '\n' {
+ line += 1;
+ col = 0;
+ } else {
+ col += c.len_utf16() as u32;
+ }
+ byte_idx += c.len_utf8();
+ }
+ if start_pos.is_some() && end_pos.is_none() {
+ // range extends to end of string
+ end_pos = Some(pos(line, col));
+ }
+
+ let (start, end) = (start_pos.unwrap(), end_pos.unwrap());
+ lsp::Range { start, end }
+}
+
+/// Helper to get the `lsp::Range` of the first occurrence of
+/// `text` in `src`. Equivalent to `range_of_nth(0, text, src)`.
+fn range_of(text: impl AsRef<str>, src: impl AsRef<str>) -> lsp::Range {
+ range_of_nth(0, text, src)
+}
+
#[test]
fn lsp_startup_shutdown() {
let context = TestContextBuilder::new().use_temp_cwd().build();
@@ -12548,3 +12608,72 @@ fn lsp_cjs_internal_types_default_export() {
// previously, diagnostic about `add` not being callable
assert_eq!(json!(diagnostics.all()), json!([]));
}
+
+#[test]
+fn lsp_ts_code_fix_any_param() {
+ let context = TestContextBuilder::new().use_temp_cwd().build();
+ let temp_dir = context.temp_dir();
+
+ let mut client = context.new_lsp_command().build();
+ client.initialize_default();
+
+ let src = "export function foo(param) { console.log(param); }";
+
+ let param_def = range_of("param", src);
+
+ let main_url = temp_dir.path().join("main.ts").uri_file();
+ let diagnostics = client.did_open(json!({
+ "textDocument": {
+ "uri": main_url,
+ "languageId": "typescript",
+ "version": 1,
+ "text": src,
+ }
+ }));
+ // make sure the "implicit any type" diagnostic is there for "param"
+ assert_json_subset(
+ json!(diagnostics.all()),
+ json!([{
+ "range": param_def,
+ "code": 7006,
+ "message": "Parameter 'param' implicitly has an 'any' type."
+ }]),
+ );
+
+ // response is array of fixes
+ let response = client.write_request(
+ "textDocument/codeAction",
+ json!({
+ "textDocument": {
+ "uri": main_url,
+ },
+ "range": lsp::Range {
+ start: param_def.end,
+ ..param_def
+ },
+ "context": {
+ "diagnostics": diagnostics.all(),
+ }
+ }),
+ );
+ let fixes = response.as_array().unwrap();
+
+ // we're looking for the quick fix that pertains to our diagnostic,
+ // specifically the "Infer parameter types from usage" fix
+ for fix in fixes {
+ let Some(diags) = fix.get("diagnostics") else {
+ continue;
+ };
+ let Some(fix_title) = fix.get("title").and_then(|s| s.as_str()) else {
+ continue;
+ };
+ if diags == &json!(diagnostics.all())
+ && fix_title == "Infer parameter types from usage"
+ {
+ // found it!
+ return;
+ }
+ }
+
+ panic!("failed to find 'Infer parameter types from usage' fix in fixes: {fixes:#?}");
+}