Skip to content

Commit

Permalink
Add DeferStreamInterface to rust compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
robrichard committed Dec 21, 2020
1 parent 1357b87 commit 76375df
Show file tree
Hide file tree
Showing 96 changed files with 530 additions and 274 deletions.
2 changes: 1 addition & 1 deletion compiler/crates/graphql-ir/src/errors.rs
Expand Up @@ -407,7 +407,7 @@ pub enum ValidationMessage {
#[error("Invalid use of @stream on scalar field '{field_name}'")]
InvalidStreamOnScalarField { field_name: StringKey },

#[error("Invalid use of @stream, the 'initial_count' argument is required.")]
#[error("Invalid use of @stream, the 'initialCount' argument is required.")]
StreamInitialCountRequired,

#[error("Variable `${variable_name}` is never used in operation `{operation_name}`")]
Expand Down
79 changes: 54 additions & 25 deletions compiler/crates/relay-codegen/src/build_ast.rs
Expand Up @@ -20,10 +20,10 @@ use relay_transforms::{
extract_connection_metadata_from_directive, extract_handle_field_directives,
extract_refetch_metadata_from_directive, extract_values_from_handle_field_directive,
extract_variable_name, generate_abstract_type_refinement_key, remove_directive,
ConnectionConstants, ConnectionMetadata, DeferDirective, RelayDirective, StreamDirective,
ACTION_ARGUMENT, CLIENT_EXTENSION_DIRECTIVE_NAME, DEFER_STREAM_CONSTANTS,
DIRECTIVE_SPLIT_OPERATION, INLINE_DATA_CONSTANTS, INTERNAL_METADATA_DIRECTIVE, MATCH_CONSTANTS,
PATH_METADATA_ARGUMENT, REACT_FLIGHT_SCALAR_FLIGHT_FIELD_METADATA_KEY, REQUIRED_METADATA_KEY,
ConnectionConstants, ConnectionMetadata, DeferDirective, DeferStreamInterface, RelayDirective,
StreamDirective, ACTION_ARGUMENT, CLIENT_EXTENSION_DIRECTIVE_NAME, DIRECTIVE_SPLIT_OPERATION,
INLINE_DATA_CONSTANTS, INTERNAL_METADATA_DIRECTIVE, MATCH_CONSTANTS, PATH_METADATA_ARGUMENT,
REACT_FLIGHT_SCALAR_FLIGHT_FIELD_METADATA_KEY, REQUIRED_METADATA_KEY,
TYPE_DISCRIMINATOR_DIRECTIVE_NAME,
};
use schema::Schema;
Expand All @@ -33,9 +33,14 @@ pub fn build_request_params_ast_key(
request_parameters: RequestParameters,
ast_builder: &mut AstBuilder,
operation: &OperationDefinition,
defer_stream_interface: &DeferStreamInterface,
) -> AstKey {
let mut operation_builder =
CodegenBuilder::new(schema, CodegenVariant::Normalization, ast_builder);
let mut operation_builder = CodegenBuilder::new(
schema,
CodegenVariant::Normalization,
ast_builder,
defer_stream_interface,
);
operation_builder.build_request_parameters(operation, request_parameters)
}

Expand All @@ -45,11 +50,21 @@ pub fn build_request(
operation: &OperationDefinition,
fragment: &FragmentDefinition,
request_parameters: AstKey,
defer_stream_interface: &DeferStreamInterface,
) -> AstKey {
let mut operation_builder =
CodegenBuilder::new(schema, CodegenVariant::Normalization, ast_builder);
let mut operation_builder = CodegenBuilder::new(
schema,
CodegenVariant::Normalization,
ast_builder,
defer_stream_interface,
);
let operation = Primitive::Key(operation_builder.build_operation(operation));
let mut fragment_builder = CodegenBuilder::new(schema, CodegenVariant::Reader, ast_builder);
let mut fragment_builder = CodegenBuilder::new(
schema,
CodegenVariant::Reader,
ast_builder,
defer_stream_interface,
);
let fragment = Primitive::Key(fragment_builder.build_fragment(fragment, true));

ast_builder.intern(Ast::Object(vec![
Expand Down Expand Up @@ -86,22 +101,35 @@ pub fn build_operation(
schema: &Schema,
ast_builder: &mut AstBuilder,
operation: &OperationDefinition,
defer_stream_interface: &DeferStreamInterface,
) -> AstKey {
let mut builder = CodegenBuilder::new(schema, CodegenVariant::Normalization, ast_builder);
let mut builder = CodegenBuilder::new(
schema,
CodegenVariant::Normalization,
ast_builder,
defer_stream_interface,
);
builder.build_operation(operation)
}

pub fn build_fragment(
schema: &Schema,
ast_builder: &mut AstBuilder,
fragment: &FragmentDefinition,
defer_stream_interface: &DeferStreamInterface,
) -> AstKey {
let mut builder = CodegenBuilder::new(schema, CodegenVariant::Reader, ast_builder);
let mut builder = CodegenBuilder::new(
schema,
CodegenVariant::Reader,
ast_builder,
defer_stream_interface,
);
builder.build_fragment(fragment, false)
}

struct CodegenBuilder<'schema, 'builder> {
struct CodegenBuilder<'schema, 'builder, 'dsi> {
connection_constants: ConnectionConstants,
defer_stream_interface: &'dsi DeferStreamInterface,
schema: &'schema Schema,
variant: CodegenVariant,
ast_builder: &'builder mut AstBuilder,
Expand All @@ -113,14 +141,16 @@ enum CodegenVariant {
Normalization,
}

impl<'schema, 'builder> CodegenBuilder<'schema, 'builder> {
impl<'schema, 'builder, 'dsi> CodegenBuilder<'schema, 'builder, 'dsi> {
fn new(
schema: &'schema Schema,
variant: CodegenVariant,
ast_builder: &'builder mut AstBuilder,
defer_stream_interface: &'dsi DeferStreamInterface,
) -> Self {
Self {
connection_constants: Default::default(),
defer_stream_interface,
schema,
variant,
ast_builder,
Expand Down Expand Up @@ -413,7 +443,7 @@ impl<'schema, 'builder> CodegenBuilder<'schema, 'builder> {
];
if metadata.is_stream_connection {
object.push(ObjectEntry {
key: DEFER_STREAM_CONSTANTS.stream_name,
key: self.defer_stream_interface.stream_name,
value: Primitive::Bool(true),
})
}
Expand Down Expand Up @@ -460,7 +490,7 @@ impl<'schema, 'builder> CodegenBuilder<'schema, 'builder> {
Selection::InlineFragment(inline_frag) => {
let defer = inline_frag
.directives
.named(DEFER_STREAM_CONSTANTS.defer_name);
.named(self.defer_stream_interface.defer_name);
if let Some(defer) = defer {
vec![self.build_defer(&inline_frag, defer)]
} else if let Some(inline_data_directive) = inline_frag
Expand All @@ -469,12 +499,8 @@ impl<'schema, 'builder> CodegenBuilder<'schema, 'builder> {
{
// If inline fragment has @__inline directive (created by inline_data_fragment transform)
// we will return selection wrapped with InlineDataFragmentSpread
vec![
self.build_inline_data_fragment_spread(
&inline_frag,
&inline_data_directive,
),
]
vec![self
.build_inline_data_fragment_spread(&inline_frag, &inline_data_directive)]
} else if let Some(match_directive) = inline_frag
.directives
.named(MATCH_CONSTANTS.custom_module_directive_name)
Expand All @@ -485,7 +511,9 @@ impl<'schema, 'builder> CodegenBuilder<'schema, 'builder> {
}
}
Selection::LinkedField(field) => {
let stream = field.directives.named(DEFER_STREAM_CONSTANTS.stream_name);
let stream = field
.directives
.named(self.defer_stream_interface.stream_name);

match stream {
Some(stream) => vec![self.build_stream(&field, stream)],
Expand Down Expand Up @@ -890,7 +918,8 @@ impl<'schema, 'builder> CodegenBuilder<'schema, 'builder> {
defer: &Directive,
) -> Primitive {
let next_selections = self.build_selections(inline_fragment.selections.iter());
let DeferDirective { if_arg, label_arg } = DeferDirective::from(defer);
let DeferDirective { if_arg, label_arg } =
DeferDirective::from(defer, self.defer_stream_interface);
let if_variable_name = extract_variable_name(if_arg);
let label_name = label_arg.unwrap().value.item.expect_string_literal();

Expand Down Expand Up @@ -918,7 +947,7 @@ impl<'schema, 'builder> CodegenBuilder<'schema, 'builder> {
let next_selections = vec![self.build_linked_field(&LinkedField {
directives: remove_directive(
&linked_field.directives,
DEFER_STREAM_CONSTANTS.stream_name,
self.defer_stream_interface.stream_name,
),
..linked_field.to_owned()
})];
Expand All @@ -940,7 +969,7 @@ impl<'schema, 'builder> CodegenBuilder<'schema, 'builder> {
label_arg,
use_customized_batch_arg,
initial_count_arg: _,
} = StreamDirective::from(stream);
} = StreamDirective::from(stream, self.defer_stream_interface);
let if_variable_name = extract_variable_name(if_arg);
let use_customized_batch_variable_name =
extract_variable_name(use_customized_batch_arg);
Expand Down
65 changes: 52 additions & 13 deletions compiler/crates/relay-codegen/src/printer.rs
Expand Up @@ -15,41 +15,63 @@ use crate::indentation::print_indentation;
use crate::utils::escape;

use graphql_ir::{FragmentDefinition, OperationDefinition};
use relay_transforms::DeferStreamInterface;
use schema::Schema;

use fnv::{FnvBuildHasher, FnvHashSet};
use indexmap::IndexMap;
use interner::StringKey;
use std::fmt::{Result as FmtResult, Write};

pub fn print_operation(schema: &Schema, operation: &OperationDefinition) -> String {
Printer::without_dedupe().print_operation(schema, operation)
pub fn print_operation(
schema: &Schema,
operation: &OperationDefinition,
defer_stream_interface: &DeferStreamInterface,
) -> String {
Printer::without_dedupe().print_operation(schema, operation, defer_stream_interface)
}

pub fn print_fragment(schema: &Schema, fragment: &FragmentDefinition) -> String {
Printer::without_dedupe().print_fragment(schema, fragment)
pub fn print_fragment(
schema: &Schema,
fragment: &FragmentDefinition,
defer_stream_interface: &DeferStreamInterface,
) -> String {
Printer::without_dedupe().print_fragment(schema, fragment, defer_stream_interface)
}

pub fn print_request(
schema: &Schema,
operation: &OperationDefinition,
fragment: &FragmentDefinition,
request_parameters: RequestParameters,
defer_stream_interface: &DeferStreamInterface,
) -> String {
Printer::without_dedupe().print_request(schema, operation, fragment, request_parameters)
Printer::without_dedupe().print_request(
schema,
operation,
fragment,
request_parameters,
defer_stream_interface,
)
}

pub fn print_request_params(
schema: &Schema,
operation: &OperationDefinition,
query_id: Option<String>,
defer_stream_interface: &DeferStreamInterface,
) -> String {
let mut request_parameters = build_request_params(operation);
request_parameters.id = query_id;

let mut builder = AstBuilder::default();
let request_parameters_ast_key =
build_request_params_ast_key(schema, request_parameters, &mut builder, operation);
let request_parameters_ast_key = build_request_params_ast_key(
schema,
request_parameters,
&mut builder,
operation,
defer_stream_interface,
);
let printer = JSONPrinter::new(&builder);
printer.print(request_parameters_ast_key, false)
}
Expand Down Expand Up @@ -80,28 +102,45 @@ impl Printer {
operation: &OperationDefinition,
fragment: &FragmentDefinition,
request_parameters: RequestParameters,
defer_stream_interface: &DeferStreamInterface,
) -> String {
let request_parameters =
build_request_params_ast_key(schema, request_parameters, &mut self.builder, operation);
let request_parameters = build_request_params_ast_key(
schema,
request_parameters,
&mut self.builder,
operation,
defer_stream_interface,
);
let key = build_request(
schema,
&mut self.builder,
operation,
fragment,
request_parameters,
defer_stream_interface,
);
let printer = JSONPrinter::new(&self.builder);
printer.print(key, self.dedupe)
}

pub fn print_operation(&mut self, schema: &Schema, operation: &OperationDefinition) -> String {
let key = build_operation(schema, &mut self.builder, operation);
pub fn print_operation(
&mut self,
schema: &Schema,
operation: &OperationDefinition,
defer_stream_interface: &DeferStreamInterface,
) -> String {
let key = build_operation(schema, &mut self.builder, operation, defer_stream_interface);
let printer = JSONPrinter::new(&self.builder);
printer.print(key, self.dedupe)
}

pub fn print_fragment(&mut self, schema: &Schema, fragment: &FragmentDefinition) -> String {
let key = build_fragment(schema, &mut self.builder, fragment);
pub fn print_fragment(
&mut self,
schema: &Schema,
fragment: &FragmentDefinition,
defer_stream_interface: &DeferStreamInterface,
) -> String {
let key = build_fragment(schema, &mut self.builder, fragment, defer_stream_interface);
let printer = JSONPrinter::new(&self.builder);
printer.print(key, self.dedupe)
}
Expand Down
7 changes: 4 additions & 3 deletions compiler/crates/relay-codegen/tests/client_extensions/mod.rs
Expand Up @@ -11,7 +11,7 @@ use graphql_ir::{build, Program};
use graphql_syntax::parse_executable;
use relay_codegen::{print_fragment, print_operation};
use relay_test_schema::get_test_schema_with_extensions;
use relay_transforms::{client_extensions, sort_selections};
use relay_transforms::{client_extensions, sort_selections, DeferStreamInterface};
use std::sync::Arc;

pub fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
Expand All @@ -22,13 +22,14 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
let ir = build(&schema, &ast.definitions).unwrap();
let program = Program::from_definitions(Arc::clone(&schema), ir);
let next_program = sort_selections(&client_extensions(&program));
let defer_stream_interface = DeferStreamInterface::default();
let mut result = next_program
.fragments()
.map(|def| print_fragment(&schema, &def))
.map(|def| print_fragment(&schema, &def, &defer_stream_interface))
.chain(
next_program
.operations()
.map(|def| print_operation(&schema, &def)),
.map(|def| print_operation(&schema, &def, &defer_stream_interface)),
)
.collect::<Vec<_>>();
result.sort_unstable();
Expand Down
18 changes: 14 additions & 4 deletions compiler/crates/relay-codegen/tests/connections/mod.rs
Expand Up @@ -12,7 +12,9 @@ use graphql_syntax::parse_executable;
use graphql_test_helpers::diagnostics_to_sorted_string;
use relay_codegen::{build_request_params, Printer};
use relay_test_schema::get_test_schema;
use relay_transforms::{transform_connections, validate_connections, ConnectionInterface};
use relay_transforms::{
transform_connections, validate_connections, ConnectionInterface, DeferStreamInterface,
};
use std::sync::Arc;

pub fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
Expand All @@ -28,11 +30,13 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
let program = Program::from_definitions(Arc::clone(&schema), ir);

let connection_interface = ConnectionInterface::default();
let defer_stream_interface = DeferStreamInterface::default();

validate_connections(&program, &connection_interface)
.map_err(|diagnostics| diagnostics_to_sorted_string(fixture.content, &diagnostics))?;

let next_program = transform_connections(&program, &connection_interface);
let next_program =
transform_connections(&program, &connection_interface, &defer_stream_interface);

let mut printed = next_program
.operations()
Expand All @@ -46,11 +50,17 @@ pub fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String> {
type_condition: def.type_,
};
let request_parameters = build_request_params(&def);
printer.print_request(&schema, def, &operation_fragment, request_parameters)
printer.print_request(
&schema,
def,
&operation_fragment,
request_parameters,
&defer_stream_interface,
)
})
.collect::<Vec<_>>();
for def in next_program.fragments() {
printed.push(printer.print_fragment(&schema, def));
printed.push(printer.print_fragment(&schema, def, &defer_stream_interface));
}
printed.sort();
Ok(printed.join("\n\n"))
Expand Down

0 comments on commit 76375df

Please sign in to comment.