mirror of
https://github.com/swc-project/swc.git
synced 2024-11-24 02:06:08 +03:00
feat(es/lints): Add this handling support to no-alert
rule (#3515)
This commit is contained in:
parent
b3a55dbb4e
commit
af8200647b
7
crates/swc/tests/errors/lints/no-alert/this/.swcrc
Normal file
7
crates/swc/tests/errors/lints/no-alert/this/.swcrc
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"jsc": {
|
||||
"lints": {
|
||||
"noAlert": ["error"]
|
||||
}
|
||||
}
|
||||
}
|
50
crates/swc/tests/errors/lints/no-alert/this/input.js
Normal file
50
crates/swc/tests/errors/lints/no-alert/this/input.js
Normal file
@ -0,0 +1,50 @@
|
||||
this.alert();
|
||||
|
||||
class X {
|
||||
constructor(x) {
|
||||
this.alert(x);
|
||||
}
|
||||
|
||||
alert() {}
|
||||
|
||||
m() {
|
||||
const x = () => {
|
||||
// shouldn't fail
|
||||
this.alert();
|
||||
}
|
||||
}
|
||||
|
||||
m1() {
|
||||
class Y {}
|
||||
|
||||
this.alert();
|
||||
}
|
||||
}
|
||||
|
||||
var o = {
|
||||
a() {
|
||||
this.alert();
|
||||
},
|
||||
b: function() {
|
||||
this.alert()
|
||||
},
|
||||
c: () => {
|
||||
// should fail
|
||||
this.alert();
|
||||
},
|
||||
e: {
|
||||
a() {
|
||||
this.alert();
|
||||
}
|
||||
},
|
||||
f() {
|
||||
this.alert();
|
||||
}
|
||||
}
|
||||
|
||||
function f1() {
|
||||
const x = () => {
|
||||
// should fail
|
||||
this.alert();
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
error: Unexpected alert
|
||||
|
||||
|
|
||||
1 | this.alert();
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: Unexpected alert
|
||||
|
||||
|
|
||||
33 | this.alert();
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: Unexpected alert
|
||||
|
||||
|
|
||||
48 | this.alert();
|
||||
| ^^^^^^^^^^^^
|
||||
|
@ -40,6 +40,9 @@ struct NoAlert {
|
||||
top_level_declared_vars: AHashSet<Id>,
|
||||
pass_call_on_global_this: bool,
|
||||
inside_callee: bool,
|
||||
classes_depth: usize,
|
||||
objects_depth: usize,
|
||||
arrow_fns_depth: usize,
|
||||
obj: Option<JsWord>,
|
||||
prop: Option<JsWord>,
|
||||
}
|
||||
@ -57,6 +60,9 @@ impl NoAlert {
|
||||
top_level_declared_vars,
|
||||
pass_call_on_global_this: es_version < EsVersion::Es2020,
|
||||
inside_callee: false,
|
||||
classes_depth: 0,
|
||||
objects_depth: 0,
|
||||
arrow_fns_depth: 0,
|
||||
obj: None,
|
||||
prop: None,
|
||||
}
|
||||
@ -76,6 +82,18 @@ impl NoAlert {
|
||||
});
|
||||
}
|
||||
|
||||
fn is_inside_class(&self) -> bool {
|
||||
self.classes_depth > 0
|
||||
}
|
||||
|
||||
fn is_inside_object(&self) -> bool {
|
||||
self.objects_depth > 0
|
||||
}
|
||||
|
||||
fn is_inside_arrow_fn(&self) -> bool {
|
||||
self.arrow_fns_depth > 0
|
||||
}
|
||||
|
||||
fn check(&self, call_span: Span, obj: &Option<JsWord>, prop: &JsWord) {
|
||||
if let Some(obj) = obj {
|
||||
let obj_name: &str = &*obj;
|
||||
@ -108,6 +126,20 @@ impl NoAlert {
|
||||
true
|
||||
}
|
||||
|
||||
fn handle_member_prop(&mut self, prop: &MemberProp) {
|
||||
match prop {
|
||||
MemberProp::Ident(Ident { sym, .. }) => {
|
||||
self.prop = Some(sym.clone());
|
||||
}
|
||||
MemberProp::Computed(comp) => {
|
||||
if let Expr::Lit(Lit::Str(Str { value, .. })) = comp.expr.as_ref() {
|
||||
self.prop = Some(value.clone());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_callee(&mut self, expr: &Expr) {
|
||||
match expr {
|
||||
Expr::Ident(ident) => {
|
||||
@ -118,27 +150,32 @@ impl NoAlert {
|
||||
Expr::Member(member_expr) => {
|
||||
let MemberExpr { obj, prop, .. } = member_expr;
|
||||
|
||||
if let Expr::Ident(obj) = obj.as_ref() {
|
||||
if !self.is_satisfying_indent(obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.obj = Some(obj.sym.clone());
|
||||
|
||||
match prop {
|
||||
MemberProp::Ident(Ident { sym, .. }) => {
|
||||
self.prop = Some(sym.clone());
|
||||
match obj.as_ref() {
|
||||
Expr::Ident(obj) => {
|
||||
if !self.is_satisfying_indent(obj) {
|
||||
return;
|
||||
}
|
||||
MemberProp::Computed(comp) => {
|
||||
if let Expr::Lit(Lit::Str(Str { value, .. })) = comp.expr.as_ref() {
|
||||
self.prop = Some(value.clone());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
||||
self.obj = Some(obj.sym.clone());
|
||||
|
||||
self.handle_member_prop(prop);
|
||||
}
|
||||
Expr::This(_) => {
|
||||
let inside_arrow_fn = self.is_inside_arrow_fn();
|
||||
let inside_class = self.is_inside_class();
|
||||
|
||||
if inside_arrow_fn && inside_class {
|
||||
return;
|
||||
}
|
||||
|
||||
if !inside_arrow_fn && (inside_class || self.is_inside_object()) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.handle_member_prop(prop);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// TODO: handle call alert on "this"
|
||||
}
|
||||
Expr::OptChain(opt_chain) => {
|
||||
opt_chain.visit_children_with(self);
|
||||
@ -182,4 +219,28 @@ impl Visit for NoAlert {
|
||||
expr.visit_children_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_class(&mut self, class: &Class) {
|
||||
self.classes_depth += 1;
|
||||
|
||||
class.visit_children_with(self);
|
||||
|
||||
self.classes_depth -= 1;
|
||||
}
|
||||
|
||||
fn visit_object_lit(&mut self, lit_obj: &ObjectLit) {
|
||||
self.objects_depth += 1;
|
||||
|
||||
lit_obj.visit_children_with(self);
|
||||
|
||||
self.objects_depth -= 1;
|
||||
}
|
||||
|
||||
fn visit_arrow_expr(&mut self, arrow_fn: &ArrowExpr) {
|
||||
self.arrow_fns_depth += 1;
|
||||
|
||||
arrow_fn.visit_children_with(self);
|
||||
|
||||
self.arrow_fns_depth -= 1;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user