Include backend comments in Python and Rust codegen

This is of limited usefulness at the moment, as it doesn't help consumers
of the public API.

Also removed detached comments from the included comments.
This commit is contained in:
Damien Elmes 2023-06-16 10:59:00 +10:00
parent 02a1c891a6
commit 81ac5a91ad
5 changed files with 38 additions and 15 deletions

1
Cargo.lock generated
View File

@ -202,6 +202,7 @@ dependencies = [
"anki_io",
"anyhow",
"inflections",
"itertools",
"num_enum",
"prost",
"prost-build",

View File

@ -13,6 +13,7 @@ rust-version.workspace = true
anki_io = { version = "0.0.0", path = "../io" }
anyhow = "1.0.71"
inflections = "1.1.1"
itertools = "0.10.5"
prost-build = "0.11.9"
prost-reflect = "0.11.4"
prost-types = "0.11.9"

View File

@ -16,6 +16,8 @@ use prost_reflect::MessageDescriptor;
use prost_reflect::MethodDescriptor;
use prost_reflect::ServiceDescriptor;
use crate::utils::Comments;
pub(crate) fn write_python_interface(pool: &DescriptorPool) -> Result<()> {
let output_path = Path::new("../../out/pylib/anki/_backend_generated.py");
create_dir_all(output_path.parent().unwrap())?;
@ -26,8 +28,9 @@ pub(crate) fn write_python_interface(pool: &DescriptorPool) -> Result<()> {
if service.name() == "AnkidroidService" {
continue;
}
let comments = Comments::from_file(service.parent_file().file_descriptor_proto());
for method in service.methods() {
render_method(&service, &method, &mut out);
render_method(&service, &method, &comments, &mut out);
}
}
@ -45,18 +48,24 @@ pub(crate) fn write_python_interface(pool: &DescriptorPool) -> Result<()> {
/// output = anki.generic_pb2.StringList()
/// output.ParseFromString(raw_bytes)
/// return output.vals
fn render_method(service: &ServiceDescriptor, method: &MethodDescriptor, out: &mut impl Write) {
fn render_method(
service: &ServiceDescriptor,
method: &MethodDescriptor,
comments: &Comments,
out: &mut impl Write,
) {
let method_name = method.name().to_snake_case();
let input = method.input();
let output = method.output();
let service_idx = service.index();
let method_idx = method.index();
let comments = format_comments(comments.get_for_path(method.path()));
// raw bytes
write!(
out,
r#" def {method_name}_raw(self, message: bytes) -> bytes:
return self._run_command({service_idx}, {method_idx}, message)
{comments}return self._run_command({service_idx}, {method_idx}, message)
"#
)
@ -69,7 +78,7 @@ fn render_method(service: &ServiceDescriptor, method: &MethodDescriptor, out: &m
write!(
out,
r#" def {method_name}({input_params}) -> {output_type}:
{input_assign}
{comments}{input_assign}
raw_bytes = self._run_command({service_idx}, {method_idx}, message.SerializeToString())
output = {output_constructor}()
output.ParseFromString(raw_bytes)
@ -80,6 +89,18 @@ fn render_method(service: &ServiceDescriptor, method: &MethodDescriptor, out: &m
.unwrap();
}
fn format_comments(comments: Option<&str>) -> String {
comments
.as_ref()
.map(|c| {
format!(
r#""""{c}"""
"#
)
})
.unwrap_or_default()
}
/// If any of the following apply to the input type:
/// - it has a single field
/// - its name ends in Request

View File

@ -11,6 +11,7 @@ use anki_io::read_file;
use anki_io::write_file_if_changed;
use anyhow::Context;
use anyhow::Result;
use itertools::Itertools;
use prost_build::ServiceGenerator;
use prost_reflect::DescriptorPool;
@ -151,12 +152,20 @@ pub trait Service {
);
for method in &service.methods {
let comments = method
.comments
.leading
.iter()
.map(|c| format!(" /// {c}"))
.join("\n");
write!(
buf,
concat!(
" fn {method_name}(&self, input: super::{input_type}) -> ",
"{comments}\n",
"fn {method_name}(&self, input: super::{input_type}) -> ",
"Result<super::{output_type}, Self::Error>;\n"
),
comments = comments,
method_name = method.name,
input_type = method.input_type,
output_type = method.output_type

View File

@ -19,16 +19,7 @@ impl Comments {
.unwrap()
.location
.iter()
.map(|l| {
(
l.path.clone(),
format!(
"{}{}",
l.leading_detached_comments.join("\n").trim(),
l.leading_comments().trim()
),
)
})
.map(|l| (l.path.clone(), l.leading_comments().trim().to_string()))
.collect(),
}
}