diff --git a/compiler/crates/dependency-analyzer/src/ast.rs b/compiler/crates/dependency-analyzer/src/ast.rs index 023191fe8b4a3..52ba84e52e584 100644 --- a/compiler/crates/dependency-analyzer/src/ast.rs +++ b/compiler/crates/dependency-analyzer/src/ast.rs @@ -21,7 +21,7 @@ pub struct ReachableAst { pub base_fragment_names: FragmentDefinitionNameSet, } -/// Get all definitions that reachable from project defintions +/// Get all definitions that reachable from project definitions pub fn get_reachable_ast( project_definitions: Vec, base_definitions: Vec, diff --git a/compiler/crates/dependency-analyzer/src/ir.rs b/compiler/crates/dependency-analyzer/src/ir.rs index b185f27c74871..f3918e70dab34 100644 --- a/compiler/crates/dependency-analyzer/src/ir.rs +++ b/compiler/crates/dependency-analyzer/src/ir.rs @@ -13,7 +13,7 @@ use graphql_ir::*; use intern::string_key::StringKey; use intern::string_key::StringKeyMap; use intern::string_key::StringKeySet; -use relay_transforms::get_resolver_fragment_name; +use relay_transforms::get_resolver_fragment_dependency_name; use schema::SDLSchema; use schema::Schema; @@ -37,7 +37,7 @@ impl fmt::Debug for Node { /// building a dependency graph where edges are either explicit fragment spreads, /// or "implicit dependencies" such as those created by Relay Resolvers. /// -/// New implicit dependencies are detected by walking the chaged documents, +/// New implicit dependencies are detected by walking the changed documents, /// whereas preexisting implicit dependencies must be passed in as /// `implicit_dependencies`. pub fn get_reachable_ir( @@ -135,7 +135,7 @@ fn build_dependency_graph( dependency_graph } -fn update_dependecy_graph( +fn update_dependency_graph( current_node: StringKey, parent_name: StringKey, dependency_graph: &mut StringKeyMap, @@ -172,7 +172,7 @@ fn visit_selections( match selection { Selection::FragmentSpread(node) => { let current_node = node.fragment.item.0; - update_dependecy_graph(current_node, parent_name, dependency_graph, children); + update_dependency_graph(current_node, parent_name, dependency_graph, children); } Selection::InlineFragment(node) => { visit_selections( @@ -184,10 +184,11 @@ fn visit_selections( ); } Selection::LinkedField(linked_field) => { - if let Some(fragment_name) = - get_resolver_fragment_name(schema.field(linked_field.definition.item)) - { - update_dependecy_graph( + if let Some(fragment_name) = get_resolver_fragment_dependency_name( + schema.field(linked_field.definition.item), + schema, + ) { + update_dependency_graph( fragment_name.0, parent_name, dependency_graph, @@ -203,10 +204,11 @@ fn visit_selections( ); } Selection::ScalarField(scalar_field) => { - if let Some(fragment_name) = - get_resolver_fragment_name(schema.field(scalar_field.definition.item)) - { - update_dependecy_graph( + if let Some(fragment_name) = get_resolver_fragment_dependency_name( + schema.field(scalar_field.definition.item), + schema, + ) { + update_dependency_graph( fragment_name.0, parent_name, dependency_graph, @@ -227,8 +229,8 @@ fn visit_selections( } } -// From `key` of changed definition, recusively traverse up the depenency tree, and add all related nodes (ancestors -// of changned definitions which are not from base definitions, and all of their desendants) into the `result` +// From `key` of changed definition, recursively traverse up the dependency tree, and add all related nodes (ancestors +// of changed definitions which are not from base definitions, and all of their descendants) into the `result` fn add_related_nodes( visited: &mut StringKeySet, result: &mut StringKeyMap, diff --git a/compiler/crates/relay-compiler/src/build_project/project_asts.rs b/compiler/crates/relay-compiler/src/build_project/project_asts.rs index 431b2f749b6c6..c4b08731f8002 100644 --- a/compiler/crates/relay-compiler/src/build_project/project_asts.rs +++ b/compiler/crates/relay-compiler/src/build_project/project_asts.rs @@ -14,7 +14,7 @@ use graphql_ir::FragmentDefinitionNameSet; use graphql_syntax::ExecutableDefinition; use intern::string_key::StringKeySet; use relay_config::ProjectConfig; -use relay_transforms::get_resolver_fragment_name; +use relay_transforms::get_resolver_fragment_dependency_name; use schema::SDLSchema; use schema::Schema; @@ -150,7 +150,7 @@ fn find_base_resolver_fragment_asts( ) -> Vec { let mut base_resolver_fragments = StringKeySet::default(); for field in schema.fields() { - if let Some(fragment_name) = get_resolver_fragment_name(field) { + if let Some(fragment_name) = get_resolver_fragment_dependency_name(field, schema) { if base_definition_asts.contains(&fragment_name.0) { base_resolver_fragments.insert(fragment_name.0); } diff --git a/compiler/crates/relay-transforms/src/lib.rs b/compiler/crates/relay-transforms/src/lib.rs index db46b368333c4..a3c82bef5fd54 100644 --- a/compiler/crates/relay-transforms/src/lib.rs +++ b/compiler/crates/relay-transforms/src/lib.rs @@ -172,7 +172,7 @@ pub use relay_client_component::RELAY_CLIENT_COMPONENT_MODULE_ID_ARGUMENT_NAME; pub use relay_client_component::RELAY_CLIENT_COMPONENT_SERVER_DIRECTIVE_NAME; pub use relay_directive::RelayDirective; pub use relay_node_identifier::RelayLocationAgnosticBehavior; -pub use relay_resolvers::get_resolver_fragment_name; +pub use relay_resolvers::get_resolver_fragment_dependency_name; pub use relay_resolvers::relay_resolvers; pub use relay_resolvers::FragmentDataInjectionMode; pub use relay_resolvers::RelayResolverMetadata; diff --git a/compiler/crates/relay-transforms/src/relay_resolvers.rs b/compiler/crates/relay-transforms/src/relay_resolvers.rs index b29a294266c99..8a8d855b95187 100644 --- a/compiler/crates/relay-transforms/src/relay_resolvers.rs +++ b/compiler/crates/relay-transforms/src/relay_resolvers.rs @@ -80,6 +80,8 @@ lazy_static! { ArgumentName("inject_fragment_data".intern()); pub static ref RELAY_RESOLVER_WEAK_OBJECT_DIRECTIVE: DirectiveName = DirectiveName("__RelayWeakObject".intern()); + static ref RESOLVER_MODEL_DIRECTIVE_NAME: DirectiveName = + DirectiveName("__RelayResolverModel".intern()); } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -697,7 +699,12 @@ pub(crate) fn get_bool_argument_is_true( } } -pub fn get_resolver_fragment_name(field: &Field) -> Option { +// If the field is a resolver, return its user defined fragment name. Does not +// return generated fragment names. +pub fn get_resolver_fragment_dependency_name( + field: &Field, + schema: &SDLSchema, +) -> Option { if !field.is_extension { return None; } @@ -710,9 +717,29 @@ pub fn get_resolver_fragment_name(field: &Field) -> Option bool { + if let Some(parent_type) = field.parent_type { + let directives = match parent_type { + schema::Type::Object(object_id) => &schema.object(object_id).directives, + schema::Type::Interface(interface_id) => &schema.interface(interface_id).directives, + schema::Type::Union(union_id) => &schema.union(union_id).directives, + _ => panic!("Expected parent to be an object, interface or union."), + }; + + directives.named(*RESOLVER_MODEL_DIRECTIVE_NAME).is_some() + } else { + false + } +} + fn to_camel_case(non_camelized_string: String) -> String { let mut camelized_string = String::with_capacity(non_camelized_string.len()); let mut last_character_was_not_alphanumeric = false;