octocrate-api-builder 0.1.1

Github API builder for octocrate
Documentation
use proc_macro2::TokenStream;
use quote::quote;
use syn::{
    braced,
    parse::{Parse, ParseBuffer, ParseStream},
    Attribute, Ident, Result,
};

use crate::request::Request;

#[derive(Debug)]
pub struct RequestContext {
    pub name: Ident,
    pub attributes: Vec<Attribute>,
    pub requests: Vec<Request>,
}

impl RequestContext {
    pub fn generate_ast(&self) -> TokenStream {
        let name = &self.name;
        let attributes = &self.attributes;
        let requests = self.requests.iter().map(|request| request.generate_ast());

        let tests = self
            .requests
            .iter()
            .map(|request| request.generate_test_ast());

        let ast = quote! {
          use std::ops::Deref;
          use octocrate_infra::{ExpirableToken, GithubAPIClient};

          #(#attributes)*
          #[derive(Clone, Debug)]
          pub struct #name {
            client: std::sync::Arc<GithubAPIClient>,
          }

          impl #name {
            pub fn new(client: std::sync::Arc<GithubAPIClient>) -> Self {
              Self { client }
            }

            #(#requests)*

          }

          #[cfg(test)]
          mod github_api_tests {
            use super::#name;
            use crate::utils::test_utils;
            use octocrate_infra::GithubResult;
            use std::sync::Arc;

            #(#tests)*

          }
        };

        ast
    }
}

impl Parse for RequestContext {
    fn parse(input: ParseStream) -> Result<Self> {
        let attributes = match input.call(Attribute::parse_outer) {
            Ok(attr) => attr,
            Err(_) => Vec::new(),
        };
        let name: Ident = input.parse()?;

        let mut requests: Vec<Request> = Vec::new();
        if !input.is_empty() {
            let content: ParseBuffer;
            braced!(content in input);

            while !content.is_empty() {
                let request = Request::parse(name.clone(), &content as ParseStream)?;

                requests.push(request);
            }
        }

        Ok(RequestContext {
            name,
            requests,
            attributes,
        })
    }
}