aboutsummaryrefslogtreecommitdiff
path: root/lib/src/lints/collapsible_let_in.rs
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-10-03 12:27:34 +0100
committerAkshay <[email protected]>2021-10-03 12:28:38 +0100
commitfc6409142e68335addc65763a1733526130256b0 (patch)
treee39163c7705268645b4afcb042d1bc59faec80b9 /lib/src/lints/collapsible_let_in.rs
parentc5c4b55c2b3a3fb824c3fd64e33bb30f1b011b71 (diff)
new lint: collapsible_let_in
Diffstat (limited to 'lib/src/lints/collapsible_let_in.rs')
-rw-r--r--lib/src/lints/collapsible_let_in.rs60
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/src/lints/collapsible_let_in.rs b/lib/src/lints/collapsible_let_in.rs
new file mode 100644
index 0000000..c2cdf9b
--- /dev/null
+++ b/lib/src/lints/collapsible_let_in.rs
@@ -0,0 +1,60 @@
1use crate::{make, Lint, Metadata, Report, Rule, Suggestion};
2
3use if_chain::if_chain;
4use macros::lint;
5use rowan::Direction;
6use rnix::{
7 types::{LetIn, TypedNode},
8 NodeOrToken, SyntaxElement, SyntaxKind, TextRange
9};
10
11#[lint(
12 name = "collapsible let in",
13 note = "These let-in expressions are collapsible",
14 code = 6,
15 match_with = SyntaxKind::NODE_LET_IN
16)]
17struct CollapsibleLetIn;
18
19impl Rule for CollapsibleLetIn {
20 fn validate(&self, node: &SyntaxElement) -> Option<Report> {
21 if_chain! {
22 if let NodeOrToken::Node(node) = node;
23 if let Some(let_in_expr) = LetIn::cast(node.clone());
24 if let Some(body) = let_in_expr.body();
25
26 if LetIn::cast(body.clone()).is_some();
27 then {
28 let first_annotation = node.text_range();
29 let first_message = "This let-in expression contains a nested let-in expression";
30
31 let second_annotation = body.text_range();
32 let second_message = "This let-in expression is nested";
33
34 let replacement_at = {
35 let start = body
36 .siblings_with_tokens(Direction::Prev)
37 .find(|elem| elem.kind() == SyntaxKind::TOKEN_IN)?
38 .text_range()
39 .start();
40 let end = body
41 .descendants_with_tokens()
42 .find(|elem| elem.kind() == SyntaxKind::TOKEN_LET)?
43 .text_range()
44 .end();
45 TextRange::new(start, end)
46 };
47 let replacement = make::empty().node().clone();
48
49 Some(
50 Self::report()
51 .diagnostic(first_annotation, first_message)
52 .suggest(second_annotation, second_message, Suggestion::new(replacement_at, replacement))
53 )
54 } else {
55 None
56 }
57 }
58 }
59}
60