Skip to main content

graphql_schema_diff/
change.rs

1/// A change that represents a meaningful difference between the two schemas. Changes have a
2/// direction: from source to target. For example, if `kind` is `AddField`, it means the field does
3/// not exist in the `source` schema but it does exist in the `target` schema.
4#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct Change {
7    // /!\ The order of fields matters for the PartialOrd derive /!\
8    /// Where the change happened in the schema. It is dot separated where relevant. For example if
9    /// the change happened in a field argument, the path will be something like
10    /// `ParentTypeName.fieldName.argumentName`.
11    ///
12    /// See [crate::path::Path] for the full documentation.
13    pub path: String,
14    /// The nature of the change.
15    pub kind: ChangeKind,
16    /// Contents depend on the change kind:
17    ///
18    /// - [ChangeQueryType]/[ChangeMutationType]/[ChangeSubscriptionType]: the new type
19    /// - [AddObjectType]/[AddUnion]/[AddEnum]/[AddScalar]/[AddInterface]/[AddInputObject]/[AddSchemaDefinition]/[AddDirectiveDefinition]: the whole definition.
20    /// - [AddInterfaceImplementation]/[RemoveInterfaceImplementation]: empty
21    /// - [ChangeFieldType]/[ChangeFieldArgumentType]: the new type
22    /// - [RemoveObjectType]/[RemoveField]/[RemoveUnion]/[RemoveUnionMember]/[RemoveEnum]/[RemoveScalar]/[RemoveInterface]/[RemoveDirectiveDefinition]/[RemoveSchemaDefinition]/[RemoveInputObject]/[RemoveFieldArgument]/[RemoveFieldArgumentDefault]: empty
23    /// - [AddField]: the whole field definition
24    /// - [AddUnionMember]: the union member added
25    /// - [AddEnumValue]/[RemoveEnumValue]: empty
26    /// - [AddFieldArgument]: the value of the argument, potentially with the default
27    /// - [AddFieldArgumentDefault]/[ChangeFieldArgumentDefault]: the default value of the argument
28    pub span: Span,
29}
30
31#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
32#[allow(missing_docs)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34#[repr(u8)]
35pub enum ChangeKind {
36    // /!\ The order of variants matters for the PartialOrd derive /!\
37    ChangeQueryType,
38    ChangeMutationType,
39    ChangeSubscriptionType,
40    RemoveObjectType,
41    AddObjectType,
42    AddInterfaceImplementation,
43    RemoveInterfaceImplementation,
44    ChangeFieldType,
45    RemoveField,
46    AddField,
47    AddUnion,
48    RemoveUnion,
49    AddUnionMember,
50    RemoveUnionMember,
51    AddEnum,
52    RemoveEnum,
53    AddEnumValue,
54    RemoveEnumValue,
55    AddScalar,
56    RemoveScalar,
57    AddInterface,
58    RemoveInterface,
59    AddDirectiveDefinition,
60    RemoveDirectiveDefinition,
61    AddSchemaDefinition,
62    RemoveSchemaDefinition,
63    AddSchemaExtension,
64    RemoveSchemaExtension,
65    AddInputObject,
66    RemoveInputObject,
67    AddFieldArgument,
68    RemoveFieldArgument,
69    AddFieldArgumentDefault,
70    RemoveFieldArgumentDefault,
71    ChangeFieldArgumentDefault,
72    ChangeFieldArgumentType,
73}
74
75impl ChangeKind {
76    /// The change kind as a string.
77    pub fn as_str(&self) -> &'static str {
78        use ChangeKind::*;
79
80        match self {
81            ChangeQueryType => "ChangeQueryType",
82            ChangeMutationType => "ChangeMutationType",
83            ChangeSubscriptionType => "ChangeSubscriptionType",
84            RemoveObjectType => "RemoveObjectType",
85            AddObjectType => "AddObjectType",
86            AddInterfaceImplementation => "AddInterfaceImplementation",
87            RemoveInterfaceImplementation => "RemoveInterfaceImplementation",
88            ChangeFieldType => "ChangeFieldType",
89            RemoveField => "RemoveField",
90            AddField => "AddField",
91            AddUnion => "AddUnion",
92            RemoveUnion => "RemoveUnion",
93            AddUnionMember => "AddUnionMember",
94            RemoveUnionMember => "RemoveUnionMember",
95            AddEnum => "AddEnum",
96            RemoveEnum => "RemoveEnum",
97            AddEnumValue => "AddEnumValue",
98            RemoveEnumValue => "RemoveEnumValue",
99            AddScalar => "AddScalar",
100            RemoveScalar => "RemoveScalar",
101            AddInterface => "AddInterface",
102            RemoveInterface => "RemoveInterface",
103            AddDirectiveDefinition => "AddDirectiveDefinition",
104            RemoveDirectiveDefinition => "RemoveDirectiveDefinition",
105            AddSchemaDefinition => "AddSchemaDefinition",
106            AddSchemaExtension => "AddSchemaExtension",
107            RemoveSchemaDefinition => "RemoveSchemaDefinition",
108            RemoveSchemaExtension => "RemoveSchemaExtension",
109            AddInputObject => "AddInputObject",
110            RemoveInputObject => "RemoveInputObject",
111            AddFieldArgument => "AddFieldArgument",
112            RemoveFieldArgument => "RemoveFieldArgument",
113            AddFieldArgumentDefault => "AddFieldArgumentDefault",
114            RemoveFieldArgumentDefault => "RemoveFieldArgumentDefault",
115            ChangeFieldArgumentDefault => "ChangeFieldArgumentDefault",
116            ChangeFieldArgumentType => "ChangeFieldArgumentType",
117        }
118    }
119}
120
121impl std::str::FromStr for ChangeKind {
122    type Err = ();
123
124    fn from_str(s: &str) -> Result<Self, Self::Err> {
125        Ok(match s {
126            "ChangeQueryType" => Self::ChangeQueryType,
127            "ChangeMutationType" => Self::ChangeMutationType,
128            "ChangeSubscriptionType" => Self::ChangeSubscriptionType,
129            "RemoveObjectType" => Self::RemoveObjectType,
130            "AddObjectType" => Self::AddObjectType,
131            "AddInterfaceImplementation" => Self::AddInterfaceImplementation,
132            "RemoveInterfaceImplementation" => Self::RemoveInterfaceImplementation,
133            "ChangeFieldType" => Self::ChangeFieldType,
134            "RemoveField" => Self::RemoveField,
135            "AddField" => Self::AddField,
136            "AddUnion" => Self::AddUnion,
137            "RemoveUnion" => Self::RemoveUnion,
138            "AddUnionMember" => Self::AddUnionMember,
139            "RemoveUnionMember" => Self::RemoveUnionMember,
140            "AddEnum" => Self::AddEnum,
141            "RemoveEnum" => Self::RemoveEnum,
142            "AddEnumValue" => Self::AddEnumValue,
143            "RemoveEnumValue" => Self::RemoveEnumValue,
144            "AddScalar" => Self::AddScalar,
145            "RemoveScalar" => Self::RemoveScalar,
146            "AddInterface" => Self::AddInterface,
147            "RemoveInterface" => Self::RemoveInterface,
148            "AddDirectiveDefinition" => Self::AddDirectiveDefinition,
149            "RemoveDirectiveDefinition" => Self::RemoveDirectiveDefinition,
150            "AddSchemaDefinition" => Self::AddSchemaDefinition,
151            "RemoveSchemaDefinition" => Self::RemoveSchemaDefinition,
152            "AddSchemaExtension" => Self::AddSchemaExtension,
153            "RemoveSchemaExtension" => Self::RemoveSchemaExtension,
154            "AddInputObject" => Self::AddInputObject,
155            "RemoveInputObject" => Self::RemoveInputObject,
156            "AddFieldArgument" => Self::AddFieldArgument,
157            "RemoveFieldArgument" => Self::RemoveFieldArgument,
158            "AddFieldArgumentDefault" => Self::AddFieldArgumentDefault,
159            "RemoveFieldArgumentDefault" => Self::RemoveFieldArgumentDefault,
160            "ChangeFieldArgumentDefault" => Self::ChangeFieldArgumentDefault,
161            "ChangeFieldArgumentType" => Self::ChangeFieldArgumentType,
162            _ => return Err(()),
163        })
164    }
165}
166
167/// A span in a source file.
168#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug, serde::Serialize, serde::Deserialize, Copy)]
169pub struct Span {
170    /// The byte offset where the span starts.
171    pub start: usize,
172    /// The byte offset where the span stops (exclusive).
173    pub end: usize,
174}
175
176impl Span {
177    /// Create a span from start and end.
178    pub fn new(start: usize, end: usize) -> Self {
179        Span { start, end }
180    }
181
182    pub(crate) const fn empty() -> Span {
183        Span { start: 0, end: 0 }
184    }
185}
186
187impl From<cynic_parser::Span> for Span {
188    fn from(cynic_parser::Span { start, end }: cynic_parser::Span) -> Self {
189        Span { start, end }
190    }
191}
192
193impl std::ops::Index<Span> for str {
194    type Output = str;
195
196    fn index(&self, Span { start, end }: Span) -> &Self::Output {
197        &self[start..end]
198    }
199}