Skip to content

Commit 6421a43

Browse files
authored
use fully-qualified names in doc references (#58)
This allows e.g. `pdoc3` to turn them into the appropriate hyperlinks. Signed-off-by: Joel Dice <joel.dice@fermyon.com>
1 parent b1ad308 commit 6421a43

4 files changed

Lines changed: 88 additions & 25 deletions

File tree

src/command.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ pub struct Bindings {
7171
///
7272
/// This will be created if it does not already exist.
7373
pub output_dir: PathBuf,
74+
75+
/// Optional name of top-level module to use for bindings.
76+
///
77+
/// If this is not specified, the module name will be derived from the world name.
78+
#[arg(long)]
79+
pub world_module: Option<String>,
7480
}
7581

7682
pub fn run<T: Into<OsString> + Clone, I: IntoIterator<Item = T>>(args: I) -> Result<()> {
@@ -87,6 +93,7 @@ fn generate_bindings(common: Common, bindings: Bindings) -> Result<()> {
8793
.wit_path
8894
.unwrap_or_else(|| Path::new("wit").to_owned()),
8995
common.world.as_deref(),
96+
bindings.world_module.as_deref(),
9097
&bindings.output_dir,
9198
)
9299
}

src/lib.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,19 @@ impl Invoker for MyInvoker {
167167
}
168168
}
169169

