mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
feat(linter) oxc: approx constant (#1818)
Co-authored-by: Dunqing <dengqing0821@gmail.com>
This commit is contained in:
parent
ce851bb9a5
commit
7d9d920148
3 changed files with 166 additions and 0 deletions
|
|
@ -246,6 +246,7 @@ mod jsx_a11y {
|
|||
}
|
||||
|
||||
mod oxc {
|
||||
pub mod approx_constant;
|
||||
pub mod const_comparisons;
|
||||
pub mod double_comparisons;
|
||||
pub mod no_accumulating_spread;
|
||||
|
|
@ -467,6 +468,7 @@ oxc_macros::declare_all_lint_rules! {
|
|||
jsx_a11y::scope,
|
||||
jsx_a11y::tab_index_no_positive,
|
||||
jsx_a11y::no_distracting_elements,
|
||||
oxc::approx_constant,
|
||||
oxc::const_comparisons,
|
||||
oxc::double_comparisons,
|
||||
oxc::no_accumulating_spread,
|
||||
|
|
|
|||
96
crates/oxc_linter/src/rules/oxc/approx_constant.rs
Normal file
96
crates/oxc_linter/src/rules/oxc/approx_constant.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// Based on https://github.com/rust-lang/rust-clippy//blob/c9a43b18f11219fa70fe632b29518581fcd589c8/clippy_lints/src/approx_const.rs
|
||||
// https://rust-lang.github.io/rust-clippy/master/#approx_constant
|
||||
use oxc_ast::AstKind;
|
||||
use oxc_diagnostics::{
|
||||
miette::{self, Diagnostic},
|
||||
thiserror::{self, Error},
|
||||
};
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
use std::f64::consts as f64;
|
||||
|
||||
use crate::{context::LintContext, rule::Rule, AstNode};
|
||||
|
||||
#[derive(Debug, Error, Diagnostic)]
|
||||
#[error("oxc(approx-constant): Approximate value of `{1}` found.")]
|
||||
#[diagnostic(severity(warning), help("Use `Math.{1}` instead"))]
|
||||
struct ApproxConstantDiagnostic(#[label] pub Span, pub &'static str);
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ApproxConstant;
|
||||
|
||||
declare_oxc_lint!(
|
||||
/// ### What it does
|
||||
///
|
||||
/// Disallows the use of approximate constants, instead preferring the use of the constants in the `Math` object.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
///
|
||||
/// Approximate constants are not as accurate as the constants in the `Math` object.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```javascript
|
||||
/// ```
|
||||
ApproxConstant,
|
||||
suspicious
|
||||
);
|
||||
|
||||
impl Rule for ApproxConstant {
|
||||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
let AstKind::NumberLiteral(number_literal) = node.kind() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let number_lit_str = number_literal.value.to_string();
|
||||
for (constant, name, min_digits) in &KNOWN_CONSTS {
|
||||
if is_approx_const(*constant, &number_lit_str, *min_digits) {
|
||||
ctx.diagnostic(ApproxConstantDiagnostic(number_literal.span, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const KNOWN_CONSTS: [(f64, &str, usize); 8] = [
|
||||
(f64::E, "E", 4),
|
||||
(f64::LN_10, "LN10", 4),
|
||||
(f64::LN_2, "LN2", 4),
|
||||
(f64::LOG2_E, "LOG2E", 4),
|
||||
(f64::LOG10_E, "LOG10E", 4),
|
||||
(f64::PI, "PI", 4),
|
||||
(f64::FRAC_1_SQRT_2, "SQRT1_2", 4),
|
||||
(f64::SQRT_2, "SQRT2", 4),
|
||||
];
|
||||
|
||||
#[must_use]
|
||||
fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool {
|
||||
if value.len() <= min_digits {
|
||||
false
|
||||
} else if constant.to_string().starts_with(value) {
|
||||
// The value is a truncated constant
|
||||
true
|
||||
} else {
|
||||
let round_const = format!("{constant:.*}", value.len() - 2);
|
||||
value == round_const
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
use crate::tester::Tester;
|
||||
|
||||
let pass = vec!["const x = 1234;"];
|
||||
|
||||
let fail = vec![
|
||||
"const getArea = (radius) => 3.141 * radius * radius;",
|
||||
"let e = 2.718281", // E
|
||||
"let ln10 = 2.302585", // LN10
|
||||
"let ln2 = 0.693147", // LN2
|
||||
"let log10e = 0.434294", // LOG10E
|
||||
"let log2e = 1.442695", // LOG2E
|
||||
"let pi = 3.141592", // PI
|
||||
"let sqrt12 = 0.707106", // SQRT1_2
|
||||
"let sqrt2 = 1.414213", // SQRT2
|
||||
];
|
||||
|
||||
Tester::new_without_config(ApproxConstant::NAME, pass, fail).test_and_snapshot();
|
||||
}
|
||||
68
crates/oxc_linter/src/snapshots/approx_constant.snap
Normal file
68
crates/oxc_linter/src/snapshots/approx_constant.snap
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
source: crates/oxc_linter/src/tester.rs
|
||||
expression: approx_constant
|
||||
---
|
||||
⚠ oxc(approx-constant): Approximate value of `PI` found.
|
||||
╭─[approx_constant.tsx:1:1]
|
||||
1 │ const getArea = (radius) => 3.141 * radius * radius;
|
||||
· ─────
|
||||
╰────
|
||||
help: Use `Math.PI` instead
|
||||
|
||||
⚠ oxc(approx-constant): Approximate value of `E` found.
|
||||
╭─[approx_constant.tsx:1:1]
|
||||
1 │ let e = 2.718281
|
||||
· ────────
|
||||
╰────
|
||||
help: Use `Math.E` instead
|
||||
|
||||
⚠ oxc(approx-constant): Approximate value of `LN10` found.
|
||||
╭─[approx_constant.tsx:1:1]
|
||||
1 │ let ln10 = 2.302585
|
||||
· ────────
|
||||
╰────
|
||||
help: Use `Math.LN10` instead
|
||||
|
||||
⚠ oxc(approx-constant): Approximate value of `LN2` found.
|
||||
╭─[approx_constant.tsx:1:1]
|
||||
1 │ let ln2 = 0.693147
|
||||
· ────────
|
||||
╰────
|
||||
help: Use `Math.LN2` instead
|
||||
|
||||
⚠ oxc(approx-constant): Approximate value of `LOG10E` found.
|
||||
╭─[approx_constant.tsx:1:1]
|
||||
1 │ let log10e = 0.434294
|
||||
· ────────
|
||||
╰────
|
||||
help: Use `Math.LOG10E` instead
|
||||
|
||||
⚠ oxc(approx-constant): Approximate value of `LOG2E` found.
|
||||
╭─[approx_constant.tsx:1:1]
|
||||
1 │ let log2e = 1.442695
|
||||
· ────────
|
||||
╰────
|
||||
help: Use `Math.LOG2E` instead
|
||||
|
||||
⚠ oxc(approx-constant): Approximate value of `PI` found.
|
||||
╭─[approx_constant.tsx:1:1]
|
||||
1 │ let pi = 3.141592
|
||||
· ────────
|
||||
╰────
|
||||
help: Use `Math.PI` instead
|
||||
|
||||
⚠ oxc(approx-constant): Approximate value of `SQRT1_2` found.
|
||||
╭─[approx_constant.tsx:1:1]
|
||||
1 │ let sqrt12 = 0.707106
|
||||
· ────────
|
||||
╰────
|
||||
help: Use `Math.SQRT1_2` instead
|
||||
|
||||
⚠ oxc(approx-constant): Approximate value of `SQRT2` found.
|
||||
╭─[approx_constant.tsx:1:1]
|
||||
1 │ let sqrt2 = 1.414213
|
||||
· ────────
|
||||
╰────
|
||||
help: Use `Math.SQRT2` instead
|
||||
|
||||
|
||||
Loading…
Reference in a new issue