Skip to content

Commit 4267075

Browse files
evanyeungfacebook-github-bot
authored andcommitted
Implement schema generation for weak object fields
Summary: This diff implements the ability to add fields to weak objects in the same mannger as adding a field to a strong object. We realized that, while weak object literal types were parsed into the IR, the runtime is not currently generated. We also want the ability for custom function implementation of weak object fields. This diff also disables the previous implementation of parsing object literals until the runtime JS can also be generated. Reviewed By: tyao1 Differential Revision: D58501581 fbshipit-source-id: d8df5f0f270b5669fe6cacf129671ffd29804f06
1 parent dc2cb85 commit 4267075

File tree

9 files changed

+173
-340
lines changed

9 files changed

+173
-340
lines changed

compiler/crates/relay-schema-generation/src/lib.rs

Lines changed: 111 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,10 @@ pub struct RelayResolverExtractor {
124124
)]
125125
pub enum JSImportType {
126126
Default,
127-
Namespace,
128127
Named(StringKey),
128+
// Note that namespace imports cannot be used for resolver types. Anything namespace
129+
// imported should be a "Named" import instead
130+
Namespace,
129131
}
130132
impl fmt::Display for JSImportType {
131133
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -286,6 +288,7 @@ impl RelayResolverExtractor {
286288
source_hash,
287289
source_module_path,
288290
description,
291+
false,
289292
)?
290293
}
291294
}
@@ -301,61 +304,65 @@ impl RelayResolverExtractor {
301304
self.unresolved_field_definitions
302305
.into_iter()
303306
.map(|(key, field)| {
304-
if let Some(DocblockIr::Type(ResolverTypeDocblockIr::StrongObjectResolver(
305-
object,
306-
))) = self.type_definitions.get(&key)
307-
{
308-
let arguments = if let Some(args) = field.arguments {
309-
Some(flow_type_to_field_arguments(self.current_location, &args)?)
310-
} else {
311-
None
312-
};
313-
let description_node = field.description.map(|desc| StringNode {
314-
token: Token {
315-
span: desc.location.span(),
316-
kind: TokenKind::Empty,
317-
},
318-
value: desc.item,
319-
});
320-
let field_definition = FieldDefinition {
321-
name: string_key_to_identifier(field.field_name),
322-
type_: return_type_to_type_annotation(
323-
self.current_location,
324-
&field.return_type,
325-
)?,
326-
arguments,
327-
directives: vec![],
328-
description: description_node,
329-
hack_source: None,
330-
span: field.field_name.location.span(),
331-
};
332-
let live = field
333-
.is_live
334-
.map(|loc| UnpopulatedIrField { key_location: loc });
335-
self.resolved_field_definitions.push(TerseRelayResolverIr {
336-
field: field_definition,
337-
type_: object
307+
let entity = match self.type_definitions.get(&key) {
308+
Some(DocblockIr::Type(ResolverTypeDocblockIr::StrongObjectResolver(
309+
object,
310+
))) => Ok(object
311+
.type_name
312+
.name_with_location(SourceLocationKey::Generated)),
313+
Some(DocblockIr::Type(ResolverTypeDocblockIr::WeakObjectType(object))) => {
314+
Ok(object
338315
.type_name
339-
.name_with_location(SourceLocationKey::Generated),
340-
root_fragment: None,
341-
location: field.field_name.location,
342-
deprecated: None,
343-
live,
344-
fragment_arguments: None,
345-
source_hash: field.source_hash,
346-
semantic_non_null: None,
347-
});
348-
Ok(())
349-
} else {
350-
Err(vec![Diagnostic::error(
316+
.name_with_location(SourceLocationKey::Generated))
317+
}
318+
_ => Err(vec![Diagnostic::error(
351319
SchemaGenerationError::ModuleNotFound {
352320
entity_name: field.entity_name.item,
353321
export_type: key.import_type,
354322
module_name: key.module_name,
355323
},
356324
field.entity_name.location,
357-
)])
358-
}
325+
)]),
326+
}?;
327+
let arguments = if let Some(args) = field.arguments {
328+
Some(flow_type_to_field_arguments(self.current_location, &args)?)
329+
} else {
330+
None
331+
};
332+
let description_node = field.description.map(|desc| StringNode {
333+
token: Token {
334+
span: desc.location.span(),
335+
kind: TokenKind::Empty,
336+
},
337+
value: desc.item,
338+
});
339+
let field_definition = FieldDefinition {
340+
name: string_key_to_identifier(field.field_name),
341+
type_: return_type_to_type_annotation(
342+
self.current_location,
343+
&field.return_type,
344+
)?,
345+
arguments,
346+
directives: vec![],
347+
description: description_node,
348+
hack_source: None,
349+
span: field.field_name.location.span(),
350+
};
351+
let live = field
352+
.is_live
353+
.map(|loc| UnpopulatedIrField { key_location: loc });
354+
self.resolved_field_definitions.push(TerseRelayResolverIr {
355+
field: field_definition,
356+
type_: entity,
357+
root_fragment: None,
358+
location: field.field_name.location,
359+
deprecated: None,
360+
live,
361+
fragment_arguments: None,
362+
source_hash: field.source_hash,
363+
semantic_non_null: None,
364+
});
365+
Ok(())
359366
}),
360367
)?;
361368
Ok((
@@ -566,6 +573,7 @@ impl RelayResolverExtractor {
566573
source_hash: ResolverSourceHash,
567574
source_module_path: &str,
568575
description: Option<WithLocation<StringKey>>,
576+
should_generate_fields: bool,
569577
) -> DiagnosticsResult<()> {
570578
let weak_object = WeakObjectIr {
571579
type_name: string_key_to_identifier(name),
@@ -586,55 +594,62 @@ impl RelayResolverExtractor {
586594
module_name: haste_module_name.intern(),
587595
import_type: JSImportType::Named(name.item),
588596
};
589-
// Add fields
590-
if let FlowTypeAnnotation::ObjectTypeAnnotation(object_node) = type_alias {
591-
let field_map = self.get_object_fields(&object_node)?;
592-
if !field_map.is_empty() {
593-
try_all(field_map.into_iter().map(|(field_name, field_type)| {
594-
let field_definition = FieldDefinition {
595-
name: string_key_to_identifier(field_name),
596-
type_: return_type_to_type_annotation(self.current_location, field_type)?,
597-
arguments: None,
598-
directives: vec![],
599-
description: None,
600-
hack_source: None,
601-
span: field_name.location.span(),
602-
};
603597

604-
self.resolved_field_definitions.push(TerseRelayResolverIr {
605-
field: field_definition,
606-
type_: weak_object
607-
.type_name
608-
.name_with_location(SourceLocationKey::Generated),
609-
root_fragment: None,
610-
location: field_name.location,
611-
deprecated: None,
612-
live: None,
613-
fragment_arguments: None,
614-
source_hash,
615-
semantic_non_null: None,
616-
});
617-
Ok(())
618-
}))?;
598+
// TODO: this generates the IR but not the runtime JS
599+
if should_generate_fields {
600+
if let FlowTypeAnnotation::ObjectTypeAnnotation(object_node) = type_alias {
601+
let field_map = self.get_object_fields(&object_node)?;
602+
if !field_map.is_empty() {
603+
try_all(field_map.into_iter().map(|(field_name, field_type)| {
604+
let field_definition = FieldDefinition {
605+
name: string_key_to_identifier(field_name),
606+
type_: return_type_to_type_annotation(
607+
self.current_location,
608+
field_type,
609+
)?,
610+
arguments: None,
611+
directives: vec![],
612+
description: None,
613+
hack_source: None,
614+
span: field_name.location.span(),
615+
};
619616

620-
self.type_definitions.insert(
621-
key.clone(),
622-
DocblockIr::Type(ResolverTypeDocblockIr::WeakObjectType(weak_object)),
623-
);
624-
Ok(())
617+
self.resolved_field_definitions.push(TerseRelayResolverIr {
618+
field: field_definition,
619+
type_: weak_object
620+
.type_name
621+
.name_with_location(SourceLocationKey::Generated),
622+
root_fragment: None,
623+
location: field_name.location,
624+
deprecated: None,
625+
live: None,
626+
fragment_arguments: None,
627+
source_hash,
628+
semantic_non_null: None,
629+
});
630+
Ok(())
631+
}))?;
632+
} else {
633+
let location = self.to_location(object_node.as_ref());
634+
return Err(vec![Diagnostic::error(
635+
SchemaGenerationError::ExpectedWeakObjectToHaveFields,
636+
location,
637+
)]);
638+
}
625639
} else {
626-
let location = self.to_location(object_node.as_ref());
627-
Err(vec![Diagnostic::error(
628-
SchemaGenerationError::ExpectedWeakObjectToHaveFields,
629-
location,
630-
)])
640+
return Err(vec![Diagnostic::error(
641+
SchemaGenerationError::ExpectedTypeAliasToBeObject,
642+
self.to_location(&type_alias),
643+
)]);
631644
}
632-
} else {
633-
Err(vec![Diagnostic::error(
634-
SchemaGenerationError::ExpectedTypeAliasToBeObject,
635-
self.to_location(&type_alias),
636-
)])
637645
}
646+
647+
// Add weak object
648+
self.type_definitions.insert(
649+
key.clone(),
650+
DocblockIr::Type(ResolverTypeDocblockIr::WeakObjectType(weak_object)),
651+
);
652+
Ok(())
638653
}
639654

640655
pub fn extract_function(&self, node: &Function) -> DiagnosticsResult<ResolverFlowData> {
@@ -791,19 +806,13 @@ impl RelayResolverExtractor {
791806
}
792807
_ => Err(vec![Diagnostic::error(
793808
SchemaGenerationError::ExpectedFunctionOrTypeAlias,
794-
Location::new(
795-
self.current_location,
796-
Span::new(range.start, range.end.into()),
797-
),
809+
Location::new(self.current_location, Span::new(range.start, range.end)),
798810
)]),
799811
}
800812
} else {
801813
Err(vec![Diagnostic::error(
802814
SchemaGenerationError::ExpectedNamedExport,
803-
Location::new(
804-
self.current_location,
805-
Span::new(range.start, range.end.into()),
806-
),
815+
Location::new(self.current_location, Span::new(range.start, range.end)),
807816
)])
808817
}
809818
}
@@ -856,7 +865,7 @@ impl SchemaExtractor for RelayResolverExtractor {
856865

857866
fn to_location<T: Range>(source_location: SourceLocationKey, node: &T) -> Location {
858867
let range = node.range();
859-
Location::new(source_location, Span::new(range.start, range.end.into()))
868+
Location::new(source_location, Span::new(range.start, range.end))
860869
}
861870

862871
fn string_key_to_identifier(name: WithLocation<StringKey>) -> Identifier {

0 commit comments

Comments
 (0)