Forbid imports from nested directories of flipper-common, flipper-plugin, flipper-ui-core

Summary:
Forbid imports from nested directories of flipper-common, flipper-plugin, flipper-ui-core

In the stack of D32926830 I occasionally imported from flipper-plugin/src/... which is not allowed. This should fix any auto-import related issues once and for all.

Reviewed By: timur-valiev

Differential Revision: D32987054

fbshipit-source-id: f19f6278219961ad283cacfec094a6c703ca93f8
This commit is contained in:
Andrey Goncharov
2021-12-10 06:34:37 -08:00
committed by Facebook GitHub Bot
parent 9436c32ce9
commit adb2573a1f
10 changed files with 92 additions and 30 deletions

View File

@@ -9,6 +9,9 @@
const fbjs = require('eslint-config-fbjs'); const fbjs = require('eslint-config-fbjs');
const rulesDirPlugin = require('eslint-plugin-rulesdir');
rulesDirPlugin.RULES_DIR = 'eslint-rules';
// enforces copy-right header and @format directive to be present in every file // enforces copy-right header and @format directive to be present in every file
const pattern = /^\*\r?\n[\S\s]*Facebook[\S\s]* \* @format\r?\n/; const pattern = /^\*\r?\n[\S\s]*Facebook[\S\s]* \* @format\r?\n/;
@@ -30,6 +33,39 @@ const builtInModules = [
const prettierConfig = require('./.prettierrc.json'); const prettierConfig = require('./.prettierrc.json');
// We should forbid using "flipper" import. However, we have hundreds of plugins using it.
// So we forbid it everywhere but in "plugins" directory.
// To do that we need to keep "error" level of linting for most imports, but downlevel warning for "flipper" import to "warn".
// It is not possible OOTB by eslint.
// Instead, we create a clone of the "no-restricted-imports" rule and use it to split out restricted imports in two groups: warn and error.
// https://github.com/eslint/eslint/issues/14061#issuecomment-772490154
const restrictedImportsUniversalErrorConfig = {
paths: [
{
name: 'electron',
message:
"Direct imports from 'electron' are deprecated. Most functions can be found in getFlipperLib() from flipper-plugin package instead.",
},
],
patterns: [
{
group: ['flipper-plugin/*'],
message:
"Imports from nested flipper-plugin directories are not allowed. Import from 'flipper-plugin' module directly. If it is missing an export, add it there with corresponding documentation (https://fbflipper.com/docs/extending/flipper-plugin/).",
},
{
group: ['flipper-common/*'],
message:
"Imports from nested flipper-common directories are not allowed. Import from 'flipper-common' module directly. If it is missing an export, add it there.",
},
{
group: ['flipper-ui-core/*'],
message:
"Imports from nested flipper-ui-core directories are not allowed. Import from 'flipper-ui-core' module directly. If it is missing an export, add it there.",
},
],
};
module.exports = { module.exports = {
parser: 'babel-eslint', parser: 'babel-eslint',
root: true, root: true,
@@ -45,6 +81,7 @@ module.exports = {
'flipper', 'flipper',
'promise', 'promise',
'communist-spelling', 'communist-spelling',
'rulesdir',
], ],
rules: { rules: {
// disable rules from eslint-config-fbjs // disable rules from eslint-config-fbjs
@@ -81,16 +118,17 @@ module.exports = {
}, },
], ],
'no-restricted-imports': [ 'no-restricted-imports': [
1, 'error',
{ {
name: 'flipper', ...restrictedImportsUniversalErrorConfig,
message: paths: [
"Direct imports from 'flipper' are deprecated. Import from 'flipper-plugin' instead, which can be tested and distributed stand-alone. See https://fbflipper.com/docs/extending/sandy-migration for more details.", ...restrictedImportsUniversalErrorConfig.paths,
}, {
{ name: 'flipper',
name: 'electron', message:
message: "Direct imports from 'flipper' are deprecated. Import from 'flipper-plugin' instead, which can be tested and distributed stand-alone. See https://fbflipper.com/docs/extending/sandy-migration for more details.",
"Direct imports from 'electron' are deprecated. Most functions can be found in getFlipperLib() from flipper-plugin package instead.", },
],
}, },
], ],
@@ -150,5 +188,26 @@ module.exports = {
], ],
}, },
}, },
{
files: ['plugins/**/*.ts', 'plugins/**/*.tsx'],
rules: {
'no-restricted-imports': [
'error',
restrictedImportsUniversalErrorConfig,
],
'rulesdir/no-restricted-imports-clone': [
'warn',
{
paths: [
{
name: 'flipper',
message:
"Direct imports from 'flipper' are deprecated. Import from 'flipper-plugin' instead, which can be tested and distributed stand-alone. See https://fbflipper.com/docs/extending/sandy-migration for more details.",
},
],
},
],
},
},
], ],
}; };

View File

