Skip to content

Commit

Permalink
lfx pre test lsp quick fix
Browse files Browse the repository at this point in the history
Signed-off-by: Shashank Mittal <[email protected]>
  • Loading branch information
shashank-iitbhu committed Feb 12, 2024
1 parent 80f6849 commit 82d140d
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 13 deletions.
1 change: 1 addition & 0 deletions kclvm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions kclvm/error/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ atty = "0.2"
annotate-snippets = { version = "0.9.2", default-features = false, features = ["color"] }
termize = "0.1.1"
indexmap = "1.0"
serde_json = "1.0.86"
25 changes: 21 additions & 4 deletions kclvm/error/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,23 @@ use std::hash::Hash;
use crate::{ErrorKind, WarningKind};

/// Diagnostic structure.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Diagnostic {
pub level: Level,
pub messages: Vec<Message>,
pub code: Option<DiagnosticId>,
pub data: Option<serde_json::Value>,
}

impl Hash for Diagnostic {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.level.hash(state);
for message in &self.messages {
message.hash(state);
}
self.code.hash(state);
// The `data` field is not included in the hash calculation due to complexity.
}
}

/// Position describes an arbitrary source position including the filename,
Expand Down Expand Up @@ -106,18 +118,23 @@ impl Diagnostic {
note: Option<&str>,
range: Range,
code: Option<DiagnosticId>,
suggested_replacement: Option<String>,
suggestions: Option<Vec<String>>,
) -> Self {
let data = suggestions.clone().map(|suggs| {
serde_json::json!({ "suggested_replacements": suggs })
});
// println!("Data received: {:?}", data);
Diagnostic {
level,
messages: vec![Message {
range,
style: Style::LineAndColumn,
message: message.to_string(),
note: note.map(|s| s.to_string()),
suggested_replacement,
note: note.map(String::from),
suggested_replacement: None, // Assuming your Message struct has such a field
}],
code,
data, // Now includes suggestions if provided
}
}

Expand Down
23 changes: 20 additions & 3 deletions kclvm/error/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,31 @@ impl Handler {
}

/// Construct a type error and put it into the handler diagnostic buffer
pub fn add_compile_error(&mut self, msg: &str, range: Range) -> &mut Self {
pub fn add_compile_error(
&mut self,
msg: &str,
range: Range
) -> &mut Self {
self.add_compile_error_with_suggestions(msg, range, None)
}

pub fn add_compile_error_with_suggestions(
&mut self,
msg: &str,
range: Range,
suggestions: Option<Vec<String>>,
) -> &mut Self {
let diag = Diagnostic::new_with_code(
Level::Error,
msg,
None,
range,
Some(DiagnosticId::Error(E2L23.kind)),
None,
suggestions,
);
// println!("{:?}",suggestions.clone());
self.add_diagnostic(diag);

self
}

Expand Down Expand Up @@ -165,6 +179,7 @@ impl Handler {
level: Level::Error,
messages: msgs.to_owned(),
code: Some(DiagnosticId::Error(err)),
data: None,
};
self.add_diagnostic(diag);

Expand All @@ -183,6 +198,7 @@ impl Handler {
suggested_replacement: None,
}],
code: Some(DiagnosticId::Suggestions),
data: None,
});
});

Expand All @@ -208,6 +224,7 @@ impl Handler {
level: Level::Warning,
messages: msgs.to_owned(),
code: Some(DiagnosticId::Warning(warning)),
data: None,
};
self.add_diagnostic(diag);

