feat(es/lints): Implement no-sparse-arrays rule (#4652)

This commit is contained in:
Artur 2022-05-14 09:10:49 +03:00 committed by GitHub
parent c96cbe9b27
commit 9b226a7026
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 117 additions and 0 deletions

View File

@ -0,0 +1,9 @@
{
"jsc": {
"lints": {
"no-sparse-arrays": [
"error"
]
}
}
}

View File

@ -0,0 +1,6 @@
var a = [,];
var a = [1, , 2];
var a = [1, 2,];
var a = [1, 2];
var a = [];

View File

@ -0,0 +1,12 @@
x Unexpected comma in middle of array
,----
1 | var a = [,];
: ^^^
`----
x Unexpected comma in middle of array
,----
2 | var a = [1, , 2];
: ^^^^^^^^
`----

View File

@ -195,4 +195,8 @@ pub struct LintConfig {
#[cfg(feature = "non_critical_lints")]
#[serde(default, alias = "noCompareNegZero")]
pub no_compare_neg_zero: RuleConfig<()>,
#[cfg(feature = "non_critical_lints")]
#[serde(default, alias = "noSparseArrays")]
pub no_sparse_arrays: RuleConfig<()>,
}

View File

@ -31,6 +31,7 @@ pub(crate) mod non_critical_lints {
pub mod no_obj_calls;
pub mod no_param_reassign;
pub mod no_restricted_syntax;
pub mod no_sparse_arrays;
pub mod no_throw_literal;
pub mod no_use_before_define;
pub mod no_var;
@ -171,6 +172,10 @@ pub fn all(lint_params: LintParams) -> Vec<Box<dyn Rule>> {
rules.extend(no_compare_neg_zero::no_compare_neg_zero(
&lint_config.no_compare_neg_zero,
));
rules.extend(no_sparse_arrays::no_sparse_arrays(
&lint_config.no_sparse_arrays,
));
}
rules

View File

@ -0,0 +1,81 @@
use swc_common::{errors::HANDLER, Span};
use swc_ecma_ast::*;
use swc_ecma_visit::{Visit, VisitWith};
use crate::{
config::{LintRuleReaction, RuleConfig},
rule::{visitor_rule, Rule},
};
const MESSAGE: &str = "Unexpected comma in middle of array";
pub fn no_sparse_arrays(config: &RuleConfig<()>) -> Option<Box<dyn Rule>> {
let rule_reaction = config.get_rule_reaction();
match rule_reaction {
LintRuleReaction::Off => None,
_ => Some(visitor_rule(NoSparseArrays::new(rule_reaction))),
}
}
#[derive(Debug, Default)]
struct NoSparseArrays {
expected_reaction: LintRuleReaction,
}
impl NoSparseArrays {
fn new(expected_reaction: LintRuleReaction) -> Self {
Self { expected_reaction }
}
fn emit_report(&self, span: Span) {
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();
}
_ => {}
});
}
fn check(&self, span: Span, elems: &[Option<ExprOrSpread>]) {
let len = elems.len();
// case
// []
if len == 0 {
return;
}
// case
// [,]
if len == 1 && elems[0].is_none() {
self.emit_report(span);
return;
}
let last_idx = len - 1;
let is_sparse_array = elems
.iter()
.enumerate()
.any(|(idx, x)| idx != last_idx && x.is_none());
// cases like
// [1,,2]
if is_sparse_array {
self.emit_report(span);
}
}
}
impl Visit for NoSparseArrays {
fn visit_array_lit(&mut self, n: &ArrayLit) {
self.check(n.span, n.elems.as_slice());
n.visit_children_with(self);
}
}