@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
// https://github.com/eslint/eslint/issues/14061#issuecomment-772490154
const eslint = require('eslint');
module.exports = new eslint.Linter().getRules().get('no-restricted-imports');

View File

@@ -14,6 +14,7 @@ jest.mock('promisify-child-process');
import {makeIOSBridge} from '../IOSBridge'; import {makeIOSBridge} from '../IOSBridge';
import * as promisifyChildProcess from 'promisify-child-process'; import * as promisifyChildProcess from 'promisify-child-process';
import {setFlipperServerConfig} from '../../../FlipperServerConfig'; import {setFlipperServerConfig} from '../../../FlipperServerConfig';
// eslint-disable-next-line node/no-extraneous-import
import {getRenderHostInstance} from 'flipper-ui-core'; import {getRenderHostInstance} from 'flipper-ui-core';
beforeEach(() => { beforeEach(() => {

View File

@@ -11,6 +11,7 @@ import {parseXcodeFromCoreSimPath} from '../iOSDeviceManager';
import {getLogger} from 'flipper-common'; import {getLogger} from 'flipper-common';
import {IOSBridge} from '../IOSBridge'; import {IOSBridge} from '../IOSBridge';
import {FlipperServerImpl} from '../../../FlipperServerImpl'; import {FlipperServerImpl} from '../../../FlipperServerImpl';
// eslint-disable-next-line node/no-extraneous-import
import {getRenderHostInstance} from 'flipper-ui-core'; import {getRenderHostInstance} from 'flipper-ui-core';
import { import {
getFlipperServerConfig, getFlipperServerConfig,

View File

@@ -1,21 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
module.exports = {
rules: {
'no-restricted-imports': [
'error',
{
// These paths lead to circular import issues in Flipper app and are forbidden
paths: ['flipper'],
patterns: ['flipper-ui-core/src/*'],
},
],
},
};

View File

@@ -9,6 +9,8 @@
import type {NotificationEvents} from './dispatcher/notifications'; import type {NotificationEvents} from './dispatcher/notifications';
import type {PluginNotification} from './reducers/notifications'; import type {PluginNotification} from './reducers/notifications';
// TODO: Fix me
// eslint-disable-next-line no-restricted-imports
import type {NotificationConstructorOptions} from 'electron'; import type {NotificationConstructorOptions} from 'electron';
import {FlipperLib} from 'flipper-plugin'; import {FlipperLib} from 'flipper-plugin';
import {FlipperServer, FlipperServerConfig} from 'flipper-common'; import {FlipperServer, FlipperServerConfig} from 'flipper-common';

View File

@@ -149,6 +149,7 @@
"eslint-plugin-promise": "^5.1.1", "eslint-plugin-promise": "^5.1.1",
"eslint-plugin-react": "^7.27.1", "eslint-plugin-react": "^7.27.1",
"eslint-plugin-react-hooks": "^4.3.0", "eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-rulesdir": "^0.2.1",
"expand-tilde": "^2.0.2", "expand-tilde": "^2.0.2",
"express": "^4.15.2", "express": "^4.15.2",
"fb-watchman": "^2.0.1", "fb-watchman": "^2.0.1",

View File

@@ -35,6 +35,7 @@ import copyPackageWithDependencies from './copy-package-with-dependencies';
import {staticDir, distDir} from './paths'; import {staticDir, distDir} from './paths';
import yargs from 'yargs'; import yargs from 'yargs';
import {WinPackager} from 'app-builder-lib/out/winPackager'; import {WinPackager} from 'app-builder-lib/out/winPackager';
// eslint-disable-next-line no-restricted-imports
import {Icon, getPublicIconUrl} from 'flipper-ui-core/src/utils/icons'; import {Icon, getPublicIconUrl} from 'flipper-ui-core/src/utils/icons';
// Used in some places to avoid release-to-release changes. Needs // Used in some places to avoid release-to-release changes. Needs

View File

@@ -24,6 +24,7 @@ import {
} from 'flipper-common'; } from 'flipper-common';
// Only import the type! // Only import the type!
// eslint-disable-next-line node/no-extraneous-import
import type {RenderHost} from 'flipper-ui-core'; import type {RenderHost} from 'flipper-ui-core';
const test = global.test; const test = global.test;

View File

@@ -6203,6 +6203,11 @@ eslint-plugin-react@^7.27.1:
semver "^6.3.0" semver "^6.3.0"
string.prototype.matchall "^4.0.6" string.prototype.matchall "^4.0.6"
eslint-plugin-rulesdir@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-rulesdir/-/eslint-plugin-rulesdir-0.2.1.tgz#e246bb9657e68eb0a30680c60775f40aa829ec0b"
integrity sha512-t7rQvEyfE4JZJu6dPl4/uVr6Fr0fxopBhzVbtq3isfOHMKdlIe9xW/5CtIaWZI0E1U+wzAk0lEnZC8laCD5YLA==
eslint-rule-composer@^0.3.0: eslint-rule-composer@^0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9"