summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSatya Rohith <me@satyarohith.com>2021-09-14 17:46:51 +0530
committerGitHub <noreply@github.com>2021-09-14 17:46:51 +0530
commitbb7ee4f4450882419ac46378df882d243eb150da (patch)
tree9988b101c62cfd088d001cabc6e45ebf5f6bd22b
parent6e3c8a4b058b774b7eb9eebebe8532d04c6fc61e (diff)
feat(lsp): ignore specific lint for entire file (#12023)
-rw-r--r--cli/lsp/analysis.rs74
-rw-r--r--cli/tests/integration/lsp_tests.rs34
-rw-r--r--cli/tests/testdata/lsp/code_action_ignore_lint_response.json30
-rw-r--r--cli/tests/testdata/lsp/code_action_update_ignore_lint_params.json39
-rw-r--r--cli/tests/testdata/lsp/code_action_update_ignore_lint_response.json92
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"
+ }
+ ]
+ }
+ }
+ }
+]