Skip to content

Commit f0e802a

Browse files
captbaritonefacebook-github-bot
authored andcommitted
Ensure incremental builds include all @rootfragment fragments
Reviewed By: tyao1 Differential Revision: D45709148 fbshipit-source-id: 6d305dcb60fe92f9c41cffe25f7a69e304dc18a7
1 parent 3b9b848 commit f0e802a

16 files changed

+123
-40
lines changed

compiler/crates/dependency-analyzer/src/ir.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ fn visit_selections(
189189
Selection::LinkedField(linked_field) => {
190190
if let Some(fragment_name) = get_resolver_fragment_dependency_name(
191191
schema.field(linked_field.definition.item),
192-
schema,
193192
) {
194193
update_dependency_graph(
195194
fragment_name.into(),
@@ -209,7 +208,6 @@ fn visit_selections(
209208
Selection::ScalarField(scalar_field) => {
210209
if let Some(fragment_name) = get_resolver_fragment_dependency_name(
211210
schema.field(scalar_field.definition.item),
212-
schema,
213211
) {
214212
update_dependency_graph(
215213
fragment_name.into(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
==================================== INPUT ====================================
2+
# F1
3+
query Q1 {
4+
client_user {
5+
...F1
6+
}
7+
}
8+
fragment F1 on ClientUser {
9+
pop_star_name
10+
}
11+
12+
fragment ClientUserPopStarName on ClientUser {
13+
id
14+
}
15+
16+
# %definitions%
17+
18+
%extensions%
19+
20+
extend type Query {
21+
client_user: ClientUser
22+
}
23+
24+
type ClientUser @__RelayResolverModel {
25+
id: ID!
26+
}
27+
28+
# This resolver's fragment is _not_ generated even though it's on a @__RelayResolverModel type.
29+
# Dependency tracker _should_ look for this fragment.
30+
extend type ClientUser {
31+
pop_star_name: String @relay_resolver(fragment_name: "ClientUserPopStarName", import_path: "PopStarNameResolver")
32+
}
33+
==================================== OUTPUT ===================================
34+
Fragment: ClientUserPopStarName
35+
36+
Fragment: F1
37+
38+
Operation: Q1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# F1
2+
query Q1 {
3+
client_user {
4+
...F1
5+
}
6+
}
7+
fragment F1 on ClientUser {
8+
pop_star_name
9+
}
10+
11+
fragment ClientUserPopStarName on ClientUser {
12+
id
13+
}
14+
15+
# %definitions%
16+
17+
%extensions%
18+
19+
extend type Query {
20+
client_user: ClientUser
21+
}
22+
23+
type ClientUser @__RelayResolverModel {
24+
id: ID!
25+
}
26+
27+
# This resolver's fragment is _not_ generated even though it's on a @__RelayResolverModel type.
28+
# Dependency tracker _should_ look for this fragment.
29+
extend type ClientUser {
30+
pop_star_name: String @relay_resolver(fragment_name: "ClientUserPopStarName", import_path: "PopStarNameResolver")
31+
}

compiler/crates/dependency-analyzer/tests/ir/fixtures/new-resolver-model-field.expected

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ type ClientUser @__RelayResolverModel {
2121
id: ID!
2222
}
2323

24-
# This resolver's fragment is generated because it's on a @__RelayResolverModel type.
24+
# This resolver's fragment is generated because it's on a @__RelayResolverModel
25+
# type and does not define its own fragment using @rootFragment. This is indicated with
26+
# the `generated_fragment` directive argument.
2527
# Dependency tracker should not look for this fragment.
2628
extend type ClientUser {
27-
pop_star_name: String @relay_resolver(fragment_name: "this___is___generated", import_path: "PopStarNameResolver")
29+
pop_star_name: String @relay_resolver(fragment_name: "this___is___generated", import_path: "PopStarNameResolver", generated_fragment: true)
2830
}
2931
==================================== OUTPUT ===================================
3032
Fragment: F1

compiler/crates/dependency-analyzer/tests/ir/fixtures/new-resolver-model-field.graphql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ type ClientUser @__RelayResolverModel {
2020
id: ID!
2121
}
2222

23-
# This resolver's fragment is generated because it's on a @__RelayResolverModel type.
23+
# This resolver's fragment is generated because it's on a @__RelayResolverModel
24+
# type and does not define its own fragment using @rootFragment. This is indicated with
25+
# the `generated_fragment` directive argument.
2426
# Dependency tracker should not look for this fragment.
2527
extend type ClientUser {
26-
pop_star_name: String @relay_resolver(fragment_name: "this___is___generated", import_path: "PopStarNameResolver")
28+
pop_star_name: String @relay_resolver(fragment_name: "this___is___generated", import_path: "PopStarNameResolver", generated_fragment: true)
2729
}

compiler/crates/dependency-analyzer/tests/ir_test.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<080b76ec4b2c6ea6cde4bc6b7c0fea2b>>
7+
* @generated SignedSource<<1370ea763208b340fd15717d45729c87>>
88
*/
99

1010
mod ir;
@@ -75,6 +75,13 @@ fn new_resolver_model_field() {
7575
test_fixture(transform_fixture, "new-resolver-model-field.graphql", "ir/fixtures/new-resolver-model-field.expected", input, expected);
7676
}
7777

78+
#[test]
79+
fn new_resolver_model_field_with_custom_fragment() {
80+
let input = include_str!("ir/fixtures/new-resolver-model-field-with-custom-fragment.graphql");
81+
let expected = include_str!("ir/fixtures/new-resolver-model-field-with-custom-fragment.expected");
82+
test_fixture(transform_fixture, "new-resolver-model-field-with-custom-fragment.graphql", "ir/fixtures/new-resolver-model-field-with-custom-fragment.expected", input, expected);
83+
}
84+
7885
#[test]
7986
fn query_then_fragment() {
8087
let input = include_str!("ir/fixtures/query-then-fragment.graphql");

compiler/crates/docblock-shared/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ lazy_static! {
3131
pub static ref IMPORT_PATH_ARGUMENT_NAME: ArgumentName = ArgumentName("import_path".intern());
3232
pub static ref INJECT_FRAGMENT_DATA_ARGUMENT_NAME: ArgumentName =
3333
ArgumentName("inject_fragment_data".intern());
34+
pub static ref GENERATED_FRAGMENT_ARGUMENT_NAME: ArgumentName =
35+
ArgumentName("generated_fragment".intern());
3436
pub static ref FIELD_NAME_FIELD: StringKey = "fieldName".intern();
3537
pub static ref ON_TYPE_FIELD: StringKey = "onType".intern();
3638
pub static ref ON_INTERFACE_FIELD: StringKey = "onInterface".intern();

compiler/crates/graphql-syntax/src/node/constant_value.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ impl ConstantValue {
4444
_ => None,
4545
}
4646
}
47+
48+
pub fn get_bool_literal(&self) -> Option<bool> {
49+
match self {
50+
ConstantValue::Boolean(BooleanNode { value, .. }) => Some(*value),
51+
_ => None,
52+
}
53+
}
4754
}
4855

4956
impl fmt::Display for ConstantValue {

compiler/crates/relay-compiler/src/build_project/project_asts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ fn find_base_resolver_fragment_asts(
156156
) -> Vec<ExecutableDefinition> {
157157
let mut base_resolver_fragments = ExecutableDefinitionNameSet::default();
158158
for field in schema.fields() {
159-
if let Some(fragment_name) = get_resolver_fragment_dependency_name(field, schema) {
159+
if let Some(fragment_name) = get_resolver_fragment_dependency_name(field) {
160160
if base_definition_asts.contains(&fragment_name.into()) {
161161
base_resolver_fragments.insert(fragment_name.into());
162162
}

compiler/crates/relay-docblock/src/ir.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use common::ObjectName;
1919
use common::Span;
2020
use common::WithLocation;
2121
use docblock_shared::FRAGMENT_KEY_ARGUMENT_NAME;
22+
use docblock_shared::GENERATED_FRAGMENT_ARGUMENT_NAME;
2223
use docblock_shared::HAS_OUTPUT_TYPE_ARGUMENT_NAME;
2324
use docblock_shared::IMPORT_NAME_ARGUMENT_NAME;
2425
use docblock_shared::IMPORT_PATH_ARGUMENT_NAME;
@@ -260,6 +261,7 @@ pub enum FragmentDataInjectionMode {
260261

261262
pub struct RootFragment {
262263
fragment: WithLocation<FragmentDefinitionName>,
264+
generated: bool,
263265
// For Model resolvers, we need to pass the `id` or `__relay_model_instance` field
264266
// from the fragment data to the resolver function
265267
inject_fragment_data: Option<FragmentDataInjectionMode>,
@@ -338,6 +340,13 @@ trait ResolverIr: Sized {
338340
root_fragment.fragment.map(|x| x.0),
339341
));
340342

343+
if root_fragment.generated {
344+
arguments.push(true_argument(
345+
GENERATED_FRAGMENT_ARGUMENT_NAME.0,
346+
Location::generated(),
347+
))
348+
}
349+
341350
if let Some(inject_fragment_data) = root_fragment.inject_fragment_data {
342351
match inject_fragment_data {
343352
FragmentDataInjectionMode::Field(field_name) => {
@@ -668,6 +677,7 @@ impl ResolverIr for TerseRelayResolverIr {
668677
self.root_fragment
669678
.map(|fragment| RootFragment {
670679
fragment,
680+
generated: false,
671681
inject_fragment_data: None,
672682
})
673683
.or_else(|| get_root_fragment_for_object(object))
@@ -832,6 +842,7 @@ impl ResolverIr for RelayResolverIr {
832842
self.root_fragment
833843
.map(|fragment| RootFragment {
834844
fragment,
845+
generated: false,
835846
inject_fragment_data: None,
836847
})
837848
.or_else(|| get_root_fragment_for_object(object))
@@ -1073,6 +1084,7 @@ impl ResolverIr for StrongObjectIr {
10731084
) -> Option<RootFragment> {
10741085
Some(RootFragment {
10751086
fragment: self.root_fragment,
1087+
generated: true,
10761088
inject_fragment_data: Some(FragmentDataInjectionMode::Field(
10771089
schema_info.config.node_interface_id_field,
10781090
)),
@@ -1335,6 +1347,7 @@ fn get_root_fragment_for_object(object: Option<&Object>) -> Option<RootFragment>
13351347
)
13361348
.intern(),
13371349
)),
1350+
generated: true,
13381351
inject_fragment_data: Some(FragmentDataInjectionMode::Field(
13391352
*RESOLVER_MODEL_INSTANCE_FIELD_NAME,
13401353
)),

0 commit comments

Comments
 (0)