Support types in the standard library (#5651)

* Parse an unparse type decls (and refactor impl attributes slightly)

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Remove special treatment of geometric types from parser and executor

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Generate docs for std types

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Hover tool-tips for types and fixup the frontend

Signed-off-by: Nick Cameron <nrc@ncameron.org>

* Fixes

Signed-off-by: Nick Cameron <nrc@ncameron.org>

---------

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron
2025-03-08 03:53:34 +13:00
committed by GitHub
parent 79d37d360a
commit 5d25f4a0e5
175 changed files with 2023 additions and 1647 deletions

View File

@ -32,6 +32,10 @@ pub(super) enum Hover {
callee_name: String,
range: LspRange,
},
Type {
name: String,
range: LspRange,
},
}
#[derive(Debug, Clone)]
@ -72,7 +76,6 @@ impl Program {
}
let value = self.get_expr_for_position(pos)?;
value.get_hover_value_for_position(pos, code, opts)
}
}
@ -120,8 +123,10 @@ impl Expr {
Expr::TagDeclarator(_) => None,
// TODO LSP hover info for tag
Expr::LabelledExpression(expr) => expr.expr.get_hover_value_for_position(pos, code, opts),
// TODO LSP hover info for type
Expr::AscribedExpression(expr) => expr.expr.get_hover_value_for_position(pos, code, opts),
Expr::AscribedExpression(expr) => expr
.ty
.get_hover_value_for_position(pos, code, opts)
.or_else(|| expr.expr.get_hover_value_for_position(pos, code, opts)),
// TODO: LSP hover information for symbols. https://github.com/KittyCAD/modeling-app/issues/1127
Expr::PipeSubstitution(_) => None,
}
@ -334,8 +339,43 @@ impl PipeExpression {
}
}
impl Node<Type> {
fn get_hover_value_for_position(&self, pos: usize, code: &str, _opts: &HoverOpts) -> Option<Hover> {
let range = self.as_source_range();
if range.contains(pos) {
match &self.inner {
Type::Array(t) | Type::Primitive(t) => {
let mut name = t.to_string();
if name.ends_with(')') {
name.truncate(name.find('(').unwrap());
}
return Some(Hover::Type {
name,
range: range.to_lsp_range(code),
});
}
_ => {}
}
}
None
}
}
impl FunctionExpression {
fn get_hover_value_for_position(&self, pos: usize, code: &str, opts: &HoverOpts) -> Option<Hover> {
if let Some(ty) = &self.return_type {
if let Some(h) = ty.get_hover_value_for_position(pos, code, opts) {
return Some(h);
}
}
for arg in &self.params {
if let Some(ty) = &arg.type_ {
if let Some(h) = ty.get_hover_value_for_position(pos, code, opts) {
return Some(h);
}
}
}
if let Some(value) = self.body.get_expr_for_position(pos) {
let mut vars = opts.vars.clone().unwrap_or_default();
for arg in &self.params {

View File

@ -1105,6 +1105,34 @@ impl LanguageServer for Backend {
range: Some(range),
}))
}
Hover::Type { name, range } => {
let Some(completion) = self.stdlib_completions.get(&name) else {
return Ok(None);
};
let Some(docs) = &completion.documentation else {
return Ok(None);
};
let docs = match docs {
Documentation::String(docs) => docs,
Documentation::MarkupContent(MarkupContent { value, .. }) => value,
};
let docs = if docs.len() > 320 {
let end = docs.find("\n\n").or_else(|| docs.find("\n\r\n")).unwrap_or(320);
&docs[..end]
} else {
&**docs
};
Ok(Some(LspHover {
contents: HoverContents::Markup(MarkupContent {
kind: MarkupKind::Markdown,
value: format!("```\n{}\n```\n\n{}", name, docs),
}),
range: Some(range),
}))
}
Hover::KwArg {
name,
callee_name,