gdnative_doc/documentation/
mod.rs1mod builder;
4mod helpers;
5
6use crate::Error;
7use helpers::*;
8use std::{collections::HashMap, path::PathBuf};
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
12pub enum ParameterAttribute {
13 None,
15 Opt,
17}
18
19#[derive(Clone, Debug, PartialEq, Eq, Hash)]
21pub enum Type {
22 Option(String),
24 Named(String),
26 Unit,
28}
29
30#[derive(Clone, Debug, PartialEq, Eq, Hash)]
32pub struct Method {
33 pub has_self: bool,
35 pub name: String,
37 pub self_type: String,
39 pub parameters: Vec<(String, Type, ParameterAttribute)>,
46 pub return_type: Type,
48 pub documentation: String,
53 pub file: PathBuf,
55}
56
57#[derive(Clone, Debug, PartialEq, Eq, Hash)]
79pub struct Property {
80 pub name: String,
82 pub typ: Type,
84 pub documentation: String,
86}
87
88#[derive(Clone, Debug, PartialEq, Eq, Hash)]
93pub struct GdnativeClass {
94 pub name: String,
96 pub inherit: String,
98 pub documentation: String,
100 pub properties: Vec<Property>,
102 pub methods: Vec<Method>,
108 pub file: PathBuf,
110}
111
112#[derive(Clone, Debug, PartialEq, Eq)]
114pub struct Documentation {
115 pub name: String,
117 pub root_file: PathBuf,
119 pub root_documentation: String,
121 pub classes: HashMap<String, GdnativeClass>,
125}
126
127impl Documentation {
128 pub(crate) fn from_root_file(name: String, root_file: PathBuf) -> Result<Self, Error> {
129 use syn::visit::Visit;
130
131 let root_file_content = read_file_at(&root_file)?;
132 let mut builder = builder::DocumentationBuilder {
133 documentation: Self {
134 name,
135 root_file: root_file.clone(),
136 root_documentation: String::new(),
137 classes: HashMap::new(),
138 },
139 current_file: (root_file, true),
140 current_module: Vec::new(),
141 error: None,
142 };
143 let root_documentation = get_docs(&root_file_content.attrs);
144 for item in root_file_content.items {
145 builder.visit_item(&item);
146 if let Some(error) = builder.error.take() {
147 return Err(error);
148 }
149 }
150 builder.documentation.root_documentation = root_documentation;
151 Ok(builder.documentation)
152 }
153}
154
155impl GdnativeClass {
156 fn add_method(&mut self, method: &syn::ImplItemMethod, file: PathBuf) {
158 let syn::ImplItemMethod {
159 vis, attrs, sig, ..
160 } = method;
161
162 if !matches!(vis, syn::Visibility::Public(_)) {
164 return;
165 }
166 if !(attributes_contains(attrs, "method") || sig.ident == "new") {
168 return;
169 }
170
171 let has_self = sig.receiver().is_some();
172 let syn::Signature {
173 ident: method_name,
174 inputs,
175 output,
176 ..
177 } = sig;
178
179 let mut parameters = inputs.into_iter();
180 parameters.next();
183 let parameters = {
184 let mut params = Vec::new();
185 for arg in parameters {
186 if let syn::FnArg::Typed(syn::PatType { attrs, pat, ty, .. }) = arg {
187 let arg_name = {
188 if let syn::Pat::Ident(syn::PatIdent { ident, .. }) = pat.as_ref() {
189 ident.to_string()
190 } else {
191 String::new()
192 }
193 };
194
195 params.push((
196 arg_name,
197 get_type_name(ty).unwrap_or_else(|| Type::Named("{ERROR}".to_string())),
198 if attributes_contains(attrs, "opt") {
199 ParameterAttribute::Opt
200 } else {
201 ParameterAttribute::None
202 },
203 ))
204 }
205 }
206 params
207 };
208
209 let return_type = match output {
210 syn::ReturnType::Default => Type::Unit,
211 syn::ReturnType::Type(_, typ) => get_type_name(typ).unwrap_or(Type::Unit),
212 };
213 log::trace!(
214 "added method {}: parameters = {:?}, return = {:?}",
215 method_name,
216 parameters,
217 return_type
218 );
219 self.methods.push(Method {
220 has_self,
221 name: method_name.to_string(),
222 self_type: self.name.clone(),
223 parameters,
224 return_type,
225 documentation: get_docs(attrs),
226 file,
227 })
228 }
229
230 fn get_properties(&mut self, fields: &syn::FieldsNamed) {
232 for field in &fields.named {
233 if attributes_contains(&field.attrs, "property") {
234 let property = Property {
235 name: field
236 .ident
237 .as_ref()
238 .map(|ident| ident.to_string())
239 .unwrap_or_default(),
240 typ: get_type_name(&field.ty).unwrap_or(Type::Unit),
242 documentation: get_docs(&field.attrs),
243 };
244 log::trace!(
245 "added property '{}' of type {:?}",
246 property.name,
247 property.typ
248 );
249 self.properties.push(property)
250 }
251 }
252 }
253}