Skip to content

Commit 53dc321

Browse files
grievejiafacebook-github-bot
authored andcommitted
Allow all kind of expressions to appear as decorators
Reviewed By: kbansal Differential Revision: D31865845 fbshipit-source-id: 57e8ccb13982ef2e8a3103367c830071a769bd20
1 parent 604f726 commit 53dc321

25 files changed

+621
-502
lines changed

source/analysis/attributeResolution.ml

+275-253
Large diffs are not rendered by default.

source/analysis/classSummary.ml

+1-2
Original file line numberDiff line numberDiff line change
@@ -1037,7 +1037,7 @@ module ClassSummary = struct
10371037
name: Reference.t;
10381038
qualifier: Reference.t;
10391039
bases: bases;
1040-
decorators: Decorator.t list;
1040+
decorators: Expression.t list;
10411041
class_attributes: ClassAttributes.t;
10421042
}
10431043
[@@deriving compare, eq, sexp, show, hash]
@@ -1101,7 +1101,6 @@ module ClassSummary = struct
11011101

11021102

11031103
let has_decorator { decorators; _ } decorator =
1104-
let decorators = List.map decorators ~f:Decorator.to_expression in
11051104
Expression.exists_in_list ~expression_list:decorators decorator
11061105

11071106

source/analysis/classSummary.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ type t = {
111111
name: Reference.t;
112112
qualifier: Reference.t;
113113
bases: bases;
114-
decorators: Decorator.t list;
114+
decorators: Expression.t list;
115115
class_attributes: ClassAttributes.t;
116116
}
117117
[@@deriving compare, eq, sexp, show, hash]

source/analysis/lookup.ml

+1-2
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,7 @@ module Visit = struct
212212
~location:(Define.name_location ~body_location:statement.location define)
213213
name);
214214
List.iter parameters ~f:visit_parameter;
215-
List.map decorators ~f:Ast.Statement.Decorator.to_expression
216-
|> List.iter ~f:postcondition_visit;
215+
List.iter decorators ~f:postcondition_visit;
217216
Option.iter ~f:postcondition_visit return_annotation
218217
| Import { Import.from; imports } ->
219218
let visit_import { Node.value = { Import.name; _ }; location = import_location } =

source/analysis/preprocessing.ml

