Skip to content

Commit

Permalink
feat: refactor IdReader APIs in parser (#1064)
Browse files Browse the repository at this point in the history
#### Why are we making this change?

The `IdReader` API used to rely on the implementation of
`TypeSystemId`/`ExecutableApi` to create Readers. This meant that
working with this in a generic way had some quite complicated trait
bounds, and also means that an `Id` can only be associated with one kind
of `Reader`.

#### What effects does this change have?

Adds a `new` function into the `IdReader` api which simplifies the trait
bounds and also allows multiple `Readers` to use the same `Id` should
they want to.
  • Loading branch information
obmarg authored Oct 14, 2024
1 parent f4d9f2f commit 4e94b62
Show file tree
Hide file tree
Showing 27 changed files with 212 additions and 70 deletions.
6 changes: 5 additions & 1 deletion cynic-parser/ast-generator/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,12 @@ pub fn object_output(
})?;

let id_reader_impl = format_code(quote! {
impl IdReader for #reader_name<'_> {
impl<'a> IdReader<'a> for #reader_name<'a> {
type Id = #id_name;

fn new(id: Self::Id, document: &'a #document_type) -> Self {
document.read(id)
}
}
})?;

Expand Down
6 changes: 5 additions & 1 deletion cynic-parser/ast-generator/src/union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,12 @@ pub fn union_output(
})?;

let id_reader_impl = format_code(quote! {
impl IdReader for #reader_name<'_> {
impl<'a> IdReader<'a> for #reader_name<'a> {
type Id = #id_name;

fn new(id: Self::Id, document: &'a #document_type) -> Self {
document.read(id)
}
}
})?;

Expand Down
5 changes: 4 additions & 1 deletion cynic-parser/src/executable/generated/argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ impl ExecutableId for ArgumentId {
}
}

impl IdReader for Argument<'_> {
impl<'a> IdReader<'a> for Argument<'a> {
type Id = ArgumentId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}
5 changes: 4 additions & 1 deletion cynic-parser/src/executable/generated/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ impl ExecutableId for ExecutableDefinitionId {
}
}

impl IdReader for ExecutableDefinition<'_> {
impl<'a> IdReader<'a> for ExecutableDefinition<'a> {
type Id = ExecutableDefinitionId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}
5 changes: 4 additions & 1 deletion cynic-parser/src/executable/generated/directive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ impl ExecutableId for DirectiveId {
}
}

impl IdReader for Directive<'_> {
impl<'a> IdReader<'a> for Directive<'a> {
type Id = DirectiveId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}
5 changes: 4 additions & 1 deletion cynic-parser/src/executable/generated/fragment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ impl ExecutableId for FragmentDefinitionId {
}
}

impl IdReader for FragmentDefinition<'_> {
impl<'a> IdReader<'a> for FragmentDefinition<'a> {
type Id = FragmentDefinitionId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}
5 changes: 4 additions & 1 deletion cynic-parser/src/executable/generated/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ impl ExecutableId for OperationDefinitionId {
}
}

impl IdReader for OperationDefinition<'_> {
impl<'a> IdReader<'a> for OperationDefinition<'a> {
type Id = OperationDefinitionId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}
20 changes: 16 additions & 4 deletions cynic-parser/src/executable/generated/selections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ impl ExecutableId for SelectionId {
}
}

impl IdReader for Selection<'_> {
impl<'a> IdReader<'a> for Selection<'a> {
type Id = SelectionId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}

pub struct FieldSelectionRecord {
Expand Down Expand Up @@ -100,8 +103,11 @@ impl ExecutableId for FieldSelectionId {
}
}

impl IdReader for FieldSelection<'_> {
impl<'a> IdReader<'a> for FieldSelection<'a> {
type Id = FieldSelectionId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}

pub struct InlineFragmentRecord {
Expand Down Expand Up @@ -154,8 +160,11 @@ impl ExecutableId for InlineFragmentId {
}
}

impl IdReader for InlineFragment<'_> {
impl<'a> IdReader<'a> for InlineFragment<'a> {
type Id = InlineFragmentId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}

