diff options
Diffstat (limited to 'lib/src/lints/eta_reduction.rs')
-rw-r--r-- | lib/src/lints/eta_reduction.rs | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/lib/src/lints/eta_reduction.rs b/lib/src/lints/eta_reduction.rs new file mode 100644 index 0000000..8c34205 --- /dev/null +++ b/lib/src/lints/eta_reduction.rs | |||
@@ -0,0 +1,51 @@ | |||
1 | use crate::{Lint, Metadata, Report, Rule, Suggestion}; | ||
2 | |||
3 | use if_chain::if_chain; | ||
4 | use macros::lint; | ||
5 | use rnix::{ | ||
6 | types::{Lambda, Ident, Apply, TypedNode, TokenWrapper}, | ||
7 | NodeOrToken, SyntaxElement, SyntaxKind, | ||
8 | }; | ||
9 | |||
10 | #[lint( | ||
11 | name = "eta reduction", | ||
12 | note = "This function expression is eta reducible", | ||
13 | code = 7, | ||
14 | match_with = SyntaxKind::NODE_LAMBDA | ||
15 | )] | ||
16 | struct EtaReduction; | ||
17 | |||
18 | impl Rule for EtaReduction { | ||
19 | fn validate(&self, node: &SyntaxElement) -> Option<Report> { | ||
20 | if_chain! { | ||
21 | if let NodeOrToken::Node(node) = node; | ||
22 | if let Some(lambda_expr) = Lambda::cast(node.clone()); | ||
23 | |||
24 | if let Some(arg_node) = lambda_expr.arg(); | ||
25 | if let Some(arg) = Ident::cast(arg_node); | ||
26 | |||
27 | if let Some(body_node) = lambda_expr.body(); | ||
28 | if let Some(body) = Apply::cast(body_node); | ||
29 | |||
30 | if let Some(value_node) = body.value(); | ||
31 | if let Some(value) = Ident::cast(value_node); | ||
32 | |||
33 | if arg.as_str() == value.as_str() ; | ||
34 | |||
35 | then { | ||
36 | let at = node.text_range(); | ||
37 | let replacement = body.lambda()?; | ||
38 | let message = | ||
39 | format!( | ||
40 | "Found eta-reduction: `{}`", | ||
41 | replacement.text().to_string() | ||
42 | ); | ||
43 | Some(Self::report().suggest(at, message, Suggestion::new(at, replacement))) | ||
44 | } else { | ||
45 | None | ||
46 | } | ||
47 | } | ||
48 | } | ||
49 | } | ||
50 | |||
51 | |||