Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-ft-flow": "^2.0.1",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest": "^29.0.1",
"eslint-plugin-jest": "^29.17.0",
"eslint-plugin-jsx-a11y": "^6.6.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-native": "^5.0.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/eslint-config-react-native/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ yarn add --dev eslint prettier @react-native/eslint-config

## Usage

### For ESLint 9+ (Flat Config)
### For ESLint 9 and 10 (Flat Config)

Add to your `eslint.config.js`:

Expand All @@ -39,6 +39,8 @@ export default [
];
```

The flat config parses `.js` and `.jsx` files with [`flow-eslint`](https://www.npmjs.com/package/flow-eslint), which supports Flow and JSX syntax.

### For ESLint 8 (Legacy Config)

Add to your eslint config (`.eslintrc`, or `eslintConfig` field in `package.json`):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/

import eslintConfigReactNative from '..';
import eslintConfigReactNativeFlat from '../flat';
import eslintConfigPrettier from 'eslint-config-prettier';

test('eslint-config-prettier is not globally overridden', () => {
Expand Down Expand Up @@ -49,3 +50,22 @@ for (const override of overrides) {
// Technically, `overrides` can contain more `overrides`. Since we don't
// currently use that and it is less common, we don't worry about it.
}

for (const config of eslintConfigReactNativeFlat) {
if (config === eslintConfigPrettier || config.rules == null) {
continue;
}
const configIdentifier = JSON.stringify(config.files ?? '<all files>');

test(`eslint-config-prettier is not overridden in flat config for ${configIdentifier}`, () => {
const overriddenRules = [];

for (const ruleName of Object.keys(eslintConfigPrettier.rules)) {
if (Object.hasOwn(config.rules, ruleName)) {
overriddenRules.push(ruleName);
}
}

expect(overriddenRules).toEqual([]);
});
}
22 changes: 13 additions & 9 deletions packages/eslint-config-react-native/flat.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@
*/

const sharedConfig = require('./shared.js');
const babelParser = require('@babel/eslint-parser');
const eslintCommentsPlugin = require('@eslint-community/eslint-plugin-eslint-comments');
const {fixupPluginRules} = require('@eslint/compat');
const reactNativePlugin = require('@react-native/eslint-plugin');
const typescriptPlugin = require('@typescript-eslint/eslint-plugin');
const typescriptParser = require('@typescript-eslint/parser');
const prettierConfig = require('eslint-config-prettier');
const eslintCommentsPlugin = require('eslint-plugin-eslint-comments');
const ftFlowPlugin = require('eslint-plugin-ft-flow');
const jestPlugin = require('eslint-plugin-jest');
const reactPlugin = require('eslint-plugin-react');
const reactHooksPlugin = require('eslint-plugin-react-hooks');
const reactNativeExternalPlugin = require('eslint-plugin-react-native');
const flowParser = require('flow-eslint');

// Convert globals from legacy format (true/false) to flat config format ('readonly'/'writable')
const convertGlobals = globals => {
Expand All @@ -31,6 +32,9 @@ const convertGlobals = globals => {
};

// Flat Config for ESLint 9+
//
// `fixupPluginRules` adapts plugins that still call rule context methods
// removed in ESLint 10 (e.g. `context.getSourceCode()`).
module.exports = [
// Apply prettier config first (to disable conflicting rules)
prettierConfig,
Expand All @@ -45,33 +49,33 @@ module.exports = [
},
plugins: {
'eslint-comments': eslintCommentsPlugin,
react: reactPlugin,
react: fixupPluginRules(reactPlugin),
'react-hooks': reactHooksPlugin,
'react-native': reactNativeExternalPlugin,
'react-native': fixupPluginRules(reactNativeExternalPlugin),
'@react-native': reactNativePlugin,
jest: jestPlugin,
},
settings: sharedConfig.settings,
rules: sharedConfig.rules,
},

// JavaScript files with Babel parser and Flow
// JavaScript files, parsed as Flow
{
...sharedConfig.overrides.flow,
files: ['**/*.js'],
languageOptions: {
parser: babelParser,
parser: flowParser,
},
plugins: {
'ft-flow': ftFlowPlugin,
'ft-flow': fixupPluginRules(ftFlowPlugin),
},
},

// JSX files with Babel parser
// JSX files, parsed as Flow
{
files: ['**/*.jsx'],
languageOptions: {
parser: babelParser,
parser: flowParser,
},
},

Expand Down
15 changes: 9 additions & 6 deletions packages/eslint-config-react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,22 @@
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/eslint-parser": "^7.25.1",
"@eslint-community/eslint-plugin-eslint-comments": "^4.8.1",
"@eslint/compat": "^2.1.1",
"@react-native/eslint-plugin": "0.87.0-main",
"@typescript-eslint/eslint-plugin": "^8.59.2",
"@typescript-eslint/parser": "^8.59.2",
"@typescript-eslint/eslint-plugin": "^8.71.2",
"@typescript-eslint/parser": "^8.71.2",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-ft-flow": "^3.0.11",
"eslint-plugin-jest": "^29.0.1",
"eslint-plugin-jest": "^29.17.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-native": "^5.0.0"
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-native": "^5.0.0",
"flow-eslint": "0.333.0"
},
"peerDependencies": {
"eslint": "^8.0.0 || ^9.0.0",
"eslint": "^8.0.0 || ^9.0.0 || ^10.0.0",
"prettier": ">=2"
},
"devDependencies": {
Expand Down
7 changes: 6 additions & 1 deletion packages/eslint-config-react-native/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,12 @@ module.exports = {
'no-undef-init': 1, // disallow use of undefined when initializing variables
'no-unused-vars': [
1,
{vars: 'all', args: 'none', ignoreRestSiblings: true},
{
vars: 'all',
args: 'none',
caughtErrors: 'none',
ignoreRestSiblings: true,
},
], // disallow declaration of variables that are not used in the code
'no-use-before-define': 0, // disallow use of variables before they are defined

Expand Down
17 changes: 13 additions & 4 deletions packages/eslint-plugin-specs/react-native-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,19 @@ function isModuleRequire(node) {
return true;
}

// `context.sourceCode` and `context.filename` were added in ESLint 8.40, and
// the method forms were removed in ESLint 10.
function getSourceCode(context) {
return context.sourceCode ?? context.getSourceCode();
}

function getFilename(context) {
return context.filename ?? context.getFilename();
}

function isGeneratedFile(context) {
return (
context
.getSourceCode()
getSourceCode(context)
.getText()
.indexOf('@' + 'generated SignedSource<<') !== -1
);
Expand All @@ -137,7 +146,7 @@ module.exports = {
},

create(context) {
const filename = context.getFilename();
const filename = getFilename(context);
const hasteModuleName = path.basename(filename).replace(/\.js$/, '');

if (isGeneratedFile(context)) {
Expand Down Expand Up @@ -172,7 +181,7 @@ module.exports = {

const [parsingErrors, tryParse] = createParserErrorCapturer();

const sourceCode = context.getSourceCode().getText();
const sourceCode = getSourceCode(context).getText();
const ast = parser.getAst(sourceCode, filename);

tryParse(() => {
Expand Down
Loading
Loading