From b1050e856319c5485653b5879ba8d73731feaf98 Mon Sep 17 00:00:00 2001 From: peefy Date: Fri, 17 Nov 2023 17:03:34 +0800 Subject: [PATCH] feat: add mod metadata fetch Signed-off-by: peefy --- .gitignore | 2 +- kclvm/driver/src/kpm_metadata.rs | 46 ++++++++++++++++++++++++--- kclvm/tools/src/LSP/src/completion.rs | 7 ++-- kclvm/tools/src/LSP/src/request.rs | 11 ++++--- kclvm/tools/src/LSP/src/state.rs | 2 +- kclvm/tools/src/LSP/src/tests.rs | 22 ++++++------- kclvm/tools/src/LSP/src/util.rs | 22 +------------ 7 files changed, 65 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index 9595591e4..0d57d4d98 100644 --- a/.gitignore +++ b/.gitignore @@ -94,5 +94,5 @@ _a.out_*.* llvm* llvm-* -# kpm +# KCL mod lock file !.mod.lock diff --git a/kclvm/driver/src/kpm_metadata.rs b/kclvm/driver/src/kpm_metadata.rs index a8d615fa2..a42b05f95 100644 --- a/kclvm/driver/src/kpm_metadata.rs +++ b/kclvm/driver/src/kpm_metadata.rs @@ -15,7 +15,7 @@ pub(crate) fn fill_pkg_maps_for_k_file( // 1. find the kcl.mod dir for the kcl package contains 'k_file_path'. match lookup_the_nearest_file_dir(k_file_path, MANIFEST_FILE) { Some(mod_dir) => { - // 2. call `kpm metadata`. + // 2. get the module metadata. let metadata = fetch_metadata(mod_dir.canonicalize()?)?; // 3. fill the external packages local paths into compilation option [`LoadProgramOptions`]. let maps: HashMap = metadata @@ -32,7 +32,7 @@ pub(crate) fn fill_pkg_maps_for_k_file( } #[derive(Deserialize, Serialize, Default, Debug, Clone)] -/// [`Metadata`] is the metadata of the current KCL package, +/// [`Metadata`] is the metadata of the current KCL module, /// currently only the mapping between the name and path of the external dependent package is included. pub struct Metadata { pub packages: HashMap, @@ -55,8 +55,17 @@ impl Metadata { } } -/// [`fetch_metadata`] will call `kpm metadata` to obtain the metadata. +/// [`fetch_metadata`] returns the KCL module metadata. +#[inline] pub fn fetch_metadata(manifest_path: PathBuf) -> Result { + fetch_mod_metadata(manifest_path.clone()).or(fetch_kpm_metadata(manifest_path)) +} + +/// [`fetch_kpm_metadata`] will call `kpm metadata` to obtain the metadata. +/// +/// TODO: this function will be removed at kcl v0.8.0 for the command migration +/// `kpm -> kcl mod`. +pub(crate) fn fetch_kpm_metadata(manifest_path: PathBuf) -> Result { use std::result::Result::Ok; match Command::new(kpm()) .arg("metadata") @@ -78,6 +87,30 @@ pub fn fetch_metadata(manifest_path: PathBuf) -> Result { } } +/// [`fetch_mod_metadata`] will call `kcl mod metadata` to obtain the metadata. +pub(crate) fn fetch_mod_metadata(manifest_path: PathBuf) -> Result { + use std::result::Result::Ok; + match Command::new(kcl()) + .arg("mod") + .arg("metadata") + .current_dir(manifest_path) + .output() + { + Ok(output) => { + if !output.status.success() { + bail!( + "fetch metadata failed with error: {}", + String::from_utf8_lossy(&output.stderr) + ); + } + Ok(Metadata::parse( + String::from_utf8_lossy(&output.stdout).to_string(), + )?) + } + Err(err) => bail!("fetch metadata failed with error: {}", err), + } +} + /// [`lookup_the_nearest_file_dir`] will start from [`from`] and search for file [`the_nearest_file`] in the parent directories. /// If found, it will return the [`Some`] of [`the_nearest_file`] file path. If not found, it will return [`None`] pub(crate) fn lookup_the_nearest_file_dir( @@ -99,6 +132,11 @@ pub(crate) fn lookup_the_nearest_file_dir( } } +/// [`kcl`] will return the path for executable kcl binary. +pub fn kcl() -> PathBuf { + get_path_for_executable("kcl") +} + /// [`kpm`] will return the path for executable kpm binary. pub fn kpm() -> PathBuf { get_path_for_executable("kpm") @@ -108,7 +146,7 @@ pub fn kpm() -> PathBuf { pub fn get_path_for_executable(executable_name: &'static str) -> PathBuf { // The current implementation checks $PATH for an executable to use: // `` - // example: for kpm, this tries just `kpm`, which will succeed if `kpm` is on the $PATH + // example: for , this tries just , which will succeed if is on the $PATH if lookup_in_path(executable_name) { return executable_name.into(); diff --git a/kclvm/tools/src/LSP/src/completion.rs b/kclvm/tools/src/LSP/src/completion.rs index 07eb148f4..1a23a622e 100644 --- a/kclvm/tools/src/LSP/src/completion.rs +++ b/kclvm/tools/src/LSP/src/completion.rs @@ -21,7 +21,7 @@ use std::{fs, path::Path}; use crate::goto_def::find_def_with_gs; use indexmap::IndexSet; use kclvm_ast::ast::{Expr, ImportStmt, Program, Stmt}; -use kclvm_ast::pos::GetPos; + use kclvm_ast::MAIN_PKG; use kclvm_config::modfile::KCL_FILE_EXTENSION; use kclvm_sema::core::global_state::GlobalState; @@ -33,9 +33,8 @@ use kclvm_sema::resolver::scope::ProgramScope; use kclvm_sema::ty::{FunctionType, SchemaType, Type}; use lsp_types::{CompletionItem, CompletionItemKind}; -use crate::goto_def::{find_def, Definition}; use crate::util::get_real_path_from_external; -use crate::util::{inner_most_expr_in_stmt, is_in_docstring, is_in_schema_expr}; +use crate::util::{inner_most_expr_in_stmt, is_in_docstring}; #[derive(Debug, Clone, PartialEq, Hash, Eq)] pub enum KCLCompletionItemKind { @@ -890,7 +889,7 @@ mod tests { }; let got = completion(None, &program, &pos, &prog_scope, &gs).unwrap(); - let got_labels: Vec = match &got { + let _got_labels: Vec = match &got { CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(), CompletionResponse::List(_) => panic!("test failed"), }; diff --git a/kclvm/tools/src/LSP/src/request.rs b/kclvm/tools/src/LSP/src/request.rs index f019fd608..cde19cbf0 100644 --- a/kclvm/tools/src/LSP/src/request.rs +++ b/kclvm/tools/src/LSP/src/request.rs @@ -1,6 +1,6 @@ use anyhow::{anyhow, Ok}; use crossbeam_channel::Sender; -use kclvm_ast::pos::GetPos; + use kclvm_sema::info::is_valid_kcl_name; use lsp_types::{Location, TextEdit}; use ra_ap_vfs::VfsPath; @@ -291,9 +291,9 @@ pub(crate) fn handle_rename( // 3. return the workspaceEdit to rename all the references with the new name let mut workspace_edit = lsp_types::WorkspaceEdit::default(); - let changes = locations - .into_iter() - .fold(HashMap::new(), |mut map, location| { + let changes = locations.into_iter().fold( + HashMap::new(), + |mut map: HashMap>, location| { let uri = location.uri; map.entry(uri.clone()) .or_insert_with(Vec::new) @@ -302,7 +302,8 @@ pub(crate) fn handle_rename( new_text: new_name.clone(), }); map - }); + }, + ); workspace_edit.changes = Some(changes); anyhow::Ok(Some(workspace_edit)) } diff --git a/kclvm/tools/src/LSP/src/state.rs b/kclvm/tools/src/LSP/src/state.rs index f9fd26f97..80e07f2fe 100644 --- a/kclvm/tools/src/LSP/src/state.rs +++ b/kclvm/tools/src/LSP/src/state.rs @@ -4,7 +4,7 @@ use crate::db::AnalysisDatabase; use crate::to_lsp::{kcl_diag_to_lsp_diags, url}; use crate::util::{build_word_index, get_file_name, parse_param_and_compile, to_json, Param}; use crossbeam_channel::{select, unbounded, Receiver, Sender}; -use indexmap::{IndexMap, IndexSet}; +use indexmap::IndexSet; use lsp_server::{ReqQueue, Response}; use lsp_types::Url; use lsp_types::{ diff --git a/kclvm/tools/src/LSP/src/tests.rs b/kclvm/tools/src/LSP/src/tests.rs index f1a3e527a..dbb7824d1 100644 --- a/kclvm/tools/src/LSP/src/tests.rs +++ b/kclvm/tools/src/LSP/src/tests.rs @@ -642,7 +642,7 @@ fn notification_test() { path.push("src/test_data/diagnostics.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let server = Project {}.server(InitializeParams::default()); // Mock open file @@ -691,7 +691,7 @@ fn close_file_test() { path.push("src/test_data/diagnostics.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let server = Project {}.server(InitializeParams::default()); // Mock open file @@ -776,7 +776,7 @@ fn cancel_test() { path.push("src/test_data/goto_def_test/goto_def.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let server = Project {}.server(InitializeParams::default()); // Mock open file @@ -822,7 +822,7 @@ fn goto_def_test() { path.push("src/test_data/goto_def_test/goto_def.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let server = Project {}.server(InitializeParams::default()); // Mock open file @@ -879,7 +879,7 @@ fn complete_test() { path.push("src/test_data/completion_test/dot/completion.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let server = Project {}.server(InitializeParams::default()); // Mock open file @@ -947,7 +947,7 @@ fn hover_test() { path.push("src/test_data/hover_test/hover.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let server = Project {}.server(InitializeParams::default()); // Mock open file @@ -1004,7 +1004,7 @@ fn hover_assign_in_lambda_test() { path.push("src/test_data/hover_test/assign_in_lambda.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let server = Project {}.server(InitializeParams::default()); // Mock open file @@ -1057,7 +1057,7 @@ fn formatting_test() { path.push("src/test_data/format/format_range.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let server = Project {}.server(InitializeParams::default()); // Mock open file @@ -1546,7 +1546,7 @@ fn find_refs_test() { path.push("src/test_data/find_refs_test/main.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let mut initialize_params = InitializeParams::default(); initialize_params.workspace_folders = Some(vec![WorkspaceFolder { uri: Url::from_file_path(root.clone()).unwrap(), @@ -1636,7 +1636,7 @@ fn find_refs_with_file_change_test() { path.push("src/test_data/find_refs_test/main.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let mut initialize_params = InitializeParams::default(); initialize_params.workspace_folders = Some(vec![WorkspaceFolder { uri: Url::from_file_path(root.clone()).unwrap(), @@ -1739,7 +1739,7 @@ fn rename_test() { main_path.push("src/test_data/rename_test/main.k"); let path = path.to_str().unwrap(); - let src = std::fs::read_to_string(path.clone()).unwrap(); + let src = std::fs::read_to_string(path).unwrap(); let mut initialize_params = InitializeParams::default(); initialize_params.workspace_folders = Some(vec![WorkspaceFolder { uri: Url::from_file_path(root.clone()).unwrap(), diff --git a/kclvm/tools/src/LSP/src/util.rs b/kclvm/tools/src/LSP/src/util.rs index 3fab6c3cb..7b228a6e6 100644 --- a/kclvm/tools/src/LSP/src/util.rs +++ b/kclvm/tools/src/LSP/src/util.rs @@ -1,7 +1,6 @@ use indexmap::{IndexMap, IndexSet}; use kclvm_ast::ast::{ - ConfigEntry, Expr, Identifier, Node, NodeRef, PosTuple, Program, SchemaExpr, SchemaStmt, Stmt, - Type, + ConfigEntry, Expr, Identifier, Node, NodeRef, PosTuple, Program, SchemaStmt, Stmt, Type, }; use kclvm_ast::pos::ContainsPos; use kclvm_ast::MAIN_PKG; @@ -595,25 +594,6 @@ fn inner_most_expr_in_config_entry( } } -pub(crate) fn is_in_schema_expr( - program: &Program, - pos: &KCLPos, -) -> Option<(Node, SchemaExpr)> { - match program.pos_to_stmt(pos) { - Some(node) => { - let parent_expr = inner_most_expr_in_stmt(&node.node, pos, None).1; - match parent_expr { - Some(expr) => match expr.node { - Expr::Schema(schema) => Some((node, schema)), - _ => None, - }, - None => None, - } - } - None => None, - } -} - pub(crate) fn is_in_docstring( program: &Program, pos: &KCLPos,