mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 21:54:36 +03:00
feat(es/lints): Implement no-new-symbol
rule (#4076)
This commit is contained in:
parent
174b48d4c3
commit
b39e345d8e
@ -0,0 +1,9 @@
|
||||
{
|
||||
"jsc": {
|
||||
"lints": {
|
||||
"no-new-symbol": [
|
||||
"error"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
new Symbol();
|
||||
|
||||
new A(new Symbol())
|
||||
|
||||
Symbol()
|
||||
|
||||
function f1(Symbol) {
|
||||
new Symbol()
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
|
||||
x `Symbol` cannot be called as a constructor
|
||||
,----
|
||||
2 | new Symbol();
|
||||
: ^^^^^^^^^^^^
|
||||
`----
|
||||
|
||||
x `Symbol` cannot be called as a constructor
|
||||
,----
|
||||
4 | new A(new Symbol())
|
||||
: ^^^^^^^^^^^^
|
||||
`----
|
@ -138,4 +138,8 @@ pub struct LintConfig {
|
||||
#[cfg(feature = "non_critical_lints")]
|
||||
#[serde(default)]
|
||||
pub yoda: RuleConfig<YodaConfig>,
|
||||
|
||||
#[cfg(feature = "non_critical_lints")]
|
||||
#[serde(default, alias = "noNewSymbol")]
|
||||
pub no_new_symbol: RuleConfig<()>,
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ pub(crate) mod non_critical_lints {
|
||||
pub mod no_empty_pattern;
|
||||
pub mod no_loop_func;
|
||||
pub mod no_new;
|
||||
pub mod no_new_symbol;
|
||||
pub mod no_restricted_syntax;
|
||||
pub mod no_use_before_define;
|
||||
pub mod prefer_regex_literals;
|
||||
@ -130,6 +131,12 @@ pub fn all(lint_params: LintParams) -> Vec<Box<dyn Rule>> {
|
||||
));
|
||||
|
||||
rules.extend(yoda::yoda(&lint_config.yoda));
|
||||
|
||||
rules.extend(no_new_symbol::no_new_symbol(
|
||||
program,
|
||||
top_level_ctxt,
|
||||
&lint_config.no_new_symbol,
|
||||
));
|
||||
}
|
||||
|
||||
rules
|
||||
|
83
crates/swc_ecma_lints/src/rules/no_new_symbol.rs
Normal file
83
crates/swc_ecma_lints/src/rules/no_new_symbol.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use swc_common::{collections::AHashSet, errors::HANDLER, Span, SyntaxContext};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_utils::{collect_decls_with_ctxt, ident::IdentLike};
|
||||
use swc_ecma_visit::{noop_visit_type, Visit, VisitWith};
|
||||
|
||||
use crate::{
|
||||
config::{LintRuleReaction, RuleConfig},
|
||||
rule::{visitor_rule, Rule},
|
||||
};
|
||||
|
||||
const MESSAGE: &str = "`Symbol` cannot be called as a constructor";
|
||||
|
||||
pub fn no_new_symbol(
|
||||
program: &Program,
|
||||
top_level_ctxt: SyntaxContext,
|
||||
config: &RuleConfig<()>,
|
||||
) -> Option<Box<dyn Rule>> {
|
||||
let expected_reaction = config.get_rule_reaction();
|
||||
|
||||
match expected_reaction {
|
||||
LintRuleReaction::Off => None,
|
||||
_ => Some(visitor_rule(NoNewSymbol::new(
|
||||
collect_decls_with_ctxt(program, top_level_ctxt),
|
||||
top_level_ctxt,
|
||||
expected_reaction,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
struct NoNewSymbol {
|
||||
expected_reaction: LintRuleReaction,
|
||||
top_level_ctxt: SyntaxContext,
|
||||
top_level_declared_vars: AHashSet<Id>,
|
||||
}
|
||||
|
||||
impl NoNewSymbol {
|
||||
fn new(
|
||||
top_level_declared_vars: AHashSet<Id>,
|
||||
top_level_ctxt: SyntaxContext,
|
||||
expected_reaction: LintRuleReaction,
|
||||
) -> Self {
|
||||
Self {
|
||||
expected_reaction,
|
||||
top_level_ctxt,
|
||||
top_level_declared_vars,
|
||||
}
|
||||
}
|
||||
|
||||
fn check(&self, span: Span, ident: &Ident) {
|
||||
if self.top_level_declared_vars.contains(&ident.to_id()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ident.span.ctxt != self.top_level_ctxt {
|
||||
return;
|
||||
}
|
||||
|
||||
if &*ident.sym == "Symbol" {
|
||||
HANDLER.with(|handler| match self.expected_reaction {
|
||||
LintRuleReaction::Error => {
|
||||
handler.struct_span_err(span, MESSAGE).emit();
|
||||
}
|
||||
LintRuleReaction::Warning => {
|
||||
handler.struct_span_warn(span, MESSAGE).emit();
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for NoNewSymbol {
|
||||
noop_visit_type!();
|
||||
|
||||
fn visit_new_expr(&mut self, new_expr: &NewExpr) {
|
||||
if let Expr::Ident(ident) = new_expr.callee.as_ref() {
|
||||
self.check(new_expr.span, ident);
|
||||
}
|
||||
|
||||
new_expr.visit_children_with(self);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user