Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ env:
CARGO_TERM_COLOR: always

jobs:
msrv:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install Rust 1.88.0
run: rustup toolchain install 1.88.0 --profile minimal
- name: Check minimum Rust version
run: cargo +1.88.0 check --workspace --all-targets --all-features

lint:
runs-on: ubuntu-latest
steps:
Expand Down
5 changes: 2 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ resolver = "2"

[workspace.package]
version = "0.3.1"
rust-version = "1.88"

[workspace.lints.clippy]
wildcard_imports = "deny"
Expand All @@ -26,7 +27,7 @@ bluejay-printer = { path = "./bluejay-printer", version = "=0.3.1" }
bluejay-schema-comparator = { path = "./bluejay-schema-comparator", version = "=0.3.1" }
bluejay-typegen = { path = "./bluejay-typegen", version = "=0.3.1" }
bluejay-typegen-codegen = { path = "./bluejay-typegen-codegen", version = "=0.3.1" }
bluejay-typegen-macro = { path = "./bluejay-typegen-macro", version = "=0.3.1" }
bluejay-typegen-macro = { path = "./bluejay-typegen-macro", version = "=0.3.1", default-features = false }
bluejay-validator = { path = "./bluejay-validator", version = "=0.3.1" }
bluejay-operation-normalizer = { path = "./bluejay-operation-normalizer", version = "=0.3.1" }
bluejay-visibility = { path = "./bluejay-visibility", version = "=0.3.1" }
Expand Down
1 change: 1 addition & 0 deletions bluejay-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "bluejay-core"
version.workspace = true
rust-version.workspace = true
edition = "2021"
license = "MIT"
repository = "https://github.com/Shopify/bluejay"
Expand Down
2 changes: 1 addition & 1 deletion bluejay-core/src/definition/schema_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub trait SchemaDefinition:
fn get_type_definition(
&self,
name: &str,
) -> Option<TypeDefinitionReference<Self::TypeDefinition>>;
) -> Option<TypeDefinitionReference<'_, Self::TypeDefinition>>;
fn type_definitions(&self) -> Self::TypeDefinitions<'_>;
fn get_directive_definition(&self, name: &str) -> Option<&Self::DirectiveDefinition>;
fn directive_definitions(&self) -> Self::DirectiveDefinitions<'_>;
Expand Down
1 change: 1 addition & 0 deletions bluejay-operation-normalizer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "bluejay-operation-normalizer"
version.workspace = true
rust-version.workspace = true
edition = "2021"
license = "MIT"
repository = "https://github.com/Shopify/bluejay"
Expand Down
2 changes: 1 addition & 1 deletion bluejay-operation-normalizer/benches/normalize.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bluejay_parser::ast::{executable::ExecutableDocument, Parse};
use criterion::{criterion_group, criterion_main, Criterion};

