Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

Commit

Permalink
feat(rome_js_analyze): useIsArray
Browse files Browse the repository at this point in the history
  • Loading branch information
Conaclos committed Jul 18, 2023
1 parent ec54d1d commit 0144a8e
Show file tree
Hide file tree
Showing 58 changed files with 1,057 additions and 438 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ if no error diagnostics are emitted.

This rule disallows useless `export {}`.

- Add [`useIsArray`](https://docs.rome.tools/lint/rules/useIsArray/)

This rule proposes using `Array.isArray()` instead of `instanceof Array`.

#### Other changes

- Add new TypeScript globals (`AsyncDisposable`, `Awaited`, `DecoratorContext`, and others) [4643](https://github.com/rome/tools/issues/4643).
Expand Down
1 change: 1 addition & 0 deletions crates/rome_diagnostics_categories/src/categories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ define_categories! {
"lint/nursery/useGroupedTypeImport": "https://docs.rome.tools/lint/rules/useGroupedTypeImport",
"lint/nursery/useHeadingContent": "https://docs.rome.tools/lint/rules/useHeadingContent",
"lint/nursery/useHookAtTopLevel": "https://docs.rome.tools/lint/rules/useHookAtTopLevel",
"lint/nursery/useIsArray": "https://docs.rome.tools/lint/rules/useIsArray",
"lint/nursery/useIsNan": "https://docs.rome.tools/lint/rules/useIsNan",
"lint/nursery/useLiteralEnumMembers": "https://docs.rome.tools/lint/rules/useLiteralEnumMembers",
"lint/nursery/useLiteralKeys": "https://docs.rome.tools/lint/rules/useLiteralKeys",
Expand Down
29 changes: 12 additions & 17 deletions crates/rome_formatter/src/comments/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,10 @@ mod tests {
JsSyntaxKind, JsSyntaxNode, JsUnaryExpression,
};
use rome_rowan::syntax::SyntaxElementKey;
use rome_rowan::{AstNode, BatchMutation, SyntaxNode, SyntaxTriviaPieceComments, TextRange};
use rome_rowan::{
chain_trivia_pieces, AstNode, BatchMutation, SyntaxNode, SyntaxTriviaPieceComments,
TextRange,
};
use std::cell::RefCell;

#[test]
Expand Down Expand Up @@ -874,22 +877,14 @@ b;"#;

let identifier_token = reference_identifier.value_token().unwrap();
let new_identifier_token = identifier_token
.with_leading_trivia_pieces(
l_paren
.leading_trivia()
.pieces()
.chain(l_paren.trailing_trivia().pieces())
.chain(identifier_token.leading_trivia().pieces())
.collect::<Vec<_>>(),
)
.with_trailing_trivia_pieces(
identifier_token
.trailing_trivia()
.pieces()
.chain(r_paren.leading_trivia().pieces())
.chain(r_paren.trailing_trivia().pieces())
.collect::<Vec<_>>(),
);
.prepend_trivia_pieces(chain_trivia_pieces(
l_paren.leading_trivia().pieces(),
l_paren.trailing_trivia().pieces(),
))
.append_trivia_pieces(chain_trivia_pieces(
r_paren.leading_trivia().pieces(),
r_paren.trailing_trivia().pieces(),
));

let new_reference_identifier = reference_identifier.with_value_token(new_identifier_token);

Expand Down
22 changes: 5 additions & 17 deletions crates/rome_js_analyze/src/analyzers/a11y/no_auto_focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ impl Rule for NoAutoFocus {
if node.is_custom_component() {
return None;
}

node.find_attribute_by_name("autoFocus")
}

Expand All @@ -88,24 +87,13 @@ impl Rule for NoAutoFocus {

fn action(ctx: &RuleContext<Self>, attr: &Self::State) -> Option<JsRuleAction> {
let mut mutation = ctx.root().begin();
let trailing_trivia = attr.syntax().last_trailing_trivia();
if let Some(trailing_trivia) = trailing_trivia {
if trailing_trivia.pieces().any(|piece| piece.is_comments()) {
let element = attr.syntax().ancestors().find_map(AnyJsxElement::cast);
if let Some(name) = element.and_then(|e| e.name_value_token()) {
let trivia_pieces = name
.trailing_trivia()
.pieces()
.chain(trailing_trivia.pieces())
.collect::<Vec<_>>();
let new_name = name.with_trailing_trivia_pieces(trivia_pieces);
mutation.replace_token_discard_trivia(name, new_name);
}
}
if attr.syntax().has_trailing_comments() {
let prev_token = attr.syntax().first_token()?.prev_token()?;
let new_token =
prev_token.append_trivia_pieces(attr.syntax().last_trailing_trivia()?.pieces());
mutation.replace_token_discard_trivia(prev_token, new_token);
}

mutation.remove_node(attr.clone());

Some(JsRuleAction {
category: ActionCategory::QuickFix,
applicability: Applicability::MaybeIncorrect,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rome_js_syntax::{
};

use crate::JsRuleAction;
use rome_rowan::{chain_trivia_pieces, declare_node_union, AstNode, BatchMutationExt};
use rome_rowan::{declare_node_union, AstNode, BatchMutationExt};

declare_rule! {
/// Disallow unnecessary labels.
Expand Down Expand Up @@ -111,21 +111,12 @@ impl Rule for NoUselessLabel {
// We want to remove trailing spaces and keep all comments that follows `stmt_token`
// e.g. `break /* a comment */ ` to `break /* a comment */`.
// This requires to traverse the trailing trivia in reverse order.
let mut stmt_token_trailing_trivia = stmt_token
.trailing_trivia()
.pieces()
.rev()
.skip_while(|p| p.is_newline() || p.is_whitespace())
.collect::<Vec<_>>();
// We restore initial trivia order
stmt_token_trailing_trivia.reverse();
// We keep trailing trivia of `label_stmt`
// e.g. `break label // a comment` -> `break // a comment`
// We do not keep leading trivia of `label_stmt` because we assume that they are associated to the label.
let new_stmt_token = stmt_token.with_trailing_trivia_pieces(chain_trivia_pieces(
stmt_token_trailing_trivia.into_iter(),
label_token.trailing_trivia().pieces(),
));
let new_stmt_token = stmt_token
.trim_trailing_trivia()
.append_trivia_pieces(label_token.trailing_trivia().pieces());
let mut mutation = ctx.root().begin();
mutation.remove_token(label_token);
mutation.replace_token_discard_trivia(stmt_token, new_stmt_token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rome_js_syntax::{
JsExportNamedFromSpecifier, JsExportNamedSpecifier, JsNamedImportSpecifier,
JsObjectBindingPatternProperty, JsSyntaxElement,
};
use rome_rowan::{declare_node_union, AstNode, BatchMutationExt};
use rome_rowan::{declare_node_union, trim_leading_trivia_pieces, AstNode, BatchMutationExt};

use crate::JsRuleAction;

Expand Down Expand Up @@ -126,18 +126,9 @@ impl Rule for NoUselessRename {
let last_token = x.source_name().ok()?.value().ok()?;
let export_as = x.export_as()?;
let export_as_last_token = export_as.exported_name().ok()?.value().ok()?;
let replacing_token = last_token.with_trailing_trivia_pieces(
last_token
.trailing_trivia()
.pieces()
.chain(
export_as_last_token
.trailing_trivia()
.pieces()
.skip_while(|p| p.is_newline() || p.is_whitespace()),
)
.collect::<Vec<_>>(),
);
let replacing_token = last_token.append_trivia_pieces(trim_leading_trivia_pieces(
export_as_last_token.trailing_trivia().pieces(),
));
mutation.remove_node(export_as);
mutation.replace_token_discard_trivia(last_token, replacing_token);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,9 @@ impl Rule for NoUselessSwitchCase {
let new_default_clause = default_clause
.to_owned()
.with_consequent(consequent)
.with_colon_token(
default_clause_colon_token.with_trailing_trivia_pieces(
default_clause_colon_token
.trailing_trivia()
.pieces()
.chain(useless_case.colon_token().ok()?.trailing_trivia().pieces())
.collect::<Vec<_>>(),
),
);
.with_colon_token(default_clause_colon_token.append_trivia_pieces(
useless_case.colon_token().ok()?.trailing_trivia().pieces(),
));
mutation.remove_node(default_clause.to_owned());
mutation.replace_element(
SyntaxElement::Node(useless_case.syntax().to_owned()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,49 +144,32 @@ impl Rule for UseOptionalChain {
.unwrap_or_else(|| expression.clone());
let next_expression = match next_expression {
AnyJsExpression::JsCallExpression(call_expression) => {
let mut call_expression_builder = make::js_call_expression(
call_expression.callee().ok()?,
call_expression.arguments().ok()?,
)
.with_optional_chain_token(make::token(T![?.]));
if let Some(type_arguments) = call_expression.type_arguments() {
call_expression_builder =
call_expression_builder.with_type_arguments(type_arguments);
}
let call_expression = call_expression_builder.build();
AnyJsExpression::from(call_expression)
let optional_chain_token = call_expression
.optional_chain_token()
.unwrap_or_else(|| make::token(T![?.]));
call_expression
.with_optional_chain_token(Some(optional_chain_token))
.into()
}
AnyJsExpression::JsStaticMemberExpression(member_expression) => {
let operator_token = member_expression.operator_token().ok()?;
let operator = member_expression.operator_token().ok()?;
AnyJsExpression::from(make::js_static_member_expression(
member_expression.object().ok()?,
make::token(T![?.])
.with_leading_trivia_pieces(
operator_token.leading_trivia().pieces(),
)
.with_leading_trivia_pieces(operator.leading_trivia().pieces())
.with_trailing_trivia_pieces(
operator_token.trailing_trivia().pieces(),
operator.trailing_trivia().pieces(),
),
member_expression.member().ok()?,
))
}
AnyJsExpression::JsComputedMemberExpression(member_expression) => {
let operator_token = match member_expression.optional_chain_token() {
Some(token) => make::token(T![?.])
.with_leading_trivia_pieces(token.leading_trivia().pieces())
.with_trailing_trivia_pieces(token.trailing_trivia().pieces()),
None => make::token(T![?.]),
};
AnyJsExpression::from(
make::js_computed_member_expression(
member_expression.object().ok()?,
member_expression.l_brack_token().ok()?,
member_expression.member().ok()?,
member_expression.r_brack_token().ok()?,
)
.with_optional_chain_token(operator_token)
.build(),
)
let optional_chain_token = member_expression
.optional_chain_token()
.unwrap_or_else(|| make::token(T![?.]));
member_expression
.with_optional_chain_token(Some(optional_chain_token))
.into()
}
_ => return None,
};
Expand Down Expand Up @@ -746,7 +729,6 @@ impl LogicalOrLikeChain {

fn trim_trailing_space(node: AnyJsExpression) -> Option<AnyJsExpression> {
let Some(last_token_of_left_syntax) = node.syntax().last_token() else { return Some(node) };
let next_token_of_left_syntax =
last_token_of_left_syntax.with_trailing_trivia(std::iter::empty());
let next_token_of_left_syntax = last_token_of_left_syntax.with_trailing_trivia([]);
node.replace_token_discard_trivia(last_token_of_left_syntax, next_token_of_left_syntax)
}
18 changes: 5 additions & 13 deletions crates/rome_js_analyze/src/analyzers/correctness/no_new_symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use rome_console::markup;
use rome_diagnostics::Applicability;
use rome_js_factory::make;
use rome_js_syntax::{AnyJsExpression, JsCallExpression, JsNewExpression, JsNewExpressionFields};
use rome_rowan::{AstNode, BatchMutationExt};
use rome_rowan::{chain_trivia_pieces, AstNode, BatchMutationExt};

declare_rule! {
/// Disallow `new` operators with the `Symbol` object
Expand Down Expand Up @@ -102,18 +102,10 @@ fn convert_new_expression_to_call_expression(expr: &JsNewExpression) -> Option<J
let arguments = arguments?;

if new_token.has_leading_comments() || new_token.has_trailing_comments() {
let symbol = callee.syntax().first_token()?;

let leading_trivia = new_token
.leading_trivia()
.pieces()
.chain(new_token.trailing_trivia().pieces())
.chain(symbol.leading_trivia().pieces())
.collect::<Vec<_>>();

let symbol = symbol.with_leading_trivia_pieces(leading_trivia);

callee = make::js_identifier_expression(make::js_reference_identifier(symbol)).into();
callee = callee.prepend_trivia_pieces(chain_trivia_pieces(
new_token.leading_trivia().pieces(),
new_token.trailing_trivia().pieces(),
))?;
}

Some(make::js_call_expression(callee, arguments).build())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::iter;

use rome_analyze::context::RuleContext;
use rome_analyze::{declare_rule, ActionCategory, Ast, Rule, RuleDiagnostic};
use rome_console::markup;
Expand Down Expand Up @@ -125,14 +123,15 @@ impl Rule for NoSwitchDeclarations {
let clause_token = switch_clause.clause_token().ok()?;
let colon_token = switch_clause.colon_token().ok()?;
let consequent = switch_clause.consequent();
let new_colon_token = colon_token.with_trailing_trivia(iter::empty());
let new_colon_token = colon_token.with_trailing_trivia([]);
let new_consequent = make::js_statement_list(Some(AnyJsStatement::JsBlockStatement(
make::js_block_statement(
make::token(T!['{'])
.with_leading_trivia(Some((TriviaPieceKind::Whitespace, " ")))
.with_trailing_trivia_pieces(colon_token.trailing_trivia().pieces()),
consequent.to_owned(),
make::token(T!['}']).with_leading_trivia_pieces(clause_token.indentation_trivia()),
make::token(T!['}'])
.with_leading_trivia_pieces(clause_token.indentation_trivia_pieces()),
),
)));
let mut mutation = ctx.root().begin();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use rome_analyze::{context::RuleContext, declare_rule, ActionCategory, Ast, Rule
use rome_console::markup;
use rome_diagnostics::Applicability;
use rome_js_syntax::{JsContinueStatement, JsLabeledStatement, JsSyntaxKind, JsSyntaxNode};
use rome_rowan::{chain_trivia_pieces, AstNode, BatchMutationExt};
use rome_rowan::{AstNode, BatchMutationExt};

use crate::{utils, JsRuleAction};

Expand Down Expand Up @@ -101,23 +101,7 @@ impl Rule for NoUnnecessaryContinue {

fn action(ctx: &RuleContext<Self>, _: &Self::State) -> Option<JsRuleAction> {
let node = ctx.query();
let continue_token = node.continue_token().ok()?;
let mut mutation = ctx.root().begin();
if continue_token.has_leading_comments() {
let prev_token = continue_token.prev_token()?;
let leading_trivia = continue_token.leading_trivia().pieces();
let skip_count = leading_trivia.len()
- leading_trivia
.rev()
.position(|x| x.is_comments())
.map(|pos| pos + 1)
.unwrap_or(0);
let new_token = prev_token.with_trailing_trivia_pieces(chain_trivia_pieces(
prev_token.trailing_trivia().pieces(),
continue_token.leading_trivia().pieces().skip(skip_count),
));
mutation.replace_token(prev_token, new_token);
}
utils::remove_statement(&mut mutation, node)?;
Some(JsRuleAction {
category: ActionCategory::QuickFix,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::iter;

use crate::JsRuleAction;
use rome_analyze::{context::RuleContext, declare_rule, ActionCategory, Ast, Rule, RuleDiagnostic};
use rome_console::markup;
Expand Down Expand Up @@ -156,8 +154,7 @@ impl Rule for UseGroupedTypeImport {
let new_node = node
.clone()
.with_type_token(Some(
make::token(T![type])
.with_trailing_trivia(iter::once((TriviaPieceKind::Whitespace, " "))),
make::token(T![type]).with_trailing_trivia([(TriviaPieceKind::Whitespace, " ")]),
))
.with_named_import(AnyJsNamedImport::JsNamedImportSpecifiers(
named_import_specifiers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ impl Rule for NoImplicitBoolean {
let last_token_of_name_syntax = name_syntax.last_token()?;
// drop the trailing trivia of name_syntax, at CST level it means
// clean the trailing trivia of last token of name_syntax
let next_last_token_of_name_syntax =
last_token_of_name_syntax.with_trailing_trivia(std::iter::empty());
let next_last_token_of_name_syntax = last_token_of_name_syntax.with_trailing_trivia([]);

let next_name = name.replace_token_discard_trivia(
last_token_of_name_syntax,
Expand Down
Loading

0 comments on commit 0144a8e

Please sign in to comment.