Skip to content

Commit

Permalink
feat: lsp hover for schema attr default value
Browse files Browse the repository at this point in the history
Signed-off-by: he1pa <[email protected]>
  • Loading branch information
He1pa committed Sep 24, 2024
1 parent 3f473fa commit 5e39f01
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 12 deletions.
7 changes: 7 additions & 0 deletions kclvm/sema/src/core/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1442,6 +1442,7 @@ pub struct AttributeSymbol {
pub(crate) sema_info: SymbolSemanticInfo,
pub(crate) is_optional: bool,
pub(crate) r#ref: HashSet<SymbolRef>,
pub(crate) default_value: Option<String>
}

impl Symbol for AttributeSymbol {
Expand Down Expand Up @@ -1560,6 +1561,7 @@ impl AttributeSymbol {
end: Position,
owner: SymbolRef,
is_optional: bool,
default_value: Option<String>,
) -> Self {
Self {
id: None,
Expand All @@ -1570,12 +1572,17 @@ impl AttributeSymbol {
owner,
is_optional,
r#ref: HashSet::default(),
default_value,
}
}

pub fn is_optional(&self) -> bool {
self.is_optional
}

pub fn get_default_value(&self) -> Option<String> {
self.default_value.clone()
}
}
#[allow(unused)]
#[derive(Debug, Clone)]
Expand Down
8 changes: 7 additions & 1 deletion kclvm/sema/src/namer/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use super::Namer;
use kclvm_ast::ast;
use kclvm_ast::pos::GetPos;
use kclvm_ast::walker::MutSelfTypedResultWalker;
use kclvm_ast_pretty::{print_ast_node, ASTNode};
use kclvm_error::diagnostic::Range;

impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> {
Expand Down Expand Up @@ -61,7 +62,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> {
let value_name = unification_stmt.target.node.get_name();
if self.gs.get_symbols().get_schema_symbol(owner).is_some() {
let attribute_ref = self.gs.get_symbols_mut().alloc_attribute_symbol(
AttributeSymbol::new(value_name, start_pos, end_pos, owner, false),
AttributeSymbol::new(value_name, start_pos, end_pos, owner, false, None),
self.ctx
.get_node_key(&unification_stmt.target.node.names[0].id),
self.ctx
Expand Down Expand Up @@ -270,13 +271,18 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for Namer<'ctx> {
fn walk_schema_attr(&mut self, schema_attr: &'ctx ast::SchemaAttr) -> Self::Result {
let (start_pos, end_pos): Range = schema_attr.name.get_span_pos();
let owner = self.ctx.owner_symbols.last().unwrap().clone();
let default_value = schema_attr
.value
.as_ref()
.map(|v| print_ast_node(ASTNode::Expr(v)));
let attribute_ref = self.gs.get_symbols_mut().alloc_attribute_symbol(
AttributeSymbol::new(
schema_attr.name.node.clone(),
start_pos,
end_pos,
owner,
schema_attr.is_optional,
default_value,
),
self.ctx.get_node_key(&schema_attr.name.id),
self.ctx
Expand Down
30 changes: 21 additions & 9 deletions kclvm/tools/src/LSP/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use kclvm_error::Position as KCLPos;
use kclvm_sema::{
builtin::BUILTIN_DECORATORS,
core::global_state::GlobalState,
ty::{FunctionType, Type, ANY_TYPE_STR, STR_TYPE_STR},
ty::{FunctionType, Type, ANY_TYPE_STR},
};
use lsp_types::{Hover, HoverContents, MarkedString};

Expand Down Expand Up @@ -30,7 +30,7 @@ pub fn hover(kcl_pos: &KCLPos, gs: &GlobalState) -> Option<lsp_types::Hover> {
// ----------------
// schema Foo(Base)[param: type]:
// attr1: type
// attr2? type
// attr2? type = defalut_value
// -----------------
// doc
// ```
Expand All @@ -53,15 +53,20 @@ pub fn hover(kcl_pos: &KCLPos, gs: &GlobalState) -> Option<lsp_types::Hover> {
let name = attr.get_name();
let attr_symbol =
gs.get_symbols().get_attr_symbol(schema_attr).unwrap();
let default_value_content = match attr_symbol.get_default_value() {
Some(s) => format!(" = {}", s),
None => "".to_string(),
};
let attr_ty_str = match &attr.get_sema_info().ty {
Some(ty) => ty_hover_content(ty),
None => ANY_TYPE_STR.to_string(),
};
attrs.push(format!(
" {}{}: {}",
" {}{}: {}{}",
name,
if attr_symbol.is_optional() { "?" } else { "" },
attr_ty_str,
default_value_content
));
}
}
Expand All @@ -77,10 +82,20 @@ pub fn hover(kcl_pos: &KCLPos, gs: &GlobalState) -> Option<lsp_types::Hover> {
},
kclvm_sema::core::symbol::SymbolKind::Attribute => {
let sema_info = obj.get_sema_info();
let attr_symbol = gs.get_symbols().get_attr_symbol(def_ref).unwrap();
let default_value_content = match attr_symbol.get_default_value() {
Some(s) => format!(" = {}", s),
None => "".to_string(),
};
match &sema_info.ty {
Some(ty) => {
docs.push((
format!("{}: {}", &obj.get_name(), ty.ty_str()),
format!(
"{}: {}{}",
&obj.get_name(),
ty.ty_hint(),
default_value_content
),
MarkedStringType::LanguageString,
));
if let Some(doc) = &sema_info.doc {
Expand Down Expand Up @@ -144,10 +159,7 @@ pub fn hover(kcl_pos: &KCLPos, gs: &GlobalState) -> Option<lsp_types::Hover> {
}

fn ty_hover_content(ty: &Type) -> String {
match &ty.kind {
kclvm_sema::ty::TypeKind::StrLit(s) => format!("{}({:?})", STR_TYPE_STR, s),
_ => ty.ty_str(),
}
ty.ty_hint()
}

// Convert doc to Marked String. This function will convert docs to Markedstrings
Expand Down Expand Up @@ -699,7 +711,7 @@ mod tests {
MarkedString::String("__main__".to_string()),
MarkedString::LanguageString(LanguageString {
language: "KCL".to_string(),
value: "schema Data1[m: {str:str}](Data):\n name: str\n age: int".to_string(),
value: "schema Data1[m: {str:str}](Data):\n name: str = \"1\"\n age: int".to_string(),
}),
];

Expand Down
6 changes: 4 additions & 2 deletions kclvm/tools/src/LSP/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1701,7 +1701,7 @@ fn konfig_hover_test_main() {
MarkedString::String("base.pkg.kusion_models.kube.frontend".to_string()),
MarkedString::LanguageString(lsp_types::LanguageString {
language: "KCL".to_string(),
value: "schema Server:\n name?: str\n workloadType: str(Deployment) | str(StatefulSet)\n renderType?: str(Server) | str(KubeVelaApplication)\n replicas: int\n image: str\n schedulingStrategy: SchedulingStrategy\n mainContainer: Main\n sidecarContainers?: [Sidecar]\n initContainers?: [Sidecar]\n useBuiltInLabels?: bool\n labels?: {str:str}\n annotations?: {str:str}\n useBuiltInSelector?: bool\n selector?: {str:str}\n podMetadata?: ObjectMeta\n volumes?: [Volume]\n needNamespace?: bool\n enableMonitoring?: bool\n configMaps?: [ConfigMap]\n secrets?: [Secret]\n services?: [Service]\n ingresses?: [Ingress]\n serviceAccount?: ServiceAccount\n storage?: ObjectStorage\n database?: DataBase".to_string()
value: "schema Server:\n name?: str\n workloadType: \"Deployment\" | \"StatefulSet\" = \"Deployment\"\n renderType?: \"Server\" | \"KubeVelaApplication\" = \"Server\"\n replicas: int = option(\"replicas\") or 1\n image: str = option(\"image\")\n schedulingStrategy: SchedulingStrategy = strategy.SchedulingStrategy {}\n mainContainer: Main\n sidecarContainers?: [Sidecar]\n initContainers?: [Sidecar]\n useBuiltInLabels?: bool = True\n labels?: {str:str}\n annotations?: {str:str}\n useBuiltInSelector?: bool = True\n selector?: {str:str}\n podMetadata?: ObjectMeta\n volumes?: [Volume]\n needNamespace?: bool = True\n enableMonitoring?: bool = False\n configMaps?: [ConfigMap]\n secrets?: [Secret]\n services?: [Service]\n ingresses?: [Ingress]\n serviceAccount?: ServiceAccount\n storage?: ObjectStorage\n database?: DataBase".to_string()
}),
MarkedString::String("Server is abstaction of Deployment and StatefulSet.".to_string()),
];
Expand All @@ -1722,7 +1722,9 @@ fn konfig_hover_test_main() {
let expect: Vec<MarkedString> = vec![
MarkedString::LanguageString(lsp_types::LanguageString {
language: "KCL".to_string(),
value: "schedulingStrategy: SchedulingStrategy".to_string(),
value:
"schedulingStrategy: SchedulingStrategy = strategy.SchedulingStrategy {}"
.to_string(),
}),
MarkedString::String(
"SchedulingStrategy represents scheduling strategy.".to_string(),
Expand Down

0 comments on commit 5e39f01

Please sign in to comment.