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

Commit

Permalink
chore: better auto focus code action
Browse files Browse the repository at this point in the history
  • Loading branch information
ematipico committed Oct 21, 2022
1 parent 83cd5ee commit 6f74d06
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 6 deletions.
35 changes: 34 additions & 1 deletion crates/rome_js_analyze/src/analyzers/nursery/no_auto_focus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use crate::JsRuleAction;
use rome_analyze::{context::RuleContext, declare_rule, ActionCategory, Ast, Rule, RuleDiagnostic};
use rome_console::markup;
use rome_diagnostics::Applicability;
use rome_js_syntax::{JsxAttribute, JsxOpeningElement, JsxSelfClosingElement};
use rome_js_syntax::{
JsSyntaxToken, JsxAnyElementName, JsxAttribute, JsxOpeningElement, JsxSelfClosingElement,
};
use rome_rowan::{declare_node_union, AstNode, BatchMutationExt};

declare_rule! {
Expand Down Expand Up @@ -57,6 +59,22 @@ declare_node_union! {
pub(crate) JsxAnyElement = JsxOpeningElement | JsxSelfClosingElement
}

impl JsxAnyElement {
fn name_value_token(&self) -> Option<JsSyntaxToken> {
let any_name = match self {
JsxAnyElement::JsxOpeningElement(element) => element.name().ok()?,
JsxAnyElement::JsxSelfClosingElement(element) => element.name().ok()?,
};

match any_name {
JsxAnyElementName::JsxMemberName(member) => member.member().ok()?.value_token().ok(),
JsxAnyElementName::JsxName(name) => name.value_token().ok(),
JsxAnyElementName::JsxNamespaceName(name) => name.name().ok()?.value_token().ok(),
JsxAnyElementName::JsxReferenceIdentifier(name) => name.value_token().ok(),
}
}
}

impl Rule for NoAutoFocus {
type Query = Ast<JsxAnyElement>;
type State = JsxAttribute;
Expand Down Expand Up @@ -89,6 +107,21 @@ 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(JsxAnyElement::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);
}
}
}

mutation.remove_node(attr.clone());

