Skip to content

Commit

Permalink
Add scalar codegen, and support for LinkedField as well
Browse files Browse the repository at this point in the history
Reviewed By: captbaritone

Differential Revision: D56643224

fbshipit-source-id: d595753fa5709473ae76b4a96f48ed6a3847cc7f
  • Loading branch information
itamark authored and facebook-github-bot committed May 1, 2024
1 parent 470c814 commit f4f4c9e
Show file tree
Hide file tree
Showing 40 changed files with 841 additions and 11 deletions.
2 changes: 1 addition & 1 deletion compiler/crates/relay-codegen/Cargo.toml
@@ -1,4 +1,4 @@
# @generated by autocargo from //relay/oss/crates/relay-codegen:[aliased_fragments_test,relay-codegen,relay-codegen-client-edges,relay-codegen-client-extensions,relay-codegen-client-extensions-abstract-types,relay-codegen-connections,relay-codegen-deduped_json_codegen_test,relay-codegen-defer-stream,relay-codegen-json_codegen_test,relay_actor_change_test,request_metadata_test,required_directive_codegen_test,skip_printing_nulls_test]
# @generated by autocargo from //relay/oss/crates/relay-codegen:[aliased_fragments_test,catch_directive_codegen_test,relay-codegen,relay-codegen-client-edges,relay-codegen-client-extensions,relay-codegen-client-extensions-abstract-types,relay-codegen-connections,relay-codegen-deduped_json_codegen_test,relay-codegen-defer-stream,relay-codegen-json_codegen_test,relay_actor_change_test,request_metadata_test,required_directive_codegen_test,skip_printing_nulls_test]

[package]
name = "relay-codegen"
Expand Down
30 changes: 30 additions & 0 deletions compiler/crates/relay-codegen/src/build_ast.rs
Expand Up @@ -48,6 +48,7 @@ use relay_transforms::relay_resolvers::get_resolver_info;
use relay_transforms::relay_resolvers::resolver_import_alias;
use relay_transforms::relay_resolvers::ResolverInfo;
use relay_transforms::remove_directive;
use relay_transforms::CatchMetadataDirective;
use relay_transforms::ClientEdgeMetadata;
use relay_transforms::ClientEdgeMetadataDirective;
use relay_transforms::ClientEdgeModelResolver;
Expand Down Expand Up @@ -755,6 +756,8 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> {
};
if let Some(required_metadata) = RequiredMetadataDirective::find(&field.directives) {
self.build_required_field(required_metadata, resolver_primitive)
} else if let Some(catch_metadata) = CatchMetadataDirective::find(&field.directives) {
self.build_catch_field(catch_metadata, resolver_primitive)
} else {
resolver_primitive
}
Expand Down Expand Up @@ -977,6 +980,19 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> {
}))
}

fn build_catch_field(
&mut self,
catch_metadata: &CatchMetadataDirective,
primitive: Primitive,
) -> Primitive {
Primitive::Key(self.object(object! {
kind: Primitive::String(CODEGEN_CONSTANTS.catch_field),
field: primitive,
to: Primitive::String(catch_metadata.to.into()),
path: Primitive::String(catch_metadata.path),
}))
}

