Rename doc > definition in type definitions parser

This commit is contained in:
Filip Tibell 2023-02-22 10:53:00 +01:00
parent dc8290b51b
commit 7b1b77fbba
No known key found for this signature in database
11 changed files with 85 additions and 85 deletions

View file

@ -1,20 +1,20 @@
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use super::{item::DocItem, kind::DocItemKind}; use super::{item::DefinitionsItem, kind::DefinitionsItemKind};
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct DocItemBuilder { pub struct DefinitionsItemBuilder {
exported: bool, exported: bool,
kind: Option<DocItemKind>, kind: Option<DefinitionsItemKind>,
name: Option<String>, name: Option<String>,
meta: Option<String>, meta: Option<String>,
value: Option<String>, value: Option<String>,
children: Vec<DocItem>, children: Vec<DefinitionsItem>,
arg_types: Vec<String>, arg_types: Vec<String>,
} }
#[allow(dead_code)] #[allow(dead_code)]
impl DocItemBuilder { impl DefinitionsItemBuilder {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
..Default::default() ..Default::default()
@ -27,7 +27,7 @@ impl DocItemBuilder {
self self
} }
pub fn with_kind(mut self, kind: DocItemKind) -> Self { pub fn with_kind(mut self, kind: DefinitionsItemKind) -> Self {
self.kind = Some(kind); self.kind = Some(kind);
self self
} }
@ -47,12 +47,12 @@ impl DocItemBuilder {
self self
} }
pub fn with_child(mut self, child: DocItem) -> Self { pub fn with_child(mut self, child: DefinitionsItem) -> Self {
self.children.push(child); self.children.push(child);
self self
} }
pub fn with_children(mut self, children: &[DocItem]) -> Self { pub fn with_children(mut self, children: &[DefinitionsItem]) -> Self {
self.children.extend_from_slice(children); self.children.extend_from_slice(children);
self self
} }
@ -69,11 +69,11 @@ impl DocItemBuilder {
self self
} }
pub fn build(self) -> Result<DocItem> { pub fn build(self) -> Result<DefinitionsItem> {
if let Some(kind) = self.kind { if let Some(kind) = self.kind {
let mut children = self.children; let mut children = self.children;
children.sort(); children.sort();
Ok(DocItem { Ok(DefinitionsItem {
exported: self.exported, exported: self.exported,
kind, kind,
name: self.name, name: self.name,

View file

@ -2,14 +2,14 @@ use std::cmp::Ordering;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::kind::DocItemKind; use super::kind::DefinitionsItemKind;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct DocItem { pub struct DefinitionsItem {
#[serde(skip_serializing_if = "skip_serialize_is_false")] #[serde(skip_serializing_if = "skip_serialize_is_false")]
pub(super) exported: bool, pub(super) exported: bool,
pub(super) kind: DocItemKind, pub(super) kind: DefinitionsItemKind,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub(super) name: Option<String>, pub(super) name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -17,7 +17,7 @@ pub struct DocItem {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub(super) value: Option<String>, pub(super) value: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")] #[serde(skip_serializing_if = "Vec::is_empty")]
pub(super) children: Vec<DocItem>, pub(super) children: Vec<DefinitionsItem>,
#[serde(skip_serializing_if = "Vec::is_empty")] #[serde(skip_serializing_if = "Vec::is_empty")]
pub(super) arg_types: Vec<String>, pub(super) arg_types: Vec<String>,
} }
@ -27,7 +27,7 @@ fn skip_serialize_is_false(b: &bool) -> bool {
!b !b
} }
impl PartialOrd for DocItem { impl PartialOrd for DefinitionsItem {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match self.kind.partial_cmp(&other.kind).unwrap() { match self.kind.partial_cmp(&other.kind).unwrap() {
Ordering::Equal => {} Ordering::Equal => {}
@ -52,14 +52,14 @@ impl PartialOrd for DocItem {
} }
} }
impl Ord for DocItem { impl Ord for DefinitionsItem {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.partial_cmp(other).unwrap() self.partial_cmp(other).unwrap()
} }
} }
#[allow(dead_code)] #[allow(dead_code)]
impl DocItem { impl DefinitionsItem {
pub fn is_exported(&self) -> bool { pub fn is_exported(&self) -> bool {
self.exported self.exported
} }
@ -88,7 +88,7 @@ impl DocItem {
self.kind.is_tag() self.kind.is_tag()
} }
pub fn kind(&self) -> DocItemKind { pub fn kind(&self) -> DefinitionsItemKind {
self.kind self.kind
} }
@ -104,7 +104,7 @@ impl DocItem {
self.value.as_deref() self.value.as_deref()
} }
pub fn children(&self) -> &[DocItem] { pub fn children(&self) -> &[DefinitionsItem] {
&self.children &self.children
} }

View file

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
pub enum DocItemKind { pub enum DefinitionsItemKind {
Root, Root,
Table, Table,
Property, Property,
@ -14,33 +14,33 @@ pub enum DocItemKind {
} }
#[allow(dead_code)] #[allow(dead_code)]
impl DocItemKind { impl DefinitionsItemKind {
pub fn is_root(self) -> bool { pub fn is_root(self) -> bool {
self == DocItemKind::Root self == DefinitionsItemKind::Root
} }
pub fn is_table(self) -> bool { pub fn is_table(self) -> bool {
self == DocItemKind::Table self == DefinitionsItemKind::Table
} }
pub fn is_property(self) -> bool { pub fn is_property(self) -> bool {
self == DocItemKind::Property self == DefinitionsItemKind::Property
} }
pub fn is_function(self) -> bool { pub fn is_function(self) -> bool {
self == DocItemKind::Function self == DefinitionsItemKind::Function
} }
pub fn is_description(self) -> bool { pub fn is_description(self) -> bool {
self == DocItemKind::Description self == DefinitionsItemKind::Description
} }
pub fn is_tag(self) -> bool { pub fn is_tag(self) -> bool {
self == DocItemKind::Tag self == DefinitionsItemKind::Tag
} }
} }
impl fmt::Display for DocItemKind { impl fmt::Display for DefinitionsItemKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,

View file

@ -0,0 +1,13 @@
mod builder;
mod item;
mod kind;
mod moonwave;
mod parser;
mod tag;
mod tree;
pub use item::DefinitionsItem;
pub use kind::DefinitionsItemKind;
pub use parser::PIPE_SEPARATOR;
pub use tag::DefinitionsItemTag;
pub use tree::DefinitionsTree;

View file

@ -1,12 +1,12 @@
use regex::Regex; use regex::Regex;
use super::{builder::DocItemBuilder, item::DocItem, kind::DocItemKind}; use super::{builder::DefinitionsItemBuilder, item::DefinitionsItem, kind::DefinitionsItemKind};
fn should_separate_tag_meta(tag_kind: &str) -> bool { fn should_separate_tag_meta(tag_kind: &str) -> bool {
matches!(tag_kind.trim().to_ascii_lowercase().as_ref(), "param") matches!(tag_kind.trim().to_ascii_lowercase().as_ref(), "param")
} }
fn parse_moonwave_style_tag(line: &str) -> Option<DocItem> { fn parse_moonwave_style_tag(line: &str) -> Option<DefinitionsItem> {
let tag_regex = Regex::new(r#"^@(\S+)\s*(.*)$"#).unwrap(); let tag_regex = Regex::new(r#"^@(\S+)\s*(.*)$"#).unwrap();
if tag_regex.is_match(line) { if tag_regex.is_match(line) {
let captures = tag_regex.captures(line).unwrap(); let captures = tag_regex.captures(line).unwrap();
@ -22,8 +22,8 @@ fn parse_moonwave_style_tag(line: &str) -> Option<DocItem> {
if tag_kind.is_empty() { if tag_kind.is_empty() {
None None
} else { } else {
let mut builder = DocItemBuilder::new() let mut builder = DefinitionsItemBuilder::new()
.with_kind(DocItemKind::Tag) .with_kind(DefinitionsItemKind::Tag)
.with_name(tag_kind); .with_name(tag_kind);
if !tag_name.is_empty() { if !tag_name.is_empty() {
builder = builder.with_meta(tag_name); builder = builder.with_meta(tag_name);
@ -38,7 +38,7 @@ fn parse_moonwave_style_tag(line: &str) -> Option<DocItem> {
} }
} }
pub(super) fn parse_moonwave_style_comment(comment: &str) -> Vec<DocItem> { pub(super) fn parse_moonwave_style_comment(comment: &str) -> Vec<DefinitionsItem> {
let lines = comment.lines().map(str::trim).collect::<Vec<_>>(); let lines = comment.lines().map(str::trim).collect::<Vec<_>>();
let indent_len = lines.iter().fold(usize::MAX, |acc, line| { let indent_len = lines.iter().fold(usize::MAX, |acc, line| {
let first = line.chars().enumerate().find_map(|(idx, ch)| { let first = line.chars().enumerate().find_map(|(idx, ch)| {
@ -70,8 +70,8 @@ pub(super) fn parse_moonwave_style_comment(comment: &str) -> Vec<DocItem> {
} }
if !doc_lines.is_empty() { if !doc_lines.is_empty() {
doc_items.push( doc_items.push(
DocItemBuilder::new() DefinitionsItemBuilder::new()
.with_kind(DocItemKind::Description) .with_kind(DefinitionsItemKind::Description)
.with_value(doc_lines.join("\n").trim()) .with_value(doc_lines.join("\n").trim())
.build() .build()
.unwrap(), .unwrap(),

View file

@ -9,23 +9,23 @@ use full_moon::{
use regex::Regex; use regex::Regex;
use super::{ use super::{
builder::DocItemBuilder, item::DocItem, kind::DocItemKind, builder::DefinitionsItemBuilder, item::DefinitionsItem, kind::DefinitionsItemKind,
moonwave::parse_moonwave_style_comment, moonwave::parse_moonwave_style_comment,
}; };
pub const PIPE_SEPARATOR: &str = " | "; pub const PIPE_SEPARATOR: &str = " | ";
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct DocVisitorItem { struct DefinitionsParserItem {
name: String, name: String,
comment: Option<String>, comment: Option<String>,
type_info: TypeInfo, type_info: TypeInfo,
} }
impl DocVisitorItem { impl DefinitionsParserItem {
fn into_doc_item(self, type_definition_declares: &Vec<String>) -> DocItem { fn into_doc_item(self, type_definition_declares: &Vec<String>) -> DefinitionsItem {
let mut builder = DocItemBuilder::new() let mut builder = DefinitionsItemBuilder::new()
.with_kind(DocItemKind::from(&self.type_info)) .with_kind(DefinitionsItemKind::from(&self.type_info))
.with_name(&self.name); .with_name(&self.name);
if type_definition_declares.contains(&self.name) { if type_definition_declares.contains(&self.name) {
builder = builder.as_exported(); builder = builder.as_exported();
@ -54,11 +54,11 @@ impl DocVisitorItem {
} }
} }
impl From<&TypeInfo> for DocItemKind { impl From<&TypeInfo> for DefinitionsItemKind {
fn from(value: &TypeInfo) -> Self { fn from(value: &TypeInfo) -> Self {
match value { match value {
TypeInfo::Array { .. } | TypeInfo::Table { .. } => DocItemKind::Table, TypeInfo::Array { .. } | TypeInfo::Table { .. } => DefinitionsItemKind::Table,
TypeInfo::Basic(_) | TypeInfo::String(_) => DocItemKind::Property, TypeInfo::Basic(_) | TypeInfo::String(_) => DefinitionsItemKind::Property,
TypeInfo::Optional { base, .. } => Self::from(base.as_ref()), TypeInfo::Optional { base, .. } => Self::from(base.as_ref()),
TypeInfo::Tuple { types, .. } => { TypeInfo::Tuple { types, .. } => {
let mut kinds = types.iter().map(Self::from).collect::<Vec<_>>(); let mut kinds = types.iter().map(Self::from).collect::<Vec<_>>();
@ -82,7 +82,7 @@ impl From<&TypeInfo> for DocItemKind {
) )
} }
} }
typ if type_info_is_fn(typ) => DocItemKind::Function, typ if type_info_is_fn(typ) => DefinitionsItemKind::Function,
typ => unimplemented!( typ => unimplemented!(
"Missing support for TypeInfo in type definitions parser:\n{}", "Missing support for TypeInfo in type definitions parser:\n{}",
typ.to_string() typ.to_string()
@ -111,7 +111,7 @@ fn parse_type_definitions_declares(contents: &str) -> (String, Vec<String>) {
(resulting_contents, found_declares) (resulting_contents, found_declares)
} }
pub fn parse_type_definitions_into_doc_items<S>(contents: S) -> Result<Vec<DocItem>> pub fn parse_type_definitions_into_doc_items<S>(contents: S) -> Result<Vec<DefinitionsItem>>
where where
S: AsRef<str>, S: AsRef<str>,
{ {
@ -128,7 +128,7 @@ where
Stmt::TypeDeclaration(typ) => Some((typ, typ.type_token())), Stmt::TypeDeclaration(typ) => Some((typ, typ.type_token())),
_ => None, _ => None,
} { } {
found_top_level_items.push(DocVisitorItem { found_top_level_items.push(DefinitionsParserItem {
name: declaration.type_name().token().to_string(), name: declaration.type_name().token().to_string(),
comment: find_token_moonwave_comment(token_reference), comment: find_token_moonwave_comment(token_reference),
type_info: declaration.type_definition().clone(), type_info: declaration.type_definition().clone(),

View file

@ -1,11 +1,11 @@
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::item::DocItem; use super::item::DefinitionsItem;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")] #[serde(rename_all = "PascalCase")]
pub enum DocsItemTag { pub enum DefinitionsItemTag {
Class(String), Class(String),
Within(String), Within(String),
Param((String, String)), Param((String, String)),
@ -16,7 +16,7 @@ pub enum DocsItemTag {
} }
#[allow(dead_code)] #[allow(dead_code)]
impl DocsItemTag { impl DefinitionsItemTag {
pub fn is_class(&self) -> bool { pub fn is_class(&self) -> bool {
matches!(self, Self::Class(_)) matches!(self, Self::Class(_))
} }
@ -46,9 +46,9 @@ impl DocsItemTag {
} }
} }
impl TryFrom<&DocItem> for DocsItemTag { impl TryFrom<&DefinitionsItem> for DefinitionsItemTag {
type Error = anyhow::Error; type Error = anyhow::Error;
fn try_from(value: &DocItem) -> Result<Self> { fn try_from(value: &DefinitionsItem) -> Result<Self> {
if let Some(name) = value.get_name() { if let Some(name) = value.get_name() {
Ok(match name.trim().to_ascii_lowercase().as_ref() { Ok(match name.trim().to_ascii_lowercase().as_ref() {
"class" => Self::Class( "class" => Self::Class(

View file

@ -4,20 +4,20 @@ use anyhow::{Context, Result};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{ use super::{
builder::DocItemBuilder, item::DocItem, kind::DocItemKind, builder::DefinitionsItemBuilder, item::DefinitionsItem, kind::DefinitionsItemKind,
parser::parse_type_definitions_into_doc_items, parser::parse_type_definitions_into_doc_items,
}; };
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DocTree(DocItem); pub struct DefinitionsTree(DefinitionsItem);
#[allow(dead_code)] #[allow(dead_code)]
impl DocTree { impl DefinitionsTree {
pub fn from_type_definitions<S: AsRef<str>>(type_definitions_contents: S) -> Result<Self> { pub fn from_type_definitions<S: AsRef<str>>(type_definitions_contents: S) -> Result<Self> {
let top_level_items = parse_type_definitions_into_doc_items(type_definitions_contents) let top_level_items = parse_type_definitions_into_doc_items(type_definitions_contents)
.context("Failed to visit type definitions AST")?; .context("Failed to visit type definitions AST")?;
let root = DocItemBuilder::new() let root = DefinitionsItemBuilder::new()
.with_kind(DocItemKind::Root) .with_kind(DefinitionsItemKind::Root)
.with_name("<<<ROOT>>>") .with_name("<<<ROOT>>>")
.with_children(&top_level_items) .with_children(&top_level_items)
.build()?; .build()?;
@ -29,19 +29,19 @@ impl DocTree {
true true
} }
pub fn into_inner(self) -> DocItem { pub fn into_inner(self) -> DefinitionsItem {
self.0 self.0
} }
} }
impl Deref for DocTree { impl Deref for DefinitionsTree {
type Target = DocItem; type Target = DefinitionsItem;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.0 &self.0
} }
} }
impl DerefMut for DocTree { impl DerefMut for DefinitionsTree {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }

View file

@ -1,13 +0,0 @@
mod builder;
mod item;
mod kind;
mod moonwave;
mod parser;
mod tag;
mod tree;
pub use item::DocItem;
pub use kind::DocItemKind;
pub use parser::PIPE_SEPARATOR;
pub use tag::DocsItemTag;
pub use tree::DocTree;

View file

@ -3,7 +3,7 @@ mod docs_file;
mod selene_defs; mod selene_defs;
mod wiki_dir; mod wiki_dir;
pub mod doc2; pub mod definitions;
pub use docs_file::generate_from_type_definitions as generate_docs_json_from_definitions; pub use docs_file::generate_from_type_definitions as generate_docs_json_from_definitions;
pub use selene_defs::generate_from_type_definitions as generate_selene_defs_from_definitions; pub use selene_defs::generate_from_type_definitions as generate_selene_defs_from_definitions;

View file

@ -1,12 +1,12 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use serde_yaml::{Mapping as YamlMapping, Sequence as YamlSequence, Value as YamlValue}; use serde_yaml::{Mapping as YamlMapping, Sequence as YamlSequence, Value as YamlValue};
use crate::gen::doc2::DocsItemTag; use crate::gen::definitions::DefinitionsItemTag;
use super::doc2::{DocItem, DocItemKind, DocTree, PIPE_SEPARATOR}; use super::definitions::{DefinitionsItem, DefinitionsItemKind, DefinitionsTree, PIPE_SEPARATOR};
pub fn generate_from_type_definitions(contents: &str) -> Result<String> { pub fn generate_from_type_definitions(contents: &str) -> Result<String> {
let tree = DocTree::from_type_definitions(contents)?; let tree = DefinitionsTree::from_type_definitions(contents)?;
let mut globals = YamlMapping::new(); let mut globals = YamlMapping::new();
let top_level_exported_items = tree.children().iter().filter(|top_level| { let top_level_exported_items = tree.children().iter().filter(|top_level| {
top_level.is_exported() top_level.is_exported()
@ -17,7 +17,7 @@ pub fn generate_from_type_definitions(contents: &str) -> Result<String> {
}); });
for top_level_item in top_level_exported_items { for top_level_item in top_level_exported_items {
match top_level_item.kind() { match top_level_item.kind() {
DocItemKind::Table => { DefinitionsItemKind::Table => {
let top_level_name = top_level_item let top_level_name = top_level_item
.get_name() .get_name()
.context("Missing name for top-level doc item")? .context("Missing name for top-level doc item")?
@ -37,7 +37,7 @@ pub fn generate_from_type_definitions(contents: &str) -> Result<String> {
); );
} }
} }
DocItemKind::Function => { DefinitionsItemKind::Function => {
globals.insert( globals.insert(
YamlValue::String( YamlValue::String(
top_level_item top_level_item
@ -63,14 +63,14 @@ pub fn generate_from_type_definitions(contents: &str) -> Result<String> {
)) ))
} }
fn doc_item_to_selene_yaml_mapping(item: &DocItem) -> Result<YamlMapping> { fn doc_item_to_selene_yaml_mapping(item: &DefinitionsItem) -> Result<YamlMapping> {
let mut mapping = YamlMapping::new(); let mut mapping = YamlMapping::new();
if item.is_property() || item.is_table() { if item.is_property() || item.is_table() {
let property_access_tag = item let property_access_tag = item
.children() .children()
.iter() .iter()
.find_map(|child| { .find_map(|child| {
if let Ok(tag) = DocsItemTag::try_from(child) { if let Ok(tag) = DefinitionsItemTag::try_from(child) {
if tag.is_read_only() || tag.is_read_write() { if tag.is_read_only() || tag.is_read_write() {
Some(tag) Some(tag)
} else { } else {
@ -90,8 +90,8 @@ fn doc_item_to_selene_yaml_mapping(item: &DocItem) -> Result<YamlMapping> {
YamlValue::String("property".to_string()), YamlValue::String("property".to_string()),
YamlValue::String( YamlValue::String(
match property_access_tag { match property_access_tag {
DocsItemTag::ReadOnly => "read-only", DefinitionsItemTag::ReadOnly => "read-only",
DocsItemTag::ReadWrite => "new-fields", DefinitionsItemTag::ReadWrite => "new-fields",
_ => unreachable!(), _ => unreachable!(),
} }
.to_string(), .to_string(),
@ -99,7 +99,7 @@ fn doc_item_to_selene_yaml_mapping(item: &DocItem) -> Result<YamlMapping> {
); );
} else if item.is_function() { } else if item.is_function() {
let is_must_use = item.children().iter().any(|child| { let is_must_use = item.children().iter().any(|child| {
if let Ok(tag) = DocsItemTag::try_from(child) { if let Ok(tag) = DefinitionsItemTag::try_from(child) {
tag.is_must_use() tag.is_must_use()
} else { } else {
false false