Skip to content

Commit fbfaa38

Browse files
committed
Translate Godot's BBCode links to rustdoc intra-doc links
Handles the following: * [url=U]text[/url] * [url=U][/url] * [member M] * [member C.M] * [method M] * [method C.M] * [constant M] * [constant C.M] * [enum C]
1 parent b6f2dfe commit fbfaa38

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

bindings_generator/src/class_docs.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::{collections::HashMap, fs};
22

3+
use regex::{Captures, Regex};
34
use roxmltree::Node;
45

56
#[derive(Debug)]
@@ -130,6 +131,17 @@ impl GodotXmlDocs {
130131
);
131132
}
132133

134+
fn to_rust_type(godot_type: &str) -> &str {
135+
match godot_type {
136+
"String" => "GodotString",
137+
"Error" => "GodotError",
138+
"RID" => "Rid",
139+
"G6DOFJointAxisParam" => "G6dofJointAxisParam",
140+
"G6DOFJointAxisFlag" => "G6dofJointAxisFlag",
141+
_ => godot_type,
142+
}
143+
}
144+
133145
/// Takes the Godot documentation markup and transforms it to Rustdoc.
134146
/// Very basic approach with limitations, but already helps readability quite a bit.
135147
fn reformat_as_rustdoc(godot_doc: String) -> String {
@@ -139,6 +151,66 @@ impl GodotXmlDocs {
139151
""
140152
};
141153

154+
// TODO reuse regex across classes
155+
let url_regex = Regex::new("\\[url=(.+?)](.*?)\\[/url]").unwrap();
156+
157+
let type_regex = Regex::new("\\[enum ([A-Za-z0-9_]+?)]").unwrap();
158+
let self_member_regex =
159+
Regex::new("\\[(member|method|constant) ([A-Za-z0-9_]+?)]").unwrap();
160+
let class_member_regex =
161+
Regex::new("\\[(member|method|constant) ([A-Za-z0-9_]+?)\\.([A-Za-z0-9_]+?)]").unwrap();
162+
163+
// URLs
164+
let godot_doc = url_regex.replace_all(&godot_doc, |c: &Captures| {
165+
let url = &c[1];
166+
let text = &c[2];
167+
168+
if text.is_empty() {
169+
format!("<{url}>", url = url)
170+
} else {
171+
format!("[{text}]({url})", text = text, url = url)
172+
}
173+
});
174+
175+
// Note: we currently don't use c[1], which would be the "kind" (method/member/constant/...)
176+
// This one could be used to disambiguate the doc-link, e.g. [`{method}`][fn@Self::{method}]
177+
178+
// What currently doesn't work are "indexed properties" which are not also exposed as getters, e.g.
179+
// https://docs.godotengine.org/en/stable/classes/class_area2d.html#properties 'gravity_point'
180+
// This needs to be implemented first: https://github.com/godot-rust/godot-rust/issues/689
181+
182+
// TODO: [signal M]
183+
184+
// [Type] style
185+
let godot_doc = type_regex.replace_all(&godot_doc, |c: &Captures| {
186+
let godot_ty = &c[1];
187+
let rust_ty = Self::to_rust_type(godot_ty);
188+
189+
format!(
190+
"[`{godot_ty}`][{rust_ty}]",
191+
godot_ty = godot_ty,
192+
rust_ty = rust_ty
193+
)
194+
});
195+
196+
// [Type::member] style
197+
let godot_doc = class_member_regex.replace_all(&godot_doc, |c: &Captures| {
198+
let godot_ty = &c[2];
199+
let rust_ty = Self::to_rust_type(godot_ty);
200+
201+
format!(
202+
"[`{godot_ty}.{member}`][{rust_ty}::{member}]",
203+
godot_ty = godot_ty,
204+
rust_ty = rust_ty,
205+
member = &c[3]
206+
)
207+
});
208+
209+
// [member] style
210+
let godot_doc = self_member_regex.replace_all(&godot_doc, |c: &Captures| {
211+
format!("[`{member}`][Self::{member}]", member = &c[2])
212+
});
213+
142214
let translated = godot_doc
143215
.replace("[code]", "`")
144216
.replace("[/code]", "`")

0 commit comments

Comments
 (0)