mod c_role;
mod cmake_role;
mod cpp_role;
mod http_role;
mod js_role;
mod math_role;
mod py_role;
mod rst_role;
mod sip_role;
mod std_role;
pub(crate) use c_role::c_role;
pub(crate) use cmake_role::cmake_role;
pub(crate) use cpp_role::cpp_role;
pub(crate) use http_role::http_role;
pub(crate) use js_role::js_role;
pub(crate) use math_role::math_role;
pub(crate) use py_role::py_role;
pub(crate) use rst_role::rst_role;
pub(crate) use sip_role::sip_role;
pub(crate) use std_role::std_role;
pub use c_role::CRole;
pub use cmake_role::CmakeRole;
pub use cpp_role::CppRole;
pub use http_role::HttpRole;
pub use js_role::JsRole;
pub use math_role::MathRole;
pub use py_role::PyRole;
pub use rst_role::RstRole;
pub use sip_role::SipRole;
pub use std_role::StdRole;
use winnow::{
ModalResult, Parser,
combinator::{cut_err, dispatch, eof, fail, not, terminated, trace},
error::{StrContext, StrContextValue},
};
use std::fmt::Display;
use crate::reference::word;
#[derive(Debug, PartialEq)]
pub enum SphinxType {
Std(StdRole),
C(CRole),
Python(PyRole),
Cpp(CppRole),
JavaScript(JsRole),
Mathematics(MathRole),
ReStructuredText(RstRole),
Cmake(CmakeRole),
Sip(SipRole),
Http(HttpRole),
}
impl Display for SphinxType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&match self {
SphinxType::Std(std_role) => format!("std:{std_role}"),
SphinxType::C(crole) => format!("c:{crole}"),
SphinxType::Python(py_role) => format!("py:{py_role}"),
SphinxType::Cpp(cpp_role) => format!("cpp:{cpp_role}"),
SphinxType::JavaScript(js_role) => format!("js:{js_role}"),
SphinxType::Mathematics(math_role) => format!("math:{math_role}"),
SphinxType::ReStructuredText(rst_role) => format!("rst:{rst_role}"),
SphinxType::Cmake(cmake_role) => format!("cmake:{cmake_role}"),
SphinxType::Sip(sip_role) => format!("sip:{sip_role}"),
SphinxType::Http(http_role) => format!("http:{http_role}"),
})
}
}
fn domain<'s>(input: &mut &'s str) -> ModalResult<&'s str> {
trace("domain", word).parse_next(input)
}
pub(crate) fn role_domain(input: &mut &str) -> ModalResult<SphinxType> {
cut_err(
not(eof)
.context(StrContext::Label("missing domain:role"))
.context(StrContext::Expected(StrContextValue::StringLiteral("std")))
.context(StrContext::Expected(StrContextValue::StringLiteral("py")))
.context(StrContext::Expected(StrContextValue::StringLiteral("c")))
.context(StrContext::Expected(StrContextValue::StringLiteral("rst")))
.context(StrContext::Expected(StrContextValue::StringLiteral("cpp")))
.context(StrContext::Expected(StrContextValue::StringLiteral("js")))
.context(StrContext::Expected(StrContextValue::StringLiteral("math"))),
)
.parse_next(input)?;
dispatch! {terminated(domain,':');
"std" => cut_err(std_role),
"py" => cut_err(py_role),
"c" => cut_err(c_role),
"rst" => cut_err(rst_role),
"cpp" => cut_err(cpp_role),
"js" => cut_err(js_role),
"math" => cut_err(math_role),
"cmake" => cut_err(cmake_role),
"sip" => cut_err(sip_role),
"http" => cut_err(http_role),
_ => fail
}
.parse_next(input)
}
#[cfg(test)]
mod test {
use winnow::Parser;
use crate::SphinxParseError;
use crate::roles::role_domain;
use crate::{
CRole, CppRole, JsRole, MathRole, PyRole, RstRole,
roles::{SphinxType, StdRole},
};
#[test]
fn display_js_role() {
assert_eq!(
format!("{}", SphinxType::JavaScript(JsRole::Module)),
"js:module"
);
assert_eq!(
format!("{}", SphinxType::JavaScript(JsRole::Function)),
"js:function"
);
assert_eq!(
format!("{}", SphinxType::JavaScript(JsRole::Method)),
"js:method"
);
assert_eq!(
format!("{}", SphinxType::JavaScript(JsRole::Class)),
"js:class"
);
assert_eq!(
format!("{}", SphinxType::JavaScript(JsRole::Data)),
"js:data"
);
}
#[test]
fn display_py_role() {
assert_eq!(format!("{}", SphinxType::Python(PyRole::Class)), "py:class");
assert_eq!(
format!("{}", SphinxType::Python(PyRole::Property)),
"py:property"
);
assert_eq!(
format!("{}", SphinxType::Python(PyRole::Module)),
"py:module"
);
assert_eq!(
format!("{}", SphinxType::Python(PyRole::Method)),
"py:method"
);
assert_eq!(
format!("{}", SphinxType::Python(PyRole::Function)),
"py:function"
);
assert_eq!(format!("{}", SphinxType::Python(PyRole::Type)), "py:type");
assert_eq!(
format!("{}", SphinxType::Python(PyRole::Exception)),
"py:exception"
);
assert_eq!(format!("{}", SphinxType::Python(PyRole::Data)), "py:data");
assert_eq!(
format!("{}", SphinxType::Python(PyRole::Attribute)),
"py:attribute"
);
}
#[test]
fn display_cpp_role() {
assert_eq!(format!("{}", SphinxType::Cpp(CppRole::Type)), "cpp:type");
assert_eq!(
format!("{}", SphinxType::Cpp(CppRole::Function)),
"cpp:function"
);
assert_eq!(format!("{}", SphinxType::Cpp(CppRole::Class)), "cpp:class");
assert_eq!(
format!("{}", SphinxType::Cpp(CppRole::FunctionParam)),
"cpp:functionParam"
);
assert_eq!(
format!("{}", SphinxType::Cpp(CppRole::Member)),
"cpp:member"
);
assert_eq!(
format!("{}", SphinxType::Cpp(CppRole::TemplateParam)),
"cpp:templateParam"
);
}
#[test]
fn display_c_role() {
assert_eq!(
format!("{}", SphinxType::C(CRole::Enumerator)),
"c:enumerator"
);
assert_eq!(format!("{}", SphinxType::C(CRole::Enum)), "c:enum");
assert_eq!(format!("{}", SphinxType::C(CRole::Function)), "c:function");
assert_eq!(
format!("{}", SphinxType::C(CRole::FunctionParam)),
"c:functionParam"
);
assert_eq!(format!("{}", SphinxType::C(CRole::Member)), "c:member");
assert_eq!(format!("{}", SphinxType::C(CRole::Macro)), "c:macro");
assert_eq!(format!("{}", SphinxType::C(CRole::Var)), "c:var");
assert_eq!(format!("{}", SphinxType::C(CRole::Type)), "c:type");
assert_eq!(format!("{}", SphinxType::C(CRole::Struct)), "c:struct");
assert_eq!(format!("{}", SphinxType::C(CRole::Union)), "c:union");
}
#[test]
fn display_rst_role() {
assert_eq!(
format!("{}", SphinxType::ReStructuredText(RstRole::Directive)),
"rst:directive"
);
assert_eq!(
format!("{}", SphinxType::ReStructuredText(RstRole::Option)),
"rst:directive:option"
);
}
#[test]
fn display_math_role() {
assert_eq!(
format!("{}", SphinxType::Mathematics(MathRole::Numref)),
"math:numref"
);
}
#[test]
fn display_std_type() {
assert_eq!(format!("{}", SphinxType::Std(StdRole::Doc)), "std:doc");
assert_eq!(format!("{}", SphinxType::Std(StdRole::Term)), "std:term");
assert_eq!(format!("{}", SphinxType::Std(StdRole::Label)), "std:label");
assert_eq!(
format!("{}", SphinxType::Std(StdRole::Cmdoption)),
"std:cmdoption"
);
assert_eq!(
format!("{}", SphinxType::Std(StdRole::Pdbcommand)),
"std:pdbcommand"
);
assert_eq!(format!("{}", SphinxType::Std(StdRole::Token)), "std:token");
assert_eq!(
format!("{}", SphinxType::Std(StdRole::Opcode)),
"std:opcode"
);
assert_eq!(
format!("{}", SphinxType::Std(StdRole::MonitoringEvent)),
"std:monitoring-event"
);
assert_eq!(
format!("{}", SphinxType::Std(StdRole::Envvar)),
"std:envvar"
);
}
#[test]
fn parse_c_roles() -> Result<(), SphinxParseError> {
let roles = vec![
"c:enumerator",
"c:enum",
"c:function",
"c:functionParam",
"c:member",
"c:macro",
"c:var",
"c:type",
"c:struct",
"c:union",
];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
#[test]
fn parse_std_roles() -> Result<(), SphinxParseError> {
let roles = vec![
"std:doc",
"std:label",
"std:term",
"std:cmdoption",
"std:pdbcommand",
"std:token",
"std:opcode",
"std:monitoring-event",
"std:envvar",
];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
#[test]
fn parse_python_roles() -> Result<(), SphinxParseError> {
let roles = vec![
"py:attr",
"py:attribute",
"py:class",
"py:classmethod",
"py:data",
"py:enum",
"py:exception",
"py:function",
"py:interface",
"py:method",
"py:module",
"py:parameter",
"py:property",
"py:pydantic_field",
"py:pydantic_model",
"py:pydantic_validator",
"py:staticmethod",
"py:type",
];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
#[test]
fn parse_cpp_roles() -> Result<(), SphinxParseError> {
let roles = vec![
"cpp:class",
"cpp:function",
"cpp:functionParam",
"cpp:member",
"cpp:templateParam",
"cpp:type",
];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
#[test]
fn parse_js_roles() -> Result<(), SphinxParseError> {
let roles = vec![
"js:module",
"js:data",
"js:function",
"js:method",
"js:class",
"js:attribute",
];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
#[test]
fn parse_math_roles() -> Result<(), SphinxParseError> {
let roles = vec!["math:numref"];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
#[test]
fn parse_rst_roles() -> Result<(), SphinxParseError> {
let roles = vec!["rst:directive", "rst:directive:option", "rst:role"];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
#[test]
fn parse_sip_role() -> Result<(), SphinxParseError> {
let roles = vec![
"sip:method",
"sip:member",
"sip:class",
"sip:signal",
"sip:module",
"sip:attribute",
"sip:enum",
];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
#[test]
fn parse_http_domain() -> Result<(), SphinxParseError> {
let roles = vec![
"http:any",
"http:copy",
"http:delete",
"http:get",
"http:head",
"http:post",
"http:put",
"http:put",
];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
#[test]
fn parse_cmake_roles() -> Result<(), SphinxParseError> {
let roles = vec![
"cmake:command",
"cmake:cpack_gen",
"cmake:envvar",
"cmake:generator",
"cmake:genex",
"cmake:guide",
"cmake:manual",
"cmake:module",
"cmake:policy",
"cmake:prop_cache",
"cmake:prop_dir",
"cmake:prop_gbl",
"cmake:prop_inst",
"cmake:prop_sf",
"cmake:prop_test",
"cmake:prop_tgt",
"cmake:variable",
];
for role in roles {
let _ = role_domain
.parse(role)
.map_err(|e| SphinxParseError::from_str_parse(&e, 0))?;
}
Ok(())
}
}