cynic_parser/
lib.rs

1pub mod common;
2pub mod executable;
3pub mod type_system;
4pub mod values;
5
6mod errors;
7mod lexer;
8mod span;
9
10#[allow(clippy::all)]
11mod parser;
12
13#[cfg(feature = "print")]
14pub mod printing;
15
16#[cfg(feature = "report")]
17pub use errors::Report;
18
19pub use self::{
20    errors::Error,
21    executable::ExecutableDocument,
22    span::Span,
23    type_system::TypeSystemDocument,
24    values::{ConstValue, Value},
25};
26
27pub fn parse_type_system_document(input: &str) -> Result<TypeSystemDocument, Error> {
28    if input.trim().is_empty() {
29        return Err(Error::EmptyTypeSystemDocument);
30    }
31
32    let lexer = lexer::Lexer::new(input);
33    let mut ast = type_system::writer::TypeSystemAstWriter::new();
34
35    parser::TypeSystemDocumentParser::new().parse(input, &mut ast, lexer)?;
36
37    Ok(ast.finish())
38}
39
40pub fn parse_executable_document(input: &str) -> Result<ExecutableDocument, Error> {
41    if input.trim().is_empty() {
42        return Err(Error::EmptyExecutableDocument);
43    }
44
45    let lexer = lexer::Lexer::new(input);
46    let mut ast = executable::writer::ExecutableAstWriter::new();
47
48    parser::ExecutableDocumentParser::new().parse(input, &mut ast, lexer)?;
49
50    Ok(ast.finish())
51}
52
53trait AstLookup<Id> {
54    type Output: ?Sized;
55
56    fn lookup(&self, index: Id) -> &Self::Output;
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn it_works() {
65        insta::assert_snapshot!(
66            parse_type_system_document("schema { query:Query }").unwrap().to_sdl_pretty(),
67            @r###"
68        schema {
69          query: Query
70        }
71        "###
72        );
73    }
74
75    #[test]
76    fn test_basic_object() {
77        insta::assert_snapshot!(
78            parse_type_system_document(r#"
79                type MyType implements Blah & Bloo @hello {
80                    field: Whatever @hello(name: ["string"]),
81                    other: [[Int!]]!
82                }"#
83            ).unwrap().to_sdl_pretty(),
84            @r###"
85        type MyType implements Blah & Bloo @hello {
86          field: Whatever @hello(name: ["string"])
87          other: [[Int!]]!
88        }
89        "###
90        );
91    }
92
93    #[test]
94    fn test_basic_interface() {
95        insta::assert_snapshot!(
96            parse_type_system_document(r#"
97                interface MyType implements Blah & Bloo @hello {
98                    field: Whatever @hello(name: ["string"]),
99                    other: [[Int!]]!
100                }"#
101            ).unwrap().to_sdl_pretty(),
102            @r###"
103        interface MyType implements Blah & Bloo @hello {
104          field: Whatever @hello(name: ["string"])
105          other: [[Int!]]!
106        }
107        "###
108        );
109    }
110
111    #[test]
112    fn test_basic_union() {
113        insta::assert_snapshot!(
114            parse_type_system_document(r#"
115                union MyType = Blah | Bloo
116                "#
117            ).unwrap().to_sdl_pretty(),
118            @r###"
119        union MyType = Blah | Bloo
120
121        "###
122        );
123    }
124
125    #[test]
126    fn test_basic_scalar() {
127        insta::assert_snapshot!(
128            parse_type_system_document(r#"
129                scalar MyType @hello(there: [{thing: "other"}])
130                "#
131            ).unwrap().to_sdl_pretty(),
132            @r###"
133        scalar MyType @hello(there: [{ thing: "other" }])
134        "###
135        );
136    }
137
138    #[test]
139    fn test_basic_enum() {
140        insta::assert_snapshot!(
141            parse_type_system_document(r#"
142                enum MyEnum {
143                    BLAH,
144                    BLOO
145                }
146                "#
147            ).unwrap().to_sdl_pretty(),
148            @r###"
149        enum MyEnum {
150          BLAH
151          BLOO
152        }
153        "###
154        );
155    }
156
157    #[test]
158    fn test_schema_field() {
159        // Use a keyword as a field name and make sure it's fine
160        insta::assert_snapshot!(
161            parse_type_system_document( "type MyType { query: String }").unwrap().to_sdl_pretty(),
162            @r###"
163        type MyType {
164          query: String
165        }
166        "###
167        )
168    }
169
170    #[test]
171    fn test_input() {
172        insta::assert_snapshot!(
173            parse_type_system_document(
174                r#"
175                "I am a description"
176                input MyType @hello { query: String = "Hello" }
177                "#
178            ).unwrap().to_sdl_pretty(),
179            @r###"
180        "I am a description"
181        input MyType @hello {
182          query: String = "Hello"
183        }
184        "###
185        );
186    }
187}