Skip to content

Commit

Permalink
fix: fix ${pkg_name:KCL_MOD} in entry
Browse files Browse the repository at this point in the history
Signed-off-by: he1pa <[email protected]>
  • Loading branch information
He1pa committed Sep 12, 2024
1 parent ded5e87 commit 64bd05d
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 36 deletions.
21 changes: 8 additions & 13 deletions kclvm/driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,13 @@ pub fn lookup_compile_workspace(
work_dir: work_dir.clone(),
..Default::default()
};
match canonicalize_input_files(&files, work_dir, true) {
Ok(kcl_paths) => {
// 1. find the kcl.mod path
let metadata =
fill_pkg_maps_for_k_file(tool, file.into(), &mut load_opt)
.unwrap_or(None);
(kcl_paths, Some(load_opt), metadata)
}
Err(_) => default_res,

let metadata =
fill_pkg_maps_for_k_file(tool, file.into(), &mut load_opt).unwrap_or(None);
if files.is_empty() {
default_res
} else {
(files, Some(load_opt), metadata)
}
}
Err(_) => default_res,
Expand All @@ -205,10 +203,7 @@ pub fn lookup_compile_workspace(
if let Some(files) = mod_file.get_entries() {
let work_dir = dir.to_string_lossy().to_string();
load_opt.work_dir = work_dir.clone();
match canonicalize_input_files(&files, work_dir, true) {
Ok(kcl_paths) => (kcl_paths, Some(load_opt), metadata),
Err(_) => default_res,
}
(files, Some(load_opt), metadata)
} else {
default_res
}
Expand Down
72 changes: 67 additions & 5 deletions kclvm/parser/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,10 @@ pub fn get_compile_entries_from_paths(
}
let mut result = Entries::default();
let mut k_code_queue = VecDeque::from(opts.k_code_list.clone());
for s in file_paths {
let path = ModRelativePath::from(s.to_string());
for file in file_paths {
let abs_path = abs_path(file, &opts.work_dir);

let path = ModRelativePath::from(abs_path.to_string());
// If the path is a [`ModRelativePath`] with prefix '${<package_name>:KCL_MOD}',
// calculate the real path and the package name.
if let Some((pkg_name, pkg_path)) = path.get_root_pkg_name()?.and_then(|name| {
Expand All @@ -325,11 +326,11 @@ pub fn get_compile_entries_from_paths(
entry.push_k_code(k_code_queue.pop_front());
result.push_entry(entry);
continue;
} else if let Some(root) = get_pkg_root(s) {
} else if let Some(root) = get_pkg_root(&abs_path) {
// If the path is a normal path.
let mut entry: Entry = Entry::new(kclvm_ast::MAIN_PKG.to_string(), root.clone());
entry.extend_k_files_and_codes(
get_main_files_from_pkg_path(s, &root, kclvm_ast::MAIN_PKG, opts)?,
get_main_files_from_pkg_path(&abs_path, &root, kclvm_ast::MAIN_PKG, opts)?,
&mut k_code_queue,
);
result.push_entry(entry);
Expand Down Expand Up @@ -388,10 +389,71 @@ pub fn get_compile_entries_from_paths(
}
Ok(())
})?;

Ok(result)
}

pub fn abs_path(file: &String, work_dir: &String) -> String {
let path = std::path::Path::new(file);
let is_absolute = path.is_absolute();
// If the input file or path is a relative path and it is not a absolute path in the KCL module VFS,
// join with the work directory path and convert it to a absolute path.
let path = ModRelativePath::from(file.to_string());
let abs_path = if !is_absolute
&& !path
.is_relative_path()
.map_err(|err| err.to_string())
.unwrap()
{
let filepath = std::path::Path::new(work_dir).join(file);
match filepath.canonicalize() {
Ok(path) => Some(path.adjust_canonicalization()),
Err(_) => Some(filepath.to_string_lossy().to_string()),
}
} else {
None
};
abs_path.unwrap_or(file.clone())
}

/// fix relative path, ${<pkg_name>:KCL_MOD} and ${KCL_MOD} to absolute path
pub fn fix_path(file_paths: &[String], opts: &LoadProgramOptions) -> Result<Vec<String>> {
let mut fixed_files = vec![];
let abs_paths: Vec<String> = file_paths
.iter()
.map(|f| abs_path(f, &opts.work_dir))
.collect();
let root =
match kclvm_config::modfile::get_pkg_root_from_paths(&abs_paths, opts.work_dir.clone()) {
Ok(root) => root,
Err(e) => {
return Err(anyhow::anyhow!(format!("Get pkg root failed: {:?}", e)));
}
};

for file in abs_paths {
let path = ModRelativePath::from(file.clone());
// If the path is a [`ModRelativePath`] with prefix '${<package_name>:KCL_MOD}',
// calculate the real path and the package name.
if let Some((_, pkg_path)) = path.get_root_pkg_name()?.and_then(|name| {
opts.package_maps
.get(&name)
.map(|pkg_path: &String| (name, pkg_path))
}) {
// Replace the mod relative path prefix '${<pkg_name>:KCL_MOD}' with the real path.
let s = path.canonicalize_by_root_path(pkg_path)?;
fixed_files.push(s);
} else if path.is_relative_path()? && path.get_root_pkg_name()?.is_none() {
// Replace the mod relative path prefix '${KCL_MOD}' with the real path.
let s = path.canonicalize_by_root_path(&root)?;
fixed_files.push(s);
} else {
fixed_files.push(file);
}
}

Ok(fixed_files)
}

/// Get files in the main package with the package root.
fn get_main_files_from_pkg_path(
pkg_path: &str,
Expand Down
7 changes: 2 additions & 5 deletions kclvm/runner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use kclvm_ast::{
MAIN_PKG,
};
use kclvm_config::cache::KCL_CACHE_PATH_ENV_VAR;
use kclvm_driver::{canonicalize_input_files, expand_input_files};
use kclvm_driver::expand_input_files;
use kclvm_parser::{load_program, KCLModuleCache, ParseSessionRef};
use kclvm_query::apply_overrides;
use kclvm_sema::resolver::{
Expand Down Expand Up @@ -350,11 +350,8 @@ fn build<P: AsRef<Path>>(
/// Expand and return the normalized file paths for the input file list.
pub fn expand_files(args: &ExecProgramArgs) -> Result<Vec<String>> {
let k_files = &args.k_filename_list;
let work_dir = args.work_dir.clone().unwrap_or_default();
let k_files = expand_input_files(k_files);
let kcl_paths =
canonicalize_input_files(&k_files, work_dir, false).map_err(|err| anyhow!(err))?;
Ok(kcl_paths)
Ok(k_files)
}

/// Clean all the tmp files generated during lib generating and linking.
Expand Down
18 changes: 10 additions & 8 deletions kclvm/tools/src/LSP/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ use kclvm_ast::ast::Program;
use kclvm_driver::{lookup_compile_workspace, toolchain};
use kclvm_error::Diagnostic;
use kclvm_parser::{
entry::get_normalized_k_files_from_paths, load_program, KCLModuleCache, LoadProgramOptions,
ParseSessionRef,
entry::fix_path, load_program, KCLModuleCache, LoadProgramOptions, ParseSessionRef,
};
use kclvm_sema::{
advanced_resolver::AdvancedResolver,
Expand Down Expand Up @@ -36,20 +35,22 @@ pub fn compile(
// Ignore the kcl plugin sematic check.
let mut opts = opts.unwrap_or_default();
opts.load_plugins = true;
// Get input files
let files = match get_normalized_k_files_from_paths(files, &opts) {
Ok(file_list) => file_list,

let fixed_paths = match fix_path(files, &opts) {
Ok(fixed_paths) => fixed_paths,
Err(e) => {
return (
IndexSet::new(),
Err(anyhow::anyhow!("Compile failed: {:?}", e)),
Err(anyhow::anyhow!("Fix paths error: {:?}", e)),
)
}
};
let files: Vec<&str> = files.iter().map(|s| s.as_str()).collect();

let fixed_paths: Vec<&str> = fixed_paths.iter().map(|s| s.as_str()).collect();

// Update opt.k_code_list
if let Some(vfs) = &params.vfs {
let mut k_code_list = match load_files_code_from_vfs(&files, vfs) {
let mut k_code_list = match load_files_code_from_vfs(&fixed_paths, vfs) {
Ok(code_list) => code_list,
Err(e) => {
return (
Expand Down Expand Up @@ -80,6 +81,7 @@ pub fn compile(
}
}

let files: Vec<&str> = files.iter().map(|s| s.as_str()).collect();
// Parser
let sess = ParseSessionRef::default();
let mut program = match load_program(sess.clone(), &files, Some(opts), params.module_cache) {
Expand Down
5 changes: 4 additions & 1 deletion kclvm/tools/src/LSP/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,13 @@ impl LanguageServerState {

// If all workspaces do not contain the current file, get files workspace and store in temporary_workspace
if !may_contain {
self.log_message(format!(
"Not contains in any workspace, compile: {:?}",
filename
));
let tool = Arc::clone(&self.tool);
let (workspaces, failed) =
lookup_compile_workspaces(&*tool.read(), &filename, true);

if workspaces.is_empty() {
self.temporary_workspace.write().remove(&file.file_id);
self.log_message(format!(
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[package]
name = "pkg_mod_test"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import pkg2
schema Name:
name: str
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "pkg_mod"

[dependencies]
pkg_mod_test = { path = "../../pkg_mod_test" }

[profile]
entries = ["../base/base.k", "main.k", "${pkg_mod_test:KCL_MOD}/pkg1/a.k"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import pkg_mod_test

import pkg_mod_test.pkg2
12 changes: 8 additions & 4 deletions kclvm/tools/src/LSP/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2258,10 +2258,7 @@ fn kcl_workspace_init_kclsettings_test() {
));

assert_eq!(expected, workspaces.keys().cloned().collect());
assert_eq!(
vec![a.to_str().unwrap().to_string(),],
workspaces.values().next().unwrap().0
);
assert_eq!(vec!["a.k",], workspaces.values().next().unwrap().0);
assert!(failed.is_none());
}

Expand Down Expand Up @@ -2394,3 +2391,10 @@ fn init_workspace_sema_token_test() {
let res = server.send_and_receive(r);
assert!(res.result.is_some());
}

#[test]
fn pkg_mod_test() {
let (_file, _program, diags, _gs) =
compile_test_file("src/test_data/workspace/pkg_mod_test/test/main.k");
assert_eq!(diags.iter().filter(|diag| diag.is_error()).count(), 0);
}

0 comments on commit 64bd05d

Please sign in to comment.