Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: lsp complete for exteranl pkg import #848

Merged
merged 3 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions kclvm/parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ impl Loader {

// Insert an empty vec to determine whether there is a circular import.
pkgs.insert(kclvm_ast::MAIN_PKG.to_string(), vec![]);

self.load_import_package(
&entry.path(),
entry.name().to_string(),
Expand Down Expand Up @@ -527,7 +526,7 @@ impl Loader {

if pkg_info.k_files.is_empty() {
self.missing_pkgs.push(pkgpath);
return Ok(None);
return Ok(Some(pkg_info));
}

let mut pkg_files = Vec::new();
Expand Down
38 changes: 36 additions & 2 deletions kclvm/tools/src/LSP/src/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use kclvm_sema::ty::{FunctionType, SchemaType, Type};
use lsp_types::{CompletionItem, CompletionItemKind};

use crate::goto_def::{find_def, get_identifier_last_name, Definition};
use crate::util::get_real_path_from_external;
use crate::util::{inner_most_expr_in_stmt, is_in_docstring, is_in_schema_expr};

#[derive(Debug, Clone, PartialEq, Hash, Eq)]
Expand Down Expand Up @@ -411,8 +412,12 @@ fn completion_for_import(
) -> Option<lsp_types::CompletionResponse> {
let mut items: IndexSet<KCLCompletionItem> = IndexSet::new();
let pkgpath = &stmt.path;
let real_path =
let mut real_path =
Path::new(&program.root).join(pkgpath.replace('.', &std::path::MAIN_SEPARATOR.to_string()));
if !real_path.exists() {
real_path =
get_real_path_from_external(&stmt.pkg_name, pkgpath, program.root.clone().into());
}
if real_path.is_dir() {
if let Ok(entries) = fs::read_dir(real_path) {
let mut entries = entries
Expand Down Expand Up @@ -1003,7 +1008,7 @@ mod tests {
#[bench_test]
fn import_builtin_package() {
let (file, program, prog_scope, _, gs) =
compile_test_file("src/test_data/completion_test/import/import.k");
compile_test_file("src/test_data/completion_test/import/builtin_pkg.k");
let mut items: IndexSet<KCLCompletionItem> = IndexSet::new();

// test completion for builtin packages
Expand Down Expand Up @@ -1232,4 +1237,33 @@ mod tests {
CompletionResponse::List(_) => panic!("test failed"),
}
}

use crate::util::parse_param_and_compile;
use crate::util::Param;
use parking_lot::RwLock;
use std::sync::Arc;

#[test]
fn schema_docstring_newl111ine_completion() {
He1pa marked this conversation as resolved.
Show resolved Hide resolved
let (file, program, prog_scope, _, _) = {
let file = "/Users/zz/code/KCLVM/kclvm/tools/src/LSP/src/test_data/goto_import_def_test/main.k".to_string();
He1pa marked this conversation as resolved.
Show resolved Hide resolved

let (program, prog_scope, diags, gs) = parse_param_and_compile(
Param { file: file.clone() },
Some(Arc::new(RwLock::new(Default::default()))),
)
.unwrap();
(file, program, prog_scope, diags, gs)
};

// test completion for builtin packages
let pos = KCLPos {
filename: file.to_owned(),
line: 1,
column: Some(14),
};

let got = completion(Some('.'), &program, &pos, &prog_scope).unwrap();
println!("{:?}", got);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[package]

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import k8s
60 changes: 60 additions & 0 deletions kclvm/tools/src/LSP/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,66 @@ fn file_path_from_url_test() {
}
}

#[test]
fn complete_import_external_file_test() {
let path = PathBuf::from(".")
.join("src")
.join("test_data")
.join("completion_test")
.join("import")
.join("external")
.join("main.k")
.canonicalize()
.unwrap()
.display()
.to_string();

let _ = Command::new("kpm")
.arg("metadata")
.arg("--update")
.current_dir(
PathBuf::from(".")
.join("src")
.join("test_data")
.join("goto_import_def_test")
.canonicalize()
.unwrap()
.display()
.to_string(),
)
.output()
.unwrap();

let (program, prog_scope, _, _) = parse_param_and_compile(
Param {
file: path.to_string(),
},
Some(Arc::new(RwLock::new(Default::default()))),
)
.unwrap();

// test goto import file: import .pkg.schema_def
let pos = KCLPos {
filename: path.to_string(),
line: 1,
column: Some(11),
};
let res = completion(Some('.'), &program, &pos, &prog_scope).unwrap();

let got_labels: Vec<String> = match &res {
CompletionResponse::Array(arr) => arr.iter().map(|item| item.label.clone()).collect(),
CompletionResponse::List(_) => panic!("test failed"),
};
let expected_labels: Vec<&str> = vec![
"api",
"apiextensions_apiserver",
"apimachinery",
"kube_aggregator",
"vendor",
];
assert_eq!(got_labels, expected_labels);
}

#[test]
fn goto_import_external_file_test() {
let path = PathBuf::from(".")
Expand Down
Loading