Move methods to TokenTree
This commit is contained in:
parent
47b9701321
commit
bc8d014bc3
|
@ -1,17 +1,20 @@
|
||||||
use crate::md_parser;
|
use crate::md_parser;
|
||||||
|
|
||||||
pub fn parse_group_description(content: &[md_parser::MdContent]) -> Option<String> {
|
impl md_parser::TokenTree {
|
||||||
let return_desc = content
|
pub fn parse_group_description(&self) -> Option<String> {
|
||||||
.iter()
|
let return_desc = self
|
||||||
.map(|row| row.inner_value_as_string())
|
.content
|
||||||
.collect::<Vec<String>>()
|
.iter()
|
||||||
.join("\n")
|
.map(|row| row.inner_value_as_string())
|
||||||
.trim()
|
.collect::<Vec<String>>()
|
||||||
.to_string();
|
.join("\n")
|
||||||
|
.trim()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
if return_desc.is_empty() {
|
if return_desc.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(return_desc)
|
Some(return_desc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,38 @@
|
||||||
use crate::md_parser::MdContent;
|
use crate::md_parser::{self, MdContent};
|
||||||
|
|
||||||
pub fn parse_method_description(content: &[MdContent]) -> Option<String> {
|
impl md_parser::TokenTree {
|
||||||
let return_desc = content
|
pub fn parse_method_description(&self) -> Option<String> {
|
||||||
.iter()
|
let return_desc = self
|
||||||
// skip until we get to the "Returns:" text
|
.content
|
||||||
.skip_while(|row| match row {
|
.iter()
|
||||||
MdContent::Asterisk(text) => !text.starts_with("Returns:"),
|
// skip until we get to the "Returns:" text
|
||||||
_ => true,
|
.skip_while(|row| match row {
|
||||||
})
|
MdContent::Asterisk(text) => !text.starts_with("Returns:"),
|
||||||
// there is one space before the table
|
_ => true,
|
||||||
.skip(2)
|
})
|
||||||
.skip_while(|row| match row {
|
// there is one space before the table
|
||||||
MdContent::Text(text) => !text.is_empty(),
|
.skip(2)
|
||||||
_ => true,
|
.skip_while(|row| match row {
|
||||||
})
|
MdContent::Text(text) => !text.is_empty(),
|
||||||
// and there is one space after the table
|
_ => true,
|
||||||
.skip(1)
|
})
|
||||||
// then what is left should be the description
|
// and there is one space after the table
|
||||||
.flat_map(|row| match row {
|
.skip(1)
|
||||||
MdContent::Text(text) => Some(text),
|
// then what is left should be the description
|
||||||
_ => None,
|
.flat_map(|row| match row {
|
||||||
})
|
MdContent::Text(text) => Some(text),
|
||||||
.cloned()
|
_ => None,
|
||||||
.collect::<Vec<String>>()
|
})
|
||||||
.join("\n")
|
.cloned()
|
||||||
.trim()
|
.collect::<Vec<String>>()
|
||||||
.to_string();
|
.join("\n")
|
||||||
|
.trim()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
if return_desc.is_empty() {
|
if return_desc.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(return_desc)
|
Some(return_desc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,9 @@ mod description;
|
||||||
mod return_type;
|
mod return_type;
|
||||||
mod url;
|
mod url;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use crate::{md_parser, parser::util, types};
|
use crate::{md_parser, parser::util, types};
|
||||||
|
|
||||||
pub use return_type::ReturnType;
|
pub use return_type::ReturnType;
|
||||||
|
use std::collections::HashMap;
|
||||||
use self::{
|
|
||||||
description::parse_method_description, return_type::parse_return_type, url::get_method_url,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ApiMethod {
|
pub struct ApiMethod {
|
||||||
|
@ -61,11 +55,11 @@ impl ApiMethod {
|
||||||
|
|
||||||
fn new(child: &md_parser::TokenTree, name: &str) -> Self {
|
fn new(child: &md_parser::TokenTree, name: &str) -> Self {
|
||||||
let tables = Tables::from(child);
|
let tables = Tables::from(child);
|
||||||
let method_description = parse_method_description(&child.content);
|
let method_description = child.parse_method_description();
|
||||||
let return_type = parse_return_type(&child.content);
|
let return_type = child.parse_return_type();
|
||||||
// let return_type = tables.return_type().map(|r| ReturnType::new(r));
|
// let return_type = tables.return_type().map(|r| ReturnType::new(r));
|
||||||
let parameters = tables.parameters().map(ApiParameters::new);
|
let parameters = tables.parameters().map(ApiParameters::new);
|
||||||
let method_url = get_method_url(&child.content);
|
let method_url = child.get_method_url();
|
||||||
|
|
||||||
ApiMethod {
|
ApiMethod {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
|
|
@ -11,81 +11,84 @@ pub struct ReturnType {
|
||||||
pub parameters: Vec<ReturnTypeParameter>,
|
pub parameters: Vec<ReturnTypeParameter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_return_type(content: &[MdContent]) -> Option<ReturnType> {
|
impl md_parser::TokenTree {
|
||||||
let table = content
|
pub fn parse_return_type(&self) -> Option<ReturnType> {
|
||||||
.iter()
|
let table = self
|
||||||
// The response is a ... <-- Trying to find this line
|
.content
|
||||||
// <-- The next line is empty
|
.iter()
|
||||||
// Table with the return type <-- And then extract the following type table
|
// The response is a ... <-- Trying to find this line
|
||||||
.skip_while(|row| match row {
|
// <-- The next line is empty
|
||||||
MdContent::Text(text) => !text.starts_with("The response is a"),
|
// Table with the return type <-- And then extract the following type table
|
||||||
_ => true,
|
.skip_while(|row| match row {
|
||||||
|
MdContent::Text(text) => !text.starts_with("The response is a"),
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
|
.find_map(|row| match row {
|
||||||
|
MdContent::Table(table) => Some(table),
|
||||||
|
_ => None,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let types = self.parse_object_types();
|
||||||
|
|
||||||
|
let parameters = table
|
||||||
|
.rows
|
||||||
|
.iter()
|
||||||
|
.map(|parameter| ReturnTypeParameter {
|
||||||
|
name: parameter.columns[0].clone(),
|
||||||
|
description: parameter.columns[2].clone(),
|
||||||
|
return_type: types::Type::from(
|
||||||
|
¶meter.columns[1],
|
||||||
|
¶meter.columns[0],
|
||||||
|
Some(parameter.columns[2].clone()),
|
||||||
|
&types,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|| panic!("Failed to parse type {}", ¶meter.columns[1])),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Some(ReturnType {
|
||||||
|
parameters,
|
||||||
|
is_list: self.is_list(),
|
||||||
})
|
})
|
||||||
.find_map(|row| match row {
|
}
|
||||||
MdContent::Table(table) => Some(table),
|
|
||||||
_ => None,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let types = parse_object_types(content);
|
fn is_list(&self) -> bool {
|
||||||
|
self.content
|
||||||
|
.iter()
|
||||||
|
.find_map(|row| match row {
|
||||||
|
MdContent::Text(text) if text.starts_with("The response is a") => Some(text),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.map(|found| found.contains("array"))
|
||||||
|
.unwrap_or_else(|| false)
|
||||||
|
}
|
||||||
|
|
||||||
let parameters = table
|
pub fn parse_object_types(&self) -> HashMap<String, types::TypeDescription> {
|
||||||
.rows
|
let mut output = HashMap::new();
|
||||||
.iter()
|
let mut content_it = self.content.iter();
|
||||||
.map(|parameter| ReturnTypeParameter {
|
|
||||||
name: parameter.columns[0].clone(),
|
|
||||||
description: parameter.columns[2].clone(),
|
|
||||||
return_type: types::Type::from(
|
|
||||||
¶meter.columns[1],
|
|
||||||
¶meter.columns[0],
|
|
||||||
Some(parameter.columns[2].clone()),
|
|
||||||
&types,
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|| panic!("Failed to parse type {}", ¶meter.columns[1])),
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let is_list = content
|
while let Some(entry) = content_it.next() {
|
||||||
.iter()
|
if let md_parser::MdContent::Text(content) = entry {
|
||||||
.find_map(|row| match row {
|
const POSSIBLE_VALUES_OF: &str = "Possible values of ";
|
||||||
MdContent::Text(text) if text.starts_with("The response is a") => Some(text),
|
if content.contains(POSSIBLE_VALUES_OF) {
|
||||||
_ => None,
|
// is empty
|
||||||
})
|
content_it.next();
|
||||||
.map(|found| found.contains("array"))
|
if let Some(md_parser::MdContent::Table(table)) = content_it.next() {
|
||||||
.unwrap_or_else(|| false);
|
let enum_types = to_type_descriptions(table);
|
||||||
|
|
||||||
Some(ReturnType {
|
let name = content
|
||||||
parameters,
|
.trim_start_matches(POSSIBLE_VALUES_OF)
|
||||||
is_list,
|
.replace('`', "")
|
||||||
})
|
.replace(':', "");
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_object_types(
|
output.insert(name, types::TypeDescription { values: enum_types });
|
||||||
content: &[md_parser::MdContent],
|
}
|
||||||
) -> HashMap<String, types::TypeDescription> {
|
|
||||||
let mut output = HashMap::new();
|
|
||||||
let mut content_it = content.iter();
|
|
||||||
|
|
||||||
while let Some(entry) = content_it.next() {
|
|
||||||
if let md_parser::MdContent::Text(content) = entry {
|
|
||||||
const POSSIBLE_VALUES_OF: &str = "Possible values of ";
|
|
||||||
if content.contains(POSSIBLE_VALUES_OF) {
|
|
||||||
// is empty
|
|
||||||
content_it.next();
|
|
||||||
if let Some(md_parser::MdContent::Table(table)) = content_it.next() {
|
|
||||||
let enum_types = to_type_descriptions(table);
|
|
||||||
|
|
||||||
let name = content
|
|
||||||
.trim_start_matches(POSSIBLE_VALUES_OF)
|
|
||||||
.replace('`', "")
|
|
||||||
.replace(':', "");
|
|
||||||
|
|
||||||
output.insert(name, types::TypeDescription { values: enum_types });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
output
|
output
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_type_descriptions(table: &md_parser::Table) -> Vec<types::TypeDescriptions> {
|
fn to_type_descriptions(table: &md_parser::Table) -> Vec<types::TypeDescriptions> {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use crate::{md_parser, parser::util};
|
use crate::{md_parser, parser::util};
|
||||||
|
|
||||||
pub fn get_method_url(content: &[md_parser::MdContent]) -> String {
|
impl md_parser::TokenTree {
|
||||||
const START: &str = "Name: ";
|
pub fn get_method_url(&self) -> String {
|
||||||
|
const START: &str = "Name: ";
|
||||||
|
|
||||||
util::find_content_starts_with(content, START)
|
util::find_content_starts_with(&self.content, START)
|
||||||
.map(|text| text.trim_start_matches(START).trim_matches('`').to_string())
|
.map(|text| text.trim_start_matches(START).trim_matches('`').to_string())
|
||||||
.expect("Could find method url")
|
.expect("Could find method url")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ mod url;
|
||||||
|
|
||||||
use crate::md_parser;
|
use crate::md_parser;
|
||||||
|
|
||||||
use self::{description::parse_group_description, url::get_group_url};
|
|
||||||
pub use method::*;
|
pub use method::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -15,25 +14,29 @@ pub struct ApiGroup {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_api_group(tree: &md_parser::TokenTree) -> ApiGroup {
|
impl ApiGroup {
|
||||||
let methods = tree.children.iter().flat_map(ApiMethod::try_new).collect();
|
pub fn new(tree: &md_parser::TokenTree) -> ApiGroup {
|
||||||
|
ApiGroup {
|
||||||
let group_description = parse_group_description(&tree.content);
|
name: tree.name(),
|
||||||
let group_url = get_group_url(&tree.content);
|
methods: tree.methods(),
|
||||||
|
description: tree.parse_group_description(),
|
||||||
let name = tree
|
url: tree.get_group_url(),
|
||||||
.title
|
}
|
||||||
.clone()
|
}
|
||||||
.unwrap()
|
}
|
||||||
.to_lowercase()
|
|
||||||
.trim_end_matches("(experimental)")
|
impl md_parser::TokenTree {
|
||||||
.trim()
|
fn name(&self) -> String {
|
||||||
.replace(' ', "_");
|
self.title
|
||||||
|
.clone()
|
||||||
ApiGroup {
|
.unwrap()
|
||||||
name,
|
.to_lowercase()
|
||||||
methods,
|
.trim_end_matches("(experimental)")
|
||||||
description: group_description,
|
.trim()
|
||||||
url: group_url,
|
.replace(' ', "_")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn methods(&self) -> Vec<ApiMethod> {
|
||||||
|
self.children.iter().flat_map(ApiMethod::try_new).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,15 @@ use regex::Regex;
|
||||||
|
|
||||||
use crate::{md_parser, parser::util};
|
use crate::{md_parser, parser::util};
|
||||||
|
|
||||||
pub fn get_group_url(content: &[md_parser::MdContent]) -> String {
|
impl md_parser::TokenTree {
|
||||||
let row = util::find_content_contains(content, "API methods are under")
|
pub fn get_group_url(&self) -> String {
|
||||||
.expect("Could not find api method");
|
let row = util::find_content_contains(&self.content, "API methods are under")
|
||||||
|
.expect("Could not find api method");
|
||||||
|
|
||||||
let re = Regex::new(r#"All (?:\w+\s?)+ API methods are under "(\w+)", e.g."#)
|
let re = Regex::new(r#"All (?:\w+\s?)+ API methods are under "(\w+)", e.g."#)
|
||||||
.expect("Failed to create regex");
|
.expect("Failed to create regex");
|
||||||
|
|
||||||
let res = re.captures(&row).expect("Failed find capture");
|
let res = re.captures(&row).expect("Failed find capture");
|
||||||
res[1].to_string()
|
res[1].to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::{md_parser, types};
|
use crate::{md_parser, types};
|
||||||
|
|
||||||
use self::group::parse_api_group;
|
|
||||||
|
|
||||||
mod group;
|
mod group;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
@ -19,10 +17,7 @@ pub fn parse_api_groups(token_tree: md_parser::TokenTree) -> Vec<ApiGroup> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_groups(trees: Vec<md_parser::TokenTree>) -> Vec<ApiGroup> {
|
pub fn parse_groups(trees: Vec<md_parser::TokenTree>) -> Vec<ApiGroup> {
|
||||||
trees
|
trees.iter().map(ApiGroup::new).collect()
|
||||||
.into_iter()
|
|
||||||
.map(|tree| parse_api_group(&tree))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_relevant_parts(tree: md_parser::TokenTree) -> Vec<md_parser::TokenTree> {
|
fn extract_relevant_parts(tree: md_parser::TokenTree) -> Vec<md_parser::TokenTree> {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user