Skip to content

Commit 75488cb

Browse files
committed
feat: impl Iterator for errors
fixes #139 ast.errors() now return an `impl ExactSizeIterator` which allows us to iterate, but also check for the `len()`. It should allow us to use `is_empty()` as well eventually, if / when rust-lang/rust#35428 lands.
1 parent fcbf490 commit 75488cb

File tree

13 files changed

+59
-51
lines changed

13 files changed

+59
-51
lines changed

crates/apollo-parser/README.md

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,31 @@
1818
</div>
1919

2020
## Features
21-
* Typed GraphQL AST as per [October 2021 specification]
22-
* Error resilience
23-
* lexing and parsing does not fail or `panic` if a lexical or a syntax error is found
24-
* GraphQL lexer
25-
* GraphQL parser
21+
22+
- Typed GraphQL AST as per [October 2021 specification]
23+
- Error resilience
24+
- lexing and parsing does not fail or `panic` if a lexical or a syntax error is found
25+
- GraphQL lexer
26+
- GraphQL parser
2627

2728
## Getting started
29+
2830
Add this to your `Cargo.toml` to start using `apollo-parser`:
31+
2932
```toml
3033
# Just an example, change to the necessary package version.
3134
[dependencies]
3235
apollo_parser = "0.1.0"
3336
```
3437

3538
Or using [cargo-edit]:
39+
3640
```bash
3741
cargo add apollo_parser
3842
```
3943