pub struct FragmentSpreadRecord {
Expand Down Expand Up @@ -199,6 +208,9 @@ impl ExecutableId for FragmentSpreadId {
}
}

impl IdReader for FragmentSpread<'_> {
impl<'a> IdReader<'a> for FragmentSpread<'a> {
type Id = FragmentSpreadId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}
5 changes: 4 additions & 1 deletion cynic-parser/src/executable/generated/variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ impl ExecutableId for VariableDefinitionId {
}
}

impl IdReader for VariableDefinition<'_> {
impl<'a> IdReader<'a> for VariableDefinition<'a> {
type Id = VariableDefinitionId;
fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self {
document.read(id)
}
}
32 changes: 17 additions & 15 deletions cynic-parser/src/executable/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ use std::{fmt, iter::FusedIterator};

use crate::common::{IdOperations, IdRange, IdRangeIter};

use super::ExecutableId;
use super::{ExecutableDocument, ExecutableId};

pub trait IdReader {
pub trait IdReader<'a> {
type Id: ExecutableId;

fn new(id: Self::Id, document: &'a ExecutableDocument) -> Self;
}

/// Iterator for readers in the executable module
Expand All @@ -14,15 +16,15 @@ pub trait IdReader {
#[derive(Clone)]
pub struct Iter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
{
ids: IdRangeIter<T::Id>,
document: &'a super::ExecutableDocument,
}

impl<'a, T> Iter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
{
pub(crate) fn new(range: IdRange<T::Id>, document: &'a super::ExecutableDocument) -> Self
where
Expand Down Expand Up @@ -50,7 +52,7 @@ where

impl<'a, T> Iterator for Iter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
T::Id: IdOperations,
{
type Item = <T::Id as ExecutableId>::Reader<'a>;
Expand All @@ -66,21 +68,21 @@ where

impl<'a, T> ExactSizeIterator for Iter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
T::Id: IdOperations,
{
}

impl<'a, T> FusedIterator for Iter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
T::Id: IdOperations,
{
}

impl<'a, T> DoubleEndedIterator for Iter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
T::Id: IdOperations,
{
// Required method
Expand All @@ -91,7 +93,7 @@ where

impl<'a, T> fmt::Debug for Iter<'a, T>
where
T: IdReader + Copy,
T: IdReader<'a> + Copy,
Self: Iterator,
<Self as Iterator>::Item: fmt::Debug,
{
Expand All @@ -106,15 +108,15 @@ where
#[derive(Clone)]
pub struct IdIter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
{
ids: IdRangeIter<T::Id>,
document: &'a super::ExecutableDocument,
}

impl<'a, T> Iterator for IdIter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
T::Id: IdOperations,
{
type Item = (T::Id, <T::Id as ExecutableId>::Reader<'a>);
Expand All @@ -132,21 +134,21 @@ where

impl<'a, T> ExactSizeIterator for IdIter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
T::Id: IdOperations,
{
}

impl<'a, T> FusedIterator for IdIter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
T::Id: IdOperations,
{
}

impl<'a, T> DoubleEndedIterator for IdIter<'a, T>
where
T: IdReader,
T: IdReader<'a>,
T::Id: IdOperations,
{
// Required method
Expand All @@ -159,7 +161,7 @@ where

impl<'a, T> fmt::Debug for IdIter<'a, T>
where
T: IdReader + Copy,
T: IdReader<'a> + Copy,
Self: Iterator,
<Self as Iterator>::Item: fmt::Debug,
{
Expand Down
8 changes: 4 additions & 4 deletions cynic-parser/src/printing/display/executable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl fmt::Display for FragmentDefinition<'_> {
}
}

impl fmt::Display for iter::Iter<'_, VariableDefinition<'_>> {
impl<'a> fmt::Display for iter::Iter<'a, VariableDefinition<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.len() != 0 {
write!(f, "(")?;
Expand Down Expand Up @@ -96,7 +96,7 @@ impl std::fmt::Display for VariableDefinition<'_> {
}
}

impl std::fmt::Display for iter::Iter<'_, Selection<'_>> {
impl<'a> std::fmt::Display for iter::Iter<'a, Selection<'a>> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.len() != 0 {
writeln!(f, "{{")?;
Expand Down Expand Up @@ -166,7 +166,7 @@ impl fmt::Display for FragmentSpread<'_> {
}
}

impl fmt::Display for iter::Iter<'_, Directive<'_>> {
impl<'a> fmt::Display for iter::Iter<'a, Directive<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for directive in self.clone() {
write!(f, " {directive}")?;
Expand All @@ -181,7 +181,7 @@ impl fmt::Display for Directive<'_> {
}
}

impl fmt::Display for iter::Iter<'_, Argument<'_>> {
impl<'a> fmt::Display for iter::Iter<'a, Argument<'a>> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.len() != 0 {
write!(f, "(")?;
Expand Down
19 changes: 9 additions & 10 deletions cynic-parser/src/printing/pretty/type_system/field_sequence.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::iter::Enumerate;
use std::{iter::Enumerate, marker::PhantomData};

use pretty::{DocAllocator, Pretty};

use crate::{common::IdOperations, printing::pretty::printer::PrettyOptions};

use super::{
iter::IdReader, Allocator, EnumValueDefinition, FieldDefinition, InputValueDefinition,
NodeDisplay, TypeSystemId,
NodeDisplay,
};

/// A sequence of things with docstrings attached.
Expand All @@ -20,17 +20,17 @@ use super::{
/// but arguments should use ArgumentSequence
pub(super) struct FieldSequence<'a, T>
where
T: IdReader + Field<'a>,
T: IdReader<'a> + Field<'a>,
{
iterator: Enumerate<std::vec::IntoIter<<<T as IdReader>::Id as TypeSystemId>::Reader<'a>>>,
iterator: Enumerate<std::vec::IntoIter<T>>,
options: PrettyOptions,
phantom: PhantomData<&'a T>,
}

impl<'a, T> FieldSequence<'a, T>
where
T: IdReader + Field<'a>,
T: IdReader<'a> + Field<'a>,
T::Id: IdOperations,
<<T as IdReader>::Id as TypeSystemId>::Reader<'a>: Field<'a>,
{
pub fn new(iterator: crate::type_system::iter::Iter<'a, T>, options: PrettyOptions) -> Self {
let mut fields = iterator.collect::<Vec<_>>();
Expand All @@ -41,6 +41,7 @@ where
FieldSequence {
iterator: fields.into_iter().enumerate(),
options,
phantom: PhantomData,
}
}
}
Expand Down Expand Up @@ -82,11 +83,9 @@ impl<'a> Field<'a> for EnumValueDefinition<'a> {

impl<'a, T> Pretty<'a, Allocator<'a>> for FieldSequence<'a, T>
where
T: Field<'a> + IdReader,
T: Field<'a> + IdReader<'a>,
T::Id: IdOperations,
// This is a bit much :/
<<T as IdReader>::Id as TypeSystemId>::Reader<'a>: Field<'a>,
NodeDisplay<<<T as IdReader>::Id as TypeSystemId>::Reader<'a>>: Pretty<'a, Allocator<'a>>,
NodeDisplay<T>: Pretty<'a, Allocator<'a>>,
{
fn pretty(self, allocator: &'a Allocator<'a>) -> pretty::DocBuilder<'a, Allocator<'a>, ()> {
let mut document = allocator.nil();
Expand Down
6 changes: 5 additions & 1 deletion cynic-parser/src/type_system/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ impl TypeSystemId for DefinitionId {
}
}

impl IdReader for Definition<'_> {
impl<'a> IdReader<'a> for Definition<'a> {
type Id = DefinitionId;

fn new(id: Self::Id, document: &'a super::TypeSystemDocument) -> Self {
document.read(id)
}
}
5 changes: 4 additions & 1 deletion cynic-parser/src/type_system/generated/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ impl TypeSystemId for ArgumentId {
}
}

impl IdReader for Argument<'_> {
impl<'a> IdReader<'a> for Argument<'a> {
type Id = ArgumentId;
fn new(id: Self::Id, document: &'a TypeSystemDocument) -> Self {
document.read(id)
}
}
Loading

0 comments on commit 4e94b62

Please sign in to comment.