-
-
Notifications
You must be signed in to change notification settings - Fork 961
feat(js_analyze): implement noFloatingClasses #8754
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ca90c6a
3e6bbfd
13afafd
d0e78b7
e2cc1cb
3fb1b00
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| --- | ||
| "@biomejs/biome": patch | ||
| --- | ||
|
|
||
| Added the nursery rule [`noFloatingClasses`](https://biomejs.dev/linter/rules/no-floating-classes). Disallow `new` operators outside of assignments or comparisons. | ||
|
|
||
| **Invalid:** | ||
|
|
||
| ```js | ||
| new Date(); | ||
| ``` |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| use biome_analyze::{ | ||
| Ast, Rule, RuleDiagnostic, RuleSource, context::RuleContext, declare_lint_rule, | ||
| }; | ||
| use biome_console::markup; | ||
| use biome_js_syntax::{JsNewExpression, JsSyntaxKind}; | ||
| use biome_rowan::{AstNode, SyntaxNodeOptionExt}; | ||
| use biome_rule_options::no_floating_classes::NoFloatingClassesOptions; | ||
|
|
||
| declare_lint_rule! { | ||
| /// Disallow `new` operators outside of assignments or comparisons. | ||
| /// | ||
| /// The goal of using `new` with a constructor is typically to create an object of a particular type and store that object in a variable, such as: | ||
| /// | ||
| /// ```js | ||
| /// const person = new Person(); | ||
| /// ``` | ||
| /// | ||
| /// It's less common to use `new` and not store the result, such as: | ||
| /// | ||
| /// ```js,ignore | ||
| /// new Person(); | ||
| /// ``` | ||
| /// | ||
| /// In this case, the created object is thrown away because its reference isn't stored anywhere, and in many cases, this means that the constructor should be replaced with a function that doesn't require `new` to be used. | ||
| /// | ||
| /// ## Examples | ||
| /// | ||
| /// ### Invalid | ||
| /// | ||
| /// ```js,expect_diagnostic | ||
| /// new Thing(); | ||
| /// ``` | ||
| /// | ||
| /// ### Valid | ||
| /// | ||
| /// ```js | ||
| /// const thing = new Thing(); | ||
| /// ``` | ||
| /// | ||
| pub NoFloatingClasses { | ||
| version: "next", | ||
| name: "noFloatingClasses", | ||
| language: "js", | ||
| recommended: false, | ||
| sources: &[RuleSource::Eslint("no-new").same()], | ||
| } | ||
| } | ||
|
|
||
| impl Rule for NoFloatingClasses { | ||
| type Query = Ast<JsNewExpression>; | ||
| type State = (); | ||
| type Signals = Option<Self::State>; | ||
| type Options = NoFloatingClassesOptions; | ||
|
|
||
| fn run(ctx: &RuleContext<Self>) -> Self::Signals { | ||
| let node = ctx.query(); | ||
|
|
||
| node.syntax() | ||
| .parent() | ||
| .kind() | ||
| .is_some_and(|kind| kind == JsSyntaxKind::JS_EXPRESSION_STATEMENT) | ||
| .then_some(()) | ||
| } | ||
|
|
||
| fn diagnostic(ctx: &RuleContext<Self>, _state: &Self::State) -> Option<RuleDiagnostic> { | ||
| let node = ctx.query(); | ||
| Some( | ||
| RuleDiagnostic::new( | ||
| rule_category!(), | ||
| node.range(), | ||
| markup! { | ||
| "Using the `new` operator outside of assignments or comparisons is not allowed." | ||
| }, | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ) | ||
| .note(markup! { | ||
| "The created object is thrown away because its reference isn't stored anywhere. Assign the object to a variable or replace with a function that doesn't require `new` to be used." | ||
| }), | ||
| ) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| /* should generate diagnostics */ | ||
| new Date() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| --- | ||
| source: crates/biome_js_analyze/tests/spec_tests.rs | ||
| expression: invalid.js | ||
| --- | ||
| # Input | ||
| ```js | ||
| /* should generate diagnostics */ | ||
| new Date() | ||
|
|
||
| ``` | ||
|
|
||
| # Diagnostics | ||
| ``` | ||
| invalid.js:2:1 lint/nursery/noFloatingClasses ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
|
|
||
| i Using the `new` operator outside of assignments or comparisons is not allowed. | ||
|
|
||
| 1 │ /* should generate diagnostics */ | ||
| > 2 │ new Date() | ||
| │ ^^^^^^^^^^ | ||
| 3 │ | ||
|
|
||
| i The created object is thrown away because its reference isn't stored anywhere. Assign the object to a variable or replace with a function that doesn't require `new` to be used. | ||
|
|
||
| i This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information. | ||
|
|
||
|
|
||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| /* should not generate diagnostics */ | ||
| var a = new Date() | ||
|
|
||
| var a; | ||
| if (a === new Date()) { | ||
| a = false; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| --- | ||
| source: crates/biome_js_analyze/tests/spec_tests.rs | ||
| expression: valid.js | ||
| --- | ||
| # Input | ||
| ```js | ||
| /* should not generate diagnostics */ | ||
| var a = new Date() | ||
|
|
||
| var a; | ||
| if (a === new Date()) { | ||
| a = false; | ||
| } | ||
|
|
||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| use biome_deserialize_macros::{Deserializable, Merge}; | ||
| use serde::{Deserialize, Serialize}; | ||
| #[derive(Default, Clone, Debug, Deserialize, Deserializable, Merge, Eq, PartialEq, Serialize)] | ||
| #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] | ||
| #[serde(rename_all = "camelCase", deny_unknown_fields, default)] | ||
| pub struct NoFloatingClassesOptions {} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.