From e0f107972eab7a181e0132646a16e80d31fac36f Mon Sep 17 00:00:00 2001 From: vince-fugnitto <vincent.fugnitto@ericsson.com> Date: Tue, 5 Oct 2021 15:18:52 -0400 Subject: [PATCH] eslint: add plugin to warn against `src` imports The commit adds a new `no-src-import` rule to our custom eslint-plugin in order to warn against the use of `/src/` imports over `/lib/` which causes the build to fail and is not trivial for developers to identify as to why. The rule should help write developers more easily identify when they are using imports incorrectly. Signed-off-by: vince-fugnitto <vincent.fugnitto@ericsson.com> --- configs/errors.eslintrc.json | 1 + dev-packages/eslint-plugin/README.md | 5 ++ dev-packages/eslint-plugin/index.js | 1 + .../eslint-plugin/rules/no-src-import.js | 54 +++++++++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 dev-packages/eslint-plugin/rules/no-src-import.js diff --git a/configs/errors.eslintrc.json b/configs/errors.eslintrc.json index eba71b89cac10..b74cb1fdfd0a0 100644 --- a/configs/errors.eslintrc.json +++ b/configs/errors.eslintrc.json @@ -130,6 +130,7 @@ } } ], + "@theia/no-src-import": "error", "@theia/runtime-import-check": "error", "@theia/shared-dependencies": "error", "import/no-extraneous-dependencies": "error", diff --git a/dev-packages/eslint-plugin/README.md b/dev-packages/eslint-plugin/README.md index 4644f411a5fd6..09232928c5fbe 100644 --- a/dev-packages/eslint-plugin/README.md +++ b/dev-packages/eslint-plugin/README.md @@ -17,6 +17,11 @@ The plugin helps identify problems during development through static analysis in ## Rules +### `no-src-import`: + +The rule prevents imports using `/src/` rather than `/lib/` as it causes build failures. +The rule helps developers more easily identify the cause of build errors caused by the incorrect import. + #### `runtime-import-check`: The rule prevents imports from folders meant for incompatible runtimes. diff --git a/dev-packages/eslint-plugin/index.js b/dev-packages/eslint-plugin/index.js index 8030884b943ee..487bebf5930d0 100644 --- a/dev-packages/eslint-plugin/index.js +++ b/dev-packages/eslint-plugin/index.js @@ -17,6 +17,7 @@ /** @type {{[ruleId: string]: import('eslint').Rule.RuleModule}} */ exports.rules = { + "no-src-import": require('./rules/no-src-import'), "runtime-import-check": require('./rules/runtime-import-check'), "shared-dependencies": require('./rules/shared-dependencies') }; diff --git a/dev-packages/eslint-plugin/rules/no-src-import.js b/dev-packages/eslint-plugin/rules/no-src-import.js new file mode 100644 index 0000000000000..9e9487dc45755 --- /dev/null +++ b/dev-packages/eslint-plugin/rules/no-src-import.js @@ -0,0 +1,54 @@ +// @ts-check +/******************************************************************************** + * Copyright (C) 2021 Ericsson and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +const path = require('path'); + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'problem', + fixable: 'code', + docs: { + description: 'prevent imports from \'src\'.', + }, + }, + create(context) { + return { + ImportDeclaration(node) { + checkModuleImport(node.source); + }, + TSExternalModuleReference(node) { + checkModuleImport(node.expression); + }, + }; + function checkModuleImport(node) { + const module = /** @type {string} */(node.value); + const extension = path.parse(module).ext; + const re = /^@theia\/\S+\/src\//; + if (re.test(module) && extension === '') { + context.report({ + node, + message: `'${module}' should not be imported with '/src/'`, + fix: function (fixer) { + const updatedModule = `'${module.replace('/src/', '/lib/')}'`; + return fixer.replaceText(node, updatedModule); + } + }); + } + } + } +};