Skip to content

Commit 3120d62

Browse files
authored
Splitting summary and description in OpenAPI output (#2608)
* test * further test * refactoring * linter * using segmenter to split sentences * removing newlines + unit test * comment * handled specific case
1 parent d97e9ac commit 3120d62

File tree

7 files changed

+101274
-685
lines changed

7 files changed

+101274
-685
lines changed

compiler-rs/Cargo.lock

+212
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler-rs/clients_schema_to_openapi/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ serde = {version = "1.0", features=["derive"]}
1111
serde_json = "1.0"
1212
serde_path_to_error = "0.1"
1313
serde_ignored = "0.1"
14+
icu_segmenter = "1.5.0"
1415
openapiv3 = "1.0"
1516
anyhow = "1.0"
1617
indexmap = "1.9"

compiler-rs/clients_schema_to_openapi/src/paths.rs

+67-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::fmt::Write;
2121
use anyhow::{anyhow, bail};
2222
use clients_schema::Property;
2323
use indexmap::indexmap;
24+
use icu_segmenter::SentenceSegmenter;
2425
use openapiv3::{
2526
MediaType, Parameter, ParameterData, ParameterSchemaOrContent, PathItem, PathStyle, Paths, QueryStyle, ReferenceOr,
2627
RequestBody, Response, Responses, StatusCode,
@@ -191,11 +192,13 @@ pub fn add_endpoint(
191192

192193
parameters.append(&mut query_params.clone());
193194

195+
let sum_desc = split_summary_desc(&endpoint.description);
196+
194197
// Create the operation, it will be repeated if we have several methods
195198
let operation = openapiv3::Operation {
196199
tags: vec![endpoint.name.clone()],
197-
summary: Some(endpoint.description.clone()),
198-
description: Some(endpoint.description.clone()),
200+
summary: sum_desc.summary,
201+
description: sum_desc.description,
199202
external_docs: tac.convert_external_docs(endpoint),
200203
operation_id: None, // set in clone_operation below with operation_counter
201204
parameters,
@@ -311,6 +314,39 @@ fn get_path_parameters(template: &str) -> Vec<&str> {
311314
result
312315
}
313316

317+
// Splits the original endpoint description into OpenAPI summary and description, where summary
318+
// is the first sentence of the original description with no trailing `.`, and description contains
319+
// the remaining sentences, if there are any left.
320+
fn split_summary_desc(desc: &str) -> SplitDesc{
321+
let segmenter = SentenceSegmenter::new();
322+
323+
let desc_no_newlines = desc.replace("\n\n",".\n").replace('\n'," ");
324+
325+
let breakpoints: Vec<usize> = segmenter
326+
.segment_str(&desc_no_newlines)
327+
.collect();
328+
329+
if breakpoints.len()<2{
330+
return SplitDesc {
331+
summary: None,
332+
description: None
333+
}
334+
}
335+
let first_line = &desc_no_newlines[breakpoints[0]..breakpoints[1]];
336+
let rest = &desc_no_newlines[breakpoints[1]..breakpoints[breakpoints.len()-1]];
337+
338+
SplitDesc {
339+
summary: Some(String::from(first_line.trim().strip_suffix('.').unwrap_or(first_line))),
340+
description: if !rest.is_empty() {Some(String::from(rest.trim()))} else {None}
341+
}
342+
}
343+
344+
#[derive(PartialEq,Debug)]
345+
struct SplitDesc {
346+
summary: Option<String>,
347+
description: Option<String>
348+
}
349+
314350
#[cfg(test)]
315351
mod tests {
316352
use super::*;
@@ -325,4 +361,33 @@ mod tests {
325361
assert_eq!(get_path_parameters("{index}{id/"), vec! {"index"});
326362
assert_eq!(get_path_parameters("{index{id}/"), vec! {"index{id"});
327363
}
364+
365+
#[test]
366+
fn test_split_summary_desc() {
367+
assert_eq!(split_summary_desc("One sentence."),
368+
SplitDesc{
369+
summary: Some(String::from("One sentence")),
370+
description: None
371+
});
372+
assert_eq!(split_summary_desc("This is\nstill one. sentence: all; together"),
373+
SplitDesc{
374+
summary: Some(String::from("This is still one. sentence: all; together")),
375+
description: None
376+
});
377+
assert_eq!(split_summary_desc("These are two totally. Separate sentences!"),
378+
SplitDesc{
379+
summary: Some(String::from("These are two totally")),
380+
description: Some(String::from("Separate sentences!"))
381+
});
382+
assert_eq!(split_summary_desc("Such a weird way to separate sentences\n\nRight?"),
383+
SplitDesc{
384+
summary: Some(String::from("Such a weird way to separate sentences")),
385+
description: Some(String::from("Right?"))
386+
});
387+
assert_eq!(split_summary_desc(""),
388+
SplitDesc{
389+
summary: None,
390+
description: None
391+
});
392+
}
328393
}
Binary file not shown.

0 commit comments

Comments
 (0)