Skip to content

Commit

Permalink
style(linter): introduce the writing style from PR #5491 and reduce t…
Browse files Browse the repository at this point in the history
…he if nesting (#5512)

Related to #5491
  • Loading branch information
shulaoda authored Sep 6, 2024
1 parent c3cfbfb commit 2a43fa4
Show file tree
Hide file tree
Showing 28 changed files with 508 additions and 517 deletions.
8 changes: 2 additions & 6 deletions crates/oxc_linter/src/ast_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,11 +430,7 @@ pub fn get_function_like_declaration<'b>(
ctx: &LintContext<'b>,
) -> Option<&'b BindingIdentifier<'b>> {
let parent = outermost_paren_parent(node, ctx)?;
let decl = parent.kind().as_variable_declarator()?;

if let AstKind::VariableDeclarator(decl) = parent.kind() {
let ident = decl.id.get_binding_identifier()?;
Some(ident)
} else {
None
}
decl.id.get_binding_identifier()
}
41 changes: 23 additions & 18 deletions crates/oxc_linter/src/rules/eslint/default_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,25 +65,30 @@ impl Rule for DefaultCase {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::SwitchStatement(switch) = node.kind() {
let cases = &switch.cases;
if !cases.is_empty() && !cases.iter().any(|case| case.test.is_none()) {
if let Some(last_case) = cases.last() {
let has_default_comment = ctx
.semantic()
.trivias()
.comments_range(last_case.span.start..switch.span.end)
.last()
.is_some_and(|comment| {
let raw = comment.span.source_text(ctx.semantic().source_text()).trim();
match &self.comment_pattern {
Some(comment_pattern) => comment_pattern.is_match(raw),
None => raw.eq_ignore_ascii_case("no default"),
}
});

if !has_default_comment {
ctx.diagnostic(default_case_diagnostic(switch.span));

if cases.is_empty() || cases.iter().any(|case| case.test.is_none()) {
return;
}

let Some(last_case) = cases.last() else {
return;
};

let has_default_comment = ctx
.semantic()
.trivias()
.comments_range(last_case.span.start..switch.span.end)
.last()
.is_some_and(|comment| {
let raw = comment.span.source_text(ctx.semantic().source_text()).trim();
match &self.comment_pattern {
Some(comment_pattern) => comment_pattern.is_match(raw),
None => raw.eq_ignore_ascii_case("no default"),
}
}
});

if !has_default_comment {
ctx.diagnostic(default_case_diagnostic(switch.span));
}
}
}
Expand Down
128 changes: 67 additions & 61 deletions crates/oxc_linter/src/rules/eslint/for_direction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,68 +83,74 @@ declare_oxc_lint!(

impl Rule for ForDirection {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::ForStatement(for_loop) = node.kind() {
if let Some(Expression::BinaryExpression(test)) = &for_loop.test {
let (counter, counter_position) = match (&test.left, &test.right) {
(Expression::Identifier(counter), _) => (counter, LEFT),
(_, Expression::Identifier(counter)) => (counter, RIGHT),
_ => return,
};
let test_operator = &test.operator;
let wrong_direction = match (test_operator, counter_position) {
(BinaryOperator::LessEqualThan | BinaryOperator::LessThan, RIGHT)
| (BinaryOperator::GreaterEqualThan | BinaryOperator::GreaterThan, LEFT) => {
FORWARD
}
(BinaryOperator::LessEqualThan | BinaryOperator::LessThan, LEFT)
| (BinaryOperator::GreaterEqualThan | BinaryOperator::GreaterThan, RIGHT) => {
BACKWARD
}
_ => return,
};
if let Some(update) = &for_loop.update {
let update_direction = get_update_direction(update, counter);
if update_direction == wrong_direction {
let update_span = get_update_span(update);
ctx.diagnostic_with_dangerous_fix(
for_direction_diagnostic(test.span, update_span),
|fixer| {
let mut start = 0;
let mut end = 0;
if let Expression::UpdateExpression(update) = update {
if update.span().start == update.argument.span().start {
start = update.argument.span().end;
end = update.span().end;
} else {
start = update.span().start;
end = update.argument.span().start;
}
} else if let Expression::AssignmentExpression(update) = update {
start = update.left.span().end;
end = update.right.span().start;
}
let span = Span::new(start, end);
let mut new_operator_str = "";
if let Expression::UpdateExpression(update) = update {
if let UpdateOperator::Increment = update.operator {
new_operator_str = "--";
} else if let UpdateOperator::Decrement = update.operator {
new_operator_str = "++";
}
} else if let Expression::AssignmentExpression(update) = update {
if let AssignmentOperator::Addition = update.operator {
new_operator_str = "-=";
} else if let AssignmentOperator::Subtraction = update.operator
{
new_operator_str = "+=";
}
}
fixer.replace(span, new_operator_str)
},
);
let AstKind::ForStatement(for_loop) = node.kind() else {
return;
};

let Some(Expression::BinaryExpression(test)) = &for_loop.test else {
return;
};

let (counter, counter_position) = match (&test.left, &test.right) {
(Expression::Identifier(counter), _) => (counter, LEFT),
(_, Expression::Identifier(counter)) => (counter, RIGHT),
_ => return,
};

let test_operator = &test.operator;
let wrong_direction = match (test_operator, counter_position) {
(BinaryOperator::LessEqualThan | BinaryOperator::LessThan, RIGHT)
| (BinaryOperator::GreaterEqualThan | BinaryOperator::GreaterThan, LEFT) => FORWARD,
(BinaryOperator::LessEqualThan | BinaryOperator::LessThan, LEFT)
| (BinaryOperator::GreaterEqualThan | BinaryOperator::GreaterThan, RIGHT) => BACKWARD,
_ => return,
};

let Some(update) = &for_loop.update else {
return;
};

let update_direction = get_update_direction(update, counter);
if update_direction == wrong_direction {
ctx.diagnostic_with_dangerous_fix(
for_direction_diagnostic(test.span, get_update_span(update)),
|fixer| {
let mut span = Span::new(0, 0);

let mut new_operator_str = "";

match update {
Expression::UpdateExpression(update) => {
if update.span().start == update.argument.span().start {
span.start = update.argument.span().end;
span.end = update.span().end;
} else {
span.start = update.span().start;
span.end = update.argument.span().start;
}

if let UpdateOperator::Increment = update.operator {
new_operator_str = "--";
} else if let UpdateOperator::Decrement = update.operator {
new_operator_str = "++";
}
}
Expression::AssignmentExpression(update) => {
span.start = update.left.span().end;
span.end = update.right.span().start;

if let AssignmentOperator::Addition = update.operator {
new_operator_str = "-=";
} else if let AssignmentOperator::Subtraction = update.operator {
new_operator_str = "+=";
}
}
_ => {}
}
}
}

fixer.replace(span, new_operator_str)
},
);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ impl Rule for NoAsyncPromiseExecutor {
let mut span = match expression.get_inner_expression() {
Expression::ArrowFunctionExpression(arrow) if arrow.r#async => arrow.span,
Expression::FunctionExpression(func) if func.r#async => func.span,

_ => return,
};

Expand Down
31 changes: 16 additions & 15 deletions crates/oxc_linter/src/rules/eslint/no_console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,22 @@ impl Rule for NoConsole {
}

fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::CallExpression(call_expr) = node.kind() {
if let Some(mem) = call_expr.callee.as_member_expression() {
if let Expression::Identifier(ident) = mem.object() {
if ctx.semantic().is_reference_to_global_variable(ident)
&& ident.name == "console"
&& !self
.allow
.iter()
.any(|s| mem.static_property_name().is_some_and(|f| f == s))
{
if let Some(mem) = mem.static_property_info() {
ctx.diagnostic(no_console_diagnostic(mem.0));
}
}
}
let AstKind::CallExpression(call_expr) = node.kind() else {
return;
};
let Some(mem) = call_expr.callee.as_member_expression() else {
return;
};
let Expression::Identifier(ident) = mem.object() else {
return;
};

if ctx.semantic().is_reference_to_global_variable(ident)
&& ident.name == "console"
&& !self.allow.iter().any(|s| mem.static_property_name().is_some_and(|f| f == s))
{
if let Some(mem) = mem.static_property_info() {
ctx.diagnostic(no_console_diagnostic(mem.0));
}
}
}
Expand Down
54 changes: 28 additions & 26 deletions crates/oxc_linter/src/rules/eslint/no_template_curly_in_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,36 +34,38 @@ declare_oxc_lint!(

impl Rule for NoTemplateCurlyInString {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
if let AstKind::StringLiteral(literal) = node.kind() {
let text = literal.value.as_str();
if let Some(start_index) = text.find("${") {
let mut open_braces_count = 0;
let mut end_index = None;
let AstKind::StringLiteral(literal) = node.kind() else {
return;
};

for (i, c) in text[start_index..].char_indices() {
let real_index = start_index + i;
if c == '{' {
open_braces_count += 1;
} else if c == '}' && open_braces_count > 0 {
open_braces_count -= 1;
if open_braces_count == 0 {
end_index = Some(real_index);
break;
}
let text = literal.value.as_str();
if let Some(start_index) = text.find("${") {
let mut open_braces_count = 0;
let mut end_index = None;

for (i, c) in text[start_index..].char_indices() {
let real_index = start_index + i;
if c == '{' {
open_braces_count += 1;
} else if c == '}' && open_braces_count > 0 {
open_braces_count -= 1;
if open_braces_count == 0 {
end_index = Some(real_index);
break;
}
}
}

if let Some(end_index) = end_index {
let literal_span_start = literal.span.start + 1;
let match_start = u32::try_from(start_index)
.expect("Conversion from usize to u32 failed for match_start");
let match_end = u32::try_from(end_index + 1)
.expect("Conversion from usize to u32 failed for match_end");
ctx.diagnostic(no_template_curly_in_string_diagnostic(Span::new(
literal_span_start + match_start,
literal_span_start + match_end,
)));
}
if let Some(end_index) = end_index {
let literal_span_start = literal.span.start + 1;
let match_start = u32::try_from(start_index)
.expect("Conversion from usize to u32 failed for match_start");
let match_end = u32::try_from(end_index + 1)
.expect("Conversion from usize to u32 failed for match_end");
ctx.diagnostic(no_template_curly_in_string_diagnostic(Span::new(
literal_span_start + match_start,
literal_span_start + match_end,
)));
}
}
}
Expand Down
18 changes: 9 additions & 9 deletions crates/oxc_linter/src/rules/eslint/no_this_before_super.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,15 @@ impl Rule for NoThisBeforeSuper {
impl NoThisBeforeSuper {
fn is_wanted_node(node: &AstNode, ctx: &LintContext<'_>) -> Option<bool> {
let parent = ctx.nodes().parent_node(node.id())?;
if let AstKind::MethodDefinition(mdef) = parent.kind() {
if matches!(mdef.kind, MethodDefinitionKind::Constructor) {
let parent_2 = ctx.nodes().parent_node(parent.id())?;
let parent_3 = ctx.nodes().parent_node(parent_2.id())?;
if let AstKind::Class(c) = parent_3.kind() {
let super_class = c.super_class.as_ref()?;
return Some(!matches!(super_class, Expression::NullLiteral(_)));
}
}
let method_def = parent.kind().as_method_definition()?;

if matches!(method_def.kind, MethodDefinitionKind::Constructor) {
let parent_2 = ctx.nodes().parent_node(parent.id())?;
let parent_3 = ctx.nodes().parent_node(parent_2.id())?;

let class = parent_3.kind().as_class()?;
let super_class = class.super_class.as_ref()?;
return Some(!matches!(super_class, Expression::NullLiteral(_)));
}

Some(false)
Expand Down
7 changes: 2 additions & 5 deletions crates/oxc_linter/src/rules/eslint/no_unused_vars/allowed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,8 @@ impl NoUnusedVars {
// find FormalParameters. Should be the next parent of param, but this
// is safer.
let Some((params, params_id)) = symbol.iter_parents().find_map(|p| {
if let AstKind::FormalParameters(params) = p.kind() {
Some((params, p.id()))
} else {
None
}
let params = p.kind().as_formal_parameters()?;
Some((params, p.id()))
}) else {
debug_assert!(false, "FormalParameter should always have a parent FormalParameters");
return false;
Expand Down
Loading

0 comments on commit 2a43fa4

Please sign in to comment.