1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use attributes;
use failure;
use syn;

static DEPRECATION_ERROR: &'static str = "deprecated must be one of 'allow', 'deny', or 'warn'";

/// Whether an item is deprecated, with context.
#[derive(Debug, PartialEq, Hash, Clone)]
pub enum DeprecationStatus {
    /// Not deprecated
    Current,
    /// Deprecated
    Deprecated(Option<String>),
}

/// The available deprecation startegies.
#[derive(Debug, PartialEq)]
pub enum DeprecationStrategy {
    /// Allow use of deprecated items in queries, and say nothing.
    Allow,
    /// Fail compilation if a deprecated item is used.
    Deny,
    /// Allow use of deprecated items in queries, but warn about them (default).
    Warn,
}

impl Default for DeprecationStrategy {
    fn default() -> Self {
        DeprecationStrategy::Warn
    }
}

/// Get the deprecation from a struct attribute in the derive case.
pub fn extract_deprecation_strategy(
    ast: &syn::DeriveInput,
) -> Result<DeprecationStrategy, failure::Error> {
    match attributes::extract_attr(&ast, "deprecated")?
        .to_lowercase()
        .as_str()
    {
        "allow" => Ok(DeprecationStrategy::Allow),
        "deny" => Ok(DeprecationStrategy::Deny),
        "warn" => Ok(DeprecationStrategy::Warn),
        _ => Err(format_err!("{}", DEPRECATION_ERROR))?,
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_deprecation_strategy() {
        let input = "
        #[derive(GraphQLQuery)]
        #[graphql(
            schema_path = \"x\",
            query_path = \"x\",
            deprecated = \"warn\",
        )]
        struct MyQuery;
        ";
        let parsed = syn::parse_str(input).unwrap();
        assert_eq!(
            extract_deprecation_strategy(&parsed).unwrap(),
            DeprecationStrategy::Warn
        );
    }

    #[test]
    fn test_deprecation_strategy_is_case_insensitive() {
        let input = "
        #[derive(GraphQLQuery)]
        #[graphql(
            schema_path = \"x\",
            query_path = \"x\",
            deprecated = \"DeNy\",
        )]
        struct MyQuery;
        ";
        let parsed = syn::parse_str(input).unwrap();
        assert_eq!(
            extract_deprecation_strategy(&parsed).unwrap(),
            DeprecationStrategy::Deny
        );
    }

    #[test]
    fn test_invalid_deprecation_strategy() {
        let input = "
        #[derive(GraphQLQuery)]
        #[graphql(
            schema_path = \"x\",
            query_path = \"x\",
            deprecated = \"foo\",
        )]
        struct MyQuery;
        ";
        let parsed = syn::parse_str(input).unwrap();
        match extract_deprecation_strategy(&parsed) {
            Ok(_) => panic!("parsed unexpectedly"),
            Err(e) => assert_eq!(&format!("{}", e), DEPRECATION_ERROR),
        };
    }
}