Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(compiler): add schema coordinates #757

Merged
merged 14 commits into from
Dec 19, 2023
Merged

Conversation

goto-bus-stop
Copy link
Member

@goto-bus-stop goto-bus-stop commented Nov 22, 2023

Implements parsing and printing for the Schema Coordinates RFC.

Here, SchemaCoordinate is an enum of all the different kinds of coordinates. Each kind of coordinate is also its own type.

use apollo_compiler::name;
use apollo_compiler::coordinate::{SchemaCoordinate, FieldArgumentCoordinate};

let coord: SchemaCoordinate = "Type.field(argument:)".parse().unwrap();
assert_eq!(coord, SchemaCoordinate::FieldArgument(
    FieldArgumentCoordinate {
        ty: name!("Type"),
        field: name!("field"),
        argument: name!("argument"),
    },
));
use apollo_compiler::coord;

assert_eq!(coord!(@directive).to_string(), "@directive");
assert_eq!(coord!(@directive(arg:)).to_string(), "@directive(arg:)");
assert_eq!(coord!(Type).to_string(), "Type");
assert_eq!(coord!(Type.field).to_string(), "Type.field");
assert_eq!(coord!(Type.field(arg:)).to_string(), "Type.field(arg:)");

The goal of this API is:

  • easily tracking the current coordinate while walking a tree (eg with the .argument() method). Each kind of coordinate having its own impl is handy for this
  • look up a typed coordinate in the schema
    • not yet implemented but imagine an fn lookup(&Schema, FieldArgumentCoordinate) -> Option<Node<InputValueDefinition>>, so the return value can be typed. I'm not 100% convinced of how important this is as you may often have just a SchemaCoordinate, which can return multiple types.
    • Backed out for now, we can do it later, typed lookup is certainly possible.
  • Printing for use in error messages (Port PR #674 to 1.0: improve validation error summary #691)

Some other options:

  • TypeCoordinate could just be an alias of NamedType 🤪
  • Just have a SchemaCoordinate enum without all the specific types--I like this less for how it's used in validation (different types with simple methods for pushing/popping are ideal)
  • A more flat text representation, so not having 3 separate refcounted strings like here. Just representing a schema coordinate as its source text is actually fairly efficient (like literally storing the string Type.field(arg:)). A schema coordinate could then be pointer-sized, here it's 3 pointers + a discriminant. A downside is that you need to allocate when you append a field or argument or something.

@goto-bus-stop goto-bus-stop changed the title Add schema coordinates feat(compiler): add schema coordinates Nov 22, 2023
Copy link
Contributor

@SimonSapin SimonSapin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there other kinds of schema coordinates that diagnostics could use too? Like enum value definition, or implements of an interface by an object type, etc.

I tend to prefer structured data over stringly-typed, but if the main purpose is to be formatted into a string anyway 🤷 I don’t think 3× refcount traffic is very significant compared to allocating a new string. Do you think size_of::<SchemaCoordinate>() is something to worry about? We may care less (to some extent) about performance of reporting errors than about validation performance of valid schemas/documents.

@sachindshinde I think I already asked but sorry I don’t remember the conclusion 😅 Is there overlap between this and federation-next’s referencers/positions? Any change you’d suggest here?

crates/apollo-compiler/src/coordinate.rs Outdated Show resolved Hide resolved
crates/apollo-compiler/src/coordinate.rs Outdated Show resolved Hide resolved
@goto-bus-stop
Copy link
Member Author

Oh hmm, a FieldCoordinate can also refer to an enum value. The RFC actually calls it a type attribute rather than a field: https://github.com/graphql/graphql-wg/blob/main/rfcs/SchemaCoordinates.md#typeattribute

So you can have Query.products referring to a field and ProductType.book referring to an enum value. that makes the typed lookup by coordinate idea a bit less interesting.

@goto-bus-stop
Copy link
Member Author

I think for pointing out a specific implements, or pointing out a directive application, we would use both a coordinate + a string (or another coordinate) for the more specific thing in the error message. It does mean that the coordinates for error locations would often be a parent node of where the error actually occurred, but it's not gonna be super far away...

For example, if you do something like

type Example {
  name @deprecated(reason: false)
}

you could get an error with its location at coordinate Example.name, and the message formatting using two coordinates:

Expected type String, but Boolean was provided to `@deprecated(reason:)` on `Example.name`

(would need some copy workshopping to make it read well)

@goto-bus-stop
Copy link
Member Author

goto-bus-stop commented Nov 27, 2023

Something else you can't point to is a schema definition, so we couldn't require a coordinate for diagnostics on those

e; As discussed in the call, the initial use for this would be for diagnostic messages, not really as a substitute for location information.

fuzz/fuzz_targets/coordinate.rs Outdated Show resolved Hide resolved
crates/apollo-compiler/src/coordinate.rs Outdated Show resolved Hide resolved
crates/apollo-compiler/CHANGELOG.md Outdated Show resolved Hide resolved
@goto-bus-stop
Copy link
Member Author

goto-bus-stop commented Dec 18, 2023

As discussed in checkin, we keep lookup out for now, since we aren't really sure of the utility or about parts of the design (like the trait). Replaced coordinate: String uses in diagnostics with either a specific coordinate type or SchemaCoordinate.

@goto-bus-stop goto-bus-stop merged commit d41dd71 into main Dec 19, 2023
@goto-bus-stop goto-bus-stop deleted the schema-coordinates branch December 19, 2023 08:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants