Skip to content

Commit

Permalink
Sort unions conditionally
Browse files Browse the repository at this point in the history
Reviewed By: tyao1

Differential Revision: D34584664

fbshipit-source-id: 53c520341aa025af578dec88ba88ebfedf3a497f
  • Loading branch information
rbalicki2 authored and facebook-github-bot committed Mar 11, 2022
1 parent b04b2b7 commit 9f0dea4
Show file tree
Hide file tree
Showing 65 changed files with 470 additions and 295 deletions.
17 changes: 10 additions & 7 deletions compiler/crates/relay-typegen/src/flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl Writer for FlowPrinter {
AST::Local3DPayload(document_name, selections) => {
self.write_local_3d_payload(*document_name, selections)
}
AST::FragmentReference(fragments) => self.write_fragment_references(fragments),
AST::FragmentReference(fragments) => self.write_fragment_references(&***fragments),
AST::FragmentReferenceType(fragment) => {
write!(&mut self.result, "{}$fragmentType", fragment)
}
Expand Down Expand Up @@ -325,7 +325,7 @@ impl FlowPrinter {

#[cfg(test)]
mod tests {
use crate::writer::{ExactObject, InexactObject, KeyValuePairProp};
use crate::writer::{ExactObject, InexactObject, KeyValuePairProp, SortedASTList};

use super::*;
use intern::string_key::Intern;
Expand All @@ -346,7 +346,10 @@ mod tests {
#[test]
fn union_type() {
assert_eq!(
print_type(&AST::Union(vec![AST::String, AST::Number])),
print_type(&AST::Union(SortedASTList::new(
vec![AST::String, AST::Number],
true
))),
"string | number".to_string()
);
}
Expand All @@ -367,10 +370,10 @@ mod tests {
);

assert_eq!(
print_type(&AST::Nullable(Box::new(AST::Union(vec![
AST::String,
AST::Number,
])))),
print_type(&AST::Nullable(Box::new(AST::Union(SortedASTList::new(
vec![AST::String, AST::Number,],
true
))))),
"?(string | number)"
)
}
Expand Down
142 changes: 85 additions & 57 deletions compiler/crates/relay-typegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ use schema::{EnumID, SDLSchema, ScalarID, Schema, Type, TypeReference};
use std::{fmt::Result as FmtResult, hash::Hash, path::Path};
use typescript::TypeScriptPrinter;
use writer::{
ExactObject, GetterSetterPairProp, InexactObject, KeyValuePairProp, Prop, SpreadProp, Writer,
AST,
ExactObject, GetterSetterPairProp, InexactObject, KeyValuePairProp, Prop, SortedASTList,
SortedStringKeyList, SpreadProp, Writer, AST,
};

static REACT_RELAY_MULTI_ACTOR: &str = "react-relay/multi-actor";
Expand Down Expand Up @@ -222,7 +222,10 @@ impl<'a> TypeGenerator<'a> {
runtime_imports: RuntimeImports::default(),
writer: match &typegen_config.language {
TypegenLanguage::Flow => Box::new(FlowPrinter::new(flow_typegen_phase)),
TypegenLanguage::TypeScript => Box::new(TypeScriptPrinter::new(typegen_config)),
TypegenLanguage::TypeScript => Box::new(TypeScriptPrinter::new(
typegen_config,
should_sort_typegen_items,
)),
},
has_actor_change: false,
flow_typegen_phase,
Expand Down Expand Up @@ -472,7 +475,10 @@ impl<'a> TypeGenerator<'a> {
key: *KEY_FRAGMENT_SPREADS,
optional: false,
read_only: true,
value: AST::FragmentReference(vec![fragment_name]),
value: AST::FragmentReference(SortedStringKeyList::new(
vec![fragment_name],
self.should_sort_typegen_items,
)),
});
let is_plural_fragment = is_plural(fragment_definition);
let mut ref_type = AST::InexactObject(InexactObject::new(
Expand Down Expand Up @@ -896,16 +902,19 @@ impl<'a> TypeGenerator<'a> {
let mut typename_aliases = IndexSet::new();
for (concrete_type, selections) in by_concrete_type {
types.push(
group_refs(base_fields.values().cloned().chain(selections))
.map(|selection| {
if selection.is_typename() {
typename_aliases.insert(selection.get_field_name_or_alias().expect(
group_refs(
base_fields.values().cloned().chain(selections),
self.should_sort_typegen_items,
)
.map(|selection| {
if selection.is_typename() {
typename_aliases.insert(selection.get_field_name_or_alias().expect(
"Just checked this exists by checking that the field is typename",
));
}
self.make_prop(selection, unmasked, Some(concrete_type))
})
.collect(),
}
self.make_prop(selection, unmasked, Some(concrete_type))
})
.collect(),
);
}

Expand Down Expand Up @@ -940,39 +949,42 @@ impl<'a> TypeGenerator<'a> {
true,
);
}
let selection_map_values = group_refs(hashmap_into_values(selection_map))
.map(|sel| {
if let TypeSelection::ScalarField(ref scalar_field) = sel {
if sel.is_typename() {
if let Some(type_condition) = scalar_field.concrete_type {
let mut scalar_field = scalar_field.clone();
scalar_field.conditional = false;
return self.make_prop(
TypeSelection::ScalarField(scalar_field),
unmasked,
Some(type_condition),
);
}
}
} else if let TypeSelection::LinkedField(ref linked_field) = sel {
if let Some(concrete_type) = linked_field.concrete_type {
let mut linked_field = linked_field.clone();
linked_field.concrete_type = None;
let selection_map_values = group_refs(
hashmap_into_values(selection_map),
self.should_sort_typegen_items,
)
.map(|sel| {
if let TypeSelection::ScalarField(ref scalar_field) = sel {
if sel.is_typename() {
if let Some(type_condition) = scalar_field.concrete_type {
let mut scalar_field = scalar_field.clone();
scalar_field.conditional = false;
return self.make_prop(
TypeSelection::LinkedField(linked_field),
TypeSelection::ScalarField(scalar_field),
unmasked,
Some(concrete_type),
Some(type_condition),
);
}
}
} else if let TypeSelection::LinkedField(ref linked_field) = sel {
if let Some(concrete_type) = linked_field.concrete_type {
let mut linked_field = linked_field.clone();
linked_field.concrete_type = None;
return self.make_prop(
TypeSelection::LinkedField(linked_field),
unmasked,
Some(concrete_type),
);
}
}

self.make_prop(sel, unmasked, None)
})
.collect();
self.make_prop(sel, unmasked, None)
})
.collect();
types.push(selection_map_values);
}

AST::Union(
AST::Union(SortedASTList::new(
types
.into_iter()
.map(|mut props: Vec<Prop>| {
Expand All @@ -994,7 +1006,8 @@ impl<'a> TypeGenerator<'a> {
}
})
.collect(),
)
self.should_sort_typegen_items,
))
}

fn raw_response_selections_to_babel(
Expand Down Expand Up @@ -1063,7 +1076,7 @@ impl<'a> TypeGenerator<'a> {
self.append_local_3d_payload(&mut types, &base_fields, concrete_type);
}

AST::Union(types)
AST::Union(SortedASTList::new(types, self.should_sort_typegen_items))
}

fn append_local_3d_payload(
Expand Down Expand Up @@ -1133,6 +1146,7 @@ impl<'a> TypeGenerator<'a> {
}
} else {
let setter_parameter = AST::Union(
SortedASTList::new(
just_fragments
.iter()
.map(|fragment_spread| {
Expand Down Expand Up @@ -1171,7 +1185,7 @@ impl<'a> TypeGenerator<'a> {
], self.should_sort_typegen_items))
})
.collect(),
);
self.should_sort_typegen_items));
if linked_field.node_type.is_list() {
AST::ReadOnlyArray(Box::new(setter_parameter))
} else {
Expand Down Expand Up @@ -1487,8 +1501,10 @@ impl<'a> TypeGenerator<'a> {
members.push(AST::StringLiteral(*FUTURE_ENUM_VALUE));
}

self.writer
.write_export_type(enum_type.name.lookup(), &AST::Union(members))?;
self.writer.write_export_type(
enum_type.name.lookup(),
&AST::Union(SortedASTList::new(members, self.should_sort_typegen_items)),
)?;
}
}
Ok(())
Expand Down Expand Up @@ -1743,13 +1759,16 @@ impl<'a> TypeGenerator<'a> {
],
self.should_sort_typegen_items,
));
let return_type = AST::Union(vec![
AST::InexactObject(InexactObject::new(
vec![id_prop, fragment_spread_prop, return_value_discriminator],
self.should_sort_typegen_items,
)),
AST::RawType(intern!("false")),
]);
let return_type = AST::Union(SortedASTList::new(
vec![
AST::InexactObject(InexactObject::new(
vec![id_prop, fragment_spread_prop, return_value_discriminator],
self.should_sort_typegen_items,
)),
AST::RawType(intern!("false")),
],
self.should_sort_typegen_items,
));

let (open_comment, close_comment) = match self.typegen_config.language {
TypegenLanguage::Flow => ("/*", "*/"),
Expand Down Expand Up @@ -1832,13 +1851,16 @@ impl<'a> TypeGenerator<'a> {
],
self.should_sort_typegen_items,
));
let return_type = AST::Union(vec![
AST::InexactObject(InexactObject::new(
vec![id_prop, fragment_spread_prop, return_value_discriminator],
self.should_sort_typegen_items,
)),
AST::RawType(intern!("false")),
]);
let return_type = AST::Union(SortedASTList::new(
vec![
AST::InexactObject(InexactObject::new(
vec![id_prop, fragment_spread_prop, return_value_discriminator],
self.should_sort_typegen_items,
)),
AST::RawType(intern!("false")),
],
self.should_sort_typegen_items,
));

let (open_comment, close_comment) = match self.typegen_config.language {
TypegenLanguage::Flow => ("/*", "*/"),
Expand Down Expand Up @@ -2149,7 +2171,10 @@ fn selections_to_map(

// TODO: T85950736 Fix these clippy errors
#[allow(clippy::while_let_on_iterator, clippy::useless_conversion)]
fn group_refs(props: impl Iterator<Item = TypeSelection>) -> impl Iterator<Item = TypeSelection> {
fn group_refs(
props: impl Iterator<Item = TypeSelection>,
should_sort_typegen_items: bool,
) -> impl Iterator<Item = TypeSelection> {
let mut fragment_spreads = None;
let mut props = props.into_iter();
std::iter::from_fn(move || {
Expand All @@ -2169,7 +2194,10 @@ fn group_refs(props: impl Iterator<Item = TypeSelection>) -> impl Iterator<Item
if let Some(refs) = fragment_spreads.take() {
return Some(TypeSelection::ScalarField(TypeSelectionScalarField {
field_name_or_alias: *KEY_FRAGMENT_SPREADS,
value: AST::FragmentReference(refs),
value: AST::FragmentReference(SortedStringKeyList::new(
refs,
should_sort_typegen_items,
)),
special_field: None,
conditional: false,
concrete_type: None,
Expand Down
Loading

0 comments on commit 9f0dea4

Please sign in to comment.