mirror of
https://github.com/CompeyDev/lune-packaging.git
synced 2025-01-09 20:29:10 +00:00
Fix visibility issues for selene gen
This commit is contained in:
parent
67f9d4eb9f
commit
dc8290b51b
4 changed files with 82 additions and 44 deletions
|
@ -4,6 +4,7 @@ use super::{item::DocItem, kind::DocItemKind};
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct DocItemBuilder {
|
pub struct DocItemBuilder {
|
||||||
|
exported: bool,
|
||||||
kind: Option<DocItemKind>,
|
kind: Option<DocItemKind>,
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
meta: Option<String>,
|
meta: Option<String>,
|
||||||
|
@ -20,6 +21,12 @@ impl DocItemBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::wrong_self_convention)]
|
||||||
|
pub fn as_exported(mut self) -> Self {
|
||||||
|
self.exported = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_kind(mut self, kind: DocItemKind) -> Self {
|
pub fn with_kind(mut self, kind: DocItemKind) -> Self {
|
||||||
self.kind = Some(kind);
|
self.kind = Some(kind);
|
||||||
self
|
self
|
||||||
|
@ -67,6 +74,7 @@ impl DocItemBuilder {
|
||||||
let mut children = self.children;
|
let mut children = self.children;
|
||||||
children.sort();
|
children.sort();
|
||||||
Ok(DocItem {
|
Ok(DocItem {
|
||||||
|
exported: self.exported,
|
||||||
kind,
|
kind,
|
||||||
name: self.name,
|
name: self.name,
|
||||||
meta: self.meta,
|
meta: self.meta,
|
||||||
|
|
|
@ -7,6 +7,8 @@ use super::kind::DocItemKind;
|
||||||
#[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 DocItem {
|
||||||
|
#[serde(skip_serializing_if = "skip_serialize_is_false")]
|
||||||
|
pub(super) exported: bool,
|
||||||
pub(super) kind: DocItemKind,
|
pub(super) kind: DocItemKind,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub(super) name: Option<String>,
|
pub(super) name: Option<String>,
|
||||||
|
@ -20,6 +22,11 @@ pub struct DocItem {
|
||||||
pub(super) arg_types: Vec<String>,
|
pub(super) arg_types: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||||
|
fn skip_serialize_is_false(b: &bool) -> bool {
|
||||||
|
!b
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialOrd for DocItem {
|
impl PartialOrd for DocItem {
|
||||||
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() {
|
||||||
|
@ -53,10 +60,18 @@ impl Ord for DocItem {
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl DocItem {
|
impl DocItem {
|
||||||
|
pub fn is_exported(&self) -> bool {
|
||||||
|
self.exported
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_root(&self) -> bool {
|
pub fn is_root(&self) -> bool {
|
||||||
self.kind.is_root()
|
self.kind.is_root()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_table(&self) -> bool {
|
||||||
|
self.kind.is_table()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_property(&self) -> bool {
|
pub fn is_property(&self) -> bool {
|
||||||
self.kind.is_property()
|
self.kind.is_property()
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,26 +22,31 @@ struct DocVisitorItem {
|
||||||
type_info: TypeInfo,
|
type_info: TypeInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DocVisitorItem> for DocItem {
|
impl DocVisitorItem {
|
||||||
fn from(value: DocVisitorItem) -> Self {
|
fn into_doc_item(self, type_definition_declares: &Vec<String>) -> DocItem {
|
||||||
let mut builder = DocItemBuilder::new()
|
let mut builder = DocItemBuilder::new()
|
||||||
.with_kind(DocItemKind::from(&value.type_info))
|
.with_kind(DocItemKind::from(&self.type_info))
|
||||||
.with_name(&value.name);
|
.with_name(&self.name);
|
||||||
if let Some(comment) = value.comment {
|
if type_definition_declares.contains(&self.name) {
|
||||||
|
builder = builder.as_exported();
|
||||||
|
}
|
||||||
|
if let Some(comment) = self.comment {
|
||||||
builder = builder.with_children(&parse_moonwave_style_comment(&comment));
|
builder = builder.with_children(&parse_moonwave_style_comment(&comment));
|
||||||
}
|
}
|
||||||
if let Some(args) = try_extract_normalized_function_args(&value.type_info) {
|
if let Some(args) = try_extract_normalized_function_args(&self.type_info) {
|
||||||
println!("{} > {args:?}", value.name);
|
|
||||||
builder = builder.with_arg_types(&args);
|
builder = builder.with_arg_types(&args);
|
||||||
}
|
}
|
||||||
if let TypeInfo::Table { fields, .. } = value.type_info {
|
if let TypeInfo::Table { fields, .. } = self.type_info {
|
||||||
for field in fields.iter() {
|
for field in fields.iter() {
|
||||||
if let TypeFieldKey::Name(name) = field.key() {
|
if let TypeFieldKey::Name(name) = field.key() {
|
||||||
builder = builder.with_child(DocItem::from(DocVisitorItem {
|
builder = builder.with_child(
|
||||||
name: name.token().to_string(),
|
Self {
|
||||||
comment: find_token_moonwave_comment(name),
|
name: name.token().to_string(),
|
||||||
type_info: field.value().clone(),
|
comment: find_token_moonwave_comment(name),
|
||||||
}));
|
type_info: field.value().clone(),
|
||||||
|
}
|
||||||
|
.into_doc_item(type_definition_declares),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,9 +59,9 @@ impl From<&TypeInfo> for DocItemKind {
|
||||||
match value {
|
match value {
|
||||||
TypeInfo::Array { .. } | TypeInfo::Table { .. } => DocItemKind::Table,
|
TypeInfo::Array { .. } | TypeInfo::Table { .. } => DocItemKind::Table,
|
||||||
TypeInfo::Basic(_) | TypeInfo::String(_) => DocItemKind::Property,
|
TypeInfo::Basic(_) | TypeInfo::String(_) => DocItemKind::Property,
|
||||||
TypeInfo::Optional { base, .. } => DocItemKind::from(base.as_ref()),
|
TypeInfo::Optional { base, .. } => Self::from(base.as_ref()),
|
||||||
TypeInfo::Tuple { types, .. } => {
|
TypeInfo::Tuple { types, .. } => {
|
||||||
let mut kinds = types.iter().map(DocItemKind::from).collect::<Vec<_>>();
|
let mut kinds = types.iter().map(Self::from).collect::<Vec<_>>();
|
||||||
let kinds_all_the_same = kinds.windows(2).all(|w| w[0] == w[1]);
|
let kinds_all_the_same = kinds.windows(2).all(|w| w[0] == w[1]);
|
||||||
if kinds_all_the_same && !kinds.is_empty() {
|
if kinds_all_the_same && !kinds.is_empty() {
|
||||||
kinds.pop().unwrap()
|
kinds.pop().unwrap()
|
||||||
|
@ -67,8 +72,8 @@ impl From<&TypeInfo> for DocItemKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeInfo::Union { left, right, .. } | TypeInfo::Intersection { left, right, .. } => {
|
TypeInfo::Union { left, right, .. } | TypeInfo::Intersection { left, right, .. } => {
|
||||||
let kind_left = DocItemKind::from(left.as_ref());
|
let kind_left = Self::from(left.as_ref());
|
||||||
let kind_right = DocItemKind::from(right.as_ref());
|
let kind_right = Self::from(right.as_ref());
|
||||||
if kind_left == kind_right {
|
if kind_left == kind_right {
|
||||||
kind_left
|
kind_left
|
||||||
} else {
|
} else {
|
||||||
|
@ -86,13 +91,35 @@ impl From<&TypeInfo> for DocItemKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_type_definitions_declares(contents: &str) -> (String, Vec<String>) {
|
||||||
|
// TODO: Properly handle the "declare class" syntax, for now we just skip it
|
||||||
|
let mut no_class_declares = contents.to_string();
|
||||||
|
while let Some(dec) = no_class_declares.find("\ndeclare class") {
|
||||||
|
let end = no_class_declares.find("\nend").unwrap();
|
||||||
|
let before = &no_class_declares[0..dec];
|
||||||
|
let after = &no_class_declares[end + 4..];
|
||||||
|
no_class_declares = format!("{before}{after}");
|
||||||
|
}
|
||||||
|
let regex_declare = Regex::new(r#"declare (\w+): "#).unwrap();
|
||||||
|
let resulting_contents = regex_declare
|
||||||
|
.replace_all(&no_class_declares, "export type $1 =")
|
||||||
|
.to_string();
|
||||||
|
let found_declares = regex_declare
|
||||||
|
.captures_iter(&no_class_declares)
|
||||||
|
.map(|cap| cap[1].to_string())
|
||||||
|
.collect();
|
||||||
|
(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<DocItem>>
|
||||||
where
|
where
|
||||||
S: AsRef<str>,
|
S: AsRef<str>,
|
||||||
{
|
{
|
||||||
let mut found_top_level_items = Vec::new();
|
let mut found_top_level_items = Vec::new();
|
||||||
let ast = full_moon::parse(&cleanup_type_definitions(contents.as_ref()))
|
let (type_definition_contents, type_definition_declares) =
|
||||||
.context("Failed to parse type definitions")?;
|
parse_type_definitions_declares(contents.as_ref());
|
||||||
|
let ast =
|
||||||
|
full_moon::parse(&type_definition_contents).context("Failed to parse type definitions")?;
|
||||||
for stmt in ast.nodes().stmts() {
|
for stmt in ast.nodes().stmts() {
|
||||||
if let Some((declaration, token_reference)) = match stmt {
|
if let Some((declaration, token_reference)) = match stmt {
|
||||||
Stmt::ExportedTypeDeclaration(exp) => {
|
Stmt::ExportedTypeDeclaration(exp) => {
|
||||||
|
@ -108,7 +135,10 @@ where
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(found_top_level_items.drain(..).map(DocItem::from).collect())
|
Ok(found_top_level_items
|
||||||
|
.drain(..)
|
||||||
|
.map(|visitor_item| visitor_item.into_doc_item(&type_definition_declares))
|
||||||
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simple_stringify_type_info(typ: &TypeInfo) -> String {
|
fn simple_stringify_type_info(typ: &TypeInfo) -> String {
|
||||||
|
@ -261,19 +291,3 @@ fn find_token_moonwave_comment(token: &TokenReference) -> Option<String> {
|
||||||
.last()
|
.last()
|
||||||
.map(|comment| comment.trim().to_string())
|
.map(|comment| comment.trim().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cleanup_type_definitions(contents: &str) -> String {
|
|
||||||
// TODO: Properly handle the "declare class" syntax, for now we just skip it
|
|
||||||
let mut no_declares = contents.to_string();
|
|
||||||
while let Some(dec) = no_declares.find("\ndeclare class") {
|
|
||||||
let end = no_declares.find("\nend").unwrap();
|
|
||||||
let before = &no_declares[0..dec];
|
|
||||||
let after = &no_declares[end + 4..];
|
|
||||||
no_declares = format!("{before}{after}");
|
|
||||||
}
|
|
||||||
let (regex, replacement) = (
|
|
||||||
Regex::new(r#"declare (?P<n>\w+): "#).unwrap(),
|
|
||||||
r#"export type $n = "#,
|
|
||||||
);
|
|
||||||
regex.replace_all(&no_declares, replacement).to_string()
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,13 +8,14 @@ use super::doc2::{DocItem, DocItemKind, DocTree, 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 = DocTree::from_type_definitions(contents)?;
|
||||||
let mut globals = YamlMapping::new();
|
let mut globals = YamlMapping::new();
|
||||||
let top_level_items = tree.children().iter().filter(|top_level| {
|
let top_level_exported_items = tree.children().iter().filter(|top_level| {
|
||||||
top_level.is_function()
|
top_level.is_exported()
|
||||||
|| top_level.children().iter().any(|top_level_child| {
|
&& (top_level.is_function()
|
||||||
top_level_child.is_tag() && top_level_child.get_name().unwrap() == "class"
|
|| top_level.children().iter().any(|top_level_child| {
|
||||||
})
|
top_level_child.is_tag() && top_level_child.get_name().unwrap() == "class"
|
||||||
|
}))
|
||||||
});
|
});
|
||||||
for top_level_item in top_level_items {
|
for top_level_item in top_level_exported_items {
|
||||||
match top_level_item.kind() {
|
match top_level_item.kind() {
|
||||||
DocItemKind::Table => {
|
DocItemKind::Table => {
|
||||||
let top_level_name = top_level_item
|
let top_level_name = top_level_item
|
||||||
|
@ -24,7 +25,7 @@ pub fn generate_from_type_definitions(contents: &str) -> Result<String> {
|
||||||
for child_item in top_level_item
|
for child_item in top_level_item
|
||||||
.children()
|
.children()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|item| item.is_function() || item.is_property())
|
.filter(|item| item.is_function() || item.is_table() || item.is_property())
|
||||||
{
|
{
|
||||||
let child_name = child_item
|
let child_name = child_item
|
||||||
.get_name()
|
.get_name()
|
||||||
|
@ -64,7 +65,7 @@ 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: &DocItem) -> Result<YamlMapping> {
|
||||||
let mut mapping = YamlMapping::new();
|
let mut mapping = YamlMapping::new();
|
||||||
if item.is_property() {
|
if item.is_property() || item.is_table() {
|
||||||
let property_access_tag = item
|
let property_access_tag = item
|
||||||
.children()
|
.children()
|
||||||
.iter()
|
.iter()
|
||||||
|
|
Loading…
Reference in a new issue