Skip to content

Commit 77fc5f0

Browse files
rchen152facebook-github-bot
authored andcommitted
Move DataclassMetadata calculation into its own function
Reviewed By: stroxler Differential Revision: D80371725 fbshipit-source-id: b1ced75f3eb55d44baeba488626fc14695797fe3
1 parent 468c68e commit 77fc5f0

File tree

1 file changed

+68
-46
lines changed

1 file changed

+68
-46
lines changed

pyrefly/lib/alt/class/class_metadata.rs

Lines changed: 68 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,6 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
156156
// this does not turn the class into a dataclass! Instead, it becomes a special base class
157157
// (or metaclass) that turns child classes into dataclasses.
158158
let mut dataclass_transform_metadata = dataclass_defaults_from_base_class.clone();
159-
// If we inherit from a dataclass, inherit its metadata. Note that if this class is
160-
// itself decorated with @dataclass, we'll compute new metadata and overwrite this.
161-
let mut dataclass_metadata = bases_with_metadata.iter().find_map(|(_, metadata)| {
162-
let mut m = metadata.dataclass_metadata().cloned()?;
163-
// Avoid accidentally overwriting a non-synthesized `__init__`.
164-
m.kws.init = false;
165-
Some(m)
166-
});
167159
// This is set when we should apply dataclass-like transformations to the class. The class
168160
// should be transformed if:
169161
// - it inherits from a base class decorated with `dataclass_transform(...)`, or
@@ -246,44 +238,15 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
246238
}
247239
let mut is_final = false;
248240
let mut total_ordering_metadata = None;
249-
for (decorator, decorator_range) in decorators {
241+
for (decorator, decorator_range) in decorators.iter() {
250242
let decorator_ty = decorator.ty();
251243
match decorator_ty.callee_kind() {
252244
Some(CalleeKind::Function(FunctionKind::Final)) => {
253245
is_final = true;
254246
}
255247
Some(CalleeKind::Function(FunctionKind::TotalOrdering)) => {
256248
total_ordering_metadata = Some(TotalOrderingMetadata {
257-
location: decorator_range,
258-
});
259-
}
260-
// `@dataclass`
261-
Some(CalleeKind::Function(FunctionKind::Dataclass)) => {
262-
let dataclass_fields = self.get_dataclass_fields(cls, &bases_with_metadata);
263-
dataclass_metadata = Some(DataclassMetadata {
264-
fields: dataclass_fields,
265-
kws: DataclassKeywords::new(),
266-
field_specifiers: vec![
267-
CalleeKind::Function(FunctionKind::DataclassField),
268-
CalleeKind::Class(ClassKind::DataclassField),
269-
],
270-
});
271-
}
272-
// `@dataclass(...)`
273-
_ if let Type::KwCall(call) = decorator_ty
274-
&& call.has_function_kind(FunctionKind::Dataclass) =>
275-
{
276-
let dataclass_fields = self.get_dataclass_fields(cls, &bases_with_metadata);
277-
dataclass_metadata = Some(DataclassMetadata {
278-
fields: dataclass_fields,
279-
kws: DataclassKeywords::from_type_map(
280-
&call.keywords,
281-
&DataclassTransformKeywords::new(),
282-
),
283-
field_specifiers: vec![
284-
CalleeKind::Function(FunctionKind::DataclassField),
285-
CalleeKind::Class(ClassKind::DataclassField),
286-
],
249+
location: *decorator_range,
287250
});
288251
}
289252
// `@dataclass_transform(...)`
@@ -313,13 +276,12 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
313276
_ => {}
314277
}
315278
}
316-
if let Some((kws, field_specifiers)) = dataclass_from_dataclass_transform {
317-
dataclass_metadata = Some(DataclassMetadata {
318-
fields: self.get_dataclass_fields(cls, &bases_with_metadata),
319-
kws,
320-
field_specifiers,
321-
});
322-
}
279+
let dataclass_metadata = self.dataclass_metadata(
280+
cls,
281+
&decorators,
282+
&bases_with_metadata,
283+
dataclass_from_dataclass_transform,
284+
);
323285
if let Some(dm) = dataclass_metadata.as_ref() {
324286
self.validate_frozen_dataclass_inheritance(cls, dm, &bases_with_metadata, errors);
325287
}
@@ -542,6 +504,66 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
542504
}
543505
}
544506

507+
fn dataclass_metadata(
508+
&self,
509+
cls: &Class,
510+
decorators: &[(Arc<TypeInfo>, TextRange)],
511+
bases_with_metadata: &[(Class, Arc<ClassMetadata>)],
512+
dataclass_from_dataclass_transform: Option<(DataclassKeywords, Vec<CalleeKind>)>,
513+
) -> Option<DataclassMetadata> {
514+
// If we inherit from a dataclass, inherit its metadata. Note that if this class is
515+
// itself decorated with @dataclass, we'll compute new metadata and overwrite this.
516+
let mut dataclass_metadata = bases_with_metadata.iter().find_map(|(_, metadata)| {
517+
let mut m = metadata.dataclass_metadata().cloned()?;
518+
// Avoid accidentally overwriting a non-synthesized `__init__`.
519+
m.kws.init = false;
520+
Some(m)
521+
});
522+
for (decorator, _) in decorators {
523+
let decorator_ty = decorator.ty();
524+
match decorator_ty.callee_kind() {
525+
// `@dataclass`
526+
Some(CalleeKind::Function(FunctionKind::Dataclass)) => {
527+
let dataclass_fields = self.get_dataclass_fields(cls, bases_with_metadata);
528+
dataclass_metadata = Some(DataclassMetadata {
529+
fields: dataclass_fields,
530+
kws: DataclassKeywords::new(),
531+
field_specifiers: vec![
532+
CalleeKind::Function(FunctionKind::DataclassField),
533+
CalleeKind::Class(ClassKind::DataclassField),
534+
],
535+
});
536+
}
537+
// `@dataclass(...)`
538+
_ if let Type::KwCall(call) = decorator_ty
539+
&& call.has_function_kind(FunctionKind::Dataclass) =>
540+
{
541+
let dataclass_fields = self.get_dataclass_fields(cls, bases_with_metadata);
542+
dataclass_metadata = Some(DataclassMetadata {
543+
fields: dataclass_fields,
544+
kws: DataclassKeywords::from_type_map(
545+
&call.keywords,
546+
&DataclassTransformKeywords::new(),
547+
),
548+
field_specifiers: vec![
549+
CalleeKind::Function(FunctionKind::DataclassField),
550+
CalleeKind::Class(ClassKind::DataclassField),
551+
],
552+
});
553+
}
554+
_ => {}
555+
}
556+
}
557+
if let Some((kws, field_specifiers)) = dataclass_from_dataclass_transform {
558+
dataclass_metadata = Some(DataclassMetadata {
559+
fields: self.get_dataclass_fields(cls, bases_with_metadata),
560+
kws,
561+
field_specifiers,
562+
});
563+
}
564+
dataclass_metadata
565+
}
566+
545567
// To avoid circular computation on targs, we have a special version of `expr_infer` that only recognize a small
546568
// subset of syntactical forms, and does not look into any subscript of any expr
547569
fn base_class_expr_infer(&self, expr: &Expr, errors: &ErrorCollector) -> Option<Type> {

0 commit comments

Comments
 (0)