4044
## Usage
45+
4146
`apollo-parser` is built to parse both GraphQL schemas and queries according to the latest [October 2021 specification]. It produces
4247
a typed syntax tree that then can we walked extracting all the necessary
4348
information. You can quick start with:
@@ -63,7 +68,7 @@ fn main() {
6368
let ast = parser.parse();
6469

6570
// ast.errors() returns an errors slice encountered during lexing and parsing
66-
assert!(ast.errors().is_empty());
71+
assert_eq!(0, ast.errors().len());
6772

6873
// ast.document() get the Document, or root node, of the tree that you can
6974
// start iterating on.
@@ -73,15 +78,17 @@ fn main() {
7378

7479
### Examples
7580

76-
Two examples outlined here:
77-
* [Get field names in an object]
78-
* [Get variables used in a query]
81+
Two examples outlined here:
82+
83+
- [Get field names in an object]
84+
- [Get variables used in a query]
7985

8086
The [examples directory] in this repository has a few more useful
8187
implementations such as:
82-
* [using apollo-rs with miette to display error diagnostics]
83-
* [using apollo-rs with annotate_snippets to display error diagnostics]
84-
* [checking for unused variables]
88+
89+
- [using apollo-rs with miette to display error diagnostics]
90+
- [using apollo-rs with annotate_snippets to display error diagnostics]
91+
- [checking for unused variables]
8592

8693
#### Get field names in an object
8794

@@ -97,10 +104,10 @@ fn main() {
97104
";
98105
let parser = Parser::new(input);
99106
let ast = parser.parse();
100-
assert!(ast.errors().is_empty());
101-
107+
assert_eq!(0, ast.errors().len());
108+
102109
let doc = ast.document();
103-
110+
104111
for def in doc.definitions() {
105112
if let ast::Definition::ObjectTypeDefinition(object_type) = def {
106113
assert_eq!(object_type.name().unwrap().text(), "ProductDimension");
@@ -112,7 +119,7 @@ fn main() {
112119
}
113120
```
114121

115-
#### Get variables used in a query
122+
#### Get variables used in a query
116123

117124
```rust
118125
use apollo_parser::{ast, Parser};
@@ -127,17 +134,17 @@ fn main() {
127134
}
128135
}
129136
";
130-
137+
131138
let parser = Parser::new(input);
132139
let ast = parser.parse();
133-
assert!(&ast.errors().is_empty());
134-
140+
assert_eq!(0, &ast.errors().len());
141+
135142
let doc = ast.document();
136-
143+
137144
for def in doc.definitions() {
138145
if let ast::Definition::OperationDefinition(op_def) = def {
139146
assert_eq!(op_def.name().unwrap().text(), "GraphQuery");
140-
147+
141148
let variable_defs = op_def.variable_definitions();
142149
let variables: Vec<String> = variable_defs
143150
.iter()
@@ -155,6 +162,7 @@ fn main() {
155162
```
156163

157164
## License
165+
158166
Licensed under either of
159167

160168
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
@@ -163,16 +171,17 @@ Licensed under either of
163171
at your option.
164172

165173
#### Contribution
174+
166175
Unless you explicitly state otherwise, any contribution intentionally submitted
167176
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
168177
dual licensed as above, without any additional terms or conditions.
169178

170179
[cargo-edit]: https://github.com/killercup/cargo-edit
171-
[apollo-rs: spec-compliant GraphQL Tools in Rust]: https://www.apollographql.com/blog/announcement/tooling/apollo-rs-graphql-tools-in-rust/
180+
[apollo-rs: spec-compliant graphql tools in rust]: https://www.apollographql.com/blog/announcement/tooling/apollo-rs-graphql-tools-in-rust/
172181
[examples directory]: https://github.com/apollographql/apollo-rs/tree/main/crates/apollo-parser/examples
173-
[Get field names in an object]: https://github.com/apollographql/apollo-rs#get-field-names-in-an-object
174-
[Get variables used in a query]: https://github.com/apollographql/apollo-rs#get-variables-used-in-a-query
182+
[get field names in an object]: https://github.com/apollographql/apollo-rs#get-field-names-in-an-object
183+
[get variables used in a query]: https://github.com/apollographql/apollo-rs#get-variables-used-in-a-query
175184
[using apollo-rs with miette to display error diagnostics]: https://github.com/apollographql/apollo-rs/blob/a7f616454a53dcb8496725ceac6c63eacddefb2c/crates/apollo-parser/examples/miette.rs
176185
[using apollo-rs with annotate_snippets to display error diagnostics]: https://github.com/apollographql/apollo-rs/blob/a7f616454a53dcb8496725ceac6c63eacddefb2c/crates/apollo-parser/examples/annotate_snippet.rs
177186
[checking for unused variables]: https://github.com/apollographql/apollo-rs/blob/a7f616454a53dcb8496725ceac6c63eacddefb2c/crates/apollo-parser/examples/unused_vars.rs
178-
[October 2021 specification]: https://spec.graphql.org/October2021
187+
[october 2021 specification]: https://spec.graphql.org/October2021

crates/apollo-parser/examples/unused_vars.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn are_variables_unused() {
1111
let parser = Parser::new(&src);
1212
let ast = parser.parse();
1313

14-
assert!(&ast.errors().is_empty());
14+
assert_eq!(0, ast.errors().len());
1515

1616
let doc = ast.document();
1717

crates/apollo-parser/src/ast/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
//! let parser = Parser::new(schema);
4343
//! let ast = parser.parse();
4444
//!
45-
//! assert!(ast.errors().is_empty());
45+
//! assert_eq!(0, ast.errors().len());
4646
//! let document = ast.document();
4747
//! for definition in document.definitions() {
4848
//! match definition {

crates/apollo-parser/src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::fmt;
1616
/// let parser = Parser::new(input);
1717
/// let ast = parser.parse();
1818
///
19-
/// assert!(ast.errors().is_empty());
19+
/// assert_eq!(0, ast.errors().len());
2020
///
2121
/// let doc = ast.document();
2222
/// ```

crates/apollo-parser/src/lexer/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ impl Lexer {
5959
}
6060

6161
/// Get a reference to the lexer's tokens.
62-
pub(crate) fn errors(&self) -> &[Error] {
63-
self.errors.as_slice()
62+
pub(crate) fn errors<'e>(&'e self) -> impl ExactSizeIterator<Item = &'e Error> {
63+
self.errors.iter()
6464
}
6565
}
6666

crates/apollo-parser/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
//! let ast = parser.parse();
6363
//!
6464
//! // ast.errors() returns an errors slice encountered during lexing and parsing
65-
//! assert!(ast.errors().is_empty());
65+
//! assert_eq!(0, ast.errors().len());
6666
//!
6767
//! // ast.document() get the Document, or root node, of the tree that you can
6868
//! // start iterating on.
@@ -94,7 +94,7 @@
9494
//! ";
9595
//! let parser = Parser::new(input);
9696
//! let ast = parser.parse();
97-
//! assert!(ast.errors().is_empty());
97+
//! assert_eq!(0, ast.errors().len());
9898
//!
9999
//! let doc = ast.document();
100100
//!
@@ -125,7 +125,7 @@
125125
//!
126126
//! let parser = Parser::new(input);
127127
//! let ast = parser.parse();
128-
//! assert!(&ast.errors().is_empty());
128+
//! assert_eq!(0, ast.errors().len());
129129
//!
130130
//! let doc = ast.document();
131131
//!

crates/apollo-parser/src/parser/grammar/object.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ type Business implements NamedEntity & ValuedEntity & CatEntity {
131131
}";
132132
let parser = Parser::new(input);
133133
let ast = parser.parse();
134-
assert!(ast.errors().is_empty());
134+
assert_eq!(0, ast.errors().len());
135135

136136
let doc = ast.document();
137137

crates/apollo-parser/src/parser/grammar/selection.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ mod test {
6868
";
6969
let parser = Parser::new(input);
7070
let ast = parser.parse();
71-
assert!(&ast.errors().is_empty());
71+
assert_eq!(0, ast.errors().len());
7272

7373
let doc = ast.document();
7474

@@ -129,7 +129,7 @@ query GraphQuery($graph_id: ID!, $variant: String) {
129129
";
130130
let parser = Parser::new(input);
131131
let ast = parser.parse();
132-
assert!(&ast.errors().is_empty());
132+
assert_eq!(0, ast.errors().len());
133133

134134
let doc = ast.document();
135135

crates/apollo-parser/src/parser/grammar/union_.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ mod test {
112112
let input = "union SearchResult = Photo | Person | Cat | Dog";
113113
let parser = Parser::new(input);
114114
let ast = parser.parse();
115-
assert!(ast.errors().is_empty());
115+
assert_eq!(0, ast.errors().len());
116116

117117
let doc = ast.document();
118118

crates/apollo-parser/src/parser/grammar/value.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ query GraphQuery($graph_id: ID!, $variant: String) {
270270
";
271271
let parser = Parser::new(input);
272272
let ast = parser.parse();
273-
assert!(&ast.errors().is_empty());
273+
assert_eq!(0, ast.errors().len());
274274

275275
let doc = ast.document();
276276

crates/apollo-parser/src/parser/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub(crate) use token_text::TokenText;
4242
/// // Parse the query, and return a SyntaxTree.
4343
/// let ast = parser.parse();
4444
/// // Check that are no errors. These are not part of the AST.
45-
/// assert!(&ast.errors().is_empty());
45+
/// assert_eq!(0, ast.errors().len());
4646
///
4747
/// // Get the document root node
4848
/// let doc = ast.document();
@@ -65,7 +65,7 @@ pub(crate) use token_text::TokenText;
6565
/// let parser = Parser::new(core_schema);
6666
/// let ast = parser.parse();
6767
///
68-
/// assert!(ast.errors().is_empty());
68+
/// assert_eq!(0, ast.errors().len());
6969
///
7070
/// let document = ast.document();
7171
/// ```
@@ -91,7 +91,7 @@ impl Parser {
9191
tokens.push(s);
9292
}
9393

94-
for e in lexer.errors().to_owned() {
94+
for e in lexer.errors().cloned() {
9595
errors.push(e);
9696
}
9797

crates/apollo-parser/src/parser/syntax_tree.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ pub struct SyntaxTree {
4444

4545
impl SyntaxTree {
4646
/// Get a reference to the syntax tree's errors.
47-
pub fn errors(&self) -> &[crate::Error] {
48-
self.errors.as_ref()
47+
pub fn errors(&self) -> impl ExactSizeIterator<Item = &crate::Error> {
48+
self.errors.iter()
4949
}
5050

5151
/// Return the root typed `Document` node.
@@ -159,7 +159,7 @@ mod test {
159159
";
160160
let parser = Parser::new(input);
161161
let ast = parser.parse();
162-
assert!(ast.errors().is_empty());
162+
assert_eq!(0, ast.errors().len());
163163

164164
let doc = ast.document();
165165

crates/apollo-parser/src/tests.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,24 @@ fn parser_tests() {
5252
});
5353
}
5454

55-
fn assert_errors_are_present(errors: &[Error], path: &Path) {
55+
fn assert_errors_are_present<'e>(errors: impl ExactSizeIterator<Item = &'e Error>, path: &Path) {
5656
assert!(
57-
!errors.is_empty(),
57+
errors.len() != 0,
5858
"There should be errors in the file {:?}",
5959
path.display()
6060
);
6161
}
6262

63-
fn assert_errors_are_absent(errors: &[Error], path: &Path) {
64-
assert_eq!(
65-
errors,
66-
&[] as &[Error],
63+
fn assert_errors_are_absent<'e>(errors: impl ExactSizeIterator<Item = &'e Error>, path: &Path) {
64+
assert!(
65+
errors.len() == 0,
6766
"There should be no errors in the file {:?}",
6867
path.display(),
6968
);
7069
}
7170

7271
/// Concatenate tokens and erorrs.
73-
fn dump_tokens_and_errors(tokens: &[Token], errors: &[Error]) -> String {
72+
fn dump_tokens_and_errors<'e>(tokens: &[Token], errors: impl Iterator<Item = &'e Error>) -> String {
7473
let mut acc = String::new();
7574
for token in tokens {
7675
writeln!(acc, "{:?}", token).unwrap();

0 commit comments

Comments
 (0)