This repository has been archived by the owner on Aug 31, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 656
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(rome_js_analyze): noEmptyPattern (#2731)
- Loading branch information
1 parent
cf4189c
commit bcaf744
Showing
7 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
use rome_analyze::{context::RuleContext, declare_rule, Rule, RuleCategory, RuleDiagnostic}; | ||
use rome_console::markup; | ||
use rome_js_syntax::{JsArrayBindingPattern, JsObjectBindingPattern}; | ||
use rome_rowan::{declare_node_union, AstNode, AstSeparatedList}; | ||
|
||
declare_rule! { | ||
/// Disallows empty destructuring patterns. | ||
/// ## Examples | ||
/// | ||
/// ### Valid | ||
/// The following cases are valid because they create new bindings. | ||
/// | ||
/// ```js | ||
/// var {a = {}} = foo; | ||
/// var {a, b = {}} = foo; | ||
/// var {a = []} = foo; | ||
/// function foo({a = {}}) {} | ||
/// function foo({a = []}) {} | ||
/// var [a] = foo; | ||
/// ``` | ||
/// | ||
/// ### Invalid | ||
/// | ||
/// ```js,expect_diagnostic | ||
/// var {} = foo; | ||
/// ``` | ||
/// | ||
/// ```js,expect_diagnostic | ||
/// var {a: {}} = foo; | ||
/// ``` | ||
/// | ||
/// ```js,expect_diagnostic | ||
/// function foo({}) {} | ||
/// ``` | ||
/// | ||
pub(crate) NoEmptyPattern = "noEmptyPattern" | ||
} | ||
|
||
impl Rule for NoEmptyPattern { | ||
const CATEGORY: RuleCategory = RuleCategory::Lint; | ||
|
||
type Query = JsAnyBindPatternLike; | ||
type State = (); | ||
|
||
fn run(ctx: &RuleContext<Self>) -> Option<Self::State> { | ||
match ctx.query() { | ||
JsAnyBindPatternLike::JsArrayBindingPattern(array) => { | ||
if array.elements().len() == 0 { | ||
Some(()) | ||
} else { | ||
None | ||
} | ||
} | ||
JsAnyBindPatternLike::JsObjectBindingPattern(object) => { | ||
if object.properties().len() == 0 { | ||
Some(()) | ||
} else { | ||
None | ||
} | ||
} | ||
} | ||
} | ||
|
||
fn diagnostic(ctx: &RuleContext<Self>, _: &Self::State) -> Option<RuleDiagnostic> { | ||
let node = ctx.query(); | ||
let node_type = match node { | ||
JsAnyBindPatternLike::JsArrayBindingPattern(_) => "array", | ||
JsAnyBindPatternLike::JsObjectBindingPattern(_) => "object", | ||
}; | ||
|
||
Some(RuleDiagnostic::warning( | ||
node.range(), | ||
markup! { | ||
"Unexpected empty "{node_type}" pattern." | ||
}, | ||
)) | ||
} | ||
} | ||
|
||
declare_node_union! { | ||
/// enum of `JsObjectBindingPattern` and `JsArrayBindingPattern` | ||
pub(crate) JsAnyBindPatternLike = JsArrayBindingPattern | JsObjectBindingPattern | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// valid | ||
var {a = {}} = foo; | ||
var {a, b = {}} = foo; | ||
var {a = []} = foo; | ||
function foo({a = {}}) {} | ||
function foo({a = []}) {} | ||
var [a] = foo; | ||
// invalid | ||
var {} = foo; | ||
var [] = foo; | ||
var {a: {}} = foo; | ||
var {a, b: {}} = foo; | ||
var {a: []} = foo; | ||
function foo({}) {}; | ||
function foo([]) {}; | ||
function foo({a: {}}) {}; | ||
function foo({a: []}) {}; |
118 changes: 118 additions & 0 deletions
118
crates/rome_js_analyze/tests/specs/noEmptyPattern.js.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
--- | ||
source: crates/rome_js_analyze/tests/spec_tests.rs | ||
assertion_line: 98 | ||
expression: noEmptyPattern.js | ||
--- | ||
# Input | ||
```js | ||
// valid | ||
var {a = {}} = foo; | ||
var {a, b = {}} = foo; | ||
var {a = []} = foo; | ||
function foo({a = {}}) {} | ||
function foo({a = []}) {} | ||
var [a] = foo; | ||
// invalid | ||
var {} = foo; | ||
var [] = foo; | ||
var {a: {}} = foo; | ||
var {a, b: {}} = foo; | ||
var {a: []} = foo; | ||
function foo({}) {}; | ||
function foo([]) {}; | ||
function foo({a: {}}) {}; | ||
function foo({a: []}) {}; | ||
``` | ||
|
||
# Diagnostics | ||
``` | ||
warning[noEmptyPattern]: Unexpected empty object pattern. | ||
┌─ noEmptyPattern.js:9:5 | ||
│ | ||
9 │ var {} = foo; | ||
│ -- | ||
``` | ||
|
||
``` | ||
warning[noEmptyPattern]: Unexpected empty array pattern. | ||
┌─ noEmptyPattern.js:10:5 | ||
│ | ||
10 │ var [] = foo; | ||
│ -- | ||
``` | ||
|
||
``` | ||
warning[noEmptyPattern]: Unexpected empty object pattern. | ||
┌─ noEmptyPattern.js:11:9 | ||
│ | ||
11 │ var {a: {}} = foo; | ||
│ -- | ||
``` | ||
|
||
``` | ||
warning[noEmptyPattern]: Unexpected empty object pattern. | ||
┌─ noEmptyPattern.js:12:12 | ||
│ | ||
12 │ var {a, b: {}} = foo; | ||
│ -- | ||
``` | ||
|
||
``` | ||
warning[noEmptyPattern]: Unexpected empty array pattern. | ||
┌─ noEmptyPattern.js:13:9 | ||
│ | ||
13 │ var {a: []} = foo; | ||
│ -- | ||
``` | ||
|
||
``` | ||
warning[noEmptyPattern]: Unexpected empty object pattern. | ||
┌─ noEmptyPattern.js:14:14 | ||
│ | ||
14 │ function foo({}) {}; | ||
│ -- | ||
``` | ||
|
||
``` | ||
warning[noEmptyPattern]: Unexpected empty array pattern. | ||
┌─ noEmptyPattern.js:15:14 | ||
│ | ||
15 │ function foo([]) {}; | ||
│ -- | ||
``` | ||
|
||
``` | ||
warning[noEmptyPattern]: Unexpected empty object pattern. | ||
┌─ noEmptyPattern.js:16:18 | ||
│ | ||
16 │ function foo({a: {}}) {}; | ||
│ -- | ||
``` | ||
|
||
``` | ||
warning[noEmptyPattern]: Unexpected empty array pattern. | ||
┌─ noEmptyPattern.js:17:18 | ||
│ | ||
17 │ function foo({a: []}) {}; | ||
│ -- | ||
``` | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
--- | ||
title: Lint Rule noEmptyPattern | ||
layout: layouts/rule.liquid | ||
--- | ||
|
||
# noEmptyPattern | ||
|
||
Disallows empty destructuring patterns. | ||
|
||
## Examples | ||
|
||
### Valid | ||
|
||
The following cases are valid because they create new bindings. | ||
|
||
```jsx | ||
var {a = {}} = foo; | ||
var {a, b = {}} = foo; | ||
var {a = []} = foo; | ||
function foo({a = {}}) {} | ||
function foo({a = []}) {} | ||
var [a] = foo; | ||
``` | ||
|
||
### Invalid | ||
|
||
```jsx | ||
var {} = foo; | ||
``` | ||
|
||
{% raw %}<pre class="language-text"><code class="language-text"><span style="color: Orange;">warning</span><span style="color: Orange;">[</span><span style="color: Orange;">noEmptyPattern</span><span style="color: Orange;">]</span><em>: </em><em>Unexpected empty object pattern.</em> | ||
<span style="color: rgb(38, 148, 255);">┌</span><span style="color: rgb(38, 148, 255);">─</span> noEmptyPattern.js:1:5 | ||
<span style="color: rgb(38, 148, 255);">│</span> | ||
<span style="color: rgb(38, 148, 255);">1</span> <span style="color: rgb(38, 148, 255);">│</span> var {} = foo; | ||
<span style="color: rgb(38, 148, 255);">│</span> <span style="color: rgb(38, 148, 255);">-</span><span style="color: rgb(38, 148, 255);">-</span> | ||
|
||
</code></pre>{% endraw %} | ||
|
||
```jsx | ||
var {a: {}} = foo; | ||
``` | ||
|
||
{% raw %}<pre class="language-text"><code class="language-text"><span style="color: Orange;">warning</span><span style="color: Orange;">[</span><span style="color: Orange;">noEmptyPattern</span><span style="color: Orange;">]</span><em>: </em><em>Unexpected empty object pattern.</em> | ||
<span style="color: rgb(38, 148, 255);">┌</span><span style="color: rgb(38, 148, 255);">─</span> noEmptyPattern.js:1:9 | ||
<span style="color: rgb(38, 148, 255);">│</span> | ||
<span style="color: rgb(38, 148, 255);">1</span> <span style="color: rgb(38, 148, 255);">│</span> var {a: {}} = foo; | ||
<span style="color: rgb(38, 148, 255);">│</span> <span style="color: rgb(38, 148, 255);">-</span><span style="color: rgb(38, 148, 255);">-</span> | ||
|
||
</code></pre>{% endraw %} | ||
|
||
```jsx | ||
function foo({}) {} | ||
``` | ||
|
||
{% raw %}<pre class="language-text"><code class="language-text"><span style="color: Orange;">warning</span><span style="color: Orange;">[</span><span style="color: Orange;">noEmptyPattern</span><span style="color: Orange;">]</span><em>: </em><em>Unexpected empty object pattern.</em> | ||
<span style="color: rgb(38, 148, 255);">┌</span><span style="color: rgb(38, 148, 255);">─</span> noEmptyPattern.js:1:14 | ||
<span style="color: rgb(38, 148, 255);">│</span> | ||
<span style="color: rgb(38, 148, 255);">1</span> <span style="color: rgb(38, 148, 255);">│</span> function foo({}) {} | ||
<span style="color: rgb(38, 148, 255);">│</span> <span style="color: rgb(38, 148, 255);">-</span><span style="color: rgb(38, 148, 255);">-</span> | ||
|
||
</code></pre>{% endraw %} | ||
|