|
|
|
|
@@ -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,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|