fn parse(input: &str) -> ExecutableDocument {
fn parse(input: &str) -> ExecutableDocument<'_> {
ExecutableDocument::parse(input)
.result
.expect("parse error")
Expand Down
90 changes: 45 additions & 45 deletions bluejay-operation-normalizer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,54 +22,54 @@
//! each selection. This is a single bottom-up pass that builds and normalizes each level
//! before returning it to the parent:
//!
//! a. **Fields** — collect the field name (dropping any alias), sorted argument names,
//! sorted directives, and recursively normalized child selections.
//! ```graphql
//! # input
//! { myAlias: field(z: 1, a: 2) }
//! # normalized
//! query{field(a:,z:)}
//! ```
//! - **Fields** — collect the field name (dropping any alias), sorted argument names,
//! sorted directives, and recursively normalized child selections.
//! ```graphql
//! # input
//! { myAlias: field(z: 1, a: 2) }
//! # normalized
//! query{field(a:,z:)}
//! ```
//!
//! b. **Fragment spreads** — expand inline: replace `...FragName` with
//! `... on <TypeCondition> { <selections> }`, merging directives from both the spread
//! and the fragment definition. Unused fragments are naturally excluded. Cycles are
//! detected via a stack of currently-expanding fragment names.
//! ```graphql
//! # input
//! { ...F }
//! fragment F on User { name }
//! # normalized — spread replaced with inline fragment, named fragment dropped
//! query{...on User{name}}
//! ```
//! - **Fragment spreads** — expand inline: replace `...FragName` with
//! `... on <TypeCondition> { <selections> }`, merging directives from both the spread
//! and the fragment definition. Unused fragments are naturally excluded. Cycles are
//! detected via a stack of currently-expanding fragment names.
//! ```graphql
//! # input
//! { ...F }
//! fragment F on User { name }
//! # normalized — spread replaced with inline fragment, named fragment dropped
//! query{...on User{name}}
//! ```
//!
//! c. **Inline fragments** — if bare (no type condition, no directives), flatten their
//! children directly into the parent selection set. Otherwise, keep as-is.
//! ```graphql
//! # input — bare inline fragment (no type condition, no directives)
//! { ... { name email } }
//! # normalized — children flattened into parent
//! query{email name}
//! ```
//! - **Inline fragments** — if bare (no type condition, no directives), flatten their
//! children directly into the parent selection set. Otherwise, keep as-is.
//! ```graphql
//! # input — bare inline fragment (no type condition, no directives)
//! { ... { name email } }
//! # normalized — children flattened into parent
//! query{email name}
//! ```
//!
//! d. **Merge inline fragments** — at each level, merge inline fragments that share the
//! same `(type_condition, directives)` pair into a single inline fragment, combining
//! their child selections.
//! ```graphql
//! # input — two inline fragments on same type
//! { ... on User { name } ... on User { email } }
//! # normalized — merged into one
//! query{...on User{email name}}
//! ```
//! - **Merge inline fragments** — at each level, merge inline fragments that share the
//! same `(type_condition, directives)` pair into a single inline fragment, combining
//! their child selections.
//! ```graphql
//! # input — two inline fragments on same type
//! { ... on User { name } ... on User { email } }
//! # normalized — merged into one
//! query{...on User{email name}}
//! ```
//!
//! e. **Sort selections** — fields first (alphabetically by field name), then inline
//! fragments (by type condition, then by directives).
//! ```graphql
//! # input
//! { z a ... on User { b } m }
//! # normalized — fields sorted first, then inline fragments
//! query{a m z ...on User{b}}
//! ```
//! - **Sort selections** — fields first (alphabetically by field name), then inline
//! fragments (by type condition, then by directives).
//! ```graphql
//! # input
//! { z a ... on User { b } m }
//! # normalized — fields sorted first, then inline fragments
//! query{a m z ...on User{b}}
//! ```
//!
//! 3. **Serialize** the normalized IR to a compact canonical string:
//! - Operation type keyword (`query`, `mutation`, `subscription`) with no name.
Expand Down Expand Up @@ -147,7 +147,7 @@ mod tests {
use super::*;
use bluejay_parser::ast::{executable::ExecutableDocument as ParserDoc, Parse};

fn parse(input: &str) -> ParserDoc {
fn parse(input: &str) -> ParserDoc<'_> {
ParserDoc::parse(input).result.expect("parse error")
}

Expand Down
1 change: 1 addition & 0 deletions bluejay-parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "bluejay-parser"
version.workspace = true
rust-version.workspace = true
edition = "2021"
license = "MIT"
repository = "https://github.com/Shopify/bluejay"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct ExplicitSchemaDefinition<'a, C: Context> {
impl<'a, C: Context> ExplicitSchemaDefinition<'a, C> {
pub(crate) const SCHEMA_IDENTIFIER: &'static str = "schema";

pub(crate) fn description(&self) -> Option<&StringValue> {
pub(crate) fn description(&self) -> Option<&StringValue<'_>> {
self.description.as_ref()
}

Expand Down
4 changes: 2 additions & 2 deletions bluejay-parser/src/ast/executable/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ impl<'a> Field<'a> {
&self.name
}

pub fn arguments(&self) -> Option<&VariableArguments> {
pub fn arguments(&self) -> Option<&VariableArguments<'_>> {
self.arguments.as_ref()
}

pub fn selection_set(&self) -> Option<&SelectionSet> {
pub fn selection_set(&self) -> Option<&SelectionSet<'_>> {
self.selection_set.as_ref()
}
}
Expand Down
2 changes: 1 addition & 1 deletion bluejay-parser/src/ast/executable/fragment_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ impl<'a> FragmentDefinition<'a> {
&self.type_condition
}

pub fn selection_set(&self) -> &SelectionSet {
pub fn selection_set(&self) -> &SelectionSet<'_> {
&self.selection_set
}
}
Expand Down
2 changes: 1 addition & 1 deletion bluejay-parser/src/ast/executable/type_condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl<'a> IsMatch<'a> for TypeCondition<'a> {
impl TypeCondition<'_> {
pub(crate) const ON: &'static str = "on";

pub fn named_type(&self) -> &Name {
pub fn named_type(&self) -> &Name<'_> {
&self.named_type
}
}
6 changes: 3 additions & 3 deletions bluejay-parser/src/ast/executable/variable_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ impl<'a> FromTokens<'a> for VariableDefinition<'a> {
}

