From 81ac5a91ad89a511eed35eb0607b7efe407e9e82 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Fri, 16 Jun 2023 10:59:00 +1000 Subject: [PATCH] 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. --- Cargo.lock | 1 + rslib/proto/Cargo.toml | 1 + rslib/proto/python.rs | 29 +++++++++++++++++++++++++---- rslib/proto/rust.rs | 11 ++++++++++- rslib/proto/utils.rs | 11 +---------- 5 files changed, 38 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e641364be..30cc7b73c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -202,6 +202,7 @@ dependencies = [ "anki_io", "anyhow", "inflections", + "itertools", "num_enum", "prost", "prost-build", diff --git a/rslib/proto/Cargo.toml b/rslib/proto/Cargo.toml index 2c01f6188..c3fdafb31 100644 --- a/rslib/proto/Cargo.toml +++ b/rslib/proto/Cargo.toml @@ -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" diff --git a/rslib/proto/python.rs b/rslib/proto/python.rs index b735c1915..1f7f6f357 100644 --- a/rslib/proto/python.rs +++ b/rslib/proto/python.rs @@ -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 diff --git a/rslib/proto/rust.rs b/rslib/proto/rust.rs index 03d8a0f15..8c36172a0 100644 --- a/rslib/proto/rust.rs +++ b/rslib/proto/rust.rs @@ -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;\n" ), + comments = comments, method_name = method.name, input_type = method.input_type, output_type = method.output_type diff --git a/rslib/proto/utils.rs b/rslib/proto/utils.rs index 91c622c70..9dca9ec8d 100644 --- a/rslib/proto/utils.rs +++ b/rslib/proto/utils.rs @@ -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(), } }