mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
[compiler] Script to produce markdown of lint rule docs (#34260)
The docs site is in a separate repo, but this gives us a semi-automated way to update the docs about our lint rules. The script generates markdown files from the rule definitions which we can then manually copy/paste into the docs site somewhere. In the future we can automate this fully.
This commit is contained in:
parent
6de32a5a07
commit
425ba0ad6d
|
|
@ -19,7 +19,8 @@
|
|||
"test": "yarn workspaces run test",
|
||||
"snap": "yarn workspace babel-plugin-react-compiler run snap",
|
||||
"snap:build": "yarn workspace snap run build",
|
||||
"npm:publish": "node scripts/release/publish"
|
||||
"npm:publish": "node scripts/release/publish",
|
||||
"eslint-docs": "yarn workspace babel-plugin-react-compiler build && node scripts/build-eslint-docs.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": "^4.0.2",
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@
|
|||
|
||||
import * as t from '@babel/types';
|
||||
import {codeFrameColumns} from '@babel/code-frame';
|
||||
import type {SourceLocation} from './HIR';
|
||||
import {type SourceLocation} from './HIR';
|
||||
import {Err, Ok, Result} from './Utils/Result';
|
||||
import {assertExhaustive} from './Utils/utils';
|
||||
import invariant from 'invariant';
|
||||
|
||||
export enum ErrorSeverity {
|
||||
/**
|
||||
|
|
@ -628,7 +629,18 @@ export type LintRule = {
|
|||
recommended: boolean;
|
||||
};
|
||||
|
||||
const RULE_NAME_PATTERN = /^[a-z]+(-[a-z]+)*$/;
|
||||
|
||||
export function getRuleForCategory(category: ErrorCategory): LintRule {
|
||||
const rule = getRuleForCategoryImpl(category);
|
||||
invariant(
|
||||
RULE_NAME_PATTERN.test(rule.name),
|
||||
`Invalid rule name, got '${rule.name}' but rules must match ${RULE_NAME_PATTERN.toString()}`,
|
||||
);
|
||||
return rule;
|
||||
}
|
||||
|
||||
function getRuleForCategoryImpl(category: ErrorCategory): LintRule {
|
||||
switch (category) {
|
||||
case ErrorCategory.AutomaticEffectDependencies: {
|
||||
return {
|
||||
|
|
@ -636,7 +648,7 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
name: 'automatic-effect-dependencies',
|
||||
description:
|
||||
'Verifies that automatic effect dependencies are compiled if opted-in',
|
||||
recommended: true,
|
||||
recommended: false,
|
||||
};
|
||||
}
|
||||
case ErrorCategory.CapitalizedCalls: {
|
||||
|
|
@ -652,7 +664,7 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
return {
|
||||
category,
|
||||
name: 'config',
|
||||
description: 'Validates the configuration',
|
||||
description: 'Validates the compiler configuration options',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -678,7 +690,7 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
category,
|
||||
name: 'set-state-in-effect',
|
||||
description:
|
||||
'Validates against calling setState synchronously in an effect',
|
||||
'Validates against calling setState synchronously in an effect, which can lead to re-renders that degrade performance',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -687,7 +699,7 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
category,
|
||||
name: 'error-boundaries',
|
||||
description:
|
||||
'Validates usage of error boundaries instead of try/catch for errors in JSX',
|
||||
'Validates usage of error boundaries instead of try/catch for errors in child components',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -711,7 +723,8 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
return {
|
||||
category,
|
||||
name: 'gating',
|
||||
description: 'Validates configuration of gating mode',
|
||||
description:
|
||||
'Validates configuration of [gating mode](https://react.dev/reference/react-compiler/gating)',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -720,7 +733,8 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
category,
|
||||
name: 'globals',
|
||||
description:
|
||||
'Validates against assignment/mutation of globals during render',
|
||||
'Validates against assignment/mutation of globals during render, part of ensuring that ' +
|
||||
'[side effects must render outside of render](https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -742,7 +756,7 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
category,
|
||||
name: 'immutability',
|
||||
description:
|
||||
'Validates that immutable values (props, state, etc) are not mutated',
|
||||
'Validates against mutating props, state, and other values that [are immutable](https://react.dev/reference/rules/components-and-hooks-must-be-pure#props-and-state-are-immutable)',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -759,7 +773,9 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
category,
|
||||
name: 'preserve-manual-memoization',
|
||||
description:
|
||||
'Validates that existing manual memoized is preserved by the compiler',
|
||||
'Validates that existing manual memoized is preserved by the compiler. ' +
|
||||
'React Compiler will only compile components and hooks if its inference ' +
|
||||
'[matches or exceeds the existing manual memoization](https://react.dev/learn/react-compiler/introduction#what-should-i-do-about-usememo-usecallback-and-reactmemo)',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -768,7 +784,7 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
category,
|
||||
name: 'purity',
|
||||
description:
|
||||
'Validates that the component/hook is pure, and does not call known-impure functions',
|
||||
'Validates that [components/hooks are pure](https://react.dev/reference/rules/components-and-hooks-must-be-pure) by checking that they do not call known-impure functions',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -777,7 +793,7 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
category,
|
||||
name: 'refs',
|
||||
description:
|
||||
'Validates correct usage of refs, not reading/writing during render',
|
||||
'Validates correct usage of refs, not reading/writing during render. See the "pitfalls" section in [`useRef()` usage](https://react.dev/reference/react/useRef#usage)',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -785,7 +801,8 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
return {
|
||||
category,
|
||||
name: 'set-state-in-render',
|
||||
description: 'Validates against setting state during render',
|
||||
description:
|
||||
'Validates against setting state during render, which can trigger additional renders and potential infinite render loops',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -794,7 +811,7 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
category,
|
||||
name: 'static-components',
|
||||
description:
|
||||
'Validates that components are static, not recreated every render',
|
||||
'Validates that components are static, not recreated every render. Components that are recreated dynamically can reset state and trigger excessive re-rendering',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -826,7 +843,8 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
return {
|
||||
category,
|
||||
name: 'unsupported-syntax',
|
||||
description: 'Validates against syntax that we do not plan to support',
|
||||
description:
|
||||
'Validates against syntax that we do not plan to support in React Compiler',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
@ -834,7 +852,8 @@ export function getRuleForCategory(category: ErrorCategory): LintRule {
|
|||
return {
|
||||
category,
|
||||
name: 'use-memo',
|
||||
description: 'Validates usage of the useMemo() hook',
|
||||
description:
|
||||
'Validates usage of the useMemo() hook against common mistakes. See [`useMemo()` docs](https://react.dev/reference/react/useMemo) for more information.',
|
||||
recommended: true,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
32
compiler/scripts/build-eslint-docs.js
Normal file
32
compiler/scripts/build-eslint-docs.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
const ReactCompiler = require('../packages/babel-plugin-react-compiler/dist');
|
||||
|
||||
const combinedRules = [
|
||||
{
|
||||
name: 'rules-of-hooks',
|
||||
recommended: true,
|
||||
description:
|
||||
'Validates that components and hooks follow the [Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks)',
|
||||
},
|
||||
{
|
||||
name: 'exhaustive-deps',
|
||||
recommended: true,
|
||||
description:
|
||||
'Validates that hooks which accept dependency arrays (`useMemo()`, `useCallback()`, `useEffect()`, etc) ' +
|
||||
'list all referenced variables in their dependency array. Referencing a value without including it in the ' +
|
||||
'dependency array can lead to stale UI or callbacks.',
|
||||
},
|
||||
...ReactCompiler.LintRules,
|
||||
];
|
||||
|
||||
const printed = combinedRules
|
||||
.filter(rule => rule.recommended)
|
||||
.map(rule => {
|
||||
return `
|
||||
## \`react-hooks/${rule.name}\`
|
||||
|
||||
${rule.description}
|
||||
`.trim();
|
||||
})
|
||||
.join('\n\n');
|
||||
|
||||
console.log(printed);
|
||||
Loading…
Reference in New Issue
Block a user