Expand Down
3 changes: 2 additions & 1 deletion kclvm/sema/src/resolver/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,13 +432,14 @@ impl<'ctx> Resolver<'ctx> {
if suggs.len() > 0 {
suggestion = format!(", did you mean '{:?}'?", suggs);
}
self.handler.add_compile_error(
self.handler.add_compile_error_with_suggestions(
&format!(
"name '{}' is not defined{}",
name.replace('@', ""),
suggestion
),
range,
Some(suggs.clone()),
);
self.any_ty()
}
Expand Down
48 changes: 45 additions & 3 deletions kclvm/tools/src/LSP/src/quick_fix.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
use std::collections::HashMap;

use kclvm_error::{DiagnosticId, WarningKind};
use kclvm_error::{DiagnosticId, WarningKind, ErrorKind};
use lsp_types::{
CodeAction, CodeActionKind, CodeActionOrCommand, Diagnostic, NumberOrString, TextEdit, Url,
CodeAction, CodeActionKind, CodeActionOrCommand, Diagnostic, NumberOrString, TextEdit, Url
};
use serde_json::Value;

pub(crate) fn quick_fix(uri: &Url, diags: &Vec<Diagnostic>) -> Vec<lsp_types::CodeActionOrCommand> {
let mut code_actions: Vec<lsp_types::CodeActionOrCommand> = vec![];
for diag in diags {
if let Some(code) = &diag.code {
if let Some(id) = conver_code_to_kcl_diag_id(code) {
match id {
DiagnosticId::Error(_) => continue,
DiagnosticId::Error(error) => match error {
ErrorKind::CompileError => {
let replacement_text = extract_suggested_replacements(&diag.data).unwrap_or_else(|| "".to_string());
let mut changes = HashMap::new();
changes.insert(
uri.clone(),
vec![TextEdit {
range: diag.range,
new_text: replacement_text,
}],
);
code_actions.push(CodeActionOrCommand::CodeAction(CodeAction {
title: ErrorKind::CompileError.name(),
kind: Some(CodeActionKind::QUICKFIX),
diagnostics: Some(vec![diag.clone()]),
edit: Some(lsp_types::WorkspaceEdit {
changes: Some(changes),
..Default::default()
}),
..Default::default()
}))
}
_ => continue,
},
DiagnosticId::Warning(warn) => match warn {
WarningKind::UnusedImportWarning => {
let mut changes = HashMap::new();
Expand Down Expand Up @@ -63,13 +87,31 @@ pub(crate) fn quick_fix(uri: &Url, diags: &Vec<Diagnostic>) -> Vec<lsp_types::Co
code_actions
}

fn extract_suggested_replacements(data: &Option<Value>) -> Option<String> {
data.as_ref().and_then(|data| {
match data {
Value::Object(obj) => {
obj.get("suggested_replacements").and_then(|val| {
match val {
Value::String(s) => Some(s.clone()),
Value::Array(arr) if !arr.is_empty() => arr.iter().filter_map(|v| v.as_str()).next().map(String::from),
_ => None,
}
})
},
_ => None,
}
})
}

pub(crate) fn conver_code_to_kcl_diag_id(code: &NumberOrString) -> Option<DiagnosticId> {
match code {
NumberOrString::Number(_) => None,
NumberOrString::String(code) => match code.as_str() {
"CompilerWarning" => Some(DiagnosticId::Warning(WarningKind::CompilerWarning)),
"UnusedImportWarning" => Some(DiagnosticId::Warning(WarningKind::UnusedImportWarning)),
"ReimportWarning" => Some(DiagnosticId::Warning(WarningKind::ReimportWarning)),
"CompileError" => Some(DiagnosticId::Error(ErrorKind::CompileError)),
"ImportPositionWarning" => {
Some(DiagnosticId::Warning(WarningKind::ImportPositionWarning))
}
Expand Down
14 changes: 12 additions & 2 deletions kclvm/tools/src/LSP/src/to_lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,22 @@ pub fn kcl_diag_to_lsp_diags(diag: &KCLDiagnostic, file_name: &str) -> Vec<Diagn
} else {
None
};
diags.push(kcl_msg_to_lsp_diags(

let data = diag.data.clone();

let lsp_diag = kcl_msg_to_lsp_diags(
msg,
kcl_err_level_to_severity(diag.level),
related_msg,
code,
))
);

let lsp_diag_with_data = Diagnostic {
data,
..lsp_diag
};

diags.push(lsp_diag_with_data);
}
}
diags
Expand Down

0 comments on commit 82d140d

Please sign in to comment.