impl VariableDefinition<'_> {
pub fn variable(&self) -> &Variable {
pub fn variable(&self) -> &Variable<'_> {
&self.variable
}

pub fn r#type(&self) -> &VariableType {
pub fn r#type(&self) -> &VariableType<'_> {
&self.r#type
}

pub fn default_value(&self) -> Option<&ConstValue> {
pub fn default_value(&self) -> Option<&ConstValue<'_>> {
self.default_value.as_ref()
}
}
Expand Down
8 changes: 4 additions & 4 deletions bluejay-parser/src/ast/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub trait Tokens<'a>: Iterator<Item = LexicalToken<'a>> {
fn next_if_name(&mut self) -> Option<Name<'a>>;
fn next_if_name_matches(&mut self, name: &str) -> Option<Span>;
fn peek_variable_name(&mut self, n: usize) -> bool;
fn peek_name(&mut self, n: usize) -> Option<&Name>;
fn peek_name(&mut self, n: usize) -> Option<&Name<'_>>;
fn peek_name_matches(&mut self, n: usize, name: &str) -> bool;
fn peek_string_value(&mut self, n: usize) -> bool;
fn peek_punctuator_matches(&mut self, n: usize, punctuator_type: PunctuatorType) -> bool;
Expand Down Expand Up @@ -56,7 +56,7 @@ impl<'a, T: Lexer<'a>> LexerTokens<'a, T> {
}

#[inline]
pub fn peek_next(&mut self) -> Option<&LexicalToken> {
pub fn peek_next(&mut self) -> Option<&LexicalToken<'_>> {
self.peek(0)
}

Expand Down Expand Up @@ -201,7 +201,7 @@ impl<'a, T: Lexer<'a>> LexerTokens<'a, T> {
}

#[inline]
pub fn peek_name(&mut self, n: usize) -> Option<&Name> {
pub fn peek_name(&mut self, n: usize) -> Option<&Name<'_>> {
self.peek(n).and_then(LexicalToken::as_name)
}

Expand Down Expand Up @@ -304,7 +304,7 @@ impl<'a, T: Lexer<'a>> Tokens<'a> for LexerTokens<'a, T> {
}

#[inline]
fn peek_name(&mut self, n: usize) -> Option<&Name> {
fn peek_name(&mut self, n: usize) -> Option<&Name<'_>> {
self.peek_name(n)
}

