Skip to content

Commit a5a7947

Browse files
evanyeungfacebook-github-bot
authored andcommitted
Incrementally build Enum schema changes
Reviewed By: tyao1 Differential Revision: D54547131 fbshipit-source-id: 51619edbdaa3b21cb96be815e7f96a3a6da8f503
1 parent 9244d27 commit a5a7947

File tree

14 files changed

+393
-11
lines changed

14 files changed

+393
-11
lines changed

compiler/crates/dependency-analyzer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ graphql-syntax = { path = "../graphql-syntax" }
2222
relay-transforms = { path = "../relay-transforms" }
2323
rustc-hash = "1.1.0"
2424
schema = { path = "../schema" }
25+
schema-diff = { path = "../schema-diff" }
2526
serde = { version = "1.0.185", features = ["derive", "rc"] }
2627

2728
[dev-dependencies]

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ use rustc_hash::FxHashMap;
1515
use rustc_hash::FxHashSet;
1616
use schema::SDLSchema;
1717
use schema::Schema;
18+
use schema_diff::check;
19+
20+
use crate::schema_change_analyzer;
1821

1922
pub type ExecutableDefinitionNameSet = FxHashSet<ExecutableDefinitionName>;
2023
pub type ExecutableDefinitionNameMap<V> = FxHashMap<ExecutableDefinitionName, V>;
@@ -48,11 +51,16 @@ pub fn get_reachable_ir(
4851
base_definition_names: ExecutableDefinitionNameSet,
4952
changed_names: ExecutableDefinitionNameSet,
5053
schema: &SDLSchema,
54+
schema_changes: FxHashSet<check::IncrementalBuildSchemaChange>,
5155
) -> Vec<ExecutableDefinition> {
52-
if changed_names.is_empty() {
56+
if changed_names.is_empty() && schema_changes.is_empty() {
5357
return vec![];
5458
}
5559

60+
let mut all_changed_names: ExecutableDefinitionNameSet =
61+
schema_change_analyzer::get_affected_definitions(schema, &definitions, schema_changes);
62+
all_changed_names.extend(changed_names);
63+
5664
// For each executable definition, define a `Node` indicating its parents and children
5765
// Note: There are situations where a name in `changed_names` may not appear
5866
// in `definitions`, and thus would be missing from `dependency_graph`. This can arise
@@ -64,7 +72,7 @@ pub fn get_reachable_ir(
6472
let mut visited = Default::default();
6573
let mut filtered_definitions = Default::default();
6674

67-
for key in changed_names.into_iter() {
75+
for key in all_changed_names.into_iter() {
6876
if dependency_graph.contains_key(&key) {
6977
add_related_nodes(
7078
&mut visited,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
mod ast;
1414
mod ir;
1515
mod minimized_executable;
16+
mod schema_change_analyzer;
1617

1718
pub use ast::get_definition_references;
1819
pub use ast::get_reachable_ast;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
use std::collections::HashSet;
9+
10+
use graphql_ir::*;
11+
use rustc_hash::FxHashSet;
12+
use schema::SDLSchema;
13+
use schema::Schema;
14+
use schema_diff::check::IncrementalBuildSchemaChange;
15+
16+
use crate::ExecutableDefinitionNameSet;
17+
18+
pub fn get_affected_definitions(
19+
schema: &SDLSchema,
20+
definitions: &[ExecutableDefinition],
21+
schema_changes: FxHashSet<IncrementalBuildSchemaChange>,
22+
) -> ExecutableDefinitionNameSet {
23+
SchemaChangeDefinitionFinder::get_definitions(schema, definitions, schema_changes)
24+
}
25+
26+
struct SchemaChangeDefinitionFinder<'a, 'b> {
27+
changed_definitions: ExecutableDefinitionNameSet,
28+
current_executable: &'a ExecutableDefinition,
29+
schema: &'b SDLSchema,
30+
schema_changes: FxHashSet<IncrementalBuildSchemaChange>,
31+
}
32+
33+
impl SchemaChangeDefinitionFinder<'_, '_> {
34+
fn get_definitions(
35+
schema: &SDLSchema,
36+
definitions: &[ExecutableDefinition],
37+
schema_changes: FxHashSet<IncrementalBuildSchemaChange>,
38+
) -> ExecutableDefinitionNameSet {
39+
if definitions.is_empty() || schema_changes.is_empty() {
40+
return HashSet::default();
41+
}
42+
43+
let mut finder = SchemaChangeDefinitionFinder {
44+
changed_definitions: HashSet::default(),
45+
current_executable: &definitions[0],
46+
schema,
47+
schema_changes,
48+
};
49+
for def in definitions.iter() {
50+
finder.current_executable = def;
51+
match def {
52+
ExecutableDefinition::Operation(operation) => finder.visit_operation(operation),
53+
ExecutableDefinition::Fragment(fragment) => finder.visit_fragment(fragment),
54+
};
55+
}
56+
finder.changed_definitions
57+
}
58+
59+
fn get_name_from_executable(&self) -> ExecutableDefinitionName {
60+
match self.current_executable {
61+
ExecutableDefinition::Operation(node) => {
62+
ExecutableDefinitionName::OperationDefinitionName(node.name.item)
63+
}
64+
ExecutableDefinition::Fragment(node) => {
65+
ExecutableDefinitionName::FragmentDefinitionName(node.name.item)
66+
}
67+
}
68+
}
69+
}
70+
71+
impl Visitor for SchemaChangeDefinitionFinder<'_, '_> {
72+
const NAME: &'static str = "DependencyAnalyzerSchemaChangeDefinitionFinder";
73+
const VISIT_ARGUMENTS: bool = false;
74+
const VISIT_DIRECTIVES: bool = false;
75+
76+
fn visit_scalar_field(&mut self, field: &ScalarField) {
77+
let id = field.definition.item;
78+
let type_ = self.schema.field(id).type_.inner();
79+
match type_ {
80+
schema::definitions::Type::Enum(id) => {
81+
let enum_type = self.schema.enum_(id);
82+
let key = enum_type.name.item.0;
83+
if self
84+
.schema_changes
85+
.contains(&IncrementalBuildSchemaChange::Enum(key))
86+
{
87+
self.changed_definitions
88+
.insert(self.get_name_from_executable());
89+
}
90+
}
91+
// We only care about enum fields at the moment. As more changes can be handled,
92+
// they should be added here
93+
_ => (),
94+
}
95+
}
96+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
==================================== INPUT ====================================
2+
# F1, Q2
3+
query Q1 {
4+
me {
5+
...F1
6+
...F2
7+
}
8+
}
9+
10+
fragment F1 on User {
11+
userEnum
12+
}
13+
14+
fragment F2 on User {
15+
name
16+
}
17+
18+
query Q2 {
19+
me {
20+
...F2
21+
...F3
22+
}
23+
}
24+
25+
fragment F3 on User {
26+
alternate_name
27+
}
28+
29+
query QUnrelated {
30+
me {
31+
...F3
32+
}
33+
}
34+
35+
%extensions%
36+
# Enum: TestEnum
37+
38+
enum TestEnum {
39+
A
40+
B
41+
}
42+
43+
extend type User {
44+
userEnum: TestEnum
45+
}
46+
==================================== OUTPUT ===================================
47+
Fragment: F1
48+
49+
Fragment: F2
50+
51+
Fragment: F3
52+
53+
Operation: Q1
54+
55+
Operation: Q2
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# F1, Q2
2+
query Q1 {
3+
me {
4+
...F1
5+
...F2
6+
}
7+
}
8+
9+
fragment F1 on User {
10+
userEnum
11+
}
12+
13+
fragment F2 on User {
14+
name
15+
}
16+
17+
query Q2 {
18+
me {
19+
...F2
20+
...F3
21+
}
22+
}
23+
24+
fragment F3 on User {
25+
alternate_name
26+
}
27+
28+
query QUnrelated {
29+
me {
30+
...F3
31+
}
32+
}
33+
34+
%extensions%
35+
# Enum: TestEnum
36+
37+
enum TestEnum {
38+
A
39+
B
40+
}
41+
42+
extend type User {
43+
userEnum: TestEnum
44+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
==================================== INPUT ====================================
2+
#
3+
query Q1 {
4+
me {
5+
...F1
6+
...F2
7+
}
8+
}
9+
10+
fragment F1 on User {
11+
userEnum
12+
}
13+
14+
fragment F2 on User {
15+
name
16+
}
17+
18+
query QUnrelated {
19+
me {
20+
...F2
21+
...F3
22+
}
23+
}
24+
25+
fragment F3 on User {
26+
alternate_name
27+
}
28+
29+
%extensions%
30+
# Enum: TestEnum
31+
32+
enum TestEnum {
33+
A
34+
B
35+
}
36+
37+
extend type User {
38+
userEnum: TestEnum
39+
}
40+
==================================== OUTPUT ===================================
41+
Fragment: F1
42+
43+
Fragment: F2
44+
45+
Operation: Q1
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#
2+
query Q1 {
3+
me {
4+
...F1
5+
...F2
6+
}
7+
}
8+
9+
fragment F1 on User {
10+
userEnum
11+
}
12+
13+
fragment F2 on User {
14+
name
15+
}
16+
17+
query QUnrelated {
18+
me {
19+
...F2
20+
...F3
21+
}
22+
}
23+
24+
fragment F3 on User {
25+
alternate_name
26+
}
27+
28+
%extensions%
29+
# Enum: TestEnum
30+
31+
enum TestEnum {
32+
A
33+
B
34+
}
35+
36+
extend type User {
37+
userEnum: TestEnum
38+
}

0 commit comments

Comments
 (0)