Skip to content

Commit b0cf72e

Browse files
gabotechsgabotechs
authored andcommitted
feat: accept directives in schema
1 parent c0cad31 commit b0cf72e

File tree

3 files changed

+63
-10
lines changed

3 files changed

+63
-10
lines changed

graphqxl_parser/src/ast_schema.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
use crate::ast_description::{parse_description_and_continue, DescriptionAndNext};
2+
use crate::ast_directive::parse_directive;
23
use crate::ast_identifier::{parse_identifier, Identifier};
34
use crate::parser::Rule;
45
use crate::utils::{unknown_rule_error, OwnedSpan};
6+
use crate::Directive;
57
use pest::iterators::Pair;
68

79
#[derive(Debug, Clone, PartialEq, Default)]
810
pub struct Schema {
911
pub span: OwnedSpan,
1012
pub description: String,
11-
// TODO: add directives
13+
pub directives: Vec<Directive>,
1214
pub query: Identifier,
1315
pub mutation: Identifier,
1416
pub subscription: Identifier,
@@ -38,6 +40,11 @@ impl Schema {
3840
self.description = description.to_string();
3941
self.clone()
4042
}
43+
44+
pub fn directive(&mut self, directive: Directive) -> Self {
45+
self.directives.push(directive);
46+
self.clone()
47+
}
4148
}
4249

4350
enum SchemaKey {
@@ -68,11 +75,16 @@ pub(crate) fn parse_schema(
6875
Rule::schema_def => {
6976
let span = OwnedSpan::from(pair.as_span(), file);
7077
let mut childs = pair.into_inner();
71-
let DescriptionAndNext(description, next) =
78+
let DescriptionAndNext(description, mut next) =
7279
parse_description_and_continue(&mut childs, file);
7380
let mut query = Identifier::from("");
7481
let mut mutation = Identifier::from("");
7582
let mut subscription = Identifier::from("");
83+
let mut directives = vec![];
84+
while let Rule::directive = next.as_rule() {
85+
directives.push(parse_directive(next, file)?);
86+
next = childs.next().unwrap();
87+
}
7688
for field in next.into_inner() {
7789
let mut field_parts = field.into_inner();
7890
let key = parse_schema_key(field_parts.next().unwrap(), file)?;
@@ -85,6 +97,7 @@ pub(crate) fn parse_schema(
8597
}
8698
Ok(Schema {
8799
span,
100+
directives,
88101
description,
89102
query,
90103
mutation,
@@ -112,6 +125,27 @@ mod tests {
112125
)
113126
}
114127

128+
#[test]
129+
fn test_accepts_directive() {
130+
assert_eq!(
131+
parse_input("schema @dir { query: Query }"),
132+
Ok(Schema::build()
133+
.query("Query")
134+
.directive(Directive::build("dir")))
135+
)
136+
}
137+
138+
#[test]
139+
fn test_accepts_two_directives() {
140+
assert_eq!(
141+
parse_input("schema @dir1 @dir2 { query: Query }"),
142+
Ok(Schema::build()
143+
.query("Query")
144+
.directive(Directive::build("dir1"))
145+
.directive(Directive::build("dir2")))
146+
)
147+
}
148+
115149
#[test]
116150
fn test_parses_query_with_description() {
117151
assert_eq!(

graphqxl_parser/src/grammar.pest

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ filename = @{ "\"" ~ (!("\n" | "\r\n") ~ char_no_double_quote)* ~ "\"" }
55

66
def = _{ schema_def | type_def | generic_type_def | input_def | generic_input_def | enum_def | interface_def | scalar_def | union_def | directive_def }
77

8-
schema_def = { description? ~ "schema" ~ schema_selection_set }
8+
schema_def = { description? ~ "schema" ~ directive* ~ schema_selection_set }
99
schema_key = @{ "query" | "mutation" | "subscription" }
1010
schema_selection_set = { "{" ~ schema_field+ ~ "}"}
1111
schema_field = { schema_key ~ ":" ~ identifier }

graphqxl_synthesizer/src/synth_schema.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::synth_description::DescriptionSynth;
2+
use crate::synth_directive::DirectiveSynth;
23
use crate::synths::{ChainSynth, MultilineListSynth, PairSynth, StringSynth};
34
use crate::{Synth, SynthContext};
45
use graphqxl_parser::Schema;
@@ -23,13 +24,16 @@ impl Synth for SchemaSynth {
2324
if to_include.is_empty() {
2425
return false;
2526
}
26-
let pair_synth = PairSynth::top_level(
27-
DescriptionSynth::text(&self.0.description),
28-
ChainSynth(vec![
29-
Box::new(StringSynth::from("schema ")),
30-
Box::new(MultilineListSynth::no_suffix(("{", to_include, "}"))),
31-
]),
32-
);
27+
let mut v: Vec<Box<dyn Synth>> = vec![Box::new(StringSynth::from("schema "))];
28+
for directive in self.0.directives.iter() {
29+
v.push(Box::new(DirectiveSynth(directive.clone())));
30+
v.push(Box::new(StringSynth::from(" ")));
31+
}
32+
v.push(Box::new(MultilineListSynth::no_suffix((
33+
"{", to_include, "}",
34+
))));
35+
let pair_synth =
36+
PairSynth::top_level(DescriptionSynth::text(&self.0.description), ChainSynth(v));
3337
pair_synth.synth(context)
3438
}
3539
}
@@ -38,13 +42,28 @@ impl Synth for SchemaSynth {
3842
mod tests {
3943
use super::*;
4044
use crate::SynthConfig;
45+
use graphqxl_parser::Directive;
4146

4247
#[test]
4348
fn test_with_query() {
4449
let synth = SchemaSynth(Schema::build().query("Query"));
4550
assert_eq!(synth.synth_zero(), "schema {\n query: Query\n}")
4651
}
4752

53+
#[test]
54+
fn test_with_query_and_directives() {
55+
let synth = SchemaSynth(
56+
Schema::build()
57+
.query("Query")
58+
.directive(Directive::build("dir1"))
59+
.directive(Directive::build("dir2")),
60+
);
61+
assert_eq!(
62+
synth.synth_zero(),
63+
"schema @dir1 @dir2 {\n query: Query\n}"
64+
)
65+
}
66+
4867
#[test]
4968
fn test_with_query_mutation_subscription() {
5069
let synth = SchemaSynth(

0 commit comments

Comments
 (0)