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

Commit

Permalink
Support React global
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaReiser committed Nov 9, 2022
1 parent 556ccff commit 9927363
Show file tree
Hide file tree
Showing 20 changed files with 281 additions and 378 deletions.
5 changes: 3 additions & 2 deletions crates/rome_js_analyze/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ mod tests {
String::from_utf8(buffer).unwrap()
}

const SOURCE: &str = r#"<img src="image.png" aria-label="alt text" />
"#;
const SOURCE: &str = r#"React.createElement("div", { tabIndex: '1' })
React.createElement("div", { tabIndex: 1 })
React.createElement("div", { tabIndex: +1 })"#;

let parsed = parse(SOURCE, FileId::zero(), SourceType::jsx());

Expand Down
51 changes: 29 additions & 22 deletions crates/rome_js_analyze/src/react.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,20 +260,24 @@ pub(crate) fn is_react_call_api(
let object = node.object().ok()?;
let identifier = object.as_js_identifier_expression()?.name().ok()?;

return model.declaration(&identifier).and_then(|binding| {
let binding_identifier = JsIdentifierBinding::cast_ref(binding.syntax())?;

if let Some(js_import) = binding_identifier
.syntax()
.ancestors()
.find_map(|ancestor| JsImport::cast_ref(&ancestor))
{
js_import.source_is("react").ok()
} else {
Some(false)
match model.declaration(&identifier) {
Some(binding) => {
let binding_identifier = JsIdentifierBinding::cast_ref(binding.syntax())?;

if let Some(js_import) = binding_identifier
.syntax()
.ancestors()
.find_map(|ancestor| JsImport::cast_ref(&ancestor))
{
js_import.source_is("react").ok()?
} else {
false
}
}
});
None => identifier.has_name("React"),
}
}

JsAnyExpression::JsIdentifierExpression(identifier) => {
let name = identifier.name().ok()?;

Expand Down Expand Up @@ -304,17 +308,20 @@ pub(crate) fn jsx_member_name_is_react_fragment(
return Some(false);
}

model.declaration(object).and_then(|declaration| {
if let Some(js_import) = declaration
.syntax()
.ancestors()
.find_map(|ancestor| JsImport::cast_ref(&ancestor))
{
js_import.source_is("react").ok()
} else {
Some(false)
match model.declaration(object) {
Some(declaration) => {
if let Some(js_import) = declaration
.syntax()
.ancestors()
.find_map(|ancestor| JsImport::cast_ref(&ancestor))
{
js_import.source_is("react").ok()
} else {
Some(false)
}
}
})
None => Some(object.value_token().ok()?.text_trimmed() == "React"),
}
}

/// Checks if the node `JsxReferenceIdentifier` is a react fragment.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from "react";

React.createElement("div", { tabIndex: '1' })
React.createElement("div", { tabIndex: 1 })
React.createElement("div", { tabIndex: +1 })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ expression: reactCreateElementInvalid.js
---
# Input
```js
import React from "react";

React.createElement("div", { tabIndex: '1' })
React.createElement("div", { tabIndex: 1 })
React.createElement("div", { tabIndex: +1 })
Expand All @@ -15,65 +13,63 @@ React.createElement("div", { tabIndex: +01 })

# Diagnostics
```
reactCreateElementInvalid.js:3:40 lint/a11y/noPositiveTabindex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
reactCreateElementInvalid.js:1:40 lint/a11y/noPositiveTabindex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Avoid positive values for the tabIndex prop.
1 │ import React from "react";
2 │
> 3 │ React.createElement("div", { tabIndex: '1' })
> 1 │ React.createElement("div", { tabIndex: '1' })
│ ^^^
4 │ React.createElement("div", { tabIndex: 1 })
5 │ React.createElement("div", { tabIndex: +1 })
2 │ React.createElement("div", { tabIndex: 1 })
3 │ React.createElement("div", { tabIndex: +1 })
i Elements with a positive tabIndex override natural page content order. This causes elements without a positive tab index to come last when navigating using a keyboard.
```

```
reactCreateElementInvalid.js:4:40 lint/a11y/noPositiveTabindex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
reactCreateElementInvalid.js:2:40 lint/a11y/noPositiveTabindex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Avoid positive values for the tabIndex prop.
3 │ React.createElement("div", { tabIndex: '1' })
> 4 │ React.createElement("div", { tabIndex: 1 })
1 │ React.createElement("div", { tabIndex: '1' })
> 2 │ React.createElement("div", { tabIndex: 1 })
│ ^
5 │ React.createElement("div", { tabIndex: +1 })
6 │ React.createElement("div", { tabIndex: +01 })
3 │ React.createElement("div", { tabIndex: +1 })
4 │ React.createElement("div", { tabIndex: +01 })
i Elements with a positive tabIndex override natural page content order. This causes elements without a positive tab index to come last when navigating using a keyboard.
```

```
reactCreateElementInvalid.js:5:40 lint/a11y/noPositiveTabindex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
reactCreateElementInvalid.js:3:40 lint/a11y/noPositiveTabindex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Avoid positive values for the tabIndex prop.
3 │ React.createElement("div", { tabIndex: '1' })
4 │ React.createElement("div", { tabIndex: 1 })
> 5 │ React.createElement("div", { tabIndex: +1 })
1 │ React.createElement("div", { tabIndex: '1' })
2 │ React.createElement("div", { tabIndex: 1 })
> 3 │ React.createElement("div", { tabIndex: +1 })
│ ^^
6 │ React.createElement("div", { tabIndex: +01 })
7
4 │ React.createElement("div", { tabIndex: +01 })
5
i Elements with a positive tabIndex override natural page content order. This causes elements without a positive tab index to come last when navigating using a keyboard.
```

```
reactCreateElementInvalid.js:6:40 lint/a11y/noPositiveTabindex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
reactCreateElementInvalid.js:4:40 lint/a11y/noPositiveTabindex ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Avoid positive values for the tabIndex prop.
4 │ React.createElement("div", { tabIndex: 1 })
5 │ React.createElement("div", { tabIndex: +1 })
> 6 │ React.createElement("div", { tabIndex: +01 })
2 │ React.createElement("div", { tabIndex: 1 })
3 │ React.createElement("div", { tabIndex: +1 })
> 4 │ React.createElement("div", { tabIndex: +01 })
│ ^^^
7
5
i Elements with a positive tabIndex override natural page content order. This causes elements without a positive tab index to come last when navigating using a keyboard.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from "react";

// invalid
React.createElement('button');
React.createElement('button', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ expression: inObject.js
---
# Input
```js
import React from "react";

// invalid
React.createElement('button');
React.createElement('button', {
Expand All @@ -25,15 +23,15 @@ React.createElement('button', {

# Diagnostics
```
inObject.js:4:21 lint/a11y/useButtonType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
inObject.js:2:21 lint/a11y/useButtonType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Provide an explicit type prop for the button element.
3 │ // invalid
> 4 │ React.createElement('button');
1 │ // invalid
> 2 │ React.createElement('button');
│ ^^^^^^^^
5 │ React.createElement('button', {
6 │ "type": "bar"
3 │ React.createElement('button', {
4 │ "type": "bar"
i The default type of a button is submit, which causes the submission of a form when placed inside a `form` element. This is likely not the behaviour that you want inside a React application.
Expand All @@ -43,16 +41,16 @@ inObject.js:4:21 lint/a11y/useButtonType ━━━━━━━━━━━━━
```

```
inObject.js:6:13 lint/a11y/useButtonType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
inObject.js:4:13 lint/a11y/useButtonType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Provide a valid type prop for the button element.
4 │ React.createElement('button');
5 │ React.createElement('button', {
> 6 │ "type": "bar"
2 │ React.createElement('button');
3 │ React.createElement('button', {
> 4 │ "type": "bar"
│ ^^^^^
7 │ });
8 │ React.createElement('button', {
5 │ });
6 │ React.createElement('button', {
i The default type of a button is submit, which causes the submission of a form when placed inside a `form` element. This is likely not the behaviour that you want inside a React application.
Expand All @@ -62,19 +60,19 @@ inObject.js:6:13 lint/a11y/useButtonType ━━━━━━━━━━━━━
```

```
inObject.js:8:31 lint/a11y/useButtonType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
inObject.js:6:31 lint/a11y/useButtonType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Provide a valid type prop for the button element.
6 │ "type": "bar"
7 │ });
> 8 │ React.createElement('button', {
4 │ "type": "bar"
5 │ });
> 6 │ React.createElement('button', {
│ ^
> 9 │ "style": "background: red"
> 10 │ });
> 7 │ "style": "background: red"
> 8 │ });
│ ^
11 │ React.createElement('button', {});
12
9 │ React.createElement('button', {});
10
i The default type of a button is submit, which causes the submission of a form when placed inside a `form` element. This is likely not the behaviour that you want inside a React application.
Expand All @@ -84,16 +82,16 @@ inObject.js:8:31 lint/a11y/useButtonType ━━━━━━━━━━━━━
```

```
inObject.js:11:31 lint/a11y/useButtonType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
inObject.js:9:31 lint/a11y/useButtonType ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Provide a valid type prop for the button element.
9 │ "style": "background: red"
10 │ });
> 11 │ React.createElement('button', {});
7 │ "style": "background: red"
8 │ });
> 9 │ React.createElement('button', {});
│ ^^
12
13 │ // valid
10
11 │ // valid
i The default type of a button is submit, which causes the submission of a form when placed inside a `form` element. This is likely not the behaviour that you want inside a React application.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React, {Children, cloneElement} from "react";

// invalid
something.forEach((Element, index) => {
<Component key={index} >foo</Component>
Expand Down
Loading

0 comments on commit 9927363

Please sign in to comment.