fn build_scalar_field(&mut self, field: &ScalarField) -> Primitive {
let schema_field = self.schema.field(field.definition.item);
let (name, alias) =
Expand Down Expand Up @@ -1004,6 +1020,8 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> {

if let Some(required_metadata) = RequiredMetadataDirective::find(&field.directives) {
self.build_required_field(required_metadata, primitive)
} else if let Some(catch_metadata) = CatchMetadataDirective::find(&field.directives) {
self.build_catch_field(catch_metadata, primitive)
} else {
primitive
}
Expand Down Expand Up @@ -1102,6 +1120,8 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> {

if let Some(required_metadata) = RequiredMetadataDirective::find(&field.directives) {
self.build_required_field(required_metadata, primitive)
} else if let Some(catch_metadata) = CatchMetadataDirective::find(&field.directives) {
self.build_catch_field(catch_metadata, primitive)
} else {
primitive
}
Expand Down Expand Up @@ -1268,6 +1288,10 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> {
RequiredMetadataDirective::find(&frag_spread.directives)
{
self.build_required_field(required_metadata, resolver_primitive)
} else if let Some(catch_metadata) =
CatchMetadataDirective::find(&frag_spread.directives)
{
self.build_catch_field(catch_metadata, resolver_primitive)
} else {
resolver_primitive
}
Expand Down Expand Up @@ -1707,6 +1731,7 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> {
context: &mut ContextualMetadata,
client_edge_metadata: &ClientEdgeMetadata<'_>,
required_metadata: Option<RequiredMetadataDirective>,
catch_metadata: Option<CatchMetadataDirective>,
) -> Primitive {
context.has_client_edges = true;
let backing_field = match &client_edge_metadata.backing_field {
Expand Down Expand Up @@ -1809,6 +1834,8 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> {

if let Some(required_metadata) = required_metadata {
self.build_required_field(&required_metadata, field)
} else if let Some(catch_metadata) = catch_metadata {
self.build_catch_field(&catch_metadata, field)
} else {
field
}
Expand All @@ -1826,10 +1853,13 @@ impl<'schema, 'builder, 'config> CodegenBuilder<'schema, 'builder, 'config> {
CodegenVariant::Reader => {
let required_metadata =
RequiredMetadataDirective::find(&inline_frag.directives).cloned();
let catch_metadata =
CatchMetadataDirective::find(&inline_frag.directives).cloned();
self.build_reader_client_edge(
context,
&client_edge_metadata,
required_metadata,
catch_metadata,
)
}
CodegenVariant::Normalization => {
Expand Down
4 changes: 4 additions & 0 deletions compiler/crates/relay-codegen/src/constants.rs
Expand Up @@ -20,6 +20,7 @@ pub struct CodegenConstants {
pub argument_definitions: StringKey,
pub backward: StringKey,
pub cache_id: StringKey,
pub catch_field: StringKey,
pub client_abstract_types: StringKey,
pub client_edge_backing_field_key: StringKey,
pub client_edge_model_resolvers: StringKey,
Expand Down Expand Up @@ -117,6 +118,7 @@ pub struct CodegenConstants {
pub stream: StringKey,
pub subscription: StringKey,
pub text: StringKey,
pub to: StringKey,
pub type_: StringKey,
pub type_discriminator: StringKey,
pub updatable_query: StringKey,
Expand All @@ -138,6 +140,7 @@ lazy_static! {
argument_definitions: "argumentDefinitions".intern(),
backward: "backward".intern(),
cache_id: "cacheID".intern(),
catch_field: "CatchField".intern(),
client_abstract_types: "clientAbstractTypes".intern(),
client_edge_backing_field_key: "backingField".intern(),
client_edge_model_resolvers: "modelResolvers".intern(),
Expand Down Expand Up @@ -235,6 +238,7 @@ lazy_static! {
stream: "Stream".intern(),
subscription: "subscription".intern(),
text: "text".intern(),
to: "to".intern(),
type_: "type".intern(),
type_discriminator: "TypeDiscriminator".intern(),
updatable_query: "UpdatableQuery".intern(),
Expand Down
71 changes: 71 additions & 0 deletions compiler/crates/relay-codegen/tests/catch_directive_codegen.rs
@@ -0,0 +1,71 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

use std::sync::Arc;

use common::SourceLocationKey;
use fixture_tests::Fixture;
use graphql_ir::build;
use graphql_ir::Program;
use graphql_syntax::parse_executable;
use graphql_test_helpers::diagnostics_to_sorted_string;
use relay_codegen::print_fragment;
use relay_codegen::print_operation;
use relay_codegen::JsModuleFormat;
use relay_config::ProjectConfig;
use relay_test_schema::get_test_schema;
use relay_test_schema::get_test_schema_with_extensions;
use relay_transforms::catch_directive;

pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
let parts: Vec<_> = fixture.content.split("%extensions%").collect();
let (base, schema) = match parts.as_slice() {
[base, extensions] => (base, get_test_schema_with_extensions(extensions)),
[base] => (base, get_test_schema()),
_ => panic!("Invalid fixture input {}", fixture.content),
};

let ast = parse_executable(base, SourceLocationKey::standalone(fixture.file_name)).unwrap();
let ir = build(&schema, &ast.definitions)
.map_err(|diagnostics| diagnostics_to_sorted_string(fixture.content, &diagnostics))?;
let program = Program::from_definitions(Arc::clone(&schema), ir);

catch_directive(&program, true)
.map(|next_program| {
next_program
.fragments()
.map(|def| {
let mut import_statements = Default::default();
let fragment = print_fragment(
&schema,
def,
&ProjectConfig {
js_module_format: JsModuleFormat::Haste,
..Default::default()
},
&mut import_statements,
);
format!("{}{}", import_statements, fragment)
})
.chain(next_program.operations().map(|def| {
let mut import_statements = Default::default();
let operation = print_operation(
&schema,
def,
&ProjectConfig {
js_module_format: JsModuleFormat::Haste,
..Default::default()
},
&mut import_statements,
);
format!("{}{}", import_statements, operation)
}))
.collect::<Vec<_>>()
.join("\n\n")
})
.map_err(|diagnostics| diagnostics_to_sorted_string(fixture.content, &diagnostics))
}
@@ -0,0 +1,35 @@
==================================== INPUT ====================================
fragment MyFragment on Node {
id
name @catch(to: RESULT)
}
==================================== OUTPUT ===================================
{
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "MyFragment",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"kind": "CatchField",
"field": {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
},
"to": "RESULT",
"path": "name"
}
],
"type": "Node",
"abstractKey": "__isNode"
}
@@ -0,0 +1,4 @@
fragment MyFragment on Node {
id
name @catch(to: RESULT)
}
@@ -0,0 +1,40 @@
==================================== INPUT ====================================
fragment MyFragment on User {
address {
street @catch(to: RESULT)
}
}
==================================== OUTPUT ===================================
{
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "MyFragment",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "StreetAddress",
"kind": "LinkedField",
"name": "address",
"plural": false,
"selections": [
{
"kind": "CatchField",
"field": {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "street",
"storageKey": null
},
"to": "RESULT",
"path": "address.street"
}
],
"storageKey": null
}
],
"type": "User",
"abstractKey": null
}
@@ -0,0 +1,5 @@
fragment MyFragment on User {
address {
street @catch(to: RESULT)
}
}
@@ -0,0 +1,40 @@
==================================== INPUT ====================================
fragment MyFragment on User {
address @catch(to: RESULT) {
street
}
}
==================================== OUTPUT ===================================
{
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "MyFragment",
"selections": [
{
"kind": "CatchField",
"field": {
"alias": null,
"args": null,
"concreteType": "StreetAddress",
"kind": "LinkedField",
"name": "address",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "street",
"storageKey": null
}
],
"storageKey": null
},
"to": "RESULT",
"path": "address"
}
],
"type": "User",
"abstractKey": null
}
@@ -0,0 +1,5 @@
fragment MyFragment on User {
address @catch(to: RESULT) {
street
}
}
@@ -0,0 +1,45 @@
==================================== INPUT ====================================
fragment MyFragment on User {
address @catch {
street @catch
}
}
==================================== OUTPUT ===================================
{
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "MyFragment",
"selections": [
{
"kind": "CatchField",
"field": {
"alias": null,
"args": null,
"concreteType": "StreetAddress",
"kind": "LinkedField",
"name": "address",
"plural": false,
"selections": [
{
"kind": "CatchField",
"field": {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "street",
"storageKey": null
},
"to": "RESULT",
"path": "address.street"
}
],
"storageKey": null
},
"to": "RESULT",
"path": "address"
}
],
"type": "User",
"abstractKey": null
}
@@ -0,0 +1,5 @@
fragment MyFragment on User {
address @catch {
street @catch
}
}

0 comments on commit f4f4c9e

Please sign in to comment.