summaryrefslogtreecommitdiff
path: root/cli/lsp/analysis.rs
diff options
context:
space:
mode:
authorSatya Rohith <me@satyarohith.com>2021-06-21 12:13:35 +0530
committerGitHub <noreply@github.com>2021-06-21 16:43:35 +1000
commit952caa79b32e6c249977281ed494d4b1f98ed451 (patch)
tree3f072fc64b571eca1b203fb07df3689ad4fc3a95 /cli/lsp/analysis.rs
parentbbc2745350687f209c6af75958cc12bb43e64042 (diff)
feat(lsp): quick fix actions to ignore lint errors (#10627)
Closes #10122
Diffstat (limited to 'cli/lsp/analysis.rs')
-rw-r--r--cli/lsp/analysis.rs115
1 files changed, 115 insertions, 0 deletions
diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs
index 2235a2c83..f3af5fc8d 100644
--- a/cli/lsp/analysis.rs
+++ b/cli/lsp/analysis.rs
@@ -5,6 +5,7 @@ use super::tsc;
use crate::ast;
use crate::import_map::ImportMap;
+use crate::lsp::documents::DocumentData;
use crate::media_type::MediaType;
use crate::module_graph::parse_deno_types;
use crate::module_graph::parse_ts_reference;
@@ -619,6 +620,7 @@ pub struct DenoFixData {
#[derive(Debug, Clone)]
enum CodeActionKind {
Deno(lsp::CodeAction),
+ DenoLint(lsp::CodeAction),
Tsc(lsp::CodeAction, tsc::CodeFixAction),
}
@@ -665,6 +667,106 @@ impl CodeActionCollection {
Ok(())
}
+ pub(crate) fn add_deno_lint_ignore_action(
+ &mut self,
+ specifier: &ModuleSpecifier,
+ document: Option<&DocumentData>,
+ diagnostic: &lsp::Diagnostic,
+ ) -> Result<(), AnyError> {
+ let code = diagnostic
+ .code
+ .as_ref()
+ .map(|v| match v {
+ lsp::NumberOrString::String(v) => v.to_owned(),
+ _ => "".to_string(),
+ })
+ .unwrap();
+
+ let line_content = if let Some(doc) = document {
+ doc
+ .content_line(diagnostic.range.start.line as usize)
+ .ok()
+ .flatten()
+ } else {
+ None
+ };
+
+ let mut changes = HashMap::new();
+ changes.insert(
+ specifier.clone(),
+ vec![lsp::TextEdit {
+ new_text: prepend_whitespace(
+ format!("// deno-lint-ignore {}\n", code),
+ line_content,
+ ),
+ range: lsp::Range {
+ start: lsp::Position {
+ line: diagnostic.range.start.line,
+ character: 0,
+ },
+ end: lsp::Position {
+ line: diagnostic.range.start.line,
+ character: 0,
+ },
+ },
+ }],
+ );
+ let ignore_error_action = lsp::CodeAction {
+ title: format!("Disable {} for this line", 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_error_action));
+
+ let mut changes = HashMap::new();
+ changes.insert(
+ specifier.clone(),
+ vec![lsp::TextEdit {
+ new_text: "// deno-lint-ignore-file\n".to_string(),
+ range: lsp::Range {
+ start: lsp::Position {
+ line: 0,
+ character: 0,
+ },
+ end: lsp::Position {
+ line: 0,
+ character: 0,
+ },
+ },
+ }],
+ );
+ let ignore_file_action = lsp::CodeAction {
+ title: "Ignore lint errors for the entire file".to_string(),
+ 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));
+
+ Ok(())
+ }
+
/// Add a TypeScript code fix action to the code actions collection.
pub(crate) async fn add_ts_fix_action(
&mut self,
@@ -779,6 +881,7 @@ impl CodeActionCollection {
.map(|i| match i {
CodeActionKind::Tsc(c, _) => lsp::CodeActionOrCommand::CodeAction(c),
CodeActionKind::Deno(c) => lsp::CodeActionOrCommand::CodeAction(c),
+ CodeActionKind::DenoLint(c) => lsp::CodeActionOrCommand::CodeAction(c),
})
.collect()
}
@@ -833,6 +936,18 @@ impl CodeActionCollection {
}
}
+/// Prepend the whitespace characters found at the start of line_content to content.
+fn prepend_whitespace(content: String, line_content: Option<String>) -> String {
+ if let Some(line) = line_content {
+ let whitespaces =
+ line.chars().position(|c| !c.is_whitespace()).unwrap_or(0);
+ let whitespace = &line[0..whitespaces];
+ format!("{}{}", &whitespace, content)
+ } else {
+ content
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;