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: enhance lsp hover #621

Merged
merged 1 commit into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions kclvm/sema/src/resolver/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ pub(crate) fn parse_doc_string(ori: &String) -> Doc {
}

/// The Doc struct contains a summary of schema and all the attributes described in the the docstring.
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub(crate) struct Doc {
pub summary: String,
pub attrs: Vec<Attribute>,
Expand All @@ -287,7 +287,7 @@ impl Doc {
}

/// The Attribute struct contains the attribute name and the corresponding description.
#[derive(Debug)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub(crate) struct Attribute {
pub name: String,
pub desc: Vec<String>,
Expand Down
47 changes: 42 additions & 5 deletions kclvm/tools/src/LSP/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,51 @@ pub(crate) fn hover(
if let crate::goto_def::Definition::Object(obj) = def {
match obj.kind {
ScopeObjectKind::Definition => {
docs.insert(obj.ty.ty_str());
let doc = obj.ty.into_schema_type().doc.clone();
if !doc.is_empty() {
docs.insert(doc);
// Schema Definition hover
// ```
// pkg
// schema Foo(Base)
// -----------------
// doc
// -----------------
// Attributes:
// attr1: type
// attr2? type
// ```
let schema_ty = obj.ty.into_schema_type();
let base: String = if let Some(base) = schema_ty.base {
Peefy marked this conversation as resolved.
Show resolved Hide resolved
format!("({})", base.name)
} else {
"".to_string()
};
docs.insert(format!(
"{}\n\nschema {}{}",
schema_ty.pkgpath, schema_ty.name, base
));
if !schema_ty.doc.is_empty() {
docs.insert(schema_ty.doc.clone());
}
let mut attrs = vec!["Attributes:".to_string()];
for (name, attr) in schema_ty.attrs {
attrs.push(format!(
"{}{}:{}",
name,
if attr.is_optional { "?" } else { "" },
format!(" {}", attr.ty.ty_str()),
));
}
docs.insert(attrs.join("\n\n"));
}
// todo: hover ScopeObjectKind::Attribute optional, default value
_ => {
docs.insert(obj.ty.ty_str());
// Variable
// ```
// name: type
//```
docs.insert(format!("{}: {}", obj.name, obj.ty.ty_str()));
if let Some(doc) = obj.doc {
docs.insert(doc);
}
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions kclvm/tools/src/LSP/src/test_data/hover_test/hover.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
schema Person:
"""
hover doc test

Attributes
----------
name : str, default is False, required
name doc test
age : int, default is False, optional
age doc test
"""
name: str
age?: int

p = Person{
name: "Alice"
age: 1
}
83 changes: 81 additions & 2 deletions kclvm/tools/src/LSP/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,11 +796,17 @@ fn schema_doc_hover_test() {
match got.contents {
lsp_types::HoverContents::Array(vec) => {
if let MarkedString::String(s) = vec[0].clone() {
assert_eq!(s, "Person");
assert_eq!(s, "pkg\n\nschema Person");
}
if let MarkedString::String(s) = vec[1].clone() {
assert_eq!(s, "hover doc test");
}
if let MarkedString::String(s) = vec[2].clone() {
assert_eq!(
s,
"Attributes:\n\n__settings__?: {str:any}\n\nname: str\n\nage: int"
);
}
}
_ => unreachable!("test error"),
}
Expand All @@ -813,7 +819,80 @@ fn schema_doc_hover_test() {
match got.contents {
lsp_types::HoverContents::Scalar(marked_string) => {
if let MarkedString::String(s) = marked_string {
assert_eq!(s, "str");
assert_eq!(s, "name: str");
}
}
_ => unreachable!("test error"),
}
}

#[test]
fn schema_doc_hover_test1() {
let (file, program, prog_scope, _) = compile_test_file("src/test_data/hover_test/hover.k");

let pos = KCLPos {
filename: file.clone(),
line: 15,
column: Some(11),
};
let got = hover(&program, &pos, &prog_scope).unwrap();

match got.contents {
lsp_types::HoverContents::Array(vec) => {
if let MarkedString::String(s) = vec[0].clone() {
assert_eq!(s, "__main__\n\nschema Person");
}
if let MarkedString::String(s) = vec[1].clone() {
assert_eq!(s, "hover doc test");
}
if let MarkedString::String(s) = vec[2].clone() {
assert_eq!(
s,
"Attributes:\n\n__settings__?: {str:any}\n\nname: str\n\nage?: int"
);
}
}
_ => unreachable!("test error"),
}
}

#[test]
fn schema_attr_hover_test() {
let (file, program, prog_scope, _) = compile_test_file("src/test_data/hover_test/hover.k");

let pos = KCLPos {
filename: file.clone(),
line: 16,
column: Some(11),
};
let got = hover(&program, &pos, &prog_scope).unwrap();

match got.contents {
lsp_types::HoverContents::Array(vec) => {
if let MarkedString::String(s) = vec[0].clone() {
assert_eq!(s, "name: str");
}
if let MarkedString::String(s) = vec[1].clone() {
assert_eq!(s, "name doc test");
}
}
_ => unreachable!("test error"),
}

let pos = KCLPos {
filename: file.clone(),
line: 17,
column: Some(11),
};
let got = hover(&program, &pos, &prog_scope).unwrap();

match got.contents {
lsp_types::HoverContents::Array(vec) => {
if let MarkedString::String(s) = vec[0].clone() {
assert_eq!(s, "age: int");
}
if let MarkedString::String(s) = vec[1].clone() {
assert_eq!(s, "age doc test");
}
}
_ => unreachable!("test error"),
Expand Down
Loading