api: Replace ruma_api! compile-time path check with a test
This commit is contained in:
parent
9195a5de18
commit
2451f33a64
@ -124,6 +124,13 @@ impl Metadata {
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
// Used for generated `#[test]`s
|
||||
#[doc(hidden)]
|
||||
pub fn _path_parameters(&self) -> Vec<&'static str> {
|
||||
let path = self.history.all_paths().next().unwrap();
|
||||
path.split('/').filter_map(|segment| segment.strip_prefix(':')).collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// The complete history of this endpoint as far as Ruma knows, together with all variants on
|
||||
|
@ -12,12 +12,7 @@ use syn::{
|
||||
Attribute, Field, Token, Type,
|
||||
};
|
||||
|
||||
use self::{
|
||||
api_metadata::Metadata,
|
||||
api_request::Request,
|
||||
api_response::Response,
|
||||
request::{RequestField, RequestFieldKind},
|
||||
};
|
||||
use self::{api_metadata::Metadata, api_request::Request, api_response::Response};
|
||||
use crate::util::import_ruma_common;
|
||||
|
||||
mod api_metadata;
|
||||
@ -56,7 +51,6 @@ pub struct Api {
|
||||
impl Api {
|
||||
pub fn expand_all(self) -> TokenStream {
|
||||
let maybe_feature_error = ensure_feature_presence().map(syn::Error::to_compile_error);
|
||||
let maybe_path_error = self.check_paths().err().map(syn::Error::into_compile_error);
|
||||
|
||||
let ruma_common = import_ruma_common();
|
||||
|
||||
@ -80,7 +74,6 @@ impl Api {
|
||||
|
||||
quote! {
|
||||
#maybe_feature_error
|
||||
#maybe_path_error
|
||||
|
||||
// For some reason inlining the expression causes issues with macro parsing
|
||||
const _RUMA_API_VERSION_HISTORY: #ruma_common::api::VersionHistory = #history;
|
||||
@ -102,39 +95,6 @@ impl Api {
|
||||
type _SilenceUnusedError = #error_ty;
|
||||
}
|
||||
}
|
||||
|
||||
fn check_paths(&self) -> syn::Result<()> {
|
||||
let mut path_iter = self.metadata.history.entries.iter().filter_map(|entry| entry.path());
|
||||
|
||||
let path = path_iter.next().ok_or_else(|| {
|
||||
syn::Error::new(Span::call_site(), "at least one path metadata field must be set")
|
||||
})?;
|
||||
let path_args = path.args();
|
||||
|
||||
if let Some(req) = &self.request {
|
||||
let path_field_names: Vec<_> = req
|
||||
.fields
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter_map(|f| match RequestField::try_from(f) {
|
||||
Ok(RequestField { kind: RequestFieldKind::Path, inner }) => {
|
||||
Some(Ok(inner.ident.unwrap().to_string()))
|
||||
}
|
||||
Ok(_) => None,
|
||||
Err(e) => Some(Err(e)),
|
||||
})
|
||||
.collect::<syn::Result<_>>()?;
|
||||
|
||||
if path_args != path_field_names {
|
||||
return Err(syn::Error::new_spanned(
|
||||
req.request_kw,
|
||||
"path fields must be in the same order as they appear in the path segments",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Api {
|
||||
|
@ -389,17 +389,6 @@ pub enum HistoryEntry {
|
||||
Removed { version: MatrixVersionLiteral },
|
||||
}
|
||||
|
||||
impl HistoryEntry {
|
||||
pub(super) fn path(&self) -> Option<&EndpointPath> {
|
||||
Some(match self {
|
||||
HistoryEntry::Stable { version: _, path } => path,
|
||||
HistoryEntry::Unstable { path } => path,
|
||||
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct EndpointPath(LitStr);
|
||||
|
||||
@ -407,10 +396,6 @@ impl EndpointPath {
|
||||
pub fn value(&self) -> String {
|
||||
self.0.value()
|
||||
}
|
||||
|
||||
pub fn args(&self) -> Vec<String> {
|
||||
self.value().split('/').filter_map(|s| s.strip_prefix(':')).map(String::from).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for EndpointPath {
|
||||
|
@ -238,7 +238,7 @@ impl Request {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(&self, ruma_common: &TokenStream) -> syn::Result<Option<TokenStream>> {
|
||||
pub(super) fn check(&self, ruma_common: &TokenStream) -> syn::Result<TokenStream> {
|
||||
let http = quote! { #ruma_common::exports::http };
|
||||
|
||||
// TODO: highlight problematic fields
|
||||
@ -297,8 +297,21 @@ impl Request {
|
||||
));
|
||||
}
|
||||
|
||||
Ok((has_body_fields || has_newtype_body_field).then(|| {
|
||||
quote! {
|
||||
let path_fields = self.path_fields().map(|f| f.ident.as_ref().unwrap().to_string());
|
||||
let mut tests = quote! {
|
||||
#[::std::prelude::v1::test]
|
||||
fn path_parameters() {
|
||||
let path_params = METADATA._path_parameters();
|
||||
let request_path_fields: &[&::std::primitive::str] = &[#(#path_fields),*];
|
||||
::std::assert_eq!(
|
||||
path_params, request_path_fields,
|
||||
"Path parameters must match the `Request`'s `#[ruma_api(path)]` fields"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
if has_body_fields || has_newtype_body_field {
|
||||
tests.extend(quote! {
|
||||
#[::std::prelude::v1::test]
|
||||
fn request_is_not_get() {
|
||||
::std::assert_ne!(
|
||||
@ -306,8 +319,10 @@ impl Request {
|
||||
"GET endpoints can't have body fields",
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}))
|
||||
|
||||
Ok(tests)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user