+26-27
Original file line numberDiff line numberDiff line change
@@ -744,7 +744,7 @@ let qualify
744744
List.map
745745
decorators
746746
~f:
747-
(qualify_decorator
747+
(qualify_expression
748748
~qualify_strings:DoNotQualify
749749
~scope:{ scope with use_forward_references = true })
750750
in
@@ -778,7 +778,7 @@ let qualify
778778
}
779779
in
780780
let decorators =
781-
List.map decorators ~f:(qualify_decorator ~qualify_strings:DoNotQualify ~scope)
781+
List.map decorators ~f:(qualify_expression ~qualify_strings:DoNotQualify ~scope)
782782
in
783783
let body =
784784
let qualifier = qualify_if_needed ~qualifier name in
@@ -797,21 +797,25 @@ let qualify
797797
let return_annotation =
798798
return_annotation >>| qualify_expression ~scope ~qualify_strings:Qualify
799799
in
800-
let qualify_decorator
801-
({ Decorator.name = { Node.value = name; _ }; _ } as decorator)
802-
=
803-
match name |> Reference.as_list |> List.rev with
804-
| ["staticmethod"]
805-
| ["classmethod"]
806-
| ["property"]
807-
| "getter" :: _
808-
| "setter" :: _
809-
| "deleter" :: _ ->
800+
let qualify_decorator decorator =
801+
let is_reserved name =
802+
match Reference.as_list name |> List.rev with
803+
| ["staticmethod"]
804+
| ["classmethod"]
805+
| ["property"]
806+
| "getter" :: _
807+
| "setter" :: _
808+
| "deleter" :: _ ->
809+
true
810+
| _ -> false
811+
in
812+
match Decorator.from_expression decorator with
813+
| Some { Decorator.name = { Node.value = name; _ }; _ } when is_reserved name ->
810814
decorator
811815
| _ ->
812816
(* TODO (T41755857): Decorator qualification logic should be slightly more
813817
involved than this. *)
814-
qualify_decorator ~qualify_strings:DoNotQualify ~scope decorator
818+
qualify_expression ~qualify_strings:DoNotQualify ~scope decorator
815819
in
816820
let decorators = List.map decorators ~f:qualify_decorator in
817821
let signature =
@@ -1252,11 +1256,6 @@ let qualify
12521256
| Constant _ -> value
12531257
in
12541258
{ expression with Node.value }
1255-
and qualify_decorator ~qualify_strings ~scope { Decorator.name; arguments } =
1256-
{
1257-
Decorator.name = Node.map name ~f:(qualify_reference ~scope);
1258-
arguments = arguments >>| List.map ~f:(qualify_argument ~qualify_strings ~scope);
1259-
}
12601259
and qualify_argument { Call.Argument.name; value } ~qualify_strings ~scope =
12611260
let name =
12621261
let rename identifier =
@@ -3093,15 +3092,11 @@ module AccessCollector = struct
30933092
List.fold base_arguments ~init:collected ~f:(fun sofar { Call.Argument.value; _ } ->
30943093
from_expression sofar value)
30953094
in
3096-
List.map decorators ~f:Decorator.to_expression
3097-
|> List.fold ~init:collected ~f:from_expression
3095+
List.fold ~init:collected ~f:from_expression decorators
30983096
| Define
30993097
{ Define.signature = { Define.Signature.decorators; parameters; return_annotation; _ }; _ }
31003098
->
3101-
let collected =
3102-
List.map decorators ~f:Decorator.to_expression
3103-
|> List.fold ~init:collected ~f:from_expression
3104-
in
3099+
let collected = List.fold ~init:collected ~f:from_expression decorators in
31053100
let collected =
31063101
List.fold
31073102
parameters
@@ -3828,11 +3823,15 @@ let inline_six_metaclass ({ Source.statements; _ } as source) =
38283823
let transform_class
38293824
~class_statement:({ Class.base_arguments; decorators; _ } as class_statement)
38303825
=
3831-
let is_six_add_metaclass_decorator { Decorator.name; _ } =
3832-
Identifier.equal (Node.value name |> Reference.show) "six.add_metaclass"
3826+
let is_six_add_metaclass_decorator expression =
3827+
match Decorator.from_expression expression with
3828+
| Some ({ Decorator.name = { Node.value = name; _ }; _ } as decorator)
3829+
when Reference.equal name (Reference.create_from_list ["six"; "add_metaclass"]) ->
3830+
Either.First decorator
3831+
| _ -> Either.Second expression
38333832
in
38343833
let six_add_metaclass_decorators, rest =
3835-
List.partition_tf decorators ~f:is_six_add_metaclass_decorator
3834+
List.partition_map decorators ~f:is_six_add_metaclass_decorator
38363835
in
38373836
match six_add_metaclass_decorators with
38383837
| [

source/analysis/scope.ml

+2-6
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,7 @@ module Binding = struct
152152
let sofar = of_expression sofar value in
153153
of_unannotated_target ~kind:(Kind.AssignTarget None) sofar target
154154
| Statement.Class { Class.name; base_arguments; decorators; _ } ->
155-
let sofar =
156-
List.map decorators ~f:Decorator.to_expression |> List.fold ~init:sofar ~f:of_expression
157-
in
155+
let sofar = List.fold ~init:sofar ~f:of_expression decorators in
158156
let sofar =
159157
List.fold
160158
base_arguments
@@ -163,9 +161,7 @@ module Binding = struct
163161
in
164162
{ kind = Kind.ClassName; name = Reference.show name; location } :: sofar
165163
| Statement.Define { Define.signature = { name; decorators; parameters; _ } as signature; _ } ->
166-
let sofar =
167-
List.map decorators ~f:Decorator.to_expression |> List.fold ~init:sofar ~f:of_expression
168-
in
164+
let sofar = List.fold ~init:sofar ~f:of_expression decorators in
169165
let sofar =
170166
List.fold
171167
parameters

source/analysis/test/resolvedCallableTest.ml

+3-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ open Test
1515

1616
let test_apply_decorators context =
1717
let resolution = ScratchProject.setup ~context [] |> ScratchProject.build_global_resolution in
18-
let decorator ?arguments name = { Decorator.name = + !&name; arguments } in
1918
let create_define ~decorators ~parameters ~return_annotation =
2019
{
2120
Define.Signature.name = !&"define";
@@ -62,15 +61,15 @@ let test_apply_decorators context =
6261
Type.string;
6362
assert_apply_contextlib_decorators
6463
(create_define
65-
~decorators:[decorator "contextlib.contextmanager"]
64+
~decorators:[!"contextlib.contextmanager"]
6665
~parameters:[]
6766
~return_annotation:
6867
(Some
6968
(+Expression.Constant (Constant.String (StringLiteral.create "typing.Iterator[str]")))))
7069
(Type.parametric "contextlib._GeneratorContextManager" [Single Type.string]);
7170
assert_apply_contextlib_decorators
7271
(create_define
73-
~decorators:[decorator "contextlib.contextmanager"]
72+
~decorators:[!"contextlib.contextmanager"]
7473
~parameters:[]
7574
~return_annotation:
7675
(Some
@@ -81,7 +80,7 @@ let test_apply_decorators context =
8180
let create_parameter ~name = Parameter.create ~location:Location.any ~name () in
8281
(* Custom decorators. *)
8382
create_define
84-
~decorators:[decorator "$strip_first_parameter"]
83+
~decorators:[!"$strip_first_parameter"]
8584
~parameters:[create_parameter ~name:"self"; create_parameter ~name:"other"]
8685
~return_annotation:None
8786
|> (fun define ->

source/analysis/test/unannotatedGlobalEnvironmentTest.ml

+52-7
Original file line numberDiff line numberDiff line change
@@ -1400,7 +1400,22 @@ let test_updates context =
14001400
};
14011401
];
14021402
decorators =
1403-
[{ name = node ~start:(3, 1) ~stop:(3, 9) !&"typing.overload"; arguments = None }];
1403+
[
1404+
node
1405+
~start:(3, 1)
1406+
~stop:(3, 9)
1407+
(Expression.Name
1408+
(Name.Attribute
1409+
{
1410+
Name.Attribute.base =
1411+
node
1412+
~start:(3, 1)
1413+
~stop:(3, 9)
1414+
(Expression.Name (Name.Identifier "typing"));
1415+
attribute = "overload";
1416+
special = false;
1417+
}));
1418+
];
14041419
return_annotation =
14051420
Some (node ~start:(4, 19) ~stop:(4, 22) (Expression.Name (Name.Identifier "int")));
14061421
async = false;
@@ -1445,7 +1460,22 @@ let test_updates context =
14451460
};
14461461
];
14471462
decorators =
1448-
[{ name = node ~start:(7, 1) ~stop:(7, 9) !&"typing.overload"; arguments = None }];
1463+
[
1464+
node
1465+
~start:(7, 1)
1466+
~stop:(7, 9)
1467+
(Expression.Name
1468+
(Name.Attribute
1469+
{
1470+
Name.Attribute.base =
1471+
node
1472+
~start:(7, 1)
1473+
~stop:(7, 9)
1474+
(Expression.Name (Name.Identifier "typing"));
1475+
attribute = "overload";
1476+
special = false;
1477+
}));
1478+
];
14491479
return_annotation =
14501480
Some (node ~start:(8, 19) ~stop:(8, 22) (Expression.Name (Name.Identifier "str")));
14511481
async = false;
@@ -1552,7 +1582,12 @@ let test_updates context =
15521582
{ Parameter.name = "$parameter$self"; value = None; annotation = None };
15531583
];
15541584
decorators =
1555-
[{ name = node ~start:(3, 3) ~stop:(3, 11) !&"property"; arguments = None }];
1585+
[
1586+
node
1587+
~start:(3, 3)
1588+
~stop:(3, 11)
1589+
(Expression.Name (Name.Identifier "property"));
1590+
];
15561591
return_annotation =
15571592
Some
15581593
(node
@@ -1605,10 +1640,20 @@ let test_updates context =
16051640
];
16061641
decorators =
16071642
[
1608-
{
1609-
name = node ~start:(5, 3) ~stop:(5, 13) !&"foo.setter";
1610-
arguments = None;
1611-
};
1643+
node
1644+
~start:(5, 3)
1645+
~stop:(5, 13)
1646+
(Expression.Name
1647+
(Name.Attribute
1648+
{
1649+
Name.Attribute.base =
1650+
node
1651+
~start:(5, 3)
1652+
~stop:(5, 6)
1653+
(Expression.Name (Name.Identifier "foo"));
1654+
attribute = "setter";
1655+
special = false;
1656+
}));
16121657
];
16131658
return_annotation =
16141659
Some

0 commit comments

Comments
 (0)