feat: signal support
also ran formatter
This commit is contained in:
parent
0981ac7345
commit
3fc1aa19fd
|
@ -98,6 +98,21 @@
|
||||||
</ul>
|
</ul>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- if $type.signals -}}
|
||||||
|
<h4>Signals</h4>
|
||||||
|
<ul>
|
||||||
|
{{- range $signame, $sig := $type.signals -}}
|
||||||
|
<li>
|
||||||
|
<span class="typegray">
|
||||||
|
<a href="#signal.{{ $signame }}">{{ $signame }}</a>(
|
||||||
|
{{- partial "qmlparams.html" $sig.params -}}
|
||||||
|
)
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{{- end -}}
|
||||||
|
</ul>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
{{- if $type.variants -}}
|
{{- if $type.variants -}}
|
||||||
<h4>Variants</h4>
|
<h4>Variants</h4>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -186,6 +201,34 @@
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
{{- if $type.signals -}}
|
||||||
|
<h3>Signal Details</h3>
|
||||||
|
{{ range $signame, $sig := $type.signals }}
|
||||||
|
<div id="signal.{{ $signame }}" class = "qmlpropdef">
|
||||||
|
{{- if $sig.flags -}}
|
||||||
|
<span class="qmlprops typegray">
|
||||||
|
{{ partial "qmltypeflags.html" $sig.flags }}
|
||||||
|
</span>
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{{ $signame -}}
|
||||||
|
<span class="typegray">(
|
||||||
|
{{- partial "qmlparams.html" $sig.params -}}
|
||||||
|
)</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="qmlpropdetails">
|
||||||
|
{{- if $sig.details -}}
|
||||||
|
{{- $sig.details | $.Page.RenderString (dict "display" "block") -}}
|
||||||
|
{{- else -}}
|
||||||
|
<p style="color: #999999"><i>No details provided.</i></p>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
{{- if $type.variants -}}
|
{{- if $type.variants -}}
|
||||||
<h3>Variant Details</h3>
|
<h3>Variant Details</h3>
|
||||||
{{ range $name, $variant := $type.variants }}
|
{{ range $name, $variant := $type.variants }}
|
||||||
|
|
|
@ -2,10 +2,10 @@ use std::{collections::HashMap, path::Path};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
|
|
||||||
mod parse;
|
|
||||||
mod typespec;
|
|
||||||
mod outform;
|
mod outform;
|
||||||
|
mod parse;
|
||||||
mod resolver;
|
mod resolver;
|
||||||
|
mod typespec;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
let args = std::env::args().collect::<Vec<_>>();
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
@ -19,10 +19,17 @@ fn main() -> anyhow::Result<()> {
|
||||||
let text = std::fs::read_to_string(path).expect("failed to read module file");
|
let text = std::fs::read_to_string(path).expect("failed to read module file");
|
||||||
let module = parse::parse_module(&text)?;
|
let module = parse::parse_module(&text)?;
|
||||||
|
|
||||||
let texts = module.header.headers.iter()
|
let texts = module
|
||||||
|
.header
|
||||||
|
.headers
|
||||||
|
.iter()
|
||||||
.map(|header| {
|
.map(|header| {
|
||||||
let text = std::fs::read_to_string(dir.join(header))
|
let text = std::fs::read_to_string(dir.join(header)).with_context(|| {
|
||||||
.with_context(|| format!("failed to read module header `{header}` at {:?}", dir.join(header)))?;
|
format!(
|
||||||
|
"failed to read module header `{header}` at {:?}",
|
||||||
|
dir.join(header)
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok::<_, anyhow::Error>((header, text))
|
Ok::<_, anyhow::Error>((header, text))
|
||||||
})
|
})
|
||||||
|
@ -30,9 +37,11 @@ fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
let parser = parse::Parser::new();
|
let parser = parse::Parser::new();
|
||||||
let mut ctx = parse::ParseContext::default();
|
let mut ctx = parse::ParseContext::default();
|
||||||
texts.iter()
|
texts
|
||||||
|
.iter()
|
||||||
.map(|(header, text)| {
|
.map(|(header, text)| {
|
||||||
parser.parse(&text, &mut ctx)
|
parser
|
||||||
|
.parse(&text, &mut ctx)
|
||||||
.with_context(|| format!("while parsing module header `{header}`"))
|
.with_context(|| format!("while parsing module header `{header}`"))
|
||||||
})
|
})
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
|
@ -41,8 +50,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
let text = serde_json::to_string_pretty(&typespec).unwrap();
|
let text = serde_json::to_string_pretty(&typespec).unwrap();
|
||||||
|
|
||||||
std::fs::write(outpath, text)
|
std::fs::write(outpath, text).context("saving typespec")?;
|
||||||
.context("saving typespec")?;
|
|
||||||
},
|
},
|
||||||
Some("gendocs") => {
|
Some("gendocs") => {
|
||||||
let modinfo = args.get(2).expect("expected module file");
|
let modinfo = args.get(2).expect("expected module file");
|
||||||
|
@ -77,18 +85,24 @@ fn main() -> anyhow::Result<()> {
|
||||||
for (name, info) in types {
|
for (name, info) in types {
|
||||||
let json = serde_json::to_string_pretty(&info).unwrap();
|
let json = serde_json::to_string_pretty(&info).unwrap();
|
||||||
let datapath = datapath.join(format!("{name}.json"));
|
let datapath = datapath.join(format!("{name}.json"));
|
||||||
std::fs::write(&datapath, json).with_context(|| format!("while writing {datapath:?}"))?;
|
std::fs::write(&datapath, json)
|
||||||
|
.with_context(|| format!("while writing {datapath:?}"))?;
|
||||||
|
|
||||||
let template = format!("+++
|
let template = format!(
|
||||||
|
"+++
|
||||||
title = \"{name}\"
|
title = \"{name}\"
|
||||||
hidetitle = true
|
hidetitle = true
|
||||||
+++
|
+++
|
||||||
|
|
||||||
{{{{< qmltype module=\"{module}\" type=\"{name}\" >}}}}
|
{{{{< qmltype module=\"{module}\" type=\"{name}\" >}}}}
|
||||||
", name = name, module = module.header.name);
|
",
|
||||||
|
name = name,
|
||||||
|
module = module.header.name
|
||||||
|
);
|
||||||
|
|
||||||
let templatepath = templatepath.join(format!("{name}.md"));
|
let templatepath = templatepath.join(format!("{name}.md"));
|
||||||
std::fs::write(&templatepath, template).with_context(|| format!("while writing {templatepath:?}"))?;
|
std::fs::write(&templatepath, template)
|
||||||
|
.with_context(|| format!("while writing {templatepath:?}"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let index = outform::ModuleIndex {
|
let index = outform::ModuleIndex {
|
||||||
|
@ -98,17 +112,22 @@ hidetitle = true
|
||||||
|
|
||||||
let datapath = datapath.join("index.json");
|
let datapath = datapath.join("index.json");
|
||||||
let json = serde_json::to_string_pretty(&index).unwrap();
|
let json = serde_json::to_string_pretty(&index).unwrap();
|
||||||
std::fs::write(&datapath, json).with_context(|| format!("while writing {datapath:?}"))?;
|
std::fs::write(&datapath, json)
|
||||||
|
.with_context(|| format!("while writing {datapath:?}"))?;
|
||||||
|
|
||||||
let template = format!("+++
|
let template = format!(
|
||||||
|
"+++
|
||||||
title = \"{name}\"
|
title = \"{name}\"
|
||||||
+++
|
+++
|
||||||
|
|
||||||
{{{{< qmlmodule module=\"{name}\" >}}}}
|
{{{{< qmlmodule module=\"{name}\" >}}}}
|
||||||
", name = module.header.name);
|
",
|
||||||
|
name = module.header.name
|
||||||
|
);
|
||||||
|
|
||||||
let templatepath = templatepath.join(format!("_index.md"));
|
let templatepath = templatepath.join(format!("_index.md"));
|
||||||
std::fs::write(&templatepath, template).with_context(|| format!("while writing {templatepath:?}"))?;
|
std::fs::write(&templatepath, template)
|
||||||
|
.with_context(|| format!("while writing {templatepath:?}"))?;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
panic!("typegen invoked without mode");
|
panic!("typegen invoked without mode");
|
||||||
|
|
|
@ -26,6 +26,7 @@ pub struct ClassInfo {
|
||||||
pub flags: Vec<Flag>,
|
pub flags: Vec<Flag>,
|
||||||
pub properties: HashMap<String, Property>,
|
pub properties: HashMap<String, Property>,
|
||||||
pub functions: HashMap<String, Function>,
|
pub functions: HashMap<String, Function>,
|
||||||
|
pub signals: HashMap<String, Signal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
@ -53,6 +54,13 @@ pub struct Function {
|
||||||
pub params: HashMap<String, Type>,
|
pub params: HashMap<String, Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct Signal {
|
||||||
|
pub name: String,
|
||||||
|
pub details: Option<String>,
|
||||||
|
pub params: HashMap<String, Type>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct EnumInfo {
|
pub struct EnumInfo {
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
|
|
@ -27,13 +27,10 @@ pub fn parse_module(text: &str) -> anyhow::Result<ModuleInfo> {
|
||||||
header = header.trim();
|
header = header.trim();
|
||||||
details = details.trim();
|
details = details.trim();
|
||||||
|
|
||||||
let header = toml::from_str::<ModuleInfoHeader>(header)
|
let header =
|
||||||
.context("parsing module info header")?;
|
toml::from_str::<ModuleInfoHeader>(header).context("parsing module info header")?;
|
||||||
|
|
||||||
Ok(ModuleInfo {
|
Ok(ModuleInfo { header, details })
|
||||||
header,
|
|
||||||
details,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -47,6 +44,7 @@ pub struct ClassInfo<'a> {
|
||||||
pub comment: Option<&'a str>,
|
pub comment: Option<&'a str>,
|
||||||
pub properties: Vec<Property<'a>>,
|
pub properties: Vec<Property<'a>>,
|
||||||
pub invokables: Vec<Invokable<'a>>,
|
pub invokables: Vec<Invokable<'a>>,
|
||||||
|
pub signals: Vec<Signal<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -73,6 +71,13 @@ pub struct Invokable<'a> {
|
||||||
pub params: Vec<InvokableParam<'a>>,
|
pub params: Vec<InvokableParam<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Signal<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub comment: Option<&'a str>,
|
||||||
|
pub params: Vec<InvokableParam<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct InvokableParam<'a> {
|
pub struct InvokableParam<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
|
@ -98,6 +103,7 @@ pub struct Parser {
|
||||||
pub class_regex: Regex,
|
pub class_regex: Regex,
|
||||||
pub macro_regex: Regex,
|
pub macro_regex: Regex,
|
||||||
pub property_regex: Regex,
|
pub property_regex: Regex,
|
||||||
|
pub signals_regex: Regex,
|
||||||
pub fn_regex: Regex,
|
pub fn_regex: Regex,
|
||||||
pub fn_param_regex: Regex,
|
pub fn_param_regex: Regex,
|
||||||
pub defaultprop_classinfo_regex: Regex,
|
pub defaultprop_classinfo_regex: Regex,
|
||||||
|
@ -126,15 +132,20 @@ impl Parser {
|
||||||
class_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*class\s+(?<name>\w+)(?:\s*:\s*public\s+(?<super>\w+))?.+?\{(?<body>[\s\S]*?)};"#).unwrap(),
|
class_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*class\s+(?<name>\w+)(?:\s*:\s*public\s+(?<super>\w+))?.+?\{(?<body>[\s\S]*?)};"#).unwrap(),
|
||||||
macro_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*(?<type>(Q|QML)_\w+)\s*(\(\s*(?<args>.*)\s*\))?;"#).unwrap(),
|
macro_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*(?<type>(Q|QML)_\w+)\s*(\(\s*(?<args>.*)\s*\))?;"#).unwrap(),
|
||||||
property_regex: Regex::new(r#"^\s*(?<type>(\w|::|<|>)+\*?)\s+(?<name>\w+)(\s+(MEMBER\s+(?<member>\w+)|READ\s+(?<read>\w+)|WRITE\s+(?<write>\w+)|NOTIFY\s+(?<notify>\w+)|(?<const>CONSTANT)))+\s*$"#).unwrap(),
|
property_regex: Regex::new(r#"^\s*(?<type>(\w|::|<|>)+\*?)\s+(?<name>\w+)(\s+(MEMBER\s+(?<member>\w+)|READ\s+(?<read>\w+)|WRITE\s+(?<write>\w+)|NOTIFY\s+(?<notify>\w+)|(?<const>CONSTANT)))+\s*$"#).unwrap(),
|
||||||
fn_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*Q_INVOKABLE\s+(?<type>(\w|::|<|>)+\*?)\s+(?<name>\w+)\((?<params>[\s\S]*?)\);"#).unwrap(),
|
fn_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*(?<invokable>Q_INVOKABLE)?\s+(?<type>(\w|::|<|>)+\*?)\s+(?<name>\w+)\((?<params>[\s\S]*?)\);"#).unwrap(),
|
||||||
fn_param_regex: Regex::new(r#"(?<type>(\w|::|<|>)+\*?)\s+(?<name>\w+)(,|$)"#).unwrap(),
|
fn_param_regex: Regex::new(r#"(?<type>(\w|::|<|>)+\*?)\s+(?<name>\w+)(,|$)"#).unwrap(),
|
||||||
|
signals_regex: Regex::new(r#"signals:(?<signals>(\s*(\s*///.*\s*)*void .*;)*)"#).unwrap(),
|
||||||
defaultprop_classinfo_regex: Regex::new(r#"^\s*"DefaultProperty", "(?<prop>.+)"\s*$"#).unwrap(),
|
defaultprop_classinfo_regex: Regex::new(r#"^\s*"DefaultProperty", "(?<prop>.+)"\s*$"#).unwrap(),
|
||||||
enum_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*namespace (?<namespace>\w+)\s*\{[\s\S]*?(QML_ELEMENT|QML_NAMED_ELEMENT\((?<qml_name>\w+)\));[\s\S]*?enum\s*(?<enum_name>\w+)\s*\{(?<body>[\s\S]*?)\};[\s\S]*?\}"#).unwrap(),
|
enum_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*namespace (?<namespace>\w+)\s*\{[\s\S]*?(QML_ELEMENT|QML_NAMED_ELEMENT\((?<qml_name>\w+)\));[\s\S]*?enum\s*(?<enum_name>\w+)\s*\{(?<body>[\s\S]*?)\};[\s\S]*?\}"#).unwrap(),
|
||||||
enum_variant_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*(?<name>\w+)\s*=\s*\d+,"#).unwrap(),
|
enum_variant_regex: Regex::new(r#"(?<comment>(\s*\/\/\/.*\n)+)?\s*(?<name>\w+)\s*=\s*\d+,"#).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_classes<'a>(&self, text: &'a str, ctx: &mut ParseContext<'a>) -> anyhow::Result<()> {
|
pub fn parse_classes<'a>(
|
||||||
|
&self,
|
||||||
|
text: &'a str,
|
||||||
|
ctx: &mut ParseContext<'a>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
for class in self.class_regex.captures_iter(text) {
|
for class in self.class_regex.captures_iter(text) {
|
||||||
let comment = class.name("comment").map(|m| m.as_str());
|
let comment = class.name("comment").map(|m| m.as_str());
|
||||||
let name = class.name("name").unwrap().as_str();
|
let name = class.name("name").unwrap().as_str();
|
||||||
|
@ -148,6 +159,8 @@ impl Parser {
|
||||||
let mut properties = Vec::new();
|
let mut properties = Vec::new();
|
||||||
let mut default_property = None;
|
let mut default_property = None;
|
||||||
let mut invokables = Vec::new();
|
let mut invokables = Vec::new();
|
||||||
|
let mut notify_signals = Vec::new();
|
||||||
|
let mut signals = Vec::new();
|
||||||
|
|
||||||
(|| {
|
(|| {
|
||||||
for macro_ in self.macro_regex.captures_iter(body) {
|
for macro_ in self.macro_regex.captures_iter(body) {
|
||||||
|
@ -160,11 +173,19 @@ impl Parser {
|
||||||
"Q_OBJECT" => classtype = Some(ClassType::Object),
|
"Q_OBJECT" => classtype = Some(ClassType::Object),
|
||||||
"Q_GADGET" => classtype = Some(ClassType::Gadget),
|
"Q_GADGET" => classtype = Some(ClassType::Gadget),
|
||||||
"QML_ELEMENT" => qml_name = Some(name),
|
"QML_ELEMENT" => qml_name = Some(name),
|
||||||
"QML_NAMED_ELEMENT" => qml_name = Some(args.ok_or_else(|| anyhow!("expected name for QML_NAMED_ELEMENT"))?),
|
"QML_NAMED_ELEMENT" => {
|
||||||
|
qml_name = Some(args.ok_or_else(|| {
|
||||||
|
anyhow!("expected name for QML_NAMED_ELEMENT")
|
||||||
|
})?)
|
||||||
|
},
|
||||||
"QML_SINGLETON" => singleton = true,
|
"QML_SINGLETON" => singleton = true,
|
||||||
"QML_UNCREATABLE" => uncreatable = true,
|
"QML_UNCREATABLE" => uncreatable = true,
|
||||||
"Q_PROPERTY" => {
|
"Q_PROPERTY" => {
|
||||||
let prop = self.property_regex.captures(args.ok_or_else(|| anyhow!("expected args for Q_PROPERTY"))?)
|
let prop =
|
||||||
|
self.property_regex
|
||||||
|
.captures(args.ok_or_else(|| {
|
||||||
|
anyhow!("expected args for Q_PROPERTY")
|
||||||
|
})?)
|
||||||
.ok_or_else(|| anyhow!("unable to parse Q_PROPERTY"))?;
|
.ok_or_else(|| anyhow!("unable to parse Q_PROPERTY"))?;
|
||||||
|
|
||||||
let member = prop.name("member").is_some();
|
let member = prop.name("member").is_some();
|
||||||
|
@ -172,6 +193,10 @@ impl Parser {
|
||||||
let write = prop.name("write").is_some();
|
let write = prop.name("write").is_some();
|
||||||
let constant = prop.name("const").is_some();
|
let constant = prop.name("const").is_some();
|
||||||
|
|
||||||
|
if let Some(notify) = prop.name("notify").map(|v| v.as_str()) {
|
||||||
|
notify_signals.push(notify);
|
||||||
|
}
|
||||||
|
|
||||||
properties.push(Property {
|
properties.push(Property {
|
||||||
type_: prop.name("type").unwrap().as_str(),
|
type_: prop.name("type").unwrap().as_str(),
|
||||||
name: prop.name("name").unwrap().as_str(),
|
name: prop.name("name").unwrap().as_str(),
|
||||||
|
@ -182,7 +207,9 @@ impl Parser {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
"Q_CLASSINFO" => {
|
"Q_CLASSINFO" => {
|
||||||
let classinfo = self.defaultprop_classinfo_regex.captures(args.ok_or_else(|| anyhow!("expected args for Q_CLASSINFO"))?);
|
let classinfo = self.defaultprop_classinfo_regex.captures(
|
||||||
|
args.ok_or_else(|| anyhow!("expected args for Q_CLASSINFO"))?,
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(classinfo) = classinfo {
|
if let Some(classinfo) = classinfo {
|
||||||
let prop = classinfo.name("prop").unwrap().as_str();
|
let prop = classinfo.name("prop").unwrap().as_str();
|
||||||
|
@ -192,10 +219,26 @@ impl Parser {
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
Ok::<_, anyhow::Error>(())
|
Ok::<_, anyhow::Error>(())
|
||||||
})().with_context(|| format!("while parsing macro `{}`", macro_.get(0).unwrap().as_str()))?;
|
})()
|
||||||
|
.with_context(|| {
|
||||||
|
format!("while parsing macro `{}`", macro_.get(0).unwrap().as_str())
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(prop) = default_property {
|
||||||
|
let prop = properties
|
||||||
|
.iter_mut()
|
||||||
|
.find(|p| p.name == prop)
|
||||||
|
.ok_or_else(|| anyhow!("could not find default property `{prop}`"))?;
|
||||||
|
|
||||||
|
prop.default = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for invokable in self.fn_regex.captures_iter(body) {
|
for invokable in self.fn_regex.captures_iter(body) {
|
||||||
|
if invokable.name("invokable").is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let comment = invokable.name("comment").map(|m| m.as_str());
|
let comment = invokable.name("comment").map(|m| m.as_str());
|
||||||
let type_ = invokable.name("type").unwrap().as_str();
|
let type_ = invokable.name("type").unwrap().as_str();
|
||||||
let name = invokable.name("name").unwrap().as_str();
|
let name = invokable.name("name").unwrap().as_str();
|
||||||
|
@ -207,10 +250,7 @@ impl Parser {
|
||||||
let type_ = param.name("type").unwrap().as_str();
|
let type_ = param.name("type").unwrap().as_str();
|
||||||
let name = param.name("name").unwrap().as_str();
|
let name = param.name("name").unwrap().as_str();
|
||||||
|
|
||||||
params.push(InvokableParam {
|
params.push(InvokableParam { type_, name });
|
||||||
type_,
|
|
||||||
name,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
invokables.push(Invokable {
|
invokables.push(Invokable {
|
||||||
|
@ -221,15 +261,47 @@ impl Parser {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(prop) = default_property {
|
for signal_set in self.signals_regex.captures_iter(body) {
|
||||||
let prop = properties.iter_mut().find(|p| p.name == prop)
|
let signals_body = signal_set.name("signals").unwrap().as_str();
|
||||||
.ok_or_else(|| anyhow!("could not find default property `{prop}`"))?;
|
|
||||||
|
|
||||||
prop.default = true;
|
for signal in self.fn_regex.captures_iter(signals_body) {
|
||||||
|
if signal.name("invokable").is_some() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let comment = signal.name("comment").map(|m| m.as_str());
|
||||||
|
let type_ = signal.name("type").unwrap().as_str();
|
||||||
|
let name = signal.name("name").unwrap().as_str();
|
||||||
|
let params_raw = signal.name("params").unwrap().as_str();
|
||||||
|
|
||||||
|
if notify_signals.contains(&name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if type_ != "void" {
|
||||||
|
bail!("non void return for signal {name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut params = Vec::new();
|
||||||
|
|
||||||
|
for param in self.fn_param_regex.captures_iter(params_raw) {
|
||||||
|
let type_ = param.name("type").unwrap().as_str();
|
||||||
|
let name = param.name("name").unwrap().as_str();
|
||||||
|
|
||||||
|
params.push(InvokableParam { type_, name });
|
||||||
|
}
|
||||||
|
|
||||||
|
signals.push(Signal {
|
||||||
|
name,
|
||||||
|
comment,
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok::<_, anyhow::Error>(())
|
Ok::<_, anyhow::Error>(())
|
||||||
})().with_context(|| format!("while parsing class `{name}`"))?;
|
})()
|
||||||
|
.with_context(|| format!("while parsing class `{name}`"))?;
|
||||||
|
|
||||||
let Some(type_) = classtype else { continue };
|
let Some(type_) = classtype else { continue };
|
||||||
|
|
||||||
|
@ -243,6 +315,7 @@ impl Parser {
|
||||||
comment,
|
comment,
|
||||||
properties,
|
properties,
|
||||||
invokables,
|
invokables,
|
||||||
|
signals,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +327,10 @@ impl Parser {
|
||||||
let comment = enum_.name("comment").map(|m| m.as_str());
|
let comment = enum_.name("comment").map(|m| m.as_str());
|
||||||
let namespace = enum_.name("namespace").unwrap().as_str();
|
let namespace = enum_.name("namespace").unwrap().as_str();
|
||||||
let enum_name = enum_.name("enum_name").unwrap().as_str();
|
let enum_name = enum_.name("enum_name").unwrap().as_str();
|
||||||
let qml_name = enum_.name("qml_name").map(|m| m.as_str()).unwrap_or(namespace);
|
let qml_name = enum_
|
||||||
|
.name("qml_name")
|
||||||
|
.map(|m| m.as_str())
|
||||||
|
.unwrap_or(namespace);
|
||||||
let body = enum_.name("body").unwrap().as_str();
|
let body = enum_.name("body").unwrap().as_str();
|
||||||
|
|
||||||
let mut variants = Vec::new();
|
let mut variants = Vec::new();
|
||||||
|
@ -263,10 +339,7 @@ impl Parser {
|
||||||
let comment = variant.name("comment").map(|m| m.as_str());
|
let comment = variant.name("comment").map(|m| m.as_str());
|
||||||
let name = variant.name("name").unwrap().as_str();
|
let name = variant.name("name").unwrap().as_str();
|
||||||
|
|
||||||
variants.push(Variant {
|
variants.push(Variant { name, comment });
|
||||||
name,
|
|
||||||
comment,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.enums.push(EnumInfo {
|
ctx.enums.push(EnumInfo {
|
||||||
|
@ -292,16 +365,25 @@ impl Parser {
|
||||||
impl ParseContext<'_> {
|
impl ParseContext<'_> {
|
||||||
pub fn gen_typespec(&self, module: &str) -> typespec::TypeSpec {
|
pub fn gen_typespec(&self, module: &str) -> typespec::TypeSpec {
|
||||||
typespec::TypeSpec {
|
typespec::TypeSpec {
|
||||||
typemap: self.classes.iter().filter_map(|class| {
|
typemap: self
|
||||||
|
.classes
|
||||||
|
.iter()
|
||||||
|
.filter_map(|class| {
|
||||||
Some(typespec::QmlTypeMapping {
|
Some(typespec::QmlTypeMapping {
|
||||||
// filters gadgets
|
// filters gadgets
|
||||||
name: class.qml_name?.to_string(),
|
name: class.qml_name?.to_string(),
|
||||||
cname: class.name.to_string(),
|
cname: class.name.to_string(),
|
||||||
module: Some(module.to_string()),
|
module: Some(module.to_string()),
|
||||||
})
|
})
|
||||||
}).collect(),
|
})
|
||||||
classes: self.classes.iter().filter_map(|class| {
|
.collect(),
|
||||||
let (description, details) = class.comment.map(parse_details_desc)
|
classes: self
|
||||||
|
.classes
|
||||||
|
.iter()
|
||||||
|
.filter_map(|class| {
|
||||||
|
let (description, details) = class
|
||||||
|
.comment
|
||||||
|
.map(parse_details_desc)
|
||||||
.unwrap_or((None, None));
|
.unwrap_or((None, None));
|
||||||
|
|
||||||
Some(typespec::Class {
|
Some(typespec::Class {
|
||||||
|
@ -315,17 +397,28 @@ impl ParseContext<'_> {
|
||||||
uncreatable: class.uncreatable,
|
uncreatable: class.uncreatable,
|
||||||
properties: class.properties.iter().map(|p| (*p).into()).collect(),
|
properties: class.properties.iter().map(|p| (*p).into()).collect(),
|
||||||
functions: class.invokables.iter().map(|f| f.as_typespec()).collect(),
|
functions: class.invokables.iter().map(|f| f.as_typespec()).collect(),
|
||||||
|
signals: class.signals.iter().map(|s| s.as_typespec()).collect(),
|
||||||
})
|
})
|
||||||
}).collect(),
|
})
|
||||||
gadgets: self.classes.iter().filter_map(|class| match class.type_ {
|
.collect(),
|
||||||
|
gadgets: self
|
||||||
|
.classes
|
||||||
|
.iter()
|
||||||
|
.filter_map(|class| match class.type_ {
|
||||||
ClassType::Gadget => Some(typespec::Gadget {
|
ClassType::Gadget => Some(typespec::Gadget {
|
||||||
cname: class.name.to_string(),
|
cname: class.name.to_string(),
|
||||||
properties: class.properties.iter().map(|p| (*p).into()).collect(),
|
properties: class.properties.iter().map(|p| (*p).into()).collect(),
|
||||||
}),
|
}),
|
||||||
_ => None,
|
_ => None,
|
||||||
}).collect(),
|
})
|
||||||
enums: self.enums.iter().map(|enum_| {
|
.collect(),
|
||||||
let (description, details) = enum_.comment.map(parse_details_desc)
|
enums: self
|
||||||
|
.enums
|
||||||
|
.iter()
|
||||||
|
.map(|enum_| {
|
||||||
|
let (description, details) = enum_
|
||||||
|
.comment
|
||||||
|
.map(parse_details_desc)
|
||||||
.unwrap_or((None, None));
|
.unwrap_or((None, None));
|
||||||
|
|
||||||
typespec::Enum {
|
typespec::Enum {
|
||||||
|
@ -336,7 +429,8 @@ impl ParseContext<'_> {
|
||||||
details,
|
details,
|
||||||
varaints: enum_.variants.iter().map(|v| (*v).into()).collect(),
|
varaints: enum_.variants.iter().map(|v| (*v).into()).collect(),
|
||||||
}
|
}
|
||||||
}).collect(),
|
})
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,6 +468,16 @@ impl Invokable<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Signal<'_> {
|
||||||
|
fn as_typespec(&self) -> typespec::Signal {
|
||||||
|
typespec::Signal {
|
||||||
|
name: self.name.to_string(),
|
||||||
|
details: self.comment.map(parse_details),
|
||||||
|
params: self.params.iter().map(|p| (*p).into()).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<InvokableParam<'_>> for typespec::FnParam {
|
impl From<InvokableParam<'_>> for typespec::FnParam {
|
||||||
fn from(value: InvokableParam<'_>) -> Self {
|
fn from(value: InvokableParam<'_>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -387,7 +491,8 @@ fn parse_details(text: &str) -> String {
|
||||||
let mut seen_content = false;
|
let mut seen_content = false;
|
||||||
let mut callout = false;
|
let mut callout = false;
|
||||||
|
|
||||||
let mut str = text.lines()
|
let mut str = text
|
||||||
|
.lines()
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
line.trim()
|
line.trim()
|
||||||
.strip_prefix("///")
|
.strip_prefix("///")
|
||||||
|
@ -400,8 +505,7 @@ fn parse_details(text: &str) -> String {
|
||||||
seen_content |= any;
|
seen_content |= any;
|
||||||
filter
|
filter
|
||||||
})
|
})
|
||||||
.map(|line| {
|
.map(|line| match callout {
|
||||||
match callout {
|
|
||||||
true => {
|
true => {
|
||||||
if line.starts_with('>') {
|
if line.starts_with('>') {
|
||||||
Cow::Borrowed(line[1..].strip_prefix(' ').unwrap_or(&line[1..]))
|
Cow::Borrowed(line[1..].strip_prefix(' ').unwrap_or(&line[1..]))
|
||||||
|
@ -409,7 +513,7 @@ fn parse_details(text: &str) -> String {
|
||||||
callout = false;
|
callout = false;
|
||||||
Cow::Owned(format!("{{{{< /callout >}}}}\n{line}"))
|
Cow::Owned(format!("{{{{< /callout >}}}}\n{line}"))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
false => {
|
false => {
|
||||||
if line.starts_with("> [!") {
|
if line.starts_with("> [!") {
|
||||||
let code = line[4..].split_once(']');
|
let code = line[4..].split_once(']');
|
||||||
|
@ -422,8 +526,7 @@ fn parse_details(text: &str) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Cow::Borrowed(line);
|
return Cow::Borrowed(line);
|
||||||
}
|
},
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.fold(String::new(), |accum, line| accum + line.as_ref() + "\n");
|
.fold(String::new(), |accum, line| accum + line.as_ref() + "\n");
|
||||||
|
|
||||||
|
@ -438,8 +541,19 @@ fn parse_details_desc(text: &str) -> (Option<String>, Option<String>) {
|
||||||
let details = parse_details(text);
|
let details = parse_details(text);
|
||||||
if details.starts_with('!') {
|
if details.starts_with('!') {
|
||||||
match details[1..].split_once('\n') {
|
match details[1..].split_once('\n') {
|
||||||
Some((desc, details)) => (Some(desc.strip_prefix(' ').unwrap_or(desc).to_string()), Some(details.to_string())),
|
Some((desc, details)) => (
|
||||||
None => (Some(details[1..].strip_prefix(' ').unwrap_or(&details[1..]).to_string()), None),
|
Some(desc.strip_prefix(' ').unwrap_or(desc).to_string()),
|
||||||
|
Some(details.to_string()),
|
||||||
|
),
|
||||||
|
None => (
|
||||||
|
Some(
|
||||||
|
details[1..]
|
||||||
|
.strip_prefix(' ')
|
||||||
|
.unwrap_or(&details[1..])
|
||||||
|
.to_string(),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(None, Some(details))
|
(None, Some(details))
|
||||||
|
|
|
@ -1,24 +1,35 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{outform::{self, Flag, PropertyType}, typespec::{FnParam, Function, Property, TypeSpec}};
|
use crate::{
|
||||||
|
outform::{self, Flag, PropertyType},
|
||||||
|
typespec::{FnParam, Function, Property, Signal, TypeSpec},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result<HashMap<String, outform::TypeInfo>> {
|
pub fn resolve_types(
|
||||||
|
module: &str,
|
||||||
|
typespec: TypeSpec,
|
||||||
|
) -> anyhow::Result<HashMap<String, outform::TypeInfo>> {
|
||||||
let mut outtypes = HashMap::new();
|
let mut outtypes = HashMap::new();
|
||||||
|
|
||||||
let types = typespec.typemap.iter()
|
let types = typespec
|
||||||
|
.typemap
|
||||||
|
.iter()
|
||||||
.filter(|type_| type_.module.as_ref().map(|v| v as &str) == Some(module));
|
.filter(|type_| type_.module.as_ref().map(|v| v as &str) == Some(module));
|
||||||
|
|
||||||
let findqmltype = |cname: &str| typespec.typemap
|
let findqmltype = |cname: &str| typespec.typemap.iter().find(|type_| type_.cname == cname);
|
||||||
.iter()
|
|
||||||
.find(|type_| type_.cname == cname);
|
|
||||||
|
|
||||||
for mapping in types {
|
for mapping in types {
|
||||||
let Some(class) = typespec.classes.iter().find(|class| class.name == mapping.cname) else {
|
let Some(class) = typespec
|
||||||
|
.classes
|
||||||
|
.iter()
|
||||||
|
.find(|class| class.name == mapping.cname)
|
||||||
|
else {
|
||||||
continue
|
continue
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut properties = Vec::<&Property>::new();
|
let mut properties = Vec::<&Property>::new();
|
||||||
let mut functions = Vec::<&Function>::new();
|
let mut functions = Vec::<&Function>::new();
|
||||||
|
let mut signals = Vec::<&Signal>::new();
|
||||||
|
|
||||||
// the first superclass availible from QML
|
// the first superclass availible from QML
|
||||||
let mut superclass = &class.superclass;
|
let mut superclass = &class.superclass;
|
||||||
|
@ -29,12 +40,16 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result<HashMap
|
||||||
break outform::Type::resolve(type_.module.as_ref().map(|v| v as &str), &type_.name)
|
break outform::Type::resolve(type_.module.as_ref().map(|v| v as &str), &type_.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
let superctype = typespec.classes.iter().find(|class| &class.name == superclass);
|
let superctype = typespec
|
||||||
|
.classes
|
||||||
|
.iter()
|
||||||
|
.find(|class| &class.name == superclass);
|
||||||
|
|
||||||
match superctype {
|
match superctype {
|
||||||
Some(superctype) => {
|
Some(superctype) => {
|
||||||
properties.extend(superctype.properties.iter());
|
properties.extend(superctype.properties.iter());
|
||||||
functions.extend(superctype.functions.iter());
|
functions.extend(superctype.functions.iter());
|
||||||
|
signals.extend(superctype.signals.iter());
|
||||||
superclass = &superctype.superclass;
|
superclass = &superctype.superclass;
|
||||||
},
|
},
|
||||||
None => break outform::Type::unknown(),
|
None => break outform::Type::unknown(),
|
||||||
|
@ -42,19 +57,23 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result<HashMap
|
||||||
};
|
};
|
||||||
|
|
||||||
fn qmlparamtype(ctype: &str, typespec: &TypeSpec) -> outform::Type {
|
fn qmlparamtype(ctype: &str, typespec: &TypeSpec) -> outform::Type {
|
||||||
let qtype = typespec.typemap
|
let qtype = typespec
|
||||||
|
.typemap
|
||||||
.iter()
|
.iter()
|
||||||
.find(|type_| &type_.cname == ctype)
|
.find(|type_| &type_.cname == ctype)
|
||||||
.map(|type_| (&type_.module, &type_.name))
|
.map(|type_| (&type_.module, &type_.name))
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
typespec.enums
|
typespec
|
||||||
|
.enums
|
||||||
.iter()
|
.iter()
|
||||||
.find(|type_| type_.cname.as_ref().map(|v| v as &str) == Some(ctype))
|
.find(|type_| type_.cname.as_ref().map(|v| v as &str) == Some(ctype))
|
||||||
.map(|type_| (&type_.module, &type_.name))
|
.map(|type_| (&type_.module, &type_.name))
|
||||||
});
|
});
|
||||||
|
|
||||||
match qtype {
|
match qtype {
|
||||||
Some((module, name)) => outform::Type::resolve(module.as_ref().map(|v| v as &str), &name),
|
Some((module, name)) => {
|
||||||
|
outform::Type::resolve(module.as_ref().map(|v| v as &str), &name)
|
||||||
|
},
|
||||||
None => outform::Type::unknown(),
|
None => outform::Type::unknown(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,15 +97,16 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result<HashMap
|
||||||
flags
|
flags
|
||||||
};
|
};
|
||||||
|
|
||||||
let gadget = typespec.gadgets.iter()
|
let gadget = typespec.gadgets.iter().find(|gadget| gadget.cname == ctype);
|
||||||
.find(|gadget| gadget.cname == ctype);
|
|
||||||
|
|
||||||
match gadget {
|
match gadget {
|
||||||
Some(gadget) => outform::Property {
|
Some(gadget) => outform::Property {
|
||||||
type_: PropertyType::Gadget(
|
type_: PropertyType::Gadget(
|
||||||
gadget.properties.iter()
|
gadget
|
||||||
|
.properties
|
||||||
|
.iter()
|
||||||
.map(|prop| (prop.name.clone(), solveprop(prop, typespec).type_))
|
.map(|prop| (prop.name.clone(), solveprop(prop, typespec).type_))
|
||||||
.collect()
|
.collect(),
|
||||||
),
|
),
|
||||||
details: prop.details.clone(),
|
details: prop.details.clone(),
|
||||||
flags,
|
flags,
|
||||||
|
@ -131,7 +151,23 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result<HashMap
|
||||||
ret: qmlparamtype(&func.ret, typespec),
|
ret: qmlparamtype(&func.ret, typespec),
|
||||||
name: func.name.clone(),
|
name: func.name.clone(),
|
||||||
details: func.details.clone(),
|
details: func.details.clone(),
|
||||||
params: func.params.iter().map(|FnParam { type_, name }| (name.clone(), qmlparamtype(type_, typespec))).collect(),
|
params: func
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.map(|FnParam { type_, name }| (name.clone(), qmlparamtype(type_, typespec)))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solvesignal(func: &Signal, typespec: &TypeSpec) -> outform::Signal {
|
||||||
|
outform::Signal {
|
||||||
|
name: func.name.clone(),
|
||||||
|
details: func.details.clone(),
|
||||||
|
params: func
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.map(|FnParam { type_, name }| (name.clone(), qmlparamtype(type_, typespec)))
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,15 +177,23 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result<HashMap
|
||||||
functions.extend(class.functions.iter());
|
functions.extend(class.functions.iter());
|
||||||
functions.sort_by(|a, b| Ord::cmp(&a.name, &b.name));
|
functions.sort_by(|a, b| Ord::cmp(&a.name, &b.name));
|
||||||
|
|
||||||
let properties = properties.iter().map(|prop| (
|
signals.extend(class.signals.iter());
|
||||||
prop.name.clone(),
|
signals.sort_by(|a, b| Ord::cmp(&a.name, &b.name));
|
||||||
solveprop(prop, &typespec)
|
|
||||||
)).collect::<HashMap<_, _>>();
|
|
||||||
|
|
||||||
let functions = functions.iter().map(|func| (
|
let properties = properties
|
||||||
func.name.clone(),
|
.iter()
|
||||||
solvefunc(func, &typespec)
|
.map(|prop| (prop.name.clone(), solveprop(prop, &typespec)))
|
||||||
)).collect::<HashMap<_, _>>();
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
let functions = functions
|
||||||
|
.iter()
|
||||||
|
.map(|func| (func.name.clone(), solvefunc(func, &typespec)))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
|
let signals = signals
|
||||||
|
.iter()
|
||||||
|
.map(|signal| (signal.name.clone(), solvesignal(signal, &typespec)))
|
||||||
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
let type_ = outform::ClassInfo {
|
let type_ = outform::ClassInfo {
|
||||||
superclass,
|
superclass,
|
||||||
|
@ -168,6 +212,7 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result<HashMap
|
||||||
},
|
},
|
||||||
properties,
|
properties,
|
||||||
functions,
|
functions,
|
||||||
|
signals,
|
||||||
};
|
};
|
||||||
|
|
||||||
outtypes.insert(mapping.name.clone(), outform::TypeInfo::Class(type_));
|
outtypes.insert(mapping.name.clone(), outform::TypeInfo::Class(type_));
|
||||||
|
@ -175,16 +220,22 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result<HashMap
|
||||||
|
|
||||||
for enum_ in typespec.enums {
|
for enum_ in typespec.enums {
|
||||||
if enum_.module.as_ref().map(|v| v as &str) == Some(module) {
|
if enum_.module.as_ref().map(|v| v as &str) == Some(module) {
|
||||||
outtypes.insert(enum_.name, outform::TypeInfo::Enum(outform::EnumInfo {
|
outtypes.insert(
|
||||||
|
enum_.name,
|
||||||
|
outform::TypeInfo::Enum(outform::EnumInfo {
|
||||||
description: enum_.description,
|
description: enum_.description,
|
||||||
details: enum_.details,
|
details: enum_.details,
|
||||||
variants: enum_.varaints.into_iter().map(|variant| (
|
variants: enum_
|
||||||
variant.name,
|
.varaints
|
||||||
outform::Variant {
|
.into_iter()
|
||||||
|
.map(|variant| {
|
||||||
|
(variant.name, outform::Variant {
|
||||||
details: variant.details,
|
details: variant.details,
|
||||||
},
|
})
|
||||||
)).collect(),
|
})
|
||||||
}));
|
.collect(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ pub struct Class {
|
||||||
pub uncreatable: bool,
|
pub uncreatable: bool,
|
||||||
pub properties: Vec<Property>,
|
pub properties: Vec<Property>,
|
||||||
pub functions: Vec<Function>,
|
pub functions: Vec<Function>,
|
||||||
|
pub signals: Vec<Signal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
@ -61,7 +62,14 @@ pub struct Function {
|
||||||
pub ret: String,
|
pub ret: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub details: Option<String>,
|
pub details: Option<String>,
|
||||||
pub params: Vec<FnParam>
|
pub params: Vec<FnParam>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Signal {
|
||||||
|
pub name: String,
|
||||||
|
pub details: Option<String>,
|
||||||
|
pub params: Vec<FnParam>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
|
Loading…
Reference in a new issue