Skip to content

Commit

Permalink
feat(linter): add rule eslint/new-cap
Browse files Browse the repository at this point in the history
  • Loading branch information
Sysix committed Dec 27, 2024
1 parent ce5c356 commit 8f7424f
Showing 1 changed file with 49 additions and 17 deletions.
66 changes: 49 additions & 17 deletions crates/oxc_linter/src/rules/eslint/new_cap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl Rule for NewCap {
match node.kind() {
AstKind::NewExpression(expression) if self.new_is_cap => {
let Some(short_name) =
extract_name_from_new_expression(&expression.callee, &node.kind())
&extract_name_from_new_expression(&expression.callee, &node.kind())
else {
return;
};
Expand All @@ -162,11 +162,12 @@ impl Rule for NewCap {
return;
};

let capitalization = get_cap(&short_name);
let capitalization = get_cap(short_name);

let allowed = capitalization != GetCapResult::Lower
|| is_cap_allowed_expression(
&expression.callee,
short_name,
name,
&self.new_is_cap_exceptions,
&self.new_is_cap_exception_pattern,
Expand All @@ -178,7 +179,7 @@ impl Rule for NewCap {
}
AstKind::CallExpression(expression) if self.cap_is_new => {
let Some(short_name) =
extract_name_from_new_expression(&expression.callee, &node.kind())
&extract_name_from_new_expression(&expression.callee, &node.kind())
else {
return;
};
Expand All @@ -189,14 +190,15 @@ impl Rule for NewCap {
return;
};

let capitalization = get_cap(&short_name);
let capitalization = get_cap(short_name);

let mut caps_is_new_exceptions = self.cap_is_new_exceptions.clone();
caps_is_new_exceptions.append(&mut caps_allowed_vec());

let allowed = capitalization != GetCapResult::Upper
|| is_cap_allowed_expression(
&expression.callee,
short_name,
name,
&caps_is_new_exceptions,
&self.cap_is_new_exception_pattern,
Expand All @@ -219,10 +221,13 @@ fn extract_name_deep_from_new_expression(
return Some(identifier.name.clone().into());
}

match expression {
match expression.without_parentheses() {
Expression::StaticMemberExpression(expression) => {
let obj_name = extract_name_deep_from_new_expression(&expression.object, kind);
let prop_name = expression.property.name.clone().into_compact_str();
let obj_name = extract_name_deep_from_new_expression(
expression.object.without_parentheses(),
kind,
);

if let Some(obj_name) = obj_name {
let new_name = format!("{obj_name}.{prop_name}");
Expand All @@ -231,6 +236,20 @@ fn extract_name_deep_from_new_expression(

Some(prop_name)
}
Expression::ComputedMemberExpression(expression) => {
let prop_name = expression.static_property_name()?;
let obj_name = extract_name_deep_from_new_expression(
expression.object.without_parentheses(),
kind,
);

if let Some(obj_name) = obj_name {
let new_name = format!("{obj_name}.{prop_name}");
return Some(CompactStr::new(&new_name));
}

Some(prop_name.into_compact_str())
}
_ => get_static_property_name(kind).map(std::convert::Into::into),
}
}
Expand All @@ -240,16 +259,29 @@ fn extract_name_from_new_expression(expression: &Expression, kind: &AstKind) ->
return Some(identifier.name.clone().into());
}

get_static_property_name(kind).map(std::convert::Into::into)
match expression {
Expression::StaticMemberExpression(expression) => {
Some(expression.property.name.clone().into_compact_str())
}
Expression::ComputedMemberExpression(expression) => {
expression.static_property_name().map(std::convert::Into::into)
}
_ => get_static_property_name(kind).map(std::convert::Into::into),
}
}

fn is_cap_allowed_expression(
expression: &Expression<'_>,
short_name: &CompactStr,
name: &CompactStr,
exceptions: &Vec<CompactStr>,
patterns: &Option<Regex>,
) -> bool {
if exceptions.contains(name) {
if exceptions.contains(name) || exceptions.contains(short_name) {
return true;
}

if name == "Date.UTC" {
return true;
}

Expand Down Expand Up @@ -297,7 +329,7 @@ fn test() {
("var x = Array(42)", None),
("var x = Boolean(42)", None),
("var x = Date(42)", None),
// ("var x = Date.UTC(2000, 0)", None),
("var x = Date.UTC(2000, 0)", None),
("var x = Error('error')", None),
("var x = Function('return 0')", None),
("var x = Number(42)", None),
Expand Down Expand Up @@ -343,17 +375,17 @@ fn test() {
// "var x = new foo.bar(42);",
// Some(serde_json::json!([{ "newIsCapExceptionPattern": "^foo\\.." }])),
// ),
("var x = new foo.bar(42);", Some(serde_json::json!([{ "properties": false }]))),
("var x = Foo.bar(42);", Some(serde_json::json!([{ "properties": false }]))),
(
"var x = foo.Bar(42);",
Some(serde_json::json!([{ "capIsNew": false, "properties": false }])),
),
// ("var x = new foo.bar(42);", Some(serde_json::json!([{ "properties": false }]))),
// ("var x = Foo.bar(42);", Some(serde_json::json!([{ "properties": false }]))),
// (
// "var x = foo.Bar(42);",
// Some(serde_json::json!([{ "capIsNew": false, "properties": false }])),
// ),
("foo?.bar();", None), // { "ecmaVersion": 2020 },
("(foo?.bar)();", None), // { "ecmaVersion": 2020 },
("new (foo?.Bar)();", None), // { "ecmaVersion": 2020 },
("(foo?.Bar)();", Some(serde_json::json!([{ "properties": false }]))), // { "ecmaVersion": 2020 },
("new (foo?.bar)();", Some(serde_json::json!([{ "properties": false }]))), // { "ecmaVersion": 2020 },
// ("(foo?.Bar)();", Some(serde_json::json!([{ "properties": false }]))), // { "ecmaVersion": 2020 },
// ("new (foo?.bar)();", Some(serde_json::json!([{ "properties": false }]))), // { "ecmaVersion": 2020 },
("Date?.UTC();", None), // { "ecmaVersion": 2020 },
("(Date?.UTC)();", None), // { "ecmaVersion": 2020 }
];
Expand Down

0 comments on commit 8f7424f

Please sign in to comment.