Skip to content

Commit

Permalink
enhance lsp diags. (#1371)
Browse files Browse the repository at this point in the history
* enhance lsp diags. Change the return type of function `compile_with_params` from Result<(Program, IndexSet<Diagnostic>, GlobalState)> to (IndexSet<Diagnostic>, Result<(Program, GlobalState)>)). Returns the discovered diags when compilation fails.

Signed-off-by: he1pa <[email protected]>

* fmt code

Signed-off-by: he1pa <[email protected]>

---------

Signed-off-by: he1pa <[email protected]>
  • Loading branch information
He1pa authored May 28, 2024
1 parent 1f262c7 commit 22e472f
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 93 deletions.
6 changes: 4 additions & 2 deletions kclvm/tools/src/LSP/src/find_refs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@ pub(crate) fn find_refs_from_def<F: Fn(String) -> Result<(), anyhow::Error>>(
vfs: vfs.clone(),
entry_cache: entry_cache.clone(),
tool: Arc::new(RwLock::new(toolchain::default())),
}) {
Ok((_, _, gs)) => {
})
.1
{
Ok((_, gs)) => {
let ref_pos = kcl_pos(&file_path, ref_loc.range.start);
if *ref_loc == def_loc && !include_declaration {
return false;
Expand Down
4 changes: 2 additions & 2 deletions kclvm/tools/src/LSP/src/quick_fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,15 @@ mod tests {
test_file.push("src/test_data/quick_fix.k");
let file = test_file.to_str().unwrap();

let (_, diags, _) = compile_with_params(Params {
let diags = compile_with_params(Params {
file: file.to_string(),
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: None,
tool: Arc::new(RwLock::new(toolchain::default())),
})
.unwrap();
.0;

let diagnostics = diags
.iter()
Expand Down
89 changes: 45 additions & 44 deletions kclvm/tools/src/LSP/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,24 +228,46 @@ impl LanguageServerState {
let version =
snapshot.opened_files.read().get(&file.file_id).cloned();
let mut db = snapshot.db.write();
match compile_with_params(Params {
let (diags, compile_res) = compile_with_params(Params {
file: filename.clone(),
module_cache: Some(module_cache),
scope_cache: Some(scope_cache),
vfs: Some(snapshot.vfs),
entry_cache: Some(entry),
tool,
}) {
Ok((prog, diags, gs)) => {
let current_version = snapshot
.opened_files
.read()
.get(&file.file_id)
.cloned();
match (version, current_version) {
(Some(version), Some(current_version)) => {
// If the text is updated during compilation(current_version > version), the current compilation result will not be output.
if current_version == version {
});

let current_version =
snapshot.opened_files.read().get(&file.file_id).cloned();

match (version, current_version) {
(Some(version), Some(current_version)) => {
// If the text is updated during compilation(current_version > version), the current compilation result will not be output.
if current_version == version {
let diagnostics = diags
.iter()
.flat_map(|diag| {
kcl_diag_to_lsp_diags(
diag,
filename.as_str(),
)
})
.collect::<Vec<Diagnostic>>();
sender.send(Task::Notify(
lsp_server::Notification {
method: PublishDiagnostics::METHOD
.to_owned(),
params: to_json(PublishDiagnosticsParams {
uri,
diagnostics,
version: None,
})
.unwrap(),
},
));

match compile_res {
Ok((prog, gs)) => {
db.insert(
file.file_id,
Arc::new(AnalysisDatabase {
Expand All @@ -254,42 +276,21 @@ impl LanguageServerState {
version,
}),
);

let diagnostics = diags
.iter()
.flat_map(|diag| {
kcl_diag_to_lsp_diags(
diag,
filename.as_str(),
)
})
.collect::<Vec<Diagnostic>>();
sender.send(Task::Notify(
lsp_server::Notification {
method: PublishDiagnostics::METHOD
.to_owned(),
params: to_json(
PublishDiagnosticsParams {
uri,
diagnostics,
version: None,
},
)
.unwrap(),
},
));
}
Err(err) => {
db.remove(&file.file_id);
log_message(
format!(
"Compile failed: {:?}",
err.to_string()
),
&sender,
);
}
}
_ => {}
}
}
Err(err) => {
db.remove(&file.file_id);
log_message(
format!("Compile failed: {:?}", err.to_string()),
&sender,
);
}
_ => {}
}
}
Err(_) => {
Expand Down
37 changes: 22 additions & 15 deletions kclvm/tools/src/LSP/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,15 @@ pub(crate) fn compile_test_file(

let file = test_file.to_str().unwrap().to_string();

let (program, diags, gs) = compile_with_params(Params {
let (diags, compile_res) = compile_with_params(Params {
file: file.clone(),
module_cache: Some(KCLModuleCache::default()),
scope_cache: Some(KCLScopeCache::default()),
vfs: Some(KCLVfs::default()),
entry_cache: Some(KCLEntryCache::default()),
tool: Arc::new(RwLock::new(toolchain::default())),
})
.unwrap();
});
let (program, gs) = compile_res.unwrap();
(file, program, diags, gs)
}

Expand Down Expand Up @@ -290,15 +290,15 @@ fn diagnostics_test() {
test_file.push("src/test_data/diagnostics.k");
let file = test_file.to_str().unwrap();

let (_, diags, _) = compile_with_params(Params {
let diags = compile_with_params(Params {
file: file.to_string(),
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: Some(KCLEntryCache::default()),
tool: Arc::new(RwLock::new(toolchain::default())),
})
.unwrap();
.0;

let diagnostics = diags
.iter()
Expand Down Expand Up @@ -478,14 +478,15 @@ fn complete_import_external_file_test() {
.output()
.unwrap();

let (program, _, gs) = compile_with_params(Params {
let (program, gs) = compile_with_params(Params {
file: path.to_string(),
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: Some(KCLEntryCache::default()),
tool: Arc::new(RwLock::new(toolchain::default())),
})
.1
.unwrap();

let pos = KCLPos {
Expand Down Expand Up @@ -538,15 +539,15 @@ fn goto_import_external_file_test() {
.output()
.unwrap();

let (_program, diags, gs) = compile_with_params(Params {
let (diags, compile_res) = compile_with_params(Params {
file: path.to_string(),
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: Some(KCLEntryCache::default()),
tool: Arc::new(RwLock::new(toolchain::default())),
})
.unwrap();
});
let gs = compile_res.unwrap().1;

assert_eq!(diags.len(), 0);

Expand Down Expand Up @@ -1393,14 +1394,15 @@ fn konfig_goto_def_test_base() {
let mut base_path = konfig_path.clone();
base_path.push("appops/nginx-example/base/base.k");
let base_path_str = base_path.to_str().unwrap().to_string();
let (_program, _, gs) = compile_with_params(Params {
let (_program, gs) = compile_with_params(Params {
file: base_path_str.clone(),
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: Some(KCLEntryCache::default()),
tool: Arc::new(RwLock::new(toolchain::default())),
})
.1
.unwrap();

// schema def
Expand Down Expand Up @@ -1486,14 +1488,15 @@ fn konfig_goto_def_test_main() {
let mut main_path = konfig_path.clone();
main_path.push("appops/nginx-example/dev/main.k");
let main_path_str = main_path.to_str().unwrap().to_string();
let (_program, _, gs) = compile_with_params(Params {
let (_program, gs) = compile_with_params(Params {
file: main_path_str.clone(),
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: Some(KCLEntryCache::default()),
tool: Arc::new(RwLock::new(toolchain::default())),
})
.1
.unwrap();

// schema def
Expand Down Expand Up @@ -1551,14 +1554,15 @@ fn konfig_completion_test_main() {
let mut main_path = konfig_path.clone();
main_path.push("appops/nginx-example/dev/main.k");
let main_path_str = main_path.to_str().unwrap().to_string();
let (program, _, gs) = compile_with_params(Params {
let (program, gs) = compile_with_params(Params {
file: main_path_str.clone(),
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: Some(KCLEntryCache::default()),
tool: Arc::new(RwLock::new(toolchain::default())),
})
.1
.unwrap();

// pkg's definition(schema) completion
Expand Down Expand Up @@ -1665,14 +1669,15 @@ fn konfig_hover_test_main() {
let mut main_path = konfig_path.clone();
main_path.push("appops/nginx-example/dev/main.k");
let main_path_str = main_path.to_str().unwrap().to_string();
let (_program, _, gs) = compile_with_params(Params {
let (_program, gs) = compile_with_params(Params {
file: main_path_str.clone(),
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: Some(KCLEntryCache::default()),
tool: Arc::new(RwLock::new(toolchain::default())),
})
.1
.unwrap();

// schema def hover
Expand Down Expand Up @@ -2099,15 +2104,17 @@ fn compile_unit_test() {
test_file.push("src/test_data/compile_unit/b.k");
let file = test_file.to_str().unwrap();

let (prog, ..) = compile_with_params(Params {
let prog = compile_with_params(Params {
file: file.to_string(),
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: Some(KCLEntryCache::default()),
tool: Arc::new(RwLock::new(toolchain::default())),
})
.unwrap();
.1
.unwrap()
.0;
// b.k is not contained in kcl.yaml but need to be contained in main pkg
assert!(prog
.pkgs
Expand Down
69 changes: 39 additions & 30 deletions kclvm/tools/src/LSP/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ use parking_lot::RwLockReadGuard;
use ra_ap_vfs::{FileId, Vfs};
use serde::{de::DeserializeOwned, Serialize};

use std::fs;
use std::path::Path;
use std::{fs, panic};

#[allow(unused)]
/// Deserializes a `T` from a json value.
Expand Down Expand Up @@ -92,7 +92,7 @@ pub(crate) fn lookup_compile_unit_with_cache(

pub(crate) fn compile_with_params(
params: Params,
) -> anyhow::Result<(Program, IndexSet<Diagnostic>, GlobalState)> {
) -> (IndexSet<Diagnostic>, anyhow::Result<(Program, GlobalState)>) {
// Lookup compile unit (kcl.mod or kcl.yaml) from the entry file.
let (mut files, opt) =
lookup_compile_unit_with_cache(&*params.tool.read(), &params.entry_cache, &params.file);
Expand All @@ -105,36 +105,45 @@ pub(crate) fn compile_with_params(
opt.load_plugins = true;
// Update opt.k_code_list
if let Some(vfs) = params.vfs {
let mut k_code_list = load_files_code_from_vfs(&files, vfs)?;
let mut k_code_list = match load_files_code_from_vfs(&files, vfs) {
Ok(code_list) => code_list,
Err(e) => {
return (
IndexSet::new(),
Err(anyhow::anyhow!("Compile failed: {:?}", e)),
)
}
};
opt.k_code_list.append(&mut k_code_list);
}
match panic::catch_unwind(move || {
// Parser
let sess = ParseSessionRef::default();
let mut program = load_program(sess.clone(), &files, Some(opt), params.module_cache)
.unwrap()
.program;
// Resolver
let prog_scope = resolve_program_with_opts(
&mut program,
kclvm_sema::resolver::Options {
merge_program: false,
type_erasure: false,
..Default::default()
},
params.scope_cache,
);
// Please note that there is no global state cache at this stage.
let gs = GlobalState::default();
let gs = Namer::find_symbols(&program, gs);
let gs = AdvancedResolver::resolve_program(&program, gs, prog_scope.node_ty_map.clone())?;
// Merge parse diagnostic and resolve diagnostic
sess.append_diagnostic(prog_scope.handler.diagnostics.clone());
let diags = sess.1.borrow().diagnostics.clone();
Ok((program, diags, gs))
}) {
Ok(res) => res,
Err(e) => Err(anyhow::anyhow!("Compile failed: {:?}", e)),

let mut diags = IndexSet::new();

// Parser
let sess = ParseSessionRef::default();
let mut program = match load_program(sess.clone(), &files, Some(opt), params.module_cache) {
Ok(r) => r.program,
Err(e) => return (diags, Err(anyhow::anyhow!("Parse failed: {:?}", e))),
};
diags.extend(sess.1.borrow().diagnostics.clone());
// Resolver
let prog_scope = resolve_program_with_opts(
&mut program,
kclvm_sema::resolver::Options {
merge_program: false,
type_erasure: false,
..Default::default()
},
params.scope_cache,
);
diags.extend(prog_scope.handler.diagnostics);

// Please note that there is no global state cache at this stage.
let gs = GlobalState::default();
let gs = Namer::find_symbols(&program, gs);
match AdvancedResolver::resolve_program(&program, gs, prog_scope.node_ty_map.clone()) {
Ok(gs) => (diags, Ok((program, gs))),
Err(e) => (diags, Err(anyhow::anyhow!("Parse failed: {:?}", e))),
}
}

Expand Down

0 comments on commit 22e472f

Please sign in to comment.