diff --git a/layouts/shortcodes/qmltype.html b/layouts/shortcodes/qmltype.html
index b6ed8c8..fa5718d 100644
--- a/layouts/shortcodes/qmltype.html
+++ b/layouts/shortcodes/qmltype.html
@@ -98,6 +98,21 @@
{{- end -}}
+{{- if $type.signals -}}
+
Signals
+
+ {{- range $signame, $sig := $type.signals -}}
+ -
+
+ {{ $signame }}(
+ {{- partial "qmlparams.html" $sig.params -}}
+ )
+
+
+ {{- end -}}
+
+{{- end -}}
+
{{- if $type.variants -}}
Variants
@@ -186,6 +201,34 @@
{{- end -}}
{{- end -}}
+{{- if $type.signals -}}
+ Signal Details
+ {{ range $signame, $sig := $type.signals }}
+
+ {{- if $sig.flags -}}
+
+ {{ partial "qmltypeflags.html" $sig.flags }}
+
+ {{- end -}}
+
+
+ {{ $signame -}}
+ (
+ {{- partial "qmlparams.html" $sig.params -}}
+ )
+
+
+
+
+ {{- if $sig.details -}}
+ {{- $sig.details | $.Page.RenderString (dict "display" "block") -}}
+ {{- else -}}
+
No details provided.
+ {{- end -}}
+
+ {{- end -}}
+{{- end -}}
+
{{- if $type.variants -}}
Variant Details
{{ range $name, $variant := $type.variants }}
diff --git a/typegen/src/main.rs b/typegen/src/main.rs
index b5c6dbb..3e02e94 100644
--- a/typegen/src/main.rs
+++ b/typegen/src/main.rs
@@ -2,10 +2,10 @@ use std::{collections::HashMap, path::Path};
use anyhow::{anyhow, Context};
-mod parse;
-mod typespec;
mod outform;
+mod parse;
mod resolver;
+mod typespec;
fn main() -> anyhow::Result<()> {
let args = std::env::args().collect::>();
@@ -19,10 +19,17 @@ fn main() -> anyhow::Result<()> {
let text = std::fs::read_to_string(path).expect("failed to read module file");
let module = parse::parse_module(&text)?;
- let texts = module.header.headers.iter()
+ let texts = module
+ .header
+ .headers
+ .iter()
.map(|header| {
- let text = std::fs::read_to_string(dir.join(header))
- .with_context(|| format!("failed to read module header `{header}` at {:?}", dir.join(header)))?;
+ let text = std::fs::read_to_string(dir.join(header)).with_context(|| {
+ format!(
+ "failed to read module header `{header}` at {:?}",
+ dir.join(header)
+ )
+ })?;
Ok::<_, anyhow::Error>((header, text))
})
@@ -30,9 +37,11 @@ fn main() -> anyhow::Result<()> {
let parser = parse::Parser::new();
let mut ctx = parse::ParseContext::default();
- texts.iter()
+ texts
+ .iter()
.map(|(header, text)| {
- parser.parse(&text, &mut ctx)
+ parser
+ .parse(&text, &mut ctx)
.with_context(|| format!("while parsing module header `{header}`"))
})
.collect::>()?;
@@ -41,8 +50,7 @@ fn main() -> anyhow::Result<()> {
let text = serde_json::to_string_pretty(&typespec).unwrap();
- std::fs::write(outpath, text)
- .context("saving typespec")?;
+ std::fs::write(outpath, text).context("saving typespec")?;
},
Some("gendocs") => {
let modinfo = args.get(2).expect("expected module file");
@@ -77,18 +85,24 @@ fn main() -> anyhow::Result<()> {
for (name, info) in types {
let json = serde_json::to_string_pretty(&info).unwrap();
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}\"
hidetitle = true
+++
{{{{< qmltype module=\"{module}\" type=\"{name}\" >}}}}
-", name = name, module = module.header.name);
+",
+ name = name,
+ module = module.header.name
+ );
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 {
@@ -98,17 +112,22 @@ hidetitle = true
let datapath = datapath.join("index.json");
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}\"
+++
{{{{< qmlmodule module=\"{name}\" >}}}}
-", name = module.header.name);
+",
+ name = module.header.name
+ );
- let templatepath = templatepath.join(format!("_index.md"));
- std::fs::write(&templatepath, template).with_context(|| format!("while writing {templatepath:?}"))?;
+ let templatepath = templatepath.join(format!("_index.md"));
+ std::fs::write(&templatepath, template)
+ .with_context(|| format!("while writing {templatepath:?}"))?;
},
_ => {
panic!("typegen invoked without mode");
diff --git a/typegen/src/outform.rs b/typegen/src/outform.rs
index be7f643..8d171b1 100644
--- a/typegen/src/outform.rs
+++ b/typegen/src/outform.rs
@@ -26,6 +26,7 @@ pub struct ClassInfo {
pub flags: Vec,
pub properties: HashMap,
pub functions: HashMap,
+ pub signals: HashMap,
}
#[derive(Debug, Serialize)]
@@ -53,6 +54,13 @@ pub struct Function {
pub params: HashMap,
}
+#[derive(Debug, Serialize)]
+pub struct Signal {
+ pub name: String,
+ pub details: Option,
+ pub params: HashMap,
+}
+
#[derive(Debug, Serialize)]
pub struct EnumInfo {
pub description: Option,
diff --git a/typegen/src/parse.rs b/typegen/src/parse.rs
index 19bd59e..f27880b 100644
--- a/typegen/src/parse.rs
+++ b/typegen/src/parse.rs
@@ -27,13 +27,10 @@ pub fn parse_module(text: &str) -> anyhow::Result {
header = header.trim();
details = details.trim();
- let header = toml::from_str::(header)
- .context("parsing module info header")?;
+ let header =
+ toml::from_str::(header).context("parsing module info header")?;
- Ok(ModuleInfo {
- header,
- details,
- })
+ Ok(ModuleInfo { header, details })
}
#[derive(Debug)]
@@ -47,6 +44,7 @@ pub struct ClassInfo<'a> {
pub comment: Option<&'a str>,
pub properties: Vec>,
pub invokables: Vec>,
+ pub signals: Vec>,
}
#[derive(Debug)]
@@ -73,6 +71,13 @@ pub struct Invokable<'a> {
pub params: Vec>,
}
+#[derive(Debug, Clone)]
+pub struct Signal<'a> {
+ pub name: &'a str,
+ pub comment: Option<&'a str>,
+ pub params: Vec>,
+}
+
#[derive(Debug, Clone, Copy)]
pub struct InvokableParam<'a> {
pub name: &'a str,
@@ -98,6 +103,7 @@ pub struct Parser {
pub class_regex: Regex,
pub macro_regex: Regex,
pub property_regex: Regex,
+ pub signals_regex: Regex,
pub fn_regex: Regex,
pub fn_param_regex: Regex,
pub defaultprop_classinfo_regex: Regex,
@@ -126,15 +132,20 @@ impl Parser {
class_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*class\s+(?\w+)(?:\s*:\s*public\s+(?\w+))?.+?\{(?[\s\S]*?)};"#).unwrap(),
macro_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*(?(Q|QML)_\w+)\s*(\(\s*(?.*)\s*\))?;"#).unwrap(),
property_regex: Regex::new(r#"^\s*(?(\w|::|<|>)+\*?)\s+(?\w+)(\s+(MEMBER\s+(?\w+)|READ\s+(?\w+)|WRITE\s+(?\w+)|NOTIFY\s+(?\w+)|(?CONSTANT)))+\s*$"#).unwrap(),
- fn_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*Q_INVOKABLE\s+(?(\w|::|<|>)+\*?)\s+(?\w+)\((?[\s\S]*?)\);"#).unwrap(),
+ fn_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*(?Q_INVOKABLE)?\s+(?(\w|::|<|>)+\*?)\s+(?\w+)\((?[\s\S]*?)\);"#).unwrap(),
fn_param_regex: Regex::new(r#"(?(\w|::|<|>)+\*?)\s+(?\w+)(,|$)"#).unwrap(),
+ signals_regex: Regex::new(r#"signals:(?(\s*(\s*///.*\s*)*void .*;)*)"#).unwrap(),
defaultprop_classinfo_regex: Regex::new(r#"^\s*"DefaultProperty", "(?.+)"\s*$"#).unwrap(),
enum_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*namespace (?\w+)\s*\{[\s\S]*?(QML_ELEMENT|QML_NAMED_ELEMENT\((?\w+)\));[\s\S]*?enum\s*(?\w+)\s*\{(?[\s\S]*?)\};[\s\S]*?\}"#).unwrap(),
enum_variant_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*(?\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) {
let comment = class.name("comment").map(|m| m.as_str());
let name = class.name("name").unwrap().as_str();
@@ -148,6 +159,8 @@ impl Parser {
let mut properties = Vec::new();
let mut default_property = None;
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) {
@@ -160,18 +173,30 @@ impl Parser {
"Q_OBJECT" => classtype = Some(ClassType::Object),
"Q_GADGET" => classtype = Some(ClassType::Gadget),
"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_UNCREATABLE" => uncreatable = true,
"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"))?;
+ 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"))?;
let member = prop.name("member").is_some();
let read = prop.name("read").is_some();
let write = prop.name("write").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 {
type_: prop.name("type").unwrap().as_str(),
name: prop.name("name").unwrap().as_str(),
@@ -182,7 +207,9 @@ impl Parser {
});
},
"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 {
let prop = classinfo.name("prop").unwrap().as_str();
@@ -192,10 +219,26 @@ impl Parser {
_ => {},
}
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) {
+ if invokable.name("invokable").is_none() {
+ continue;
+ }
+
let comment = invokable.name("comment").map(|m| m.as_str());
let type_ = invokable.name("type").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 name = param.name("name").unwrap().as_str();
- params.push(InvokableParam {
- type_,
- name,
- });
+ params.push(InvokableParam { type_, name });
}
invokables.push(Invokable {
@@ -221,15 +261,47 @@ impl Parser {
});
}
- 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}`"))?;
+ for signal_set in self.signals_regex.captures_iter(body) {
+ let signals_body = signal_set.name("signals").unwrap().as_str();
- 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>(())
- })().with_context(|| format!("while parsing class `{name}`"))?;
+ })()
+ .with_context(|| format!("while parsing class `{name}`"))?;
let Some(type_) = classtype else { continue };
@@ -243,6 +315,7 @@ impl Parser {
comment,
properties,
invokables,
+ signals,
});
}
@@ -254,7 +327,10 @@ impl Parser {
let comment = enum_.name("comment").map(|m| m.as_str());
let namespace = enum_.name("namespace").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 mut variants = Vec::new();
@@ -263,10 +339,7 @@ impl Parser {
let comment = variant.name("comment").map(|m| m.as_str());
let name = variant.name("name").unwrap().as_str();
- variants.push(Variant {
- name,
- comment,
- });
+ variants.push(Variant { name, comment });
}
ctx.enums.push(EnumInfo {
@@ -292,51 +365,72 @@ impl Parser {
impl ParseContext<'_> {
pub fn gen_typespec(&self, module: &str) -> typespec::TypeSpec {
typespec::TypeSpec {
- typemap: self.classes.iter().filter_map(|class| {
- Some(typespec::QmlTypeMapping {
- // filters gadgets
- name: class.qml_name?.to_string(),
- cname: class.name.to_string(),
- module: Some(module.to_string()),
+ typemap: self
+ .classes
+ .iter()
+ .filter_map(|class| {
+ Some(typespec::QmlTypeMapping {
+ // filters gadgets
+ name: class.qml_name?.to_string(),
+ cname: class.name.to_string(),
+ module: Some(module.to_string()),
+ })
})
- }).collect(),
- classes: self.classes.iter().filter_map(|class| {
- let (description, details) = class.comment.map(parse_details_desc)
- .unwrap_or((None, None));
+ .collect(),
+ classes: self
+ .classes
+ .iter()
+ .filter_map(|class| {
+ let (description, details) = class
+ .comment
+ .map(parse_details_desc)
+ .unwrap_or((None, None));
- Some(typespec::Class {
- name: class.name.to_string(),
- module: module.to_string(),
- description,
- details,
- // filters gadgets
- superclass: class.superclass?.to_string(),
- singleton: class.singleton,
- uncreatable: class.uncreatable,
- properties: class.properties.iter().map(|p| (*p).into()).collect(),
- functions: class.invokables.iter().map(|f| f.as_typespec()).collect(),
+ Some(typespec::Class {
+ name: class.name.to_string(),
+ module: module.to_string(),
+ description,
+ details,
+ // filters gadgets
+ superclass: class.superclass?.to_string(),
+ singleton: class.singleton,
+ uncreatable: class.uncreatable,
+ properties: class.properties.iter().map(|p| (*p).into()).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_ {
- ClassType::Gadget => Some(typespec::Gadget {
- cname: class.name.to_string(),
- properties: class.properties.iter().map(|p| (*p).into()).collect(),
- }),
- _ => None,
- }).collect(),
- enums: self.enums.iter().map(|enum_| {
- let (description, details) = enum_.comment.map(parse_details_desc)
- .unwrap_or((None, None));
+ .collect(),
+ gadgets: self
+ .classes
+ .iter()
+ .filter_map(|class| match class.type_ {
+ ClassType::Gadget => Some(typespec::Gadget {
+ cname: class.name.to_string(),
+ properties: class.properties.iter().map(|p| (*p).into()).collect(),
+ }),
+ _ => None,
+ })
+ .collect(),
+ enums: self
+ .enums
+ .iter()
+ .map(|enum_| {
+ let (description, details) = enum_
+ .comment
+ .map(parse_details_desc)
+ .unwrap_or((None, None));
- typespec::Enum {
- name: enum_.qml_name.to_string(),
- module: Some(module.to_string()),
- cname: Some(format!("{}::{}", enum_.namespace, enum_.enum_name)),
- description,
- details,
- varaints: enum_.variants.iter().map(|v| (*v).into()).collect(),
- }
- }).collect(),
+ typespec::Enum {
+ name: enum_.qml_name.to_string(),
+ module: Some(module.to_string()),
+ cname: Some(format!("{}::{}", enum_.namespace, enum_.enum_name)),
+ description,
+ details,
+ varaints: enum_.variants.iter().map(|v| (*v).into()).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> for typespec::FnParam {
fn from(value: InvokableParam<'_>) -> Self {
Self {
@@ -387,45 +491,44 @@ fn parse_details(text: &str) -> String {
let mut seen_content = false;
let mut callout = false;
- let mut str = text.lines()
- .map(|line| {
+ let mut str = text
+ .lines()
+ .map(|line| {
line.trim()
.strip_prefix("///")
.map(|line| line.strip_prefix(' ').unwrap_or(line))
.unwrap_or(line)
})
- .filter(|line| {
+ .filter(|line| {
let any = !line.is_empty();
let filter = any || seen_content;
seen_content |= any;
filter
})
- .map(|line| {
- match callout {
- true => {
- if line.starts_with('>') {
- Cow::Borrowed(line[1..].strip_prefix(' ').unwrap_or(&line[1..]))
- } else {
- callout = false;
- Cow::Owned(format!("{{{{< /callout >}}}}\n{line}"))
+ .map(|line| match callout {
+ true => {
+ if line.starts_with('>') {
+ Cow::Borrowed(line[1..].strip_prefix(' ').unwrap_or(&line[1..]))
+ } else {
+ callout = false;
+ Cow::Owned(format!("{{{{< /callout >}}}}\n{line}"))
+ }
+ },
+ false => {
+ if line.starts_with("> [!") {
+ let code = line[4..].split_once(']');
+
+ if let Some((code, line)) = code {
+ let code = code.to_lowercase();
+ callout = true;
+ return Cow::Owned(format!("{{{{< callout type=\"{code}\" >}}}}\n{line}"))
}
}
- false => {
- if line.starts_with("> [!") {
- let code = line[4..].split_once(']');
- if let Some((code, line)) = code {
- let code = code.to_lowercase();
- callout = true;
- return Cow::Owned(format!("{{{{< callout type=\"{code}\" >}}}}\n{line}"))
- }
- }
-
- 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");
if callout {
str += "\n{{< /callout >}}";
@@ -438,8 +541,19 @@ fn parse_details_desc(text: &str) -> (Option, Option) {
let details = parse_details(text);
if details.starts_with('!') {
match details[1..].split_once('\n') {
- Some((desc, details)) => (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),
+ Some((desc, details)) => (
+ 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 {
(None, Some(details))
diff --git a/typegen/src/resolver.rs b/typegen/src/resolver.rs
index 352c9ec..fab29d2 100644
--- a/typegen/src/resolver.rs
+++ b/typegen/src/resolver.rs
@@ -1,24 +1,35 @@
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> {
+pub fn resolve_types(
+ module: &str,
+ typespec: TypeSpec,
+) -> anyhow::Result> {
let mut outtypes = HashMap::new();
- let types = typespec.typemap.iter()
- .filter(|type_| type_.module.as_ref().map(|v| v as &str) == Some(module));
-
- let findqmltype = |cname: &str| typespec.typemap
+ let types = typespec
+ .typemap
.iter()
- .find(|type_| type_.cname == cname);
+ .filter(|type_| type_.module.as_ref().map(|v| v as &str) == Some(module));
+
+ let findqmltype = |cname: &str| typespec.typemap.iter().find(|type_| type_.cname == cname);
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
};
let mut properties = Vec::<&Property>::new();
let mut functions = Vec::<&Function>::new();
+ let mut signals = Vec::<&Signal>::new();
// the first superclass availible from QML
let mut superclass = &class.superclass;
@@ -29,12 +40,16 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result {
properties.extend(superctype.properties.iter());
functions.extend(superctype.functions.iter());
+ signals.extend(superctype.signals.iter());
superclass = &superctype.superclass;
},
None => break outform::Type::unknown(),
@@ -42,19 +57,23 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result outform::Type {
- let qtype = typespec.typemap
+ let qtype = typespec
+ .typemap
.iter()
.find(|type_| &type_.cname == ctype)
.map(|type_| (&type_.module, &type_.name))
.or_else(|| {
- typespec.enums
+ typespec
+ .enums
.iter()
.find(|type_| type_.cname.as_ref().map(|v| v as &str) == Some(ctype))
.map(|type_| (&type_.module, &type_.name))
});
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(),
}
}
@@ -78,15 +97,16 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result outform::Property {
type_: PropertyType::Gadget(
- gadget.properties.iter()
+ gadget
+ .properties
+ .iter()
.map(|prop| (prop.name.clone(), solveprop(prop, typespec).type_))
- .collect()
+ .collect(),
),
details: prop.details.clone(),
flags,
@@ -131,7 +151,23 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result 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>();
+ signals.extend(class.signals.iter());
+ signals.sort_by(|a, b| Ord::cmp(&a.name, &b.name));
- let functions = functions.iter().map(|func| (
- func.name.clone(),
- solvefunc(func, &typespec)
- )).collect::>();
+ let properties = properties
+ .iter()
+ .map(|prop| (prop.name.clone(), solveprop(prop, &typespec)))
+ .collect::>();
+
+ let functions = functions
+ .iter()
+ .map(|func| (func.name.clone(), solvefunc(func, &typespec)))
+ .collect::>();
+
+ let signals = signals
+ .iter()
+ .map(|signal| (signal.name.clone(), solvesignal(signal, &typespec)))
+ .collect::>();
let type_ = outform::ClassInfo {
superclass,
@@ -168,6 +212,7 @@ pub fn resolve_types(module: &str, typespec: TypeSpec) -> anyhow::Result anyhow::Result,
pub functions: Vec,
+ pub signals: Vec,
}
#[derive(Debug, Serialize, Deserialize)]
@@ -61,7 +62,14 @@ pub struct Function {
pub ret: String,
pub name: String,
pub details: Option,
- pub params: Vec
+ pub params: Vec,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct Signal {
+ pub name: String,
+ pub details: Option,
+ pub params: Vec,
}
#[derive(Debug, Serialize, Deserialize)]