From db2fd70432cb7912f507dba27df279aee84fc1c5 Mon Sep 17 00:00:00 2001 From: Jelle van der Waa Date: Wed, 17 Jul 2024 22:13:54 +0200 Subject: [PATCH] feat(linter/eslint-plugin-promise): implement no-webpack-loader-syntax (#4331) Rule detail: [link](https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/no-webpack-loader-syntax.md) --- crates/oxc_linter/src/rules.rs | 2 + .../rules/import/no_webpack_loader_syntax.rs | 118 ++++++++++++++++++ .../snapshots/no_webpack_loader_syntax.snap | 58 +++++++++ 3 files changed, 178 insertions(+) create mode 100644 crates/oxc_linter/src/rules/import/no_webpack_loader_syntax.rs create mode 100644 crates/oxc_linter/src/snapshots/no_webpack_loader_syntax.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index ad727107d6f06..c9d85f32933bc 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -21,6 +21,7 @@ mod import { pub mod no_named_as_default_member; pub mod no_self_import; // pub mod no_unused_modules; + pub mod no_webpack_loader_syntax; } mod eslint { @@ -741,6 +742,7 @@ oxc_macros::declare_all_lint_rules! { // import::no_unused_modules, import::no_duplicates, import::no_default_export, + import::no_webpack_loader_syntax, jsx_a11y::alt_text, jsx_a11y::anchor_has_content, jsx_a11y::anchor_is_valid, diff --git a/crates/oxc_linter/src/rules/import/no_webpack_loader_syntax.rs b/crates/oxc_linter/src/rules/import/no_webpack_loader_syntax.rs new file mode 100644 index 0000000000000..1100ae680791d --- /dev/null +++ b/crates/oxc_linter/src/rules/import/no_webpack_loader_syntax.rs @@ -0,0 +1,118 @@ +use oxc_ast::{ + ast::{Argument, Expression}, + AstKind, +}; +use oxc_diagnostics::OxcDiagnostic; +use oxc_macros::declare_oxc_lint; +use oxc_semantic::AstNode; +use oxc_span::Span; + +use crate::{context::LintContext, rule::Rule}; + +fn no_named_as_default_diagnostic(x0: &str, span0: Span) -> OxcDiagnostic { + OxcDiagnostic::warn(format!( + "eslint-plugin-import(no-webpack-loader-syntax): Unexpected `!` in `{x0}`." + )) + .with_help("Do not use import syntax to configure webpack loaders") + .with_label(span0) +} + +#[derive(Debug, Default, Clone)] +pub struct NoWebpackLoaderSyntax; + +declare_oxc_lint!( + /// ### What it does + /// + /// Forbid Webpack loader syntax in imports. + /// + /// ### Why is this bad? + /// + /// This loader syntax is non-standard, so it couples the code to Webpack. The recommended way to + /// specify Webpack loader configuration is in a [Webpack configuration file](https://webpack.js.org/concepts/loaders/#configuration). + /// + /// ### Example + /// ```javascript + /// import myModule from 'my-loader!my-module'; + /// import theme from 'style!css!./theme.css'; + /// + /// var myModule = require('my-loader!./my-module'); + /// var theme = require('style!css!./theme.css'); + /// ``` + NoWebpackLoaderSyntax, + restriction, +); + +impl Rule for NoWebpackLoaderSyntax { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + // not in top level + if node.scope_id() != ctx.scopes().root_scope_id() { + return; + } + + match node.kind() { + AstKind::CallExpression(call_expr) => { + if let Expression::Identifier(identifier) = &call_expr.callee { + if identifier.name != "require" { + return; + } + + if call_expr.arguments.len() != 1 { + return; + } + + let Argument::StringLiteral(ident) = &call_expr.arguments[0] else { + return; + }; + + if ident.value.contains('!') { + ctx.diagnostic(no_named_as_default_diagnostic( + ident.value.as_str(), + ident.span, + )); + } + } + } + AstKind::ImportDeclaration(import_decl) => { + if import_decl.source.value.contains('!') { + ctx.diagnostic(no_named_as_default_diagnostic( + &import_decl.source.value, + import_decl.source.span, + )); + } + } + _ => {} + } + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + "import _ from 'lodash'", + "import find from 'lodash.find'", + "import foo from './foo.css'", + "import data from '@scope/my-package/data.json'", + "var _ = require('lodash')", + "var find = require('lodash.find')", + "var foo = require('./foo')", + "var foo = require('../foo')", + "var foo = require('foo')", + "var foo = require('./')", + "var foo = require('@scope/foo')", + ]; + + let fail = vec![ + "import _ from 'babel!lodash'", + "import find from '-babel-loader!lodash.find'", + "import foo from 'style!css!./foo.css'", + "import data from 'json!@scope/my-package/data.json'", + "var _ = require('babel!lodash')", + "var find = require('-babel-loader!lodash.find')", + "var foo = require('style!css!./foo.css')", + "var data = require('json!@scope/my-package/data.json')", + ]; + + Tester::new(NoWebpackLoaderSyntax::NAME, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_webpack_loader_syntax.snap b/crates/oxc_linter/src/snapshots/no_webpack_loader_syntax.snap new file mode 100644 index 0000000000000..68026934379c1 --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_webpack_loader_syntax.snap @@ -0,0 +1,58 @@ +--- +source: crates/oxc_linter/src/tester.rs +--- + ⚠ eslint-plugin-import(no-webpack-loader-syntax): Unexpected `!` in `babel!lodash`. + ╭─[no_webpack_loader_syntax.tsx:1:15] + 1 │ import _ from 'babel!lodash' + · ────────────── + ╰──── + help: Do not use import syntax to configure webpack loaders + + ⚠ eslint-plugin-import(no-webpack-loader-syntax): Unexpected `!` in `-babel-loader!lodash.find`. + ╭─[no_webpack_loader_syntax.tsx:1:18] + 1 │ import find from '-babel-loader!lodash.find' + · ─────────────────────────── + ╰──── + help: Do not use import syntax to configure webpack loaders + + ⚠ eslint-plugin-import(no-webpack-loader-syntax): Unexpected `!` in `style!css!./foo.css`. + ╭─[no_webpack_loader_syntax.tsx:1:17] + 1 │ import foo from 'style!css!./foo.css' + · ───────────────────── + ╰──── + help: Do not use import syntax to configure webpack loaders + + ⚠ eslint-plugin-import(no-webpack-loader-syntax): Unexpected `!` in `json!@scope/my-package/data.json`. + ╭─[no_webpack_loader_syntax.tsx:1:18] + 1 │ import data from 'json!@scope/my-package/data.json' + · ────────────────────────────────── + ╰──── + help: Do not use import syntax to configure webpack loaders + + ⚠ eslint-plugin-import(no-webpack-loader-syntax): Unexpected `!` in `babel!lodash`. + ╭─[no_webpack_loader_syntax.tsx:1:17] + 1 │ var _ = require('babel!lodash') + · ────────────── + ╰──── + help: Do not use import syntax to configure webpack loaders + + ⚠ eslint-plugin-import(no-webpack-loader-syntax): Unexpected `!` in `-babel-loader!lodash.find`. + ╭─[no_webpack_loader_syntax.tsx:1:20] + 1 │ var find = require('-babel-loader!lodash.find') + · ─────────────────────────── + ╰──── + help: Do not use import syntax to configure webpack loaders + + ⚠ eslint-plugin-import(no-webpack-loader-syntax): Unexpected `!` in `style!css!./foo.css`. + ╭─[no_webpack_loader_syntax.tsx:1:19] + 1 │ var foo = require('style!css!./foo.css') + · ───────────────────── + ╰──── + help: Do not use import syntax to configure webpack loaders + + ⚠ eslint-plugin-import(no-webpack-loader-syntax): Unexpected `!` in `json!@scope/my-package/data.json`. + ╭─[no_webpack_loader_syntax.tsx:1:20] + 1 │ var data = require('json!@scope/my-package/data.json') + · ────────────────────────────────── + ╰──── + help: Do not use import syntax to configure webpack loaders