Expand Down
2 changes: 1 addition & 1 deletion bluejay-parser/src/lexer/logos_lexer/block_string_lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl Token {
let common_indent = lines[1..]
.iter()
.filter_map(|&(start, end)| {
let line_bytes = raw[start..end].as_bytes();
let line_bytes = &raw.as_bytes()[start..end];
let indent = line_bytes.iter().position(|&b| b != b' ' && b != b'\t');
indent // None means all-whitespace, filtered out
})
Expand Down
1 change: 1 addition & 0 deletions bluejay-printer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "bluejay-printer"
version.workspace = true
rust-version.workspace = true
edition = "2021"
license = "MIT"
repository = "https://github.com/Shopify/bluejay"
Expand Down
1 change: 1 addition & 0 deletions bluejay-schema-comparator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "bluejay-schema-comparator"
version.workspace = true
rust-version.workspace = true
edition = "2021"
license = "MIT"
repository = "https://github.com/Shopify/bluejay"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ impl<'a, S: SchemaDefinition + 'a> DirectiveDefinitionArgumentDiff<'a, S> {
self.old_argument_definition.default_value(),
self.new_argument_definition.default_value(),
) {
(Some(old_default), Some(new_default)) => {
if old_default.as_ref() != new_default.as_ref() {
changes.push(Change::DirectiveDefinitionArgumentDefaultValueChanged {
directive_definition: self.directive_definition,
old_argument_definition: self.old_argument_definition,
new_argument_definition: self.new_argument_definition,
});
}
(Some(old_default), Some(new_default))
if old_default.as_ref() != new_default.as_ref() =>
{
changes.push(Change::DirectiveDefinitionArgumentDefaultValueChanged {
directive_definition: self.directive_definition,
old_argument_definition: self.old_argument_definition,
new_argument_definition: self.new_argument_definition,
});
}
(Some(_), None) | (None, Some(_)) => {
changes.push(Change::DirectiveDefinitionArgumentDefaultValueChanged {
Expand Down
3 changes: 1 addition & 2 deletions bluejay-typegen-codegen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "bluejay-typegen-codegen"
version.workspace = true
rust-version.workspace = true
edition = "2021"
license = "MIT"
repository = "https://github.com/Shopify/bluejay"
Expand All @@ -17,8 +18,6 @@ syn = { version = "3.0", features = ["full"] }
quote = "1.0"
proc-macro2 = "1.0"
convert_case = "0.10"
# Pin: v1.13+ requires Rust 1.86+. Remove once toolchain is upgraded.
unicode-segmentation = ">=1.11, <1.13"
itertools = "0.15.0"

[lints]
Expand Down
20 changes: 8 additions & 12 deletions bluejay-typegen-codegen/src/input_object_type_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,18 +184,14 @@ impl<'a, S: SchemaDefinition, C: CodeGenerator> InputObjectTypeDefinitionBuilder
match ty {
InputTypeReference::Base(base, _) if base.name() == target => true,
ty => match ty.base(self.config.schema_definition()) {
BaseInputTypeReference::InputObject(iotd) => {
if visited.insert(iotd.name()) {
iotd.input_field_definitions().iter().any(|ivd| {
self.contains_non_list_reference(
target,
ivd.r#type().as_ref(self.config.schema_definition()),
visited,
)
})
} else {
false
}
BaseInputTypeReference::InputObject(iotd) if visited.insert(iotd.name()) => {
iotd.input_field_definitions().iter().any(|ivd| {
self.contains_non_list_reference(
target,
ivd.r#type().as_ref(self.config.schema_definition()),
visited,
)
})
}
_ => false,
},
Expand Down
1 change: 1 addition & 0 deletions bluejay-typegen-macro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "bluejay-typegen-macro"
version.workspace = true
rust-version.workspace = true
edition = "2021"
license = "MIT"
repository = "https://github.com/Shopify/bluejay"
Expand Down
Loading
Loading