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:
@ -5,8 +5,8 @@ use crate::parsing::ast::types::{
|
||||
CallExpression, CallExpressionKw, DefaultParamVal, ElseIf, Expr, ExpressionStatement, FunctionExpression,
|
||||
Identifier, IfExpression, ImportItem, ImportSelector, ImportStatement, ItemVisibility, KclNone, LabelledExpression,
|
||||
Literal, LiteralIdentifier, LiteralValue, MemberExpression, MemberObject, ObjectExpression, ObjectProperty,
|
||||
Parameter, PipeExpression, PipeSubstitution, Program, ReturnStatement, TagDeclarator, Type, UnaryExpression,
|
||||
VariableDeclaration, VariableDeclarator, VariableKind,
|
||||
Parameter, PipeExpression, PipeSubstitution, PrimitiveType, Program, ReturnStatement, TagDeclarator, Type,
|
||||
TypeDeclaration, UnaryExpression, VariableDeclaration, VariableDeclarator, VariableKind,
|
||||
};
|
||||
|
||||
/// Position-independent digest of the AST node.
|
||||
@ -113,6 +113,7 @@ impl BodyItem {
|
||||
BodyItem::ImportStatement(s) => s.compute_digest(),
|
||||
BodyItem::ExpressionStatement(es) => es.compute_digest(),
|
||||
BodyItem::VariableDeclaration(vs) => vs.compute_digest(),
|
||||
BodyItem::TypeDeclaration(t) => t.compute_digest(),
|
||||
BodyItem::ReturnStatement(rs) => rs.compute_digest(),
|
||||
});
|
||||
|
||||
@ -191,11 +192,11 @@ impl Type {
|
||||
match self {
|
||||
Type::Primitive(prim) => {
|
||||
hasher.update(b"FnArgType::Primitive");
|
||||
hasher.update(prim.digestable_id())
|
||||
hasher.update(prim.compute_digest())
|
||||
}
|
||||
Type::Array(prim) => {
|
||||
hasher.update(b"FnArgType::Array");
|
||||
hasher.update(prim.digestable_id())
|
||||
hasher.update(prim.compute_digest())
|
||||
}
|
||||
Type::Object { properties } => {
|
||||
hasher.update(b"FnArgType::Object");
|
||||
@ -210,6 +211,21 @@ impl Type {
|
||||
}
|
||||
}
|
||||
|
||||
impl PrimitiveType {
|
||||
pub fn compute_digest(&mut self) -> Digest {
|
||||
let mut hasher = Sha256::new();
|
||||
match self {
|
||||
PrimitiveType::Named(id) => hasher.update(id.compute_digest()),
|
||||
PrimitiveType::String => hasher.update(b"string"),
|
||||
PrimitiveType::Number(suffix) => hasher.update(suffix.digestable_id()),
|
||||
PrimitiveType::Boolean => hasher.update(b"bool"),
|
||||
PrimitiveType::Tag => hasher.update(b"tag"),
|
||||
}
|
||||
|
||||
hasher.finalize().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Parameter {
|
||||
compute_digest!(|slf, hasher| {
|
||||
hasher.update(slf.identifier.compute_digest());
|
||||
@ -275,6 +291,18 @@ impl VariableDeclaration {
|
||||
});
|
||||
}
|
||||
|
||||
impl TypeDeclaration {
|
||||
compute_digest!(|slf, hasher| {
|
||||
hasher.update(slf.name.compute_digest());
|
||||
if let Some(args) = &mut slf.args {
|
||||
hasher.update([1]);
|
||||
for a in args {
|
||||
hasher.update(a.compute_digest());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
impl VariableKind {
|
||||
fn digestable_id(&self) -> [u8; 1] {
|
||||
match self {
|
||||
|
@ -13,6 +13,7 @@ impl BodyItem {
|
||||
BodyItem::ImportStatement(stmt) => stmt.module_id,
|
||||
BodyItem::ExpressionStatement(expression_statement) => expression_statement.module_id,
|
||||
BodyItem::VariableDeclaration(variable_declaration) => variable_declaration.module_id,
|
||||
BodyItem::TypeDeclaration(ty_declaration) => ty_declaration.module_id,
|
||||
BodyItem::ReturnStatement(return_statement) => return_statement.module_id,
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,9 @@ pub async fn modify_ast_for_sketch(
|
||||
let constraint_level = match ast_sketch {
|
||||
super::types::Definition::Variable(var) => var.get_constraint_level(),
|
||||
super::types::Definition::Import(import) => import.get_constraint_level(),
|
||||
super::types::Definition::Type(_) => ConstraintLevel::Ignore {
|
||||
source_ranges: Vec::new(),
|
||||
},
|
||||
};
|
||||
match &constraint_level {
|
||||
ConstraintLevel::None { source_ranges: _ } => {}
|
||||
|
@ -38,6 +38,7 @@ mod none;
|
||||
pub enum Definition<'a> {
|
||||
Variable(&'a VariableDeclarator),
|
||||
Import(NodeRef<'a, ImportStatement>),
|
||||
Type(NodeRef<'a, TypeDeclaration>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS)]
|
||||
@ -54,18 +55,6 @@ pub struct Node<T> {
|
||||
pub outer_attrs: NodeList<Annotation>,
|
||||
}
|
||||
|
||||
impl<T> Node<T> {
|
||||
pub fn metadata(&self) -> Metadata {
|
||||
Metadata {
|
||||
source_range: SourceRange::new(self.start, self.end, self.module_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains(&self, pos: usize) -> bool {
|
||||
self.start <= pos && pos <= self.end
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: JsonSchema> schemars::JsonSchema for Node<T> {
|
||||
fn schema_name() -> String {
|
||||
T::schema_name()
|
||||
@ -126,6 +115,26 @@ impl<T> Node<T> {
|
||||
pub fn as_source_ranges(&self) -> Vec<SourceRange> {
|
||||
vec![self.as_source_range()]
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> Metadata {
|
||||
Metadata {
|
||||
source_range: SourceRange::new(self.start, self.end, self.module_id),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains(&self, pos: usize) -> bool {
|
||||
self.start <= pos && pos <= self.end
|
||||
}
|
||||
|
||||
pub fn map<U>(self, f: fn(T) -> U) -> Node<U> {
|
||||
Node {
|
||||
inner: f(self.inner),
|
||||
start: self.start,
|
||||
end: self.end,
|
||||
module_id: self.module_id,
|
||||
outer_attrs: self.outer_attrs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for Node<T> {
|
||||
@ -352,7 +361,7 @@ impl Program {
|
||||
|
||||
// Recurse over the item.
|
||||
match item {
|
||||
BodyItem::ImportStatement(_) => None,
|
||||
BodyItem::ImportStatement(_) | BodyItem::TypeDeclaration(_) => None,
|
||||
BodyItem::ExpressionStatement(expression_statement) => Some(&expression_statement.expression),
|
||||
BodyItem::VariableDeclaration(variable_declaration) => variable_declaration.get_expr_for_position(pos),
|
||||
BodyItem::ReturnStatement(return_statement) => Some(&return_statement.argument),
|
||||
@ -373,6 +382,7 @@ impl Program {
|
||||
Some(BodyItem::VariableDeclaration(variable_declaration)) => {
|
||||
variable_declaration.get_expr_for_position(pos)
|
||||
}
|
||||
Some(BodyItem::TypeDeclaration(_)) => None,
|
||||
Some(BodyItem::ReturnStatement(return_statement)) => Some(&return_statement.argument),
|
||||
None => return false,
|
||||
};
|
||||
@ -395,7 +405,7 @@ impl Program {
|
||||
// We only care about the top level things in the program.
|
||||
for item in &self.body {
|
||||
match item {
|
||||
BodyItem::ImportStatement(_) => continue,
|
||||
BodyItem::ImportStatement(_) | BodyItem::TypeDeclaration(_) => continue,
|
||||
BodyItem::ExpressionStatement(expression_statement) => {
|
||||
if let Some(folding_range) = expression_statement.expression.get_lsp_folding_range() {
|
||||
ranges.push(folding_range)
|
||||
@ -425,16 +435,13 @@ impl Program {
|
||||
break;
|
||||
}
|
||||
}
|
||||
BodyItem::ExpressionStatement(_expression_statement) => {
|
||||
continue;
|
||||
}
|
||||
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
|
||||
if let Some(var_old_name) = variable_declaration.rename_symbol(new_name, pos) {
|
||||
old_name = Some(var_old_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
BodyItem::ReturnStatement(_return_statement) => continue,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,6 +465,7 @@ impl Program {
|
||||
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
|
||||
variable_declaration.get_mut_expr_for_position(pos)
|
||||
}
|
||||
BodyItem::TypeDeclaration(_) => None,
|
||||
BodyItem::ReturnStatement(ref mut return_statement) => Some(&mut return_statement.argument),
|
||||
};
|
||||
|
||||
@ -483,16 +491,17 @@ impl Program {
|
||||
fn rename_identifiers(&mut self, old_name: &str, new_name: &str) {
|
||||
for item in &mut self.body {
|
||||
match item {
|
||||
BodyItem::ImportStatement(ref mut stmt) => {
|
||||
BodyItem::ImportStatement(stmt) => {
|
||||
stmt.rename_identifiers(old_name, new_name);
|
||||
}
|
||||
BodyItem::ExpressionStatement(ref mut expression_statement) => {
|
||||
BodyItem::ExpressionStatement(expression_statement) => {
|
||||
expression_statement.expression.rename_identifiers(old_name, new_name);
|
||||
}
|
||||
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
|
||||
BodyItem::VariableDeclaration(variable_declaration) => {
|
||||
variable_declaration.rename_identifiers(old_name, new_name);
|
||||
}
|
||||
BodyItem::ReturnStatement(ref mut return_statement) => {
|
||||
BodyItem::TypeDeclaration(_) => {}
|
||||
BodyItem::ReturnStatement(return_statement) => {
|
||||
return_statement.argument.rename_identifiers(old_name, new_name);
|
||||
}
|
||||
}
|
||||
@ -506,7 +515,7 @@ impl Program {
|
||||
BodyItem::ImportStatement(_) => {
|
||||
continue;
|
||||
}
|
||||
BodyItem::ExpressionStatement(_expression_statement) => {
|
||||
BodyItem::ExpressionStatement(_) => {
|
||||
continue;
|
||||
}
|
||||
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
|
||||
@ -515,7 +524,10 @@ impl Program {
|
||||
return;
|
||||
}
|
||||
}
|
||||
BodyItem::ReturnStatement(_return_statement) => continue,
|
||||
BodyItem::TypeDeclaration(_) => {
|
||||
continue;
|
||||
}
|
||||
BodyItem::ReturnStatement(_) => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -531,6 +543,7 @@ impl Program {
|
||||
BodyItem::VariableDeclaration(ref mut variable_declaration) => {
|
||||
variable_declaration.replace_value(source_range, new_value.clone())
|
||||
}
|
||||
BodyItem::TypeDeclaration(_) => {}
|
||||
BodyItem::ReturnStatement(ref mut return_statement) => {
|
||||
return_statement.argument.replace_value(source_range, new_value.clone())
|
||||
}
|
||||
@ -555,6 +568,11 @@ impl Program {
|
||||
return Some(Definition::Variable(&variable_declaration.declaration));
|
||||
}
|
||||
}
|
||||
BodyItem::TypeDeclaration(ty_declaration) => {
|
||||
if ty_declaration.name.name == name {
|
||||
return Some(Definition::Type(ty_declaration));
|
||||
}
|
||||
}
|
||||
BodyItem::ReturnStatement(_return_statement) => continue,
|
||||
}
|
||||
}
|
||||
@ -588,6 +606,7 @@ pub enum BodyItem {
|
||||
ImportStatement(BoxNode<ImportStatement>),
|
||||
ExpressionStatement(Node<ExpressionStatement>),
|
||||
VariableDeclaration(BoxNode<VariableDeclaration>),
|
||||
TypeDeclaration(BoxNode<TypeDeclaration>),
|
||||
ReturnStatement(Node<ReturnStatement>),
|
||||
}
|
||||
|
||||
@ -597,6 +616,7 @@ impl BodyItem {
|
||||
BodyItem::ImportStatement(stmt) => stmt.start,
|
||||
BodyItem::ExpressionStatement(expression_statement) => expression_statement.start,
|
||||
BodyItem::VariableDeclaration(variable_declaration) => variable_declaration.start,
|
||||
BodyItem::TypeDeclaration(ty_declaration) => ty_declaration.start,
|
||||
BodyItem::ReturnStatement(return_statement) => return_statement.start,
|
||||
}
|
||||
}
|
||||
@ -606,6 +626,7 @@ impl BodyItem {
|
||||
BodyItem::ImportStatement(stmt) => stmt.end,
|
||||
BodyItem::ExpressionStatement(expression_statement) => expression_statement.end,
|
||||
BodyItem::VariableDeclaration(variable_declaration) => variable_declaration.end,
|
||||
BodyItem::TypeDeclaration(ty_declaration) => ty_declaration.end,
|
||||
BodyItem::ReturnStatement(return_statement) => return_statement.end,
|
||||
}
|
||||
}
|
||||
@ -615,6 +636,7 @@ impl BodyItem {
|
||||
BodyItem::ImportStatement(node) => node.outer_attrs = attr,
|
||||
BodyItem::ExpressionStatement(node) => node.outer_attrs = attr,
|
||||
BodyItem::VariableDeclaration(node) => node.outer_attrs = attr,
|
||||
BodyItem::TypeDeclaration(ty_declaration) => ty_declaration.outer_attrs = attr,
|
||||
BodyItem::ReturnStatement(node) => node.outer_attrs = attr,
|
||||
}
|
||||
}
|
||||
@ -624,6 +646,7 @@ impl BodyItem {
|
||||
BodyItem::ImportStatement(node) => &node.outer_attrs,
|
||||
BodyItem::ExpressionStatement(node) => &node.outer_attrs,
|
||||
BodyItem::VariableDeclaration(node) => &node.outer_attrs,
|
||||
BodyItem::TypeDeclaration(ty_declaration) => &ty_declaration.outer_attrs,
|
||||
BodyItem::ReturnStatement(node) => &node.outer_attrs,
|
||||
}
|
||||
}
|
||||
@ -633,6 +656,7 @@ impl BodyItem {
|
||||
BodyItem::ImportStatement(node) => &mut node.outer_attrs,
|
||||
BodyItem::ExpressionStatement(node) => &mut node.outer_attrs,
|
||||
BodyItem::VariableDeclaration(node) => &mut node.outer_attrs,
|
||||
BodyItem::TypeDeclaration(ty_declaration) => &mut ty_declaration.outer_attrs,
|
||||
BodyItem::ReturnStatement(node) => &mut node.outer_attrs,
|
||||
}
|
||||
}
|
||||
@ -1765,6 +1789,20 @@ impl ItemVisibility {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
pub struct TypeDeclaration {
|
||||
pub name: Node<Identifier>,
|
||||
pub args: Option<NodeList<Identifier>>,
|
||||
#[serde(default, skip_serializing_if = "ItemVisibility::is_default")]
|
||||
pub visibility: ItemVisibility,
|
||||
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub digest: Option<Digest>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
@ -2832,7 +2870,8 @@ impl PipeExpression {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, ts_rs::TS, JsonSchema)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
|
||||
#[ts(export)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum PrimitiveType {
|
||||
@ -2845,39 +2884,16 @@ pub enum PrimitiveType {
|
||||
Boolean,
|
||||
/// A tag.
|
||||
Tag,
|
||||
/// A sketch type.
|
||||
Sketch,
|
||||
/// A sketch surface type.
|
||||
SketchSurface,
|
||||
/// An solid type.
|
||||
Solid,
|
||||
/// A plane.
|
||||
Plane,
|
||||
/// An identifier used as a type (not really a primitive type, but whatever).
|
||||
Named(Node<Identifier>),
|
||||
}
|
||||
|
||||
impl PrimitiveType {
|
||||
pub fn digestable_id(&self) -> &[u8] {
|
||||
match self {
|
||||
PrimitiveType::String => b"string",
|
||||
PrimitiveType::Number(suffix) => suffix.digestable_id(),
|
||||
PrimitiveType::Boolean => b"bool",
|
||||
PrimitiveType::Tag => b"tag",
|
||||
PrimitiveType::Sketch => b"Sketch",
|
||||
PrimitiveType::SketchSurface => b"SketchSurface",
|
||||
PrimitiveType::Solid => b"Solid",
|
||||
PrimitiveType::Plane => b"Plane",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str, suffix: Option<NumericSuffix>) -> Option<Self> {
|
||||
pub fn primitive_from_str(s: &str, suffix: Option<NumericSuffix>) -> Option<Self> {
|
||||
match (s, suffix) {
|
||||
("string", None) => Some(PrimitiveType::String),
|
||||
("bool", None) => Some(PrimitiveType::Boolean),
|
||||
("tag", None) => Some(PrimitiveType::Tag),
|
||||
("Sketch", None) => Some(PrimitiveType::Sketch),
|
||||
("SketchSurface", None) => Some(PrimitiveType::SketchSurface),
|
||||
("Solid", None) => Some(PrimitiveType::Solid),
|
||||
("Plane", None) => Some(PrimitiveType::Plane),
|
||||
("number", None) => Some(PrimitiveType::Number(NumericSuffix::None)),
|
||||
("number", Some(s)) => Some(PrimitiveType::Number(s)),
|
||||
_ => None,
|
||||
@ -2898,10 +2914,7 @@ impl fmt::Display for PrimitiveType {
|
||||
PrimitiveType::String => write!(f, "string"),
|
||||
PrimitiveType::Boolean => write!(f, "bool"),
|
||||
PrimitiveType::Tag => write!(f, "tag"),
|
||||
PrimitiveType::Sketch => write!(f, "Sketch"),
|
||||
PrimitiveType::SketchSurface => write!(f, "SketchSurface"),
|
||||
PrimitiveType::Solid => write!(f, "Solid"),
|
||||
PrimitiveType::Plane => write!(f, "Plane"),
|
||||
PrimitiveType::Named(n) => write!(f, "{}", n.name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user