170-
pub fn generate_bindings(wit_path: &Path, world: Option<&str>, output_dir: &Path) -> Result<()> {
170+
pub fn generate_bindings(
171+
wit_path: &Path,
172+
world: Option<&str>,
173+
world_module: Option<&str>,
174+
output_dir: &Path,
175+
) -> Result<()> {
171176
let (resolve, world) = parse_wit(wit_path, world)?;
172177
let summary = Summary::try_new(&resolve, world)?;
173-
let world_dir = output_dir.join(resolve.worlds[world].name.to_snake_case().escape());
178+
let world_name = resolve.worlds[world].name.to_snake_case().escape();
179+
let world_module = world_module.unwrap_or(&world_name);
180+
let world_dir = output_dir.join(world_module.replace('.', "/"));
174181
fs::create_dir_all(&world_dir)?;
175-
summary.generate_code(&world_dir, true)?;
182+
summary.generate_code(&world_dir, world_module, true)?;
176183

177184
Ok(())
178185
}
@@ -379,8 +386,6 @@ pub async fn componentize(
379386
.as_ref()
380387
.and_then(|(r, p, c)| c.bindings.as_deref().map(|f| (r, p, f)))
381388
{
382-
summary.generate_code(world_dir.path(), false)?;
383-
384389
let paths = python_path
385390
.iter()
386391
.enumerate()
@@ -401,18 +406,22 @@ pub async fn componentize(
401406
.filter_map(Result::transpose)
402407
.collect::<Result<Vec<_>>>()?;
403408

409+
let module = paths.first().unwrap().1.replace('/', ".");
410+
411+
summary.generate_code(world_dir.path(), &module, false)?;
412+
404413
(
405414
paths
406415
.iter()
407416
.map(|(index, p)| format!("{index}/{p}"))
408417
.collect::<Vec<_>>(),
409-
paths.first().unwrap().1.replace('/', "."),
418+
module,
410419
)
411420
} else {
412421
let module = resolve.worlds[world].name.to_snake_case();
413422
let world_dir = world_dir.path().join(&module);
414423
fs::create_dir_all(&world_dir)?;
415-
summary.generate_code(&world_dir, false)?;
424+
summary.generate_code(&world_dir, &module, false)?;
416425

417426
(vec!["world".to_owned()], module)
418427
};

src/python.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,14 @@ fn python_componentize(
2929

3030
#[pyo3::pyfunction]
3131
#[pyo3(name = "generate_bindings")]
32-
#[pyo3(signature = (wit_path, world, output_dir))]
32+
#[pyo3(signature = (wit_path, world, world_module, output_dir))]
3333
fn python_generate_bindings(
3434
wit_path: PathBuf,
3535
world: Option<&str>,
36+
world_module: Option<&str>,
3637
output_dir: PathBuf,
3738
) -> PyResult<()> {
38-
crate::generate_bindings(&wit_path, world, &output_dir)
39+
crate::generate_bindings(&wit_path, world, world_module, &output_dir)
3940
.map_err(|e| PyAssertionError::new_err(format!("{e:?}")))
4041
}
4142

src/summary.rs

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use {
22
crate::{
33
abi::{self, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS},
4-
bindgen::DISPATCHABLE_CORE_PARAM_COUNT,
4+
bindgen::{self, DISPATCHABLE_CORE_PARAM_COUNT},
55
exports::exports::{
66
self, Case, Constructor, Function, FunctionExport, LocalResource, OwnedKind, OwnedType,
77
RemoteResource, Resource, Static, Symbols,
@@ -700,6 +700,8 @@ impl<'a> Summary<'a> {
700700

701701
fn function_code(
702702
&self,
703+
direction: Direction,
704+
world_module: &str,
703705
function: &MyFunction,
704706
names: &mut TypeNames,
705707
seen: &HashSet<TypeId>,
@@ -733,6 +735,27 @@ impl<'a> Summary<'a> {
733735

734736
let mut type_name = |ty| names.type_name(ty, seen, if self_ { resource } else { None });
735737

738+
let absolute_type_name = |ty| {
739+
format!(
740+
"{world_module}.{}.{}",
741+
match direction {
742+
Direction::Import => "imports",
743+
Direction::Export => "exports",
744+
},
745+
TypeNames::new(self, TypeOwner::None).type_name(
746+
ty,
747+
&if let Type::Id(id) = ty {
748+
Some(bindgen::dealias(self.resolve, id))
749+
} else {
750+
None
751+
}
752+
.into_iter()
753+
.collect::<HashSet<_>>(),
754+
None
755+
)
756+
)
757+
};
758+
736759
let params = self_
737760
.then(|| "self".to_string())
738761
.into_iter()
@@ -767,7 +790,7 @@ impl<'a> Summary<'a> {
767790
[ty] => match special_return(*ty) {
768791
SpecialReturn::Result(result) => {
769792
let error = if let Some(ty) = result.err {
770-
Some(type_name(ty))
793+
Some(absolute_type_name(ty))
771794
} else {
772795
Some("None".into())
773796
};
@@ -944,7 +967,12 @@ impl<'a> Summary<'a> {
944967
sorted
945968
}
946969

947-
pub fn generate_code(&self, path: &Path, stub_runtime_calls: bool) -> Result<()> {
970+
pub fn generate_code(
971+
&self,
972+
path: &Path,
973+
world_module: &str,
974+
stub_runtime_calls: bool,
975+
) -> Result<()> {
948976
#[derive(Default)]
949977
struct Definitions<'a> {
950978
types: Vec<String>,
@@ -964,7 +992,10 @@ impl<'a> Summary<'a> {
964992
}
965993

966994
let docstring = |docs: Option<&str>, indent_level, error: Option<&str>| {
967-
let docs = match (docs, error.map(|e| format!("Raises: Err({e})"))) {
995+
let docs = match (
996+
docs,
997+
error.map(|e| format!("Raises: `{world_module}.types.Err({e})`")),
998+
) {
968999
(Some(docs), Some(error_docs)) => Some(format!("{docs}\n\n{error_docs}")),
9691000
(Some(docs), None) => Some(docs.to_owned()),
9701001
(None, Some(error_docs)) => Some(error_docs),
@@ -1070,20 +1101,14 @@ class {name}:
10701101
.collect::<Vec<_>>()
10711102
.join(", ");
10721103

1073-
let docs = if let Some(docs) = &ty.docs.contents {
1074-
docs.lines()
1075-
.map(|line| format!("# {line}\n"))
1076-
.collect::<Vec<_>>()
1077-
.concat()
1078-
} else {
1079-
String::new()
1080-
};
1104+
let docs = docstring(ty.docs.contents.as_deref(), 0, None);
10811105

10821106
Code::Shared(format!(
10831107
"
10841108
{classes}
10851109
1086-
{docs}{camel} = Union[{cases}]
1110+
{camel} = Union[{cases}]
1111+
{docs}
10871112
"
10881113
))
10891114
}
@@ -1156,7 +1181,14 @@ class {camel}(Flag):
11561181
static_method,
11571182
result_count,
11581183
error,
1159-
} = self.function_code(function, &mut names, &seen, Some(id));
1184+
} = self.function_code(
1185+
Direction::Import,
1186+
world_module,
1187+
function,
1188+
&mut names,
1189+
&seen,
1190+
Some(id),
1191+
);
11601192

11611193
let docs = docstring(function.docs, 2, error.as_deref());
11621194

@@ -1271,7 +1303,14 @@ class {camel}:
12711303
static_method,
12721304
error,
12731305
..
1274-
} = self.function_code(function, &mut names, &seen, Some(id));
1306+
} = self.function_code(
1307+
Direction::Export,
1308+
world_module,
1309+
function,
1310+
&mut names,
1311+
&seen,
1312+
Some(id),
1313+
);
12751314

12761315
let docs = docstring(function.docs, 2, error.as_deref());
12771316

@@ -1419,7 +1458,14 @@ class {camel}(Protocol):
14191458
result_count,
14201459
error,
14211460
..
1422-
} = self.function_code(function, &mut names, &seen, None);
1461+
} = self.function_code(
1462+
Direction::Import,
1463+
world_module,
1464+
function,
1465+
&mut names,
1466+
&seen,
1467+
None,
1468+
);
14231469

14241470
match function.kind {
14251471
FunctionKind::Import => {

0 commit comments

Comments
 (0)