[compiler] Todo for fbt with multiple pronoun/plural
ghstack-source-id: 77b6980c2b080771d18aa275c3b3258884bd463c Pull Request resolved: https://github.com/facebook/react/pull/30437
Mofei Zhang committed
Jul 26, 2024 at 17:36 UTC
e0acd77aab503e63a5c7cdba605ee33a71f752e8
7 files changed
+129
-136
compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
+30
-13
@@ -2130,24 +2130,41 @@ function lowerExpression(
2130
suggestions: null,
2131
});
2132
}
2133
- const fbtEnumLocations: Array<SourceLocation> = [];
2133
+ // see `error.todo-multiple-fbt-plural` fixture for explanation
2134
+ const fbtLocations = {
2135
+ enum: new Array<SourceLocation>(),
2136
+ plural: new Array<SourceLocation>(),
2137
+ pronoun: new Array<SourceLocation>(),
2138
+ };
2139
expr.traverse({
2140
+ JSXClosingElement(path) {
2141
+ path.skip();
2142
+ },
2143
JSXNamespacedName(path) {
2136
- if (
2137
- path.node.namespace.name === tagName &&
2138
- path.node.name.name === 'enum'
2139
- ) {
2140
- fbtEnumLocations.push(path.node.loc ?? GeneratedSource);
2144
+ if (path.node.namespace.name === tagName) {
2145
+ switch (path.node.name.name) {
2146
+ case 'enum':
2147
+ fbtLocations.enum.push(path.node.loc ?? GeneratedSource);
2148
+ break;
2149
+ case 'plural':
2150
+ fbtLocations.plural.push(path.node.loc ?? GeneratedSource);
2151
+ break;
2152
+ case 'pronoun':
2153
+ fbtLocations.pronoun.push(path.node.loc ?? GeneratedSource);
2154
+ break;
2155
+ }
2156
}
2157
},
2158
});
2144
- if (fbtEnumLocations.length > 1) {
2145
- CompilerError.throwTodo({
2146
- reason: `Support <${tagName}> tags with multiple <${tagName}:enum> values`,
2147
- loc: fbtEnumLocations.at(-1) ?? GeneratedSource,
2148
- description: null,
2149
- suggestions: null,
2150
- });
2159
+ for (const [name, locations] of Object.entries(fbtLocations)) {
2160
+ if (locations.length > 1) {
2161
+ CompilerError.throwTodo({
2162
+ reason: `Support <${tagName}> tags with multiple <${tagName}:${name}> values`,
2163
+ loc: locations.at(-1) ?? GeneratedSource,
2164
+ description: null,
2165
+ suggestions: null,
2166
+ });
2167
+ }
2168
}
2169
}
2170
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/bug-multiple-fbt-plural.expect.md
deleted
-110
@@ -1,110 +0,0 @@
1
-
2
-## Input
3
-
4
-```javascript
5
-import fbt from 'fbt';
6
-
7
-/**
8
- * Forget + fbt inconsistency. Evaluator errors with the following
9
- * Found differences in evaluator results
10
- * Non-forget (expected):
11
- * (kind: ok) 1 rewrite to Rust · 2 months traveling
12
- * Forget:
13
- * (kind: ok) 1 rewrites to Rust · 2 months traveling
14
- *
15
- * The root issue here is that fbt:plural reads `.start` and `.end` from
16
- * babel nodes to slice into source strings. (fbt:enum suffers from the same
17
- * problem).
18
- * See:
19
- * - [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
20
- * - [getArgCode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtArguments.js#L88-L97)
21
- * - [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297)
22
- *
23
- * Specifically, the `count` node requires that a `.start/.end` be attached
24
- * (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))
25
- *
26
- * In this fixture, `count` nodes are the `rewrites` and `months` identifiers.
27
- */
28
-function Foo({rewrites, months}) {
29
- return (
30
- <fbt desc="Test fbt description">
31
- <fbt:plural count={rewrites} name="number of rewrites" showCount="yes">
32
- rewrite
33
- </fbt:plural>
34
- to Rust ·
35
- <fbt:plural count={months} name="number of months" showCount="yes">
36
- month
37
- </fbt:plural>
38
- traveling
39
- </fbt>
40
- );
41
-}
42
-
43
-export const FIXTURE_ENTRYPOINT = {
44
- fn: Foo,
45
- params: [{rewrites: 1, months: 2}],
46
-};
47
-
48
-```
49
-
50
-## Code
51
-
52
-```javascript
53
-import { c as _c } from "react/compiler-runtime";
54
-import fbt from "fbt";
55
-
56
-/**
57
- * Forget + fbt inconsistency. Evaluator errors with the following
58
- * Found differences in evaluator results
59
- * Non-forget (expected):
60
- * (kind: ok) 1 rewrite to Rust · 2 months traveling
61
- * Forget:
62
- * (kind: ok) 1 rewrites to Rust · 2 months traveling
63
- *
64
- * The root issue here is that fbt:plural reads `.start` and `.end` from
65
- * babel nodes to slice into source strings. (fbt:enum suffers from the same
66
- * problem).
67
- * See:
68
- * - [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
69
- * - [getArgCode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtArguments.js#L88-L97)
70
- * - [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297)
71
- *
72
- * Specifically, the `count` node requires that a `.start/.end` be attached
73
- * (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))
74
- *
75
- * In this fixture, `count` nodes are the `rewrites` and `months` identifiers.
76
- */
77
-function Foo(t0) {
78
- const $ = _c(3);
79
- const { rewrites, months } = t0;
80
- let t1;
81
- if ($[0] !== rewrites || $[1] !== months) {
82
- t1 = fbt._(
83
- {
84
- "*": {
85
- "*": "{number of rewrites} rewrites to Rust · {number of months} months traveling",
86
- },
87
- _1: { _1: "1 rewrite to Rust · 1 month traveling" },
88
- },
89
- [
90
- fbt._plural(rewrites, "number of rewrites"),
91
- fbt._plural(months, "number of months"),
92
- ],
93
- { hk: "49MfZA" },
94
- );
95
- $[0] = rewrites;
96
- $[1] = months;
97
- $[2] = t1;
98
- } else {
99
- t1 = $[2];
100
- }
101
- return t1;
102
-}
103
-
104
-export const FIXTURE_ENTRYPOINT = {
105
- fn: Foo,
106
- params: [{ rewrites: 1, months: 2 }],
107
-};
108
-
109
-```
110
-
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-multiple-fbt-plural.expect.md
new
+65
@@ -0,0 +1,65 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+import fbt from 'fbt';
6
+
7
+/**
8
+ * Forget + fbt inconsistency. Evaluator errors with the following
9
+ * Found differences in evaluator results
10
+ * Non-forget (expected):
11
+ * (kind: ok) 1 rewrite to Rust · 2 months traveling
12
+ * Forget:
13
+ * (kind: ok) 1 rewrites to Rust · 2 months traveling
14
+ *
15
+ * The root issue here is that fbt:plural/enum/pronoun read `.start` and `.end` from
16
+ * babel nodes to slice into source strings for some complex dedupe logic
17
+ * (see [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297))
18
+ *
19
+ *
20
+ * Since Forget does not add `.start` and `.end` for babel nodes it synthesizes,
21
+ * [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
22
+ * simply returns the whole source code string. As a result, all fbt nodes dedupe together
23
+ * and _getStringVariationCombinations ends up early exiting (before adding valid candidate values).
24
+ *
25
+ *
26
+ *
27
+ * For fbt:plural tags specifically, the `count` node require that a `.start/.end`
28
+ * (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))
29
+ */
30
+function Foo({rewrites, months}) {
31
+ return (
32
+ <fbt desc="Test fbt description">
33
+ <fbt:plural count={rewrites} name="number of rewrites" showCount="yes">
34
+ rewrite
35
+ </fbt:plural>
36
+ to Rust ·
37
+ <fbt:plural count={months} name="number of months" showCount="yes">
38
+ month
39
+ </fbt:plural>
40
+ traveling
41
+ </fbt>
42
+ );
43
+}
44
+
45
+export const FIXTURE_ENTRYPOINT = {
46
+ fn: Foo,
47
+ params: [{rewrites: 1, months: 2}],
48
+};
49
+
50
+```
51
+
52
+
53
+## Error
54
+
55
+```
56
+ 31 | </fbt:plural>
57
+ 32 | to Rust ·
58
+> 33 | <fbt:plural count={months} name="number of months" showCount="yes">
59
+ | ^^^^^^^^^^ Todo: Support <fbt> tags with multiple <fbt:plural> values (33:33)
60
+ 34 | month
61
+ 35 | </fbt:plural>
62
+ 36 | traveling
63
+```
64
+
65
+
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-multiple-fbt-plural.tsx
renamed
+12
-10
@@ -8,18 +8,20 @@ import fbt from 'fbt';
8
* Forget:
9
* (kind: ok) 1 rewrites to Rust · 2 months traveling
10
*
11
- * The root issue here is that fbt:plural reads `.start` and `.end` from
12
- * babel nodes to slice into source strings. (fbt:enum suffers from the same
13
- * problem).
14
- * See:
15
- * - [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
16
- * - [getArgCode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtArguments.js#L88-L97)
17
- * - [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297)
11
+ * The root issue here is that fbt:plural/enum/pronoun read `.start` and `.end` from
12
+ * babel nodes to slice into source strings for some complex dedupe logic
13
+ * (see [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297))
14
+ *
15
+ *
16
+ * Since Forget does not add `.start` and `.end` for babel nodes it synthesizes,
17
+ * [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
18
+ * simply returns the whole source code string. As a result, all fbt nodes dedupe together
19
+ * and _getStringVariationCombinations ends up early exiting (before adding valid candidate values).
20
*
19
- * Specifically, the `count` node requires that a `.start/.end` be attached
20
- * (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))
21
*
22
- * In this fixture, `count` nodes are the `rewrites` and `months` identifiers.
22
+ *
23
+ * For fbt:plural tags specifically, the `count` node require that a `.start/.end`
24
+ * (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))
25
*/
26
function Foo({rewrites, months}) {
27
return (
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-jsxtext.expect.md
+16
-1
@@ -17,6 +17,12 @@ function Foo(props) {
17
);
18
}
19
20
+export const FIXTURE_ENTRYPOINT = {
21
+ fn: Foo,
22
+ params: [{value: 1}],
23
+ sequentialRenders: [{value: 1}, {value: 0}],
24
+};
25
+
26
```
27
28
## Code
@@ -49,5 +55,14 @@ function Foo(props) {
55
return t0;
56
}
57
58
+export const FIXTURE_ENTRYPOINT = {
59
+ fn: Foo,
60
+ params: [{ value: 1 }],
61
+ sequentialRenders: [{ value: 1 }, { value: 0 }],
62
+};
63
+
64
```
53
-
\ No newline at end of file
65
+
66
+### Eval output
67
+(kind: ok) hello 1,
68
+goodbye 0,
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-preserve-jsxtext.js
+6
@@ -12,3 +12,9 @@ function Foo(props) {
12
</fbt>
13
);
14
}
15
+
16
+export const FIXTURE_ENTRYPOINT = {
17
+ fn: Foo,
18
+ params: [{value: 1}],
19
+ sequentialRenders: [{value: 1}, {value: 0}],
20
+};
compiler/packages/snap/src/SproutTodoFilter.ts
-2
@@ -440,7 +440,6 @@ const skipFilter = new Set([
440
'fbt/fbtparam-with-jsx-element-content',
441
'fbt/fbtparam-text-must-use-expression-container',
442
'fbt/fbtparam-with-jsx-fragment-value',
443
- 'fbt/fbt-preserve-jsxtext',
443
'todo.useContext-mutate-context-in-callback',
444
'loop-unused-let',
445
'reanimated-no-memo-arg',
@@ -485,7 +484,6 @@ const skipFilter = new Set([
484
'rules-of-hooks/rules-of-hooks-69521d94fa03',
485
486
// bugs
488
- 'fbt/bug-multiple-fbt-plural',
487
'fbt/bug-fbt-preserve-whitespace-param',
488
'bug-invalid-hoisting-functionexpr',
489
'original-reactive-scopes-fork/bug-nonmutating-capture-in-unsplittable-memo-block',