-
-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
651ac70
commit 02c9d65
Showing
7 changed files
with
168 additions
and
0 deletions.
There are no files selected for viewing
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
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 @@ | ||
# approx_constant | ||
## What it does | ||
Checks for number literals that approximate constants. | ||
|
||
## Why this is bad | ||
Using constants provided by the Lua standard library is more precise. | ||
|
||
## Example | ||
```lua | ||
local x = 3.14 | ||
``` | ||
|
||
...should be written as... | ||
|
||
```lua | ||
local x = math.pi | ||
``` |
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,87 @@ | ||
use super::*; | ||
use std::convert::Infallible; | ||
|
||
use full_moon::{ast::Ast, tokenizer::TokenType, visitors::Visitor}; | ||
|
||
pub struct ApproxConstantLint; | ||
|
||
impl Lint for ApproxConstantLint { | ||
type Config = (); | ||
type Error = Infallible; | ||
|
||
const SEVERITY: Severity = Severity::Warning; | ||
const LINT_TYPE: LintType = LintType::Correctness; | ||
|
||
fn new((): Self::Config) -> Result<Self, Self::Error> { | ||
Ok(ApproxConstantLint) | ||
} | ||
|
||
fn pass(&self, ast: &Ast, _: &Context, _: &AstContext) -> Vec<Diagnostic> { | ||
let mut visitor = ApproxConstantVisitor { | ||
approx_constants: Vec::new(), | ||
}; | ||
|
||
visitor.visit_ast(ast); | ||
|
||
visitor | ||
.approx_constants | ||
.iter() | ||
.map(|constant| { | ||
Diagnostic::new( | ||
"approx_constant", | ||
format!("`{}` is more precise", constant.constant), | ||
Label::new(constant.range), | ||
) | ||
}) | ||
.collect() | ||
} | ||
} | ||
|
||
struct ApproxConstantVisitor { | ||
approx_constants: Vec<ApproximatedConstant>, | ||
} | ||
|
||
struct ApproximatedConstant { | ||
range: (usize, usize), | ||
constant: String, | ||
} | ||
|
||
impl Visitor for ApproxConstantVisitor { | ||
fn visit_number(&mut self, token: &full_moon::tokenizer::Token) { | ||
if let TokenType::Number { text } = token.token_type() { | ||
if is_approx_const(std::f64::consts::PI, text, 3) { | ||
self.approx_constants.push(ApproximatedConstant { | ||
range: (token.start_position().bytes(), token.end_position().bytes()), | ||
constant: "math.pi".to_string(), | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[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 | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::{super::test_util::test_lint, *}; | ||
|
||
#[test] | ||
fn test_approx_constant() { | ||
test_lint( | ||
ApproxConstantLint::new(()).unwrap(), | ||
"approx_constant", | ||
"approx_constant", | ||
); | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
selene-lib/tests/lints/approx_constant/approx_constant.lua
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,18 @@ | ||
local good = 3 | ||
local good = 3.1 | ||
local good = 3.13 | ||
local good = 3.15 | ||
local good = 3.1417 | ||
local good = 3.14159266 | ||
|
||
local good = 0x314 | ||
local good = 3_14 | ||
|
||
local bad = 3.14 | ||
local bad = 3.141 | ||
local bad = 3.142 | ||
local bad = 3.1415 | ||
local bad = 3.14159265 | ||
|
||
local bad = 3.14 + 1 | ||
local bad = f(3.14 + 1) |
42 changes: 42 additions & 0 deletions
42
selene-lib/tests/lints/approx_constant/approx_constant.stderr
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,42 @@ | ||
error[approx_constant]: `math.pi` is more precise | ||
┌─ approx_constant.lua:11:13 | ||
│ | ||
11 │ local bad = 3.14 | ||
│ ^^^^ | ||
|
||
error[approx_constant]: `math.pi` is more precise | ||
┌─ approx_constant.lua:12:13 | ||
│ | ||
12 │ local bad = 3.141 | ||
│ ^^^^^ | ||
|
||
error[approx_constant]: `math.pi` is more precise | ||
┌─ approx_constant.lua:13:13 | ||
│ | ||
13 │ local bad = 3.142 | ||
│ ^^^^^ | ||
|
||
error[approx_constant]: `math.pi` is more precise | ||
┌─ approx_constant.lua:14:13 | ||
│ | ||
14 │ local bad = 3.1415 | ||
│ ^^^^^^ | ||
|
||
error[approx_constant]: `math.pi` is more precise | ||
┌─ approx_constant.lua:15:13 | ||
│ | ||
15 │ local bad = 3.14159265 | ||
│ ^^^^^^^^^^ | ||
|
||
error[approx_constant]: `math.pi` is more precise | ||
┌─ approx_constant.lua:17:13 | ||
│ | ||
17 │ local bad = 3.14 + 1 | ||
│ ^^^^ | ||
|
||
error[approx_constant]: `math.pi` is more precise | ||
┌─ approx_constant.lua:18:15 | ||
│ | ||
18 │ local bad = f(3.14 + 1) | ||
│ ^^^^ | ||
|