[compiler] Todo for fbt with multiple pronoun/plural

ghstack-source-id: 77b6980c2b
Pull Request resolved: https://github.com/facebook/react/pull/30437
This commit is contained in:
Mofei Zhang
2024-07-26 17:36:03 -04:00
parent a15e8d7cdc
commit e0acd77aab
7 changed files with 129 additions and 136 deletions

View File

@@ -2130,24 +2130,41 @@ function lowerExpression(
suggestions: null,
});
}
const fbtEnumLocations: Array<SourceLocation> = [];
// see `error.todo-multiple-fbt-plural` fixture for explanation
const fbtLocations = {
enum: new Array<SourceLocation>(),
plural: new Array<SourceLocation>(),
pronoun: new Array<SourceLocation>(),
};
expr.traverse({
JSXClosingElement(path) {
path.skip();
},
JSXNamespacedName(path) {
if (
path.node.namespace.name === tagName &&
path.node.name.name === 'enum'
) {
fbtEnumLocations.push(path.node.loc ?? GeneratedSource);
if (path.node.namespace.name === tagName) {
switch (path.node.name.name) {
case 'enum':
fbtLocations.enum.push(path.node.loc ?? GeneratedSource);
break;
case 'plural':
fbtLocations.plural.push(path.node.loc ?? GeneratedSource);
break;
case 'pronoun':
fbtLocations.pronoun.push(path.node.loc ?? GeneratedSource);
break;
}
}
},
});
if (fbtEnumLocations.length > 1) {
CompilerError.throwTodo({
reason: `Support <${tagName}> tags with multiple <${tagName}:enum> values`,
loc: fbtEnumLocations.at(-1) ?? GeneratedSource,
description: null,
suggestions: null,
});
for (const [name, locations] of Object.entries(fbtLocations)) {
if (locations.length > 1) {
CompilerError.throwTodo({
reason: `Support <${tagName}> tags with multiple <${tagName}:${name}> values`,
loc: locations.at(-1) ?? GeneratedSource,
description: null,
suggestions: null,
});
}
}
}

View File

@@ -1,110 +0,0 @@
## Input
```javascript
import fbt from 'fbt';
/**
* Forget + fbt inconsistency. Evaluator errors with the following
* Found differences in evaluator results
* Non-forget (expected):
* (kind: ok) 1 rewrite to Rust · 2 months traveling
* Forget:
* (kind: ok) 1 rewrites to Rust · 2 months traveling
*
* The root issue here is that fbt:plural reads `.start` and `.end` from
* babel nodes to slice into source strings. (fbt:enum suffers from the same
* problem).
* See:
* - [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
* - [getArgCode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtArguments.js#L88-L97)
* - [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297)
*
* Specifically, the `count` node requires that a `.start/.end` be attached
* (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))
*
* In this fixture, `count` nodes are the `rewrites` and `months` identifiers.
*/
function Foo({rewrites, months}) {
return (
<fbt desc="Test fbt description">
<fbt:plural count={rewrites} name="number of rewrites" showCount="yes">
rewrite
</fbt:plural>
to Rust ·
<fbt:plural count={months} name="number of months" showCount="yes">
month
</fbt:plural>
traveling
</fbt>
);
}
export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [{rewrites: 1, months: 2}],
};
```
## Code
```javascript
import { c as _c } from "react/compiler-runtime";
import fbt from "fbt";
/**
* Forget + fbt inconsistency. Evaluator errors with the following
* Found differences in evaluator results
* Non-forget (expected):
* (kind: ok) 1 rewrite to Rust · 2 months traveling
* Forget:
* (kind: ok) 1 rewrites to Rust · 2 months traveling
*
* The root issue here is that fbt:plural reads `.start` and `.end` from
* babel nodes to slice into source strings. (fbt:enum suffers from the same
* problem).
* See:
* - [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
* - [getArgCode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtArguments.js#L88-L97)
* - [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297)
*
* Specifically, the `count` node requires that a `.start/.end` be attached
* (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))
*
* In this fixture, `count` nodes are the `rewrites` and `months` identifiers.
*/
function Foo(t0) {
const $ = _c(3);
const { rewrites, months } = t0;
let t1;
if ($[0] !== rewrites || $[1] !== months) {
t1 = fbt._(
{
"*": {
"*": "{number of rewrites} rewrites to Rust · {number of months} months traveling",
},
_1: { _1: "1 rewrite to Rust · 1 month traveling" },
},
[
fbt._plural(rewrites, "number of rewrites"),
fbt._plural(months, "number of months"),
],
{ hk: "49MfZA" },
);
$[0] = rewrites;
$[1] = months;
$[2] = t1;
} else {
t1 = $[2];
}
return t1;
}
export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [{ rewrites: 1, months: 2 }],
};
```

View File

@@ -0,0 +1,65 @@
## Input
```javascript
import fbt from 'fbt';
/**
* Forget + fbt inconsistency. Evaluator errors with the following
* Found differences in evaluator results
* Non-forget (expected):
* (kind: ok) 1 rewrite to Rust · 2 months traveling
* Forget:
* (kind: ok) 1 rewrites to Rust · 2 months traveling
*
* The root issue here is that fbt:plural/enum/pronoun read `.start` and `.end` from
* babel nodes to slice into source strings for some complex dedupe logic
* (see [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297))
*
*
* Since Forget does not add `.start` and `.end` for babel nodes it synthesizes,
* [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
* simply returns the whole source code string. As a result, all fbt nodes dedupe together
* and _getStringVariationCombinations ends up early exiting (before adding valid candidate values).
*
*
*
* For fbt:plural tags specifically, the `count` node require that a `.start/.end`
* (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))
*/
function Foo({rewrites, months}) {
return (
<fbt desc="Test fbt description">
<fbt:plural count={rewrites} name="number of rewrites" showCount="yes">
rewrite
</fbt:plural>
to Rust ·
<fbt:plural count={months} name="number of months" showCount="yes">
month
</fbt:plural>
traveling
</fbt>
);
}
export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [{rewrites: 1, months: 2}],
};
```
## Error
```
31 | </fbt:plural>
32 | to Rust ·
> 33 | <fbt:plural count={months} name="number of months" showCount="yes">
| ^^^^^^^^^^ Todo: Support <fbt> tags with multiple <fbt:plural> values (33:33)
34 | month
35 | </fbt:plural>
36 | traveling
```

View File

@@ -8,18 +8,20 @@ import fbt from 'fbt';
* Forget:
* (kind: ok) 1 rewrites to Rust · 2 months traveling
*
* The root issue here is that fbt:plural reads `.start` and `.end` from
* babel nodes to slice into source strings. (fbt:enum suffers from the same
* problem).
* See:
* - [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
* - [getArgCode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtArguments.js#L88-L97)
* - [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297)
* The root issue here is that fbt:plural/enum/pronoun read `.start` and `.end` from
* babel nodes to slice into source strings for some complex dedupe logic
* (see [_getStringVariationCombinations](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/JSFbtBuilder.js#L297))
*
* Specifically, the `count` node requires that a `.start/.end` be attached
*
* Since Forget does not add `.start` and `.end` for babel nodes it synthesizes,
* [getRawSource](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/FbtUtil.js#L666-L673)
* simply returns the whole source code string. As a result, all fbt nodes dedupe together
* and _getStringVariationCombinations ends up early exiting (before adding valid candidate values).
*
*
*
* For fbt:plural tags specifically, the `count` node require that a `.start/.end`
* (see [code in FbtPluralNode](https://github.com/facebook/fbt/blob/main/packages/babel-plugin-fbt/src/fbt-nodes/FbtPluralNode.js#L87-L90))
*
* In this fixture, `count` nodes are the `rewrites` and `months` identifiers.
*/
function Foo({rewrites, months}) {
return (

View File

@@ -17,6 +17,12 @@ function Foo(props) {
);
}
export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [{value: 1}],
sequentialRenders: [{value: 1}, {value: 0}],
};
```
## Code
@@ -49,5 +55,14 @@ function Foo(props) {
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [{ value: 1 }],
sequentialRenders: [{ value: 1 }, { value: 0 }],
};
```
### Eval output
(kind: ok) hello 1,
goodbye 0,

View File

@@ -12,3 +12,9 @@ function Foo(props) {
</fbt>
);
}
export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [{value: 1}],
sequentialRenders: [{value: 1}, {value: 0}],
};

View File

@@ -440,7 +440,6 @@ const skipFilter = new Set([
'fbt/fbtparam-with-jsx-element-content',
'fbt/fbtparam-text-must-use-expression-container',
'fbt/fbtparam-with-jsx-fragment-value',
'fbt/fbt-preserve-jsxtext',
'todo.useContext-mutate-context-in-callback',
'loop-unused-let',
'reanimated-no-memo-arg',
@@ -485,7 +484,6 @@ const skipFilter = new Set([
'rules-of-hooks/rules-of-hooks-69521d94fa03',
// bugs
'fbt/bug-multiple-fbt-plural',
'fbt/bug-fbt-preserve-whitespace-param',
'bug-invalid-hoisting-functionexpr',
'original-reactive-scopes-fork/bug-nonmutating-capture-in-unsplittable-memo-block',