Skip to content

Commit

Permalink
feat(linter/node): implement no-new-require
Browse files Browse the repository at this point in the history
  • Loading branch information
jelly committed Sep 29, 2024
1 parent 646cd1d commit b5e6360
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
2 changes: 2 additions & 0 deletions crates/oxc_linter/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ mod vitest {

mod node {
pub mod no_exports_assign;
pub mod no_new_require;
}

oxc_macros::declare_all_lint_rules! {
Expand Down Expand Up @@ -733,6 +734,7 @@ oxc_macros::declare_all_lint_rules! {
nextjs::no_typos,
nextjs::no_unwanted_polyfillio,
node::no_exports_assign,
node::no_new_require,
oxc::approx_constant,
oxc::bad_array_method_on_arguments,
oxc::bad_bitwise_operator,
Expand Down
73 changes: 73 additions & 0 deletions crates/oxc_linter/src/rules/node/no_new_require.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use oxc_ast::{ast::Expression, AstKind};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;

use crate::{context::LintContext, rule::Rule, AstNode};

fn no_new_require(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Unexpected use of new with require")
.with_label(span)
.with_help("Initialise the constructor separate from the import statement")
}

#[derive(Debug, Default, Clone)]
pub struct NoNewRequire;

declare_oxc_lint!(
/// ### What it does
///
/// Warn about calling `new` on `require`.
///
/// ### Why is this bad?
///
/// The `require` function is used to include modules and might return a constructor. As this
/// is not always the case this can be confusing.
///
/// ### Examples
///
/// Examples of **incorrect** code for this rule:
/// ```js
/// var appHeader = new require('app-header');
/// ```
///
/// Examples of **correct** code for this rule:
/// ```js
/// var AppHeader = require('app-header');
/// var appHeader = new AppHeader();
/// ```
NoNewRequire,
restriction);

impl Rule for NoNewRequire {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let AstKind::NewExpression(new_expression) = node.kind() else {
return;
};

if !new_expression.callee.is_specific_id("require") {
return;
};

ctx.diagnostic(no_new_require(new_expression.span));
}
}

#[test]
fn test() {
use crate::tester::Tester;

let pass = vec![
"var appHeader = require('app-header')",
"var AppHeader = new (require('app-header'))",
"var AppHeader = new (require('headers').appHeader)",
"var AppHeader = require('app-header'); var appHeader = new AppHeader();",
];

let fail = vec![
"var appHeader = new require('app-header')",
"var appHeader = new require('headers').appHeader",
];

Tester::new(NoNewRequire::NAME, pass, fail).test_and_snapshot();
}
16 changes: 16 additions & 0 deletions crates/oxc_linter/src/snapshots/no_new_require.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: crates/oxc_linter/src/tester.rs
---
eslint-plugin-node(no-new-require): Unexpected use of new with require
╭─[no_new_require.tsx:1:17]
1var appHeader = new require('app-header')
· ─────────────────────────
╰────
help: Initialise the constructor separate from the import statement

eslint-plugin-node(no-new-require): Unexpected use of new with require
╭─[no_new_require.tsx:1:17]
1var appHeader = new require('headers').appHeader
· ──────────────────────
╰────
help: Initialise the constructor separate from the import statement

0 comments on commit b5e6360

Please sign in to comment.