diff options
author | Satya Rohith <me@satyarohith.com> | 2021-09-14 17:46:51 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-14 17:46:51 +0530 |
commit | bb7ee4f4450882419ac46378df882d243eb150da (patch) | |
tree | 9988b101c62cfd088d001cabc6e45ebf5f6bd22b | |
parent | 6e3c8a4b058b774b7eb9eebebe8532d04c6fc61e (diff) |
feat(lsp): ignore specific lint for entire file (#12023)
-rw-r--r-- | cli/lsp/analysis.rs | 74 | ||||
-rw-r--r-- | cli/tests/integration/lsp_tests.rs | 34 | ||||
-rw-r--r-- | cli/tests/testdata/lsp/code_action_ignore_lint_response.json | 30 | ||||
-rw-r--r-- | cli/tests/testdata/lsp/code_action_update_ignore_lint_params.json | 39 | ||||
-rw-r--r-- | cli/tests/testdata/lsp/code_action_update_ignore_lint_response.json | 92 |
5 files changed, 266 insertions, 3 deletions
diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs index 768ef2651..d1cf14500 100644 --- a/cli/lsp/analysis.rs +++ b/cli/lsp/analysis.rs @@ -707,9 +707,10 @@ impl CodeActionCollection { }) .unwrap(); - let line_content = document.map(|d| { - d.source() - .text_info() + let document_source = document.map(|d| d.source()); + + let line_content = document_source.map(|d| { + d.text_info() .line_text(diagnostic.range.start.line as usize) .to_string() }); @@ -752,6 +753,73 @@ impl CodeActionCollection { .actions .push(CodeActionKind::DenoLint(ignore_error_action)); + // Disable a lint error for the entire file. + let parsed_source = + document_source.and_then(|d| d.module().and_then(|r| r.as_ref().ok())); + let maybe_ignore_comment = parsed_source.and_then(|ps| { + // Note: we can use ps.get_leading_comments() but it doesn't + // work when shebang is present at the top of the file. + ps.comments().get_vec().iter().find_map(|c| { + let comment_text = c.text.trim(); + comment_text.split_whitespace().next().and_then(|prefix| { + if prefix == "deno-lint-ignore-file" { + Some(c.clone()) + } else { + None + } + }) + }) + }); + + let mut new_text = format!("// deno-lint-ignore-file {}\n", code); + let mut range = lsp::Range { + start: lsp::Position { + line: 0, + character: 0, + }, + end: lsp::Position { + line: 0, + character: 0, + }, + }; + // If ignore file comment already exists, append the lint code + // to the existing comment. + if let Some(ignore_comment) = maybe_ignore_comment { + new_text = format!(" {}", code); + // Get the end position of the comment. + let line = parsed_source + .unwrap() + .source() + .line_and_column_index(ignore_comment.span.hi()); + let position = lsp::Position { + line: line.line_index as u32, + character: line.column_index as u32, + }; + // Set the edit range to the end of the comment. + range.start = position; + range.end = position; + } + + let mut changes = HashMap::new(); + changes.insert(specifier.clone(), vec![lsp::TextEdit { new_text, range }]); + let ignore_file_action = lsp::CodeAction { + title: format!("Disable {} for the entire file", code), + kind: Some(lsp::CodeActionKind::QUICKFIX), + diagnostics: Some(vec![diagnostic.clone()]), + command: None, + is_preferred: None, + disabled: None, + data: None, + edit: Some(lsp::WorkspaceEdit { + changes: Some(changes), + change_annotations: None, + document_changes: None, + }), + }; + self + .actions + .push(CodeActionKind::DenoLint(ignore_file_action)); + let mut changes = HashMap::new(); changes.insert( specifier.clone(), diff --git a/cli/tests/integration/lsp_tests.rs b/cli/tests/integration/lsp_tests.rs index 3d87c222d..5034b6ed6 100644 --- a/cli/tests/integration/lsp_tests.rs +++ b/cli/tests/integration/lsp_tests.rs @@ -3526,3 +3526,37 @@ fn lsp_code_actions_ignore_lint() { ); shutdown(&mut client); } + +/// This test exercises updating an existing deno-lint-ignore-file comment. +#[test] +fn lsp_code_actions_update_ignore_lint() { + let mut client = init("initialize_params.json"); + did_open( + &mut client, + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": +"#!/usr/bin/env -S deno run +// deno-lint-ignore-file camelcase +let snake_case = 'Hello, Deno!'; +console.log(snake_case); +", + } + }), + ); + let (maybe_res, maybe_err) = client + .write_request( + "textDocument/codeAction", + load_fixture("code_action_update_ignore_lint_params.json"), + ) + .unwrap(); + assert!(maybe_err.is_none()); + assert_eq!( + maybe_res, + Some(load_fixture("code_action_update_ignore_lint_response.json")) + ); + shutdown(&mut client); +} diff --git a/cli/tests/testdata/lsp/code_action_ignore_lint_response.json b/cli/tests/testdata/lsp/code_action_ignore_lint_response.json index f5c24ec21..d15fccca9 100644 --- a/cli/tests/testdata/lsp/code_action_ignore_lint_response.json +++ b/cli/tests/testdata/lsp/code_action_ignore_lint_response.json @@ -30,6 +30,36 @@ } }, { + "title": "Disable prefer-const for the entire file", + "kind": "quickfix", + "diagnostics": [ + { + "range": { + "start": { "line": 1, "character": 5 }, + "end": { "line": 1, "character": 12 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'message' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + } + ], + "edit": { + "changes": { + "file:///a/file.ts": [ + { + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } + }, + "newText": "// deno-lint-ignore-file prefer-const\n" + } + ] + } + } + }, + { "title": "Ignore lint errors for the entire file", "kind": "quickfix", "diagnostics": [ diff --git a/cli/tests/testdata/lsp/code_action_update_ignore_lint_params.json b/cli/tests/testdata/lsp/code_action_update_ignore_lint_params.json new file mode 100644 index 000000000..8cbf1185f --- /dev/null +++ b/cli/tests/testdata/lsp/code_action_update_ignore_lint_params.json @@ -0,0 +1,39 @@ +{ + "textDocument": { + "uri": "file:///a/file.ts" + }, + "range": { + "start": { + "line": 3, + "character": 5 + }, + "end": { + "line": 3, + "character": 15 + } + }, + "context": { + "diagnostics": [ + { + "range": { + "start": { + "line": 3, + "character": 5 + }, + "end": { + "line": 3, + "character": 15 + } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'snake_case' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + } + ], + "only": [ + "quickfix" + ] + } +} diff --git a/cli/tests/testdata/lsp/code_action_update_ignore_lint_response.json b/cli/tests/testdata/lsp/code_action_update_ignore_lint_response.json new file mode 100644 index 000000000..a23e719e0 --- /dev/null +++ b/cli/tests/testdata/lsp/code_action_update_ignore_lint_response.json @@ -0,0 +1,92 @@ +[ + { + "title": "Disable prefer-const for this line", + "kind": "quickfix", + "diagnostics": [ + { + "range": { + "start": { "line": 3, "character": 5 }, + "end": { "line": 3, "character": 15 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'snake_case' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + } + ], + "edit": { + "changes": { + "file:///a/file.ts": [ + { + "range": { + "start": { "line": 3, "character": 0 }, + "end": { "line": 3, "character": 0 } + }, + "newText": "// deno-lint-ignore prefer-const\n" + } + ] + } + } + }, + { + "title": "Disable prefer-const for the entire file", + "kind": "quickfix", + "diagnostics": [ + { + "range": { + "start": { "line": 3, "character": 5 }, + "end": { "line": 3, "character": 15 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'snake_case' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + } + ], + "edit": { + "changes": { + "file:///a/file.ts": [ + { + "range": { + "start": { "line": 1, "character": 34 }, + "end": { "line": 1, "character": 34 } + }, + "newText": " prefer-const" + } + ] + } + } + }, + { + "title": "Ignore lint errors for the entire file", + "kind": "quickfix", + "diagnostics": [ + { + "range": { + "start": { "line": 3, "character": 5 }, + "end": { "line": 3, "character": 15 } + }, + "severity": 1, + "code": "prefer-const", + "source": "deno-lint", + "message": "'snake_case' is never reassigned\nUse 'const' instead", + "relatedInformation": [] + } + ], + "edit": { + "changes": { + "file:///a/file.ts": [ + { + "range": { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 } + }, + "newText": "// deno-lint-ignore-file\n" + } + ] + } + } + } +] |