Skip to content

Commit 045f228

Browse files
SamChou19815meta-codesync[bot]
authored andcommitted
Implement feature flag to gate rollout of flow modern syntax
Reviewed By: marcoww6 Differential Revision: D106303680 fbshipit-source-id: 593f5cff104e2abfa87f3a5b8adda92cb96848bd
1 parent d728114 commit 045f228

177 files changed

Lines changed: 3619 additions & 3468 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/crates/common/src/feature_flags.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,12 @@ pub struct FeatureFlags {
208208
#[serde(default)]
209209
pub enforce_module_name_prefix_for_non_haste: bool,
210210

211+
/// Use modern Flow syntax for generated object types.
212+
/// This enables gradual rollout of exact object type syntax and readonly
213+
/// properties across files.
214+
#[serde(default)]
215+
pub flow_modern_syntax: FeatureFlag,
216+
211217
/// When enabled, the `@nogrep` annotation is included in the docblock
212218
/// header of generated artifacts. This annotation was historically always
213219
/// emitted but is no longer needed. This flag allows incremental removal
@@ -254,6 +260,7 @@ impl Default for FeatureFlags {
254260
enable_shadow_resolvers: Default::default(),
255261
allow_legacy_relay_resolver_tag: Default::default(),
256262
enforce_module_name_prefix_for_non_haste: Default::default(),
263+
flow_modern_syntax: Default::default(),
257264
emit_nogrep_annotation: Default::default(),
258265
disable_more_precise_abstract_selection_raw_response_type: Default::default(),
259266

compiler/crates/relay-compiler/relay-compiler-config-schema.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,13 @@
706706
"type": "boolean",
707707
"default": false
708708
},
709+
"flow_modern_syntax": {
710+
"description": "Use modern Flow syntax for generated object types.\nThis enables gradual rollout of exact object type syntax and readonly\nproperties across files.",
711+
"$ref": "#/$defs/FeatureFlag",
712+
"default": {
713+
"kind": "disabled"
714+
}
715+
},
709716
"legacy_include_path_in_required_reader_nodes": {
710717
"description": "The `path` field in `@required` Reader AST nodes is no longer used. But\nremoving them in one diff is too large of a change to ship at once.\n\nThis flag will allow us to use the rollout FeatureFlag to remove them\nacross a number of diffs.",
711718
"$ref": "#/$defs/FeatureFlag",
@@ -739,6 +746,13 @@
739746
"kind": "disabled"
740747
}
741748
},
749+
"shard_extra_artifacts": {
750+
"description": "Shard generated extra artifacts into subdirectories under\n`extraArtifactsOutput` that mirror the source file's relative path,\nhonoring `shardOutput` / `shardStripRegex`.",
751+
"$ref": "#/$defs/FeatureFlag",
752+
"default": {
753+
"kind": "disabled"
754+
}
755+
},
742756
"skip_printing_nulls": {
743757
"$ref": "#/$defs/FeatureFlag",
744758
"default": {
@@ -968,6 +982,9 @@
968982
"kind": "enabled"
969983
},
970984
"enforce_module_name_prefix_for_non_haste": false,
985+
"flow_modern_syntax": {
986+
"kind": "disabled"
987+
},
971988
"legacy_include_path_in_required_reader_nodes": {
972989
"kind": "disabled"
973990
},
@@ -981,6 +998,9 @@
981998
"relay_resolver_enable_interface_output_type": {
982999
"kind": "disabled"
9831000
},
1001+
"shard_extra_artifacts": {
1002+
"kind": "disabled"
1003+
},
9841004
"skip_printing_nulls": {
9851005
"kind": "disabled"
9861006
},

compiler/crates/relay-typegen/src/flow.rs

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::writer::Writer;
2020
pub struct FlowPrinter {
2121
result: String,
2222
indentation: usize,
23+
use_flow_modern_syntax: bool,
2324
}
2425

2526
impl Write for FlowPrinter {
@@ -152,10 +153,11 @@ impl Writer for FlowPrinter {
152153
}
153154

154155
impl FlowPrinter {
155-
pub fn new() -> Self {
156+
pub fn new(use_flow_modern_syntax: bool) -> Self {
156157
Self {
157158
result: String::new(),
158159
indentation: 0,
160+
use_flow_modern_syntax,
159161
}
160162
}
161163

@@ -226,11 +228,15 @@ impl FlowPrinter {
226228

227229
fn write_object(&mut self, props: &[Prop], exact: bool) -> FmtResult {
228230
if props.is_empty() && exact {
229-
write!(&mut self.result, "{{||}}")?;
231+
if self.use_flow_modern_syntax {
232+
write!(&mut self.result, "{{}}")?;
233+
} else {
234+
write!(&mut self.result, "{{||}}")?;
235+
}
230236
return Ok(());
231237
}
232238

233-
if exact {
239+
if exact && !self.use_flow_modern_syntax {
234240
writeln!(&mut self.result, "{{|")?;
235241
} else {
236242
writeln!(&mut self.result, "{{")?;
@@ -259,7 +265,9 @@ impl FlowPrinter {
259265
)?;
260266
self.write_indentation()?;
261267
}
262-
if key_value_pair.read_only {
268+
if key_value_pair.read_only && self.use_flow_modern_syntax {
269+
write!(&mut self.result, "readonly ")?;
270+
} else if key_value_pair.read_only {
263271
write!(&mut self.result, "+")?;
264272
}
265273
write!(&mut self.result, "{}", key_value_pair.key)?;
@@ -294,7 +302,7 @@ impl FlowPrinter {
294302
}
295303
self.indentation -= 1;
296304
self.write_indentation()?;
297-
if exact {
305+
if exact && !self.use_flow_modern_syntax {
298306
write!(&mut self.result, "|}}")?;
299307
} else {
300308
write!(&mut self.result, "}}")?;
@@ -386,7 +394,11 @@ mod tests {
386394
use crate::writer::SortedASTList;
387395

388396
fn print_type(ast: &AST) -> String {
389-
let mut printer = Box::new(FlowPrinter::new());
397+
print_type_with_flow_modern_syntax(ast, false)
398+
}
399+
400+
fn print_type_with_flow_modern_syntax(ast: &AST, use_flow_modern_syntax: bool) -> String {
401+
let mut printer = Box::new(FlowPrinter::new(use_flow_modern_syntax));
390402
printer.write(ast).unwrap();
391403
printer.into_string()
392404
}
@@ -517,6 +529,58 @@ mod tests {
517529
);
518530
}
519531

532+
#[test]
533+
fn flow_modern_exact_object() {
534+
assert_eq!(
535+
print_type_with_flow_modern_syntax(
536+
&AST::ExactObject(ExactObject::new(Vec::new())),
537+
true,
538+
),
539+
r"{}".to_string()
540+
);
541+
542+
assert_eq!(
543+
print_type_with_flow_modern_syntax(
544+
&AST::ExactObject(ExactObject::new(vec![
545+
Prop::KeyValuePair(KeyValuePairProp {
546+
key: intern!("foo"),
547+
optional: true,
548+
read_only: false,
549+
value: AST::ExactObject(ExactObject::new(vec![
550+
Prop::KeyValuePair(KeyValuePairProp {
551+
key: intern!("nested_foo"),
552+
optional: true,
553+
read_only: false,
554+
value: AST::String,
555+
}),
556+
Prop::KeyValuePair(KeyValuePairProp {
557+
key: intern!("nested_foo2"),
558+
optional: false,
559+
read_only: true,
560+
value: AST::Number,
561+
}),
562+
],)),
563+
}),
564+
Prop::KeyValuePair(KeyValuePairProp {
565+
key: intern!("bar"),
566+
optional: false,
567+
read_only: true,
568+
value: AST::Number,
569+
}),
570+
],)),
571+
true,
572+
),
573+
r"{
574+
readonly bar: number,
575+
foo?: {
576+
nested_foo?: string,
577+
readonly nested_foo2: number,
578+
},
579+
}"
580+
.to_string()
581+
);
582+
}
583+
520584
#[test]
521585
fn inexact_object() {
522586
assert_eq!(
@@ -567,6 +631,35 @@ mod tests {
567631
);
568632
}
569633

634+
#[test]
635+
fn flow_modern_inexact_object_preserves_spread() {
636+
assert_eq!(
637+
print_type_with_flow_modern_syntax(
638+
&AST::InexactObject(InexactObject::new(vec![
639+
Prop::KeyValuePair(KeyValuePairProp {
640+
key: intern!("foo"),
641+
optional: false,
642+
read_only: false,
643+
value: AST::String,
644+
}),
645+
Prop::KeyValuePair(KeyValuePairProp {
646+
key: intern!("bar"),
647+
optional: true,
648+
read_only: true,
649+
value: AST::Number,
650+
})
651+
])),
652+
true,
653+
),
654+
r"{
655+
readonly bar?: number,
656+
foo: string,
657+
...
658+
}"
659+
.to_string()
660+
);
661+
}
662+
570663
#[test]
571664
fn one_of_input_object() {
572665
assert_eq!(
@@ -632,7 +725,7 @@ mod tests {
632725

633726
#[test]
634727
fn import_type() {
635-
let mut printer = Box::new(FlowPrinter::new());
728+
let mut printer = Box::new(FlowPrinter::new(false));
636729
printer.write_import_type(&["A", "B"], "module").unwrap();
637730
assert_eq!(
638731
printer.into_string(),
@@ -642,7 +735,7 @@ mod tests {
642735

643736
#[test]
644737
fn import_module() {
645-
let mut printer = Box::new(FlowPrinter::new());
738+
let mut printer = Box::new(FlowPrinter::new(false));
646739
printer.write_import_module_default("A", "module").unwrap();
647740
assert_eq!(printer.into_string(), "import A from \"module\";\n");
648741
}

compiler/crates/relay-typegen/src/lib.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ fn generate_fragment_type_exports_section_impl(
158158
is_extra_artifact_branch_module,
159159
},
160160
);
161-
let mut writer = new_writer_from_config(&project_config.typegen_config);
161+
let mut writer = new_writer_from_config(
162+
&project_config.typegen_config,
163+
use_flow_modern_syntax(project_config, fragment_definition.name.item.0),
164+
);
162165
write_fragment_type_exports_section(&typegen_context, fragment_definition, &mut writer)
163166
.unwrap();
164167
writer.into_string()
@@ -184,7 +187,10 @@ pub fn generate_named_validator_export(
184187
is_extra_artifact_branch_module: false,
185188
},
186189
);
187-
let mut writer = new_writer_from_config(&project_config.typegen_config);
190+
let mut writer = new_writer_from_config(
191+
&project_config.typegen_config,
192+
use_flow_modern_syntax(project_config, fragment_definition.name.item.0),
193+
);
188194
write_validator_function(&typegen_context, fragment_definition, &mut writer).unwrap();
189195
let validator_function_body = writer.into_string();
190196

@@ -220,7 +226,10 @@ pub fn generate_operation_type_exports_section(
220226
is_extra_artifact_branch_module: false,
221227
},
222228
);
223-
let mut writer = new_writer_from_config(&project_config.typegen_config);
229+
let mut writer = new_writer_from_config(
230+
&project_config.typegen_config,
231+
use_flow_modern_syntax(project_config, typegen_operation.name.item.0),
232+
);
224233
write_operation_type_exports_section(
225234
&typegen_context,
226235
typegen_operation,
@@ -257,7 +266,10 @@ pub fn generate_split_operation_type_exports_section(
257266
is_extra_artifact_branch_module: false,
258267
},
259268
);
260-
let mut writer = new_writer_from_config(&project_config.typegen_config);
269+
let mut writer = new_writer_from_config(
270+
&project_config.typegen_config,
271+
use_flow_modern_syntax(project_config, typegen_operation.name.item.0),
272+
);
261273

262274
write_split_operation_type_exports_section(
263275
&typegen_context,
@@ -269,6 +281,13 @@ pub fn generate_split_operation_type_exports_section(
269281
writer.into_string()
270282
}
271283

284+
fn use_flow_modern_syntax(project_config: &ProjectConfig, artifact_name: StringKey) -> bool {
285+
project_config
286+
.feature_flags
287+
.flow_modern_syntax
288+
.is_enabled_for(artifact_name)
289+
}
290+
272291
/// An immutable grab bag of configuration, etc. for type generation.
273292
/// A new `TypegenContext` is created for each operation, fragment, and so on.
274293
struct TypegenContext<'a> {

compiler/crates/relay-typegen/src/writer.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,10 +388,13 @@ pub trait Writer: Write {
388388
fn write_any_type_definition(&mut self, name: &str) -> FmtResult;
389389
}
390390

391-
pub(crate) fn new_writer_from_config(config: &TypegenConfig) -> Box<dyn Writer> {
391+
pub(crate) fn new_writer_from_config(
392+
config: &TypegenConfig,
393+
use_flow_modern_syntax: bool,
394+
) -> Box<dyn Writer> {
392395
match config.language {
393396
TypegenLanguage::JavaScript => Box::<JavaScriptPrinter>::default(),
394-
TypegenLanguage::Flow => Box::new(FlowPrinter::new()),
397+
TypegenLanguage::Flow => Box::new(FlowPrinter::new(use_flow_modern_syntax)),
395398
TypegenLanguage::TypeScript => Box::new(TypeScriptPrinter::new(config)),
396399
}
397400
}

compiler/crates/relay-typegen/tests/generate_flow.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ pub async fn transform_fixture(fixture: &Fixture<'_>) -> Result<String, String>
6969
.collect(),
7070
},
7171
relay_resolver_enable_interface_output_type: FeatureFlag::Enabled,
72+
flow_modern_syntax: if fixture
73+
.content
74+
.contains("# feature_flags.flow_modern_syntax = false")
75+
{
76+
FeatureFlag::Disabled
77+
} else {
78+
FeatureFlag::Enabled
79+
},
7280
..Default::default()
7381
};
7482
let ir = build_ir_in_relay_mode(&schema, &ast.definitions, &feature_flags)

0 commit comments

Comments
 (0)