Skip to content

Commit

Permalink
Merge branch 'main' into resolve-biomejs#2267
Browse files Browse the repository at this point in the history
  • Loading branch information
unvalley authored May 17, 2024
2 parents e29c1c1 + 62d1f71 commit 2648e9a
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b

Contributed by @Conaclos

- Add [nursery/useNumberToFixedDigitsArgument](https://biomejs.dev/linter/rules/use-number-to-fixed-digits-argument/).
Contributed by @minht11

- Add [nursery/useThrowNewError](https://biomejs.dev/linter/rules/use-throw-new-error/).
Contributed by @minht11
- Add [nursery/useTopLevelRegex](https://biomejs.dev/linter/rules/use-top-level-regex), which enforces defining regular expressions at the top level of a module. [#2148](https://github.com/biomejs/biome/issues/2148) Contributed by @dyc3.
Expand Down
10 changes: 10 additions & 0 deletions crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 31 additions & 6 deletions crates/biome_configuration/src/linter/rules.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/biome_diagnostics_categories/src/categories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ define_categories! {
"lint/nursery/useFocusableInteractive": "https://biomejs.dev/linter/rules/use-focusable-interactive",
"lint/nursery/useGenericFontNames": "https://biomejs.dev/linter/rules/use-generic-font-names",
"lint/nursery/useImportRestrictions": "https://biomejs.dev/linter/rules/use-import-restrictions",
"lint/nursery/useNumberToFixedDigitsArgument": "https://biomejs.dev/linter/rules/use-number-to-fixed-digits-argument",
"lint/nursery/useSortedClasses": "https://biomejs.dev/linter/rules/use-sorted-classes",
"lint/nursery/useThrowNewError": "https://biomejs.dev/linter/rules/use-throw-new-error",
"lint/nursery/useTopLevelRegex": "https://biomejs.dev/linter/rules/use-top-level-regex",
Expand Down
2 changes: 2 additions & 0 deletions crates/biome_js_analyze/src/lint/nursery.rs

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,126 @@
use biome_analyze::{
context::RuleContext, declare_rule, ActionCategory, Ast, FixKind, Rule, RuleDiagnostic,
RuleSource,
};
use biome_console::markup;
use biome_diagnostics::Applicability;
use biome_js_factory::make;
use biome_js_syntax::{
AnyJsCallArgument, AnyJsExpression, AnyJsLiteralExpression, JsCallArgumentList,
JsCallExpression, JsSyntaxKind,
};
use biome_rowan::{AstNode, AstSeparatedList, BatchMutationExt};

use crate::JsRuleAction;

declare_rule! {
/// Enforce using the digits argument with `Number#toFixed()`.
///
/// When using `Number#toFixed()` explicitly specify the number of digits you want to appear after the decimal point,
/// to avoid unexpected results, rather than relying on its default value of 0.
///
/// ## Examples
///
/// ### Invalid
///
/// ```js,expect_diagnostic
/// const string = number.toFixed();
/// ```
///
/// ### Valid
///
/// ```js
/// const string = foo.toFixed(0);
/// ```
/// ```js
/// const string = foo.toFixed(2);
/// ```
///
/// ## Caveats
///
/// This rule always assumes that `toFixed` is called on a number.
/// It does not check the type of the callee.
///
pub UseNumberToFixedDigitsArgument {
version: "next",
name: "useNumberToFixedDigitsArgument",
language: "js",
sources: &[RuleSource::EslintUnicorn("require-number-to-fixed-digits-argument")],
recommended: false,
fix_kind: FixKind::Unsafe,
}
}

impl Rule for UseNumberToFixedDigitsArgument {
type Query = Ast<JsCallExpression>;
type State = ();
type Signals = Option<Self::State>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Self::Signals {
let node = ctx.query();

if node.is_optional() || node.is_optional_chain() || node.arguments().ok()?.args().len() > 0
{
return None;
}

let callee = node.callee().ok()?;

// TODO. This could be improved with type inference,
// to only match if the callee is a number.
if callee.get_callee_member_name()?.token_text() != "toFixed" {
return None;
}

let is_new_expr = callee
.as_js_static_member_expression()
.and_then(|e| e.object().ok())
.is_some_and(|e| e.syntax().kind() == JsSyntaxKind::JS_NEW_EXPRESSION);

if is_new_expr {
return None;
}

Some(())
}

fn diagnostic(ctx: &RuleContext<Self>, _state: &Self::State) -> Option<RuleDiagnostic> {
let node = ctx.query().arguments().ok()?;

Some(RuleDiagnostic::new(
rule_category!(),
node.range(),
markup! {
"Specify the number of digits you want to appear after the decimal point."
},
))
}

fn action(ctx: &RuleContext<Self>, _: &Self::State) -> Option<JsRuleAction> {
let mut mutation = ctx.root().begin();

let zero_literal = AnyJsLiteralExpression::JsNumberLiteralExpression(
make::js_number_literal_expression(make::js_number_literal('0')),
);

let arg = AnyJsCallArgument::AnyJsExpression(AnyJsExpression::AnyJsLiteralExpression(
zero_literal,
));

let previous_args = ctx.query().arguments().ok()?.args();
let new_args = make::js_call_argument_list([arg], []);

mutation.replace_node::<JsCallArgumentList>(previous_args, new_args);

Some(JsRuleAction::new(
ActionCategory::QuickFix,
Applicability::MaybeIncorrect,
markup! {
"Add explicit digits argument to "<Emphasis>"toFixed"</Emphasis>" method."
}
.to_owned(),
mutation,
))
}
}
1 change: 1 addition & 0 deletions crates/biome_js_analyze/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ pub type UseNodeAssertStrict =
pub type UseNodejsImportProtocol = < lint :: style :: use_nodejs_import_protocol :: UseNodejsImportProtocol as biome_analyze :: Rule > :: Options ;
pub type UseNumberNamespace =
<lint::style::use_number_namespace::UseNumberNamespace as biome_analyze::Rule>::Options;
pub type UseNumberToFixedDigitsArgument = < lint :: nursery :: use_number_to_fixed_digits_argument :: UseNumberToFixedDigitsArgument as biome_analyze :: Rule > :: Options ;
pub type UseNumericLiterals =
<lint::style::use_numeric_literals::UseNumericLiterals as biome_analyze::Rule>::Options;
pub type UseOptionalChain =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const string1 = number.toFixed();
const string2 = number.toFixed(/* comment */);
Number(1).toFixed();

// False positive cases
const bigNumber = new BigNumber(1); const string3 = bigNumber.toFixed();
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
source: crates/biome_js_analyze/tests/spec_tests.rs
expression: invalid.js
---
# Input
```jsx
const string1 = number.toFixed();
const string2 = number.toFixed(/* comment */);
Number(1).toFixed();

// False positive cases
const bigNumber = new BigNumber(1); const string3 = bigNumber.toFixed();

```

# Diagnostics
```
invalid.js:1:31 lint/nursery/useNumberToFixedDigitsArgument FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Specify the number of digits you want to appear after the decimal point.
> 1 │ const string1 = number.toFixed();
│ ^^
2 │ const string2 = number.toFixed(/* comment */);
3 │ Number(1).toFixed();
i Unsafe fix: Add explicit digits argument to toFixed method.
1 │ const·string1·=·number.toFixed(0);
│ +
```

```
invalid.js:2:31 lint/nursery/useNumberToFixedDigitsArgument FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Specify the number of digits you want to appear after the decimal point.
1 │ const string1 = number.toFixed();
> 2 │ const string2 = number.toFixed(/* comment */);
│ ^^^^^^^^^^^^^^^
3 │ Number(1).toFixed();
4 │
i Unsafe fix: Add explicit digits argument to toFixed method.
2 │ const·string2·=·number.toFixed(/*·comment·*/0);
│ +
```

```
invalid.js:3:18 lint/nursery/useNumberToFixedDigitsArgument FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Specify the number of digits you want to appear after the decimal point.
1 │ const string1 = number.toFixed();
2 │ const string2 = number.toFixed(/* comment */);
> 3 │ Number(1).toFixed();
│ ^^
4 │
5 │ // False positive cases
i Unsafe fix: Add explicit digits argument to toFixed method.
3 │ Number(1).toFixed(0);
│ +
```

```
invalid.js:6:70 lint/nursery/useNumberToFixedDigitsArgument FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Specify the number of digits you want to appear after the decimal point.
5 │ // False positive cases
> 6 │ const bigNumber = new BigNumber(1); const string3 = bigNumber.toFixed();
│ ^^
7 │
i Unsafe fix: Add explicit digits argument to toFixed method.
6 │ const·bigNumber·=·new·BigNumber(1);·const·string3·=·bigNumber.toFixed(0);
│ +
```
Loading

0 comments on commit 2648e9a

Please sign in to comment.