feat(es/lints): Improve error messages (#4142)

This commit is contained in:
Donny/강동윤 2022-03-24 11:15:03 +09:00 committed by GitHub
parent 4e07a29112
commit 0f92eda0c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 159 additions and 64 deletions

View File

@ -2,71 +2,95 @@
x Use the isNaN function to compare with NaN
,----
1 | if (foo == NaN) {}
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
3 | if (NaN == foo) {}
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
5 | if (foo != NaN) {}
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will always return true
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
7 | if (foo == Number.NaN) {}
: ^^^^^^^^^^^^^^^^^
: ^^^^^^^^|^^^^^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
9 | if (foo != Number.NaN) {}
: ^^^^^^^^^^^^^^^^^
: ^^^^^^^^|^^^^^^^^
: `-- this will always return true
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
11 | if (foo == Number['NaN']) {}
: ^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^|^^^^^^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
20 | myArray.indexOf(NaN);
: ^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^|^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
22 | myArray.lastIndexOf(NaN);
: ^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^|^^^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
24 | myArray.lastIndexOf(Number.NaN);
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^|^^^^^^^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
26 | myArray.lastIndexOf(Number['NaN']);
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^^^|^^^^^^^^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
33 | case NaN:
: ^^^
: ^|^
: `-- this will never match the discriminant
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
41 | switch (NaN) {
: ^^^
: ^|^
: `-- this will never match the test of any case
`----
help: NaN is a special value and `NaN == NaN` is false

View File

@ -2,47 +2,63 @@
x Use the isNaN function to compare with NaN
,----
1 | if (foo == NaN) {}
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
3 | if (NaN == foo) {}
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
5 | if (foo != NaN) {}
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will always return true
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
7 | if (foo == Number.NaN) {}
: ^^^^^^^^^^^^^^^^^
: ^^^^^^^^|^^^^^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
9 | if (foo != Number.NaN) {}
: ^^^^^^^^^^^^^^^^^
: ^^^^^^^^|^^^^^^^^
: `-- this will always return true
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
11 | if (foo == Number['NaN']) {}
: ^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^|^^^^^^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
33 | case NaN:
: ^^^
: ^|^
: `-- this will never match the discriminant
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
41 | switch (NaN) {
: ^^^
: ^|^
: `-- this will never match the test of any case
`----
help: NaN is a special value and `NaN == NaN` is false

View File

@ -2,59 +2,79 @@
x Use the isNaN function to compare with NaN
,----
1 | if (foo == NaN) {}
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
3 | if (NaN == foo) {}
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
5 | if (foo != NaN) {}
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will always return true
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
7 | if (foo == Number.NaN) {}
: ^^^^^^^^^^^^^^^^^
: ^^^^^^^^|^^^^^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
9 | if (foo != Number.NaN) {}
: ^^^^^^^^^^^^^^^^^
: ^^^^^^^^|^^^^^^^^
: `-- this will always return true
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
11 | if (foo == Number['NaN']) {}
: ^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^|^^^^^^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
20 | myArray.indexOf(NaN);
: ^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^|^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
22 | myArray.lastIndexOf(NaN);
: ^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^|^^^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
24 | myArray.lastIndexOf(Number.NaN);
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^|^^^^^^^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
26 | myArray.lastIndexOf(Number['NaN']);
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^^^|^^^^^^^^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false

View File

@ -2,41 +2,55 @@
x Use the isNaN function to compare with NaN
,----
1 | switch (NaN as any) {
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will never match the test of any case
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
2 | case NaN as any:
: ^^^^^^^^^^
: ^^^^^|^^^^
: `-- this will never match the discriminant
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
3 | case Number.NaN as any:
: ^^^^^^^^^^^^^^^^^
: ^^^^^^^^|^^^^^^^^
: `-- this will never match the discriminant
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
8 | if (foo == Number.NaN as any) {}
: ^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^|^^^^^^^^^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
10 | myArray.lastIndexOf(NaN as any);
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^|^^^^^^^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
12 | myArray.lastIndexOf(Number.NaN as any);
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^^^^^|^^^^^^^^^^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false
x Use the isNaN function to compare with NaN
,----
14 | myArray.lastIndexOf(Number['NaN'] as any);
: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
: ^^^^^^^^^^^^^^^^^^^^|^^^^^^^^^^^^^^^^^^^^
: `-- this will always return -1
`----
help: NaN is a special value and `NaN == NaN` is false

View File

@ -2,5 +2,7 @@
x Use the isNaN function to compare with NaN
,----
1 | if (a == NaN) {}
: ^^^^^^^^
: ^^^^|^^^
: `-- this will always return false
`----
help: NaN is a special value and `NaN == NaN` is false

View File

@ -1,3 +1,6 @@
#![cfg_attr(feature = "non_critical_lints", deny(unused))]
#![cfg_attr(feature = "non_critical_lints", deny(clippy::all))]
pub mod config;
pub mod rule;
pub mod rules;

View File

@ -10,12 +10,12 @@ use crate::{
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
enum EqeqeqMode {
enum EqEqEqMode {
Always,
Never,
}
impl Default for EqeqeqMode {
impl Default for EqEqEqMode {
fn default() -> Self {
Self::Always
}
@ -24,7 +24,7 @@ impl Default for EqeqeqMode {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EqeqeqConfig {
#[serde(default)]
mode: EqeqeqMode,
mode: EqEqEqMode,
}
pub fn eqeqeq(config: &RuleConfig<EqeqeqConfig>) -> Option<Box<dyn Rule>> {
@ -37,7 +37,7 @@ pub fn eqeqeq(config: &RuleConfig<EqeqeqConfig>) -> Option<Box<dyn Rule>> {
#[derive(Debug, Default)]
struct Eqeqeq {
expected_reaction: LintRuleReaction,
mode: EqeqeqMode,
mode: EqEqEqMode,
}
impl Eqeqeq {
@ -65,22 +65,22 @@ impl Eqeqeq {
fn check(&self, span: Span, bin_op: &BinaryOp) {
match bin_op {
op!("==") => {
if let EqeqeqMode::Always = self.mode {
if let EqEqEqMode::Always = self.mode {
self.emit_report(span, "==", "===");
}
}
op!("!=") => {
if let EqeqeqMode::Always = self.mode {
if let EqEqEqMode::Always = self.mode {
self.emit_report(span, "!=", "!==");
}
}
op!("===") => {
if let EqeqeqMode::Never = self.mode {
if let EqEqEqMode::Never = self.mode {
self.emit_report(span, "===", "==");
}
}
op!("!==") => {
if let EqeqeqMode::Never = self.mode {
if let EqEqEqMode::Never = self.mode {
self.emit_report(span, "!==", "!=");
}
}

View File

@ -62,19 +62,22 @@ impl UseIsNan {
}
}
fn emit_report(&self, span: Span) {
HANDLER.with(|handler| match self.expected_reaction {
LintRuleReaction::Error => {
handler.struct_span_err(span, MESSAGE).emit();
fn emit_report(&self, span: Span, label_msg: &str) {
HANDLER.with(|handler| {
match self.expected_reaction {
LintRuleReaction::Error => handler.struct_span_err(span, MESSAGE),
LintRuleReaction::Warning => handler.struct_span_warn(span, MESSAGE),
_ => {
return;
}
LintRuleReaction::Warning => {
handler.struct_span_warn(span, MESSAGE).emit();
}
_ => {}
.span_label(span, label_msg)
.help("NaN is a special value and `NaN == NaN` is false")
.emit();
});
}
fn check(&self, expr_span: Option<Span>, expr: &Expr) {
fn check(&self, expr_span: Option<Span>, expr: &Expr, label_msg: &str) {
match expr {
Expr::TsAs(TsAsExpr {
expr,
@ -88,13 +91,13 @@ impl UseIsNan {
..
}) = type_ann.as_ref()
{
self.check(expr_span.or(Some(*span)), expr.as_ref());
self.check(expr_span.or(Some(*span)), expr.as_ref(), label_msg);
}
}
}
Expr::Ident(ident) => {
if &*ident.sym == "NaN" {
self.emit_report(expr_span.unwrap_or(ident.span));
self.emit_report(expr_span.unwrap_or(ident.span), label_msg);
}
}
Expr::Member(MemberExpr {
@ -113,13 +116,13 @@ impl UseIsNan {
match prop {
MemberProp::Ident(ident) => {
if &*ident.sym == "NaN" {
self.emit_report(expr_span.unwrap_or(*span));
self.emit_report(expr_span.unwrap_or(*span), label_msg);
}
}
MemberProp::Computed(ComputedPropName { expr, .. }) => {
if let Expr::Lit(Lit::Str(Str { value, .. })) = expr.as_ref() {
if &*value == "NaN" {
self.emit_report(expr_span.unwrap_or(*span));
self.emit_report(expr_span.unwrap_or(*span), label_msg);
}
}
}
@ -136,8 +139,13 @@ impl UseIsNan {
impl Visit for UseIsNan {
fn visit_bin_expr(&mut self, bin_expr: &BinExpr) {
if let op!("==") | op!("!=") = bin_expr.op {
self.check(Some(bin_expr.span), bin_expr.left.as_ref());
self.check(Some(bin_expr.span), bin_expr.right.as_ref());
let label_msg = if bin_expr.op == op!("==") {
"this will always return false"
} else {
"this will always return true"
};
self.check(Some(bin_expr.span), bin_expr.left.as_ref(), label_msg);
self.check(Some(bin_expr.span), bin_expr.right.as_ref(), label_msg);
}
}
@ -153,7 +161,7 @@ impl Visit for UseIsNan {
if sym == "indexOf" || sym == "lastIndexOf" {
if let Some(ExprOrSpread { expr, .. }) = call_expr.args.first() {
self.check(Some(call_expr.span), expr);
self.check(Some(call_expr.span), expr, "this will always return -1");
}
}
}
@ -166,7 +174,11 @@ impl Visit for UseIsNan {
fn visit_switch_case(&mut self, switch_case: &SwitchCase) {
if self.enforce_for_switch_case {
if let Some(test) = &switch_case.test {
self.check(None, test.as_ref());
self.check(
None,
test.as_ref(),
"this will never match the discriminant",
);
}
}
@ -175,7 +187,11 @@ impl Visit for UseIsNan {
fn visit_switch_stmt(&mut self, switch_stmt: &SwitchStmt) {
if self.enforce_for_switch_case {
self.check(None, switch_stmt.discriminant.as_ref());
self.check(
None,
switch_stmt.discriminant.as_ref(),
"this will never match the test of any case",
);
}
switch_stmt.visit_children_with(self);