Expand Down
2 changes: 1 addition & 1 deletion crates/rome_js_analyze/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ mod tests {
#[ignore]
#[test]
fn quick_test() {
const SOURCE: &str = r#"let spread; let a = <div {...spread} onClick={() => {}} />; a;
const SOURCE: &str = r#"<input·/*comment*/·autoFocus={"false"}·/>
"#;

let parsed = parse(SOURCE, FileId::zero(), SourceType::jsx());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@
<input autoFocus="true" />
<input autoFocus={undefined} />
<input autoFocus={"false"} />
<input autoFocus={"false"} /*comment*/ />
<input /*comment*/ autoFocus={"false"} />
<input autoFocus={"false" /*comment*/} />
<input /*comment*/ autoFocus={"false"} /*comment*/ />
</>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ expression: noAutoFocusInvalid.jsx
<input autoFocus="true" />
<input autoFocus={undefined} />
<input autoFocus={"false"} />
<input autoFocus={"false"} /*comment*/ />
<input /*comment*/ autoFocus={"false"} />
<input autoFocus={"false" /*comment*/} />
<input /*comment*/ autoFocus={"false"} /*comment*/ />
</>
```

Expand Down Expand Up @@ -80,7 +84,7 @@ noAutoFocusInvalid.jsx:5:12 lint/nursery/noAutofocus FIXABLE ━━━━━
> 5 │ <input autoFocus={undefined} />
│ ^^^^^^^^^^^^^^^^^^^^^
6 │ <input autoFocus={"false"} />
7 │ </>
7 │ <input autoFocus={"false"} /*comment*/ />
i Suggested fix: Remove the autoFocus attribute.
Expand All @@ -98,7 +102,8 @@ noAutoFocusInvalid.jsx:6:12 lint/nursery/noAutofocus FIXABLE ━━━━━
5 │ <input autoFocus={undefined} />
> 6 │ <input autoFocus={"false"} />
│ ^^^^^^^^^^^^^^^^^^^
7 │ </>
7 │ <input autoFocus={"false"} /*comment*/ />
8 │ <input /*comment*/ autoFocus={"false"} />
i Suggested fix: Remove the autoFocus attribute.
Expand All @@ -107,4 +112,88 @@ noAutoFocusInvalid.jsx:6:12 lint/nursery/noAutofocus FIXABLE ━━━━━
```

```
noAutoFocusInvalid.jsx:7:12 lint/nursery/noAutofocus FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Avoid the autoFocus attribute.
5 │ <input autoFocus={undefined} />
6 │ <input autoFocus={"false"} />
> 7 │ <input autoFocus={"false"} /*comment*/ />
│ ^^^^^^^^^^^^^^^^^^^
8 │ <input /*comment*/ autoFocus={"false"} />
9 │ <input autoFocus={"false" /*comment*/} />
i Suggested fix: Remove the autoFocus attribute.
5 5 │ <input autoFocus={undefined} />
6 6 │ <input autoFocus={"false"} />
7 │ - ····<input·autoFocus={"false"}·/*comment*/·/>
7 │ + ····<input··/*comment*/·/>
8 8 │ <input /*comment*/ autoFocus={"false"} />
9 9 │ <input autoFocus={"false" /*comment*/} />
```

```
noAutoFocusInvalid.jsx:8:24 lint/nursery/noAutofocus FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Avoid the autoFocus attribute.
6 │ <input autoFocus={"false"} />
7 │ <input autoFocus={"false"} /*comment*/ />
> 8 │ <input /*comment*/ autoFocus={"false"} />
│ ^^^^^^^^^^^^^^^^^^^
9 │ <input autoFocus={"false" /*comment*/} />
10 │ <input /*comment*/ autoFocus={"false"} /*comment*/ />
i Suggested fix: Remove the autoFocus attribute.
8 │ ····<input·/*comment*/·autoFocus={"false"}·/>
│ --------------------
```

```
noAutoFocusInvalid.jsx:9:12 lint/nursery/noAutofocus FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Avoid the autoFocus attribute.
7 │ <input autoFocus={"false"} /*comment*/ />
8 │ <input /*comment*/ autoFocus={"false"} />
> 9 │ <input autoFocus={"false" /*comment*/} />
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10 │ <input /*comment*/ autoFocus={"false"} /*comment*/ />
11 │ </>
i Suggested fix: Remove the autoFocus attribute.
9 │ ····<input·autoFocus={"false"·/*comment*/}·/>
│ --------------------------------
```

```
noAutoFocusInvalid.jsx:10:24 lint/nursery/noAutofocus FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Avoid the autoFocus attribute.
8 │ <input /*comment*/ autoFocus={"false"} />
9 │ <input autoFocus={"false" /*comment*/} />
> 10 │ <input /*comment*/ autoFocus={"false"} /*comment*/ />
│ ^^^^^^^^^^^^^^^^^^^
11 │ </>
i Suggested fix: Remove the autoFocus attribute.
8 8 │ <input /*comment*/ autoFocus={"false"} />
9 9 │ <input autoFocus={"false" /*comment*/} />
10 │ - ····<input·/*comment*/·autoFocus={"false"}·/*comment*/·/>
10 │ + ····<input·/*comment*/··/*comment*/·/>
11 11 │ </>
```


16 changes: 14 additions & 2 deletions crates/rome_rowan/src/ast/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ where

/// Push a change to replace the "prev_node" with "next_node".
///
/// Changes to take effect must be commited.
/// Changes to take effect must be committed.
pub fn replace_node_discard_trivia<T>(&mut self, prev_node: T, next_node: T)
where
T: AstNode<Language = L>,
Expand All @@ -201,9 +201,21 @@ where
next_node.into_syntax().into(),
)
}

/// Push a change to replace the "prev_token" with "next_token".
///
/// Changes to take effect must be committed.
pub fn replace_token_discard_trivia(
&mut self,
prev_token: SyntaxToken<L>,
next_token: SyntaxToken<L>,
) {
self.replace_element_discard_trivia(prev_token.into(), next_token.into())
}

/// Push a change to replace the "prev_element" with "next_element".
///
/// Changes to take effect must be commited.
/// Changes to take effect must be committed.
pub fn replace_element_discard_trivia(
&mut self,
prev_element: SyntaxElement<L>,
Expand Down

0 comments on commit 6f74d06

Please sign in to comment.