Skip to content

Commit 888ec43

Browse files
authored
Documentation generation hotfixes (#130)
* Fixed field deduping & improperly escaped names * Fixed some docs & logging * Removed an alloc * Removed unused import
1 parent 311e065 commit 888ec43

File tree

1 file changed

+54
-1
lines changed
  • crates/languages/bevy_mod_scripting_lua/src

1 file changed

+54
-1
lines changed

crates/languages/bevy_mod_scripting_lua/src/docs.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
use core::str;
12
use std::{
3+
borrow::Cow,
24
env,
35
fs::{self, File},
46
io::Write,
7+
ops::Deref,
58
process::Command,
69
};
710

811
//use bevy::asset::FileAssetIo;
912
use bevy::asset::io::file::FileAssetReader;
1013
use bevy_mod_scripting_core::prelude::*;
11-
use tealr::{TypeGenerator, TypeWalker};
14+
use tealr::{NameContainer, TypeGenerator, TypeWalker};
1215

1316
pub type TypeWalkerBuilder = fn(TypeWalker) -> TypeWalker;
1417

@@ -97,7 +100,24 @@ impl DocFragment for LuaDocFragment {
97100
// fixes bug in tealr which causes syntax errors in teal due to duplicate fields (from having both getters and setters)
98101
tw.given_types.iter_mut().for_each(|tg| {
99102
if let TypeGenerator::Record(rg) = tg {
103+
rg.fields
104+
.sort_by(|f1, f2| f1.name.deref().cmp(&f2.name.deref()));
100105
rg.fields.dedup_by(|a, b| a.name == b.name);
106+
rg.static_fields
107+
.sort_by(|f1, f2| f1.name.deref().cmp(&f2.name.deref()));
108+
rg.static_fields.dedup_by(|a, b| a.name == b.name);
109+
for field in rg.fields.iter_mut().chain(rg.static_fields.iter_mut()) {
110+
escape_name(&mut field.name);
111+
}
112+
for func in rg
113+
.functions
114+
.iter_mut()
115+
.chain(rg.mut_functions.iter_mut())
116+
.chain(rg.methods.iter_mut())
117+
.chain(rg.mut_methods.iter_mut())
118+
{
119+
escape_name(&mut func.name);
120+
}
101121
}
102122
});
103123

@@ -172,3 +192,36 @@ impl DocFragment for LuaDocFragment {
172192
Ok(())
173193
}
174194
}
195+
196+
/// Escapes a name of a table field, if that table field is a reserved keyword.
197+
///
198+
/// ## Background
199+
///
200+
/// String keys in a Lua table are allowed to be anything, even reserved
201+
/// keywords. By default when tealr generates the type definition for a table
202+
/// field, the string it generates is `{name} : {type}`. This causes a syntax
203+
/// error when writing a bare keyword, since `nil : {type}` is considered trying
204+
/// to add a type to the *value* nil (which is invalid).
205+
///
206+
/// To get around this tealr allows us to escape table fields using the
207+
/// `["{name}"] : {value}` syntax. This function detects if a name is one of the
208+
/// Lua reserved words and fixes it if so.
209+
fn escape_name(raw: &mut NameContainer) {
210+
// List of Lua reserved keywords
211+
const KEYWORD_FIELDS: &[&str] = &[
212+
"false", "true", "nil", // Values
213+
"and", "not", "or", // Operators
214+
"if", "then", "else", "elseif", "end", // If-Else
215+
"for", "in", "break", "do", "repeat", "until", "while", // Loops
216+
"function", "return", // Funcs
217+
"local", // Declarations
218+
"record", // Teal extra
219+
];
220+
let Ok(name) = str::from_utf8(&raw) else {
221+
return;
222+
};
223+
if KEYWORD_FIELDS.contains(&name) {
224+
let mapped = format!("[\"{name}\"]");
225+
*raw = NameContainer::from(Cow::Owned(mapped));
226+
}
227+
}

0 commit comments

Comments
 (0)