Add title and description to exported types in the blueprint

This also fixes a bug where the documentation of record constructor arguments would be dropped after type-checking. Took me a while to pinpoint.
This commit is contained in:
KtorZ 2023-01-27 16:51:02 +01:00
parent 59ffc6434f
commit 547696abde
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
5 changed files with 98 additions and 29 deletions

View File

@ -80,7 +80,6 @@ impl UntypedModule {
for def in consts.into_iter().chain(not_consts) {
let definition = infer_definition(def, &name, &mut hydrators, &mut environment, kind)?;
definitions.push(definition);
}
@ -339,6 +338,7 @@ fn infer_definition(
label,
annotation,
location,
doc,
..
},
t,
@ -348,7 +348,7 @@ fn infer_definition(
annotation,
location,
tipo: t.clone(),
doc: None,
doc,
}
},
)

View File

@ -5,7 +5,7 @@ pub mod validator;
use crate::{config::Config, module::CheckedModules};
use aiken_lang::uplc::CodeGenerator;
use error::*;
use schema::Schema;
use schema::NamedSchema;
use std::fmt::Debug;
use validator::{Purpose, Validator};
@ -38,11 +38,15 @@ impl Blueprint {
purpose,
datum: datum
.map(|datum| {
Schema::from_type(modules.into(), &datum.arg_name.get_label(), &datum.tipo)
.map_err(Error::Schema)
NamedSchema::from_type(
modules.into(),
&datum.arg_name.get_label(),
&datum.tipo,
)
.map_err(Error::Schema)
})
.transpose()?,
redeemer: Schema::from_type(
redeemer: NamedSchema::from_type(
modules.into(),
&redeemer.arg_name.get_label(),
&redeemer.tipo,

View File

@ -4,7 +4,10 @@ use aiken_lang::{
tipo::Type,
};
use miette::Diagnostic;
use serde::ser::{Serialize, SerializeStruct, Serializer};
use serde::{
self,
ser::{Serialize, SerializeStruct, Serializer},
};
use serde_json;
use std::{
collections::HashMap,
@ -12,6 +15,15 @@ use std::{
sync::Arc,
};
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)]
pub struct NamedSchema {
pub title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(flatten)]
pub schema: Schema,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Schema {
Integer,
@ -24,10 +36,10 @@ pub enum Schema {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Constructor {
pub index: usize,
pub fields: Vec<Schema>,
pub fields: Vec<NamedSchema>,
}
impl Schema {
impl NamedSchema {
pub fn from_type(
modules: &HashMap<String, CheckedModule>,
name: &str,
@ -39,8 +51,16 @@ impl Schema {
name: type_name,
..
} if module_name.is_empty() => match &type_name[..] {
"ByteArray" => Ok(Schema::Bytes),
"Integer" => Ok(Schema::Integer),
"ByteArray" => Ok(NamedSchema {
title: name.to_string(),
description: None,
schema: Schema::Bytes,
}),
"Integer" => Ok(NamedSchema {
title: name.to_string(),
description: None,
schema: Schema::Bytes,
}),
_ => Err(Error::UnsupportedPrimitiveType {
type_name: type_name.clone(),
}),
@ -52,7 +72,12 @@ impl Schema {
} => {
let module = modules.get(module_name).unwrap();
let constructor = find_definition(type_name, &module.ast.definitions).unwrap();
Self::from_data_type(modules, constructor)
let schema = Schema::from_data_type(modules, constructor)?;
Ok(NamedSchema {
title: constructor.name.clone(),
description: constructor.doc.clone().map(|s| s.trim().to_string()),
schema,
})
}
Type::Fn { .. } | Type::Var { .. } | Type::Tuple { .. } => {
Err(Error::UnsupportedKind {
@ -62,7 +87,9 @@ impl Schema {
}
}
}
}
impl Schema {
pub fn from_data_type(
modules: &HashMap<String, CheckedModule>,
data_type: &DataType<Arc<Type>>,
@ -71,11 +98,13 @@ impl Schema {
for (index, constructor) in data_type.constructors.iter().enumerate() {
let mut fields = vec![];
for field in constructor.arguments.iter() {
fields.push(Schema::from_type(
let mut schema = NamedSchema::from_type(
modules,
&field.label.clone().unwrap_or_default(),
&field.tipo,
)?);
)?;
schema.description = field.doc.clone().map(|s| s.trim().to_string());
fields.push(schema);
}
variants.push(Constructor { index, fields });
}
@ -187,7 +216,7 @@ pub mod test {
use super::*;
use serde_json::{self, json, Value};
pub fn assert_json(schema: &Schema, expected: Value) {
pub fn assert_json(schema: &impl Serialize, expected: Value) {
assert_eq!(serde_json::to_value(schema).unwrap(), expected);
}
@ -350,4 +379,37 @@ pub mod test {
}),
)
}
#[test]
fn serialize_named_no_description() {
let schema = NamedSchema {
title: "foo".to_string(),
description: None,
schema: Schema::Integer,
};
assert_json(
&schema,
json!({
"title": "foo",
"dataType": "integer"
}),
)
}
#[test]
fn serialize_named_description() {
let schema = NamedSchema {
title: "foo".to_string(),
description: Some("Lorem Ipsum".to_string()),
schema: Schema::Integer,
};
assert_json(
&schema,
json!({
"title": "foo",
"description": "Lorem Ipsum",
"dataType": "integer"
}),
)
}
}

View File

@ -1,4 +1,4 @@
use super::schema::Schema;
use super::schema::NamedSchema;
use pallas::ledger::primitives::babbage as cardano;
use pallas_traverse::ComputeHash;
use serde::{
@ -13,8 +13,8 @@ pub struct Validator {
pub title: String,
pub purpose: Purpose,
pub description: Option<String>,
pub datum: Option<Schema>,
pub redeemer: Schema,
pub datum: Option<NamedSchema>,
pub redeemer: NamedSchema,
pub program: Program<NamedDeBruijn>,
}
@ -82,7 +82,7 @@ impl Display for Purpose {
#[cfg(test)]
mod test {
use super::super::schema::Constructor;
use super::super::schema::{Constructor, Schema};
use super::*;
use serde_json::{self, json};
use uplc::parser;
@ -98,10 +98,14 @@ mod test {
description: Some("Lorem ipsum".to_string()),
purpose: Purpose::Spend,
datum: None,
redeemer: Schema::AnyOf(vec![Constructor {
index: 0,
fields: vec![Schema::Bytes],
}]),
redeemer: NamedSchema {
title: "Bar".to_string(),
description: None,
schema: Schema::AnyOf(vec![Constructor {
index: 0,
fields: vec![Schema::Bytes],
}]),
},
program,
};
assert_eq!(
@ -111,6 +115,7 @@ mod test {
"description": "Lorem ipsum",
"purpose": "spend",
"redeemer": {
"title": "Bar",
"dataType": "constructor",
"index": 0,
"fields": [{

View File

@ -135,11 +135,7 @@ where
let destination = destination.unwrap_or_else(|| self.root.join("docs"));
let mut parsed_modules = self.parse_sources(self.config.name.clone())?;
for (_, module) in parsed_modules.iter_mut() {
module.attach_doc_and_module_comments();
}
let parsed_modules = self.parse_sources(self.config.name.clone())?;
self.type_check(parsed_modules)?;
@ -349,7 +345,7 @@ where
// Store the name
ast.name = name.clone();
let module = ParsedModule {
let mut module = ParsedModule {
kind,
ast,
code,
@ -370,6 +366,8 @@ where
});
}
module.attach_doc_and_module_comments();
parsed_modules.insert(module.name.clone(), module);
}
Err(errs) => {