@samitouri / QOS-React / commits / e0acd77aab

[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',