aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock179
-rw-r--r--lib/Cargo.toml4
-rw-r--r--lib/src/lib.rs50
-rw-r--r--lib/src/lints.rs2
-rw-r--r--lib/src/lints/bool_comparison.rs78
5 files changed, 308 insertions, 5 deletions
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..73188a4
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,179 @@
1# This file is automatically @generated by Cargo.
2# It is not intended for manual editing.
3version = 3
4
5[[package]]
6name = "ariadne"
7version = "0.1.3"
8source = "registry+https://github.com/rust-lang/crates.io-index"
9checksum = "7080ae01b2f0c312065d4914cd0f0de045eb8832e9415b355106a6cff3073cb4"
10dependencies = [
11 "yansi",
12]
13
14[[package]]
15name = "autocfg"
16version = "1.0.1"
17source = "registry+https://github.com/rust-lang/crates.io-index"
18checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
19
20[[package]]
21name = "bin"
22version = "0.1.0"
23dependencies = [
24 "ariadne",
25 "lib",
26]
27
28[[package]]
29name = "cbitset"
30version = "0.2.0"
31source = "registry+https://github.com/rust-lang/crates.io-index"
32checksum = "29b6ad25ae296159fb0da12b970b2fe179b234584d7cd294c891e2bbb284466b"
33dependencies = [
34 "num-traits",
35]
36
37[[package]]
38name = "countme"
39version = "2.0.4"
40source = "registry+https://github.com/rust-lang/crates.io-index"
41checksum = "328b822bdcba4d4e402be8d9adb6eebf269f969f8eadef977a553ff3c4fbcb58"
42
43[[package]]
44name = "hashbrown"
45version = "0.9.1"
46source = "registry+https://github.com/rust-lang/crates.io-index"
47checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
48
49[[package]]
50name = "if_chain"
51version = "1.0.2"
52source = "registry+https://github.com/rust-lang/crates.io-index"
53checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
54
55[[package]]
56name = "lazy_static"
57version = "1.4.0"
58source = "registry+https://github.com/rust-lang/crates.io-index"
59checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
60
61[[package]]
62name = "lib"
63version = "0.1.0"
64dependencies = [
65 "if_chain",
66 "lazy_static",
67 "macros",
68 "rnix",
69]
70
71[[package]]
72name = "macros"
73version = "0.1.0"
74dependencies = [
75 "proc-macro2",
76 "quote",
77 "syn",
78]
79
80[[package]]
81name = "memoffset"
82version = "0.6.4"
83source = "registry+https://github.com/rust-lang/crates.io-index"
84checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
85dependencies = [
86 "autocfg",
87]
88
89[[package]]
90name = "num-traits"
91version = "0.2.14"
92source = "registry+https://github.com/rust-lang/crates.io-index"
93checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
94dependencies = [
95 "autocfg",
96]
97
98[[package]]
99name = "proc-macro2"
100version = "1.0.29"
101source = "registry+https://github.com/rust-lang/crates.io-index"
102checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
103dependencies = [
104 "unicode-xid",
105]
106
107[[package]]
108name = "quote"
109version = "1.0.9"
110source = "registry+https://github.com/rust-lang/crates.io-index"
111checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
112dependencies = [
113 "proc-macro2",
114]
115
116[[package]]
117name = "rnix"
118version = "0.9.0"
119source = "registry+https://github.com/rust-lang/crates.io-index"
120checksum = "1b37f8af07a0354606141df076458660af7e22238e4117a041c21c548080addd"
121dependencies = [
122 "cbitset",
123 "rowan",
124 "smol_str",
125]
126
127[[package]]
128name = "rowan"
129version = "0.12.6"
130source = "registry+https://github.com/rust-lang/crates.io-index"
131checksum = "a1b36e449f3702f3b0c821411db1cbdf30fb451726a9456dce5dabcd44420043"
132dependencies = [
133 "countme",
134 "hashbrown",
135 "memoffset",
136 "rustc-hash",
137 "text-size",
138]
139
140[[package]]
141name = "rustc-hash"
142version = "1.1.0"
143source = "registry+https://github.com/rust-lang/crates.io-index"
144checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
145
146[[package]]
147name = "smol_str"
148version = "0.1.18"
149source = "registry+https://github.com/rust-lang/crates.io-index"
150checksum = "b203e79e90905594272c1c97c7af701533d42adaab0beb3859018e477d54a3b0"
151
152[[package]]
153name = "syn"
154version = "1.0.76"
155source = "registry+https://github.com/rust-lang/crates.io-index"
156checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84"
157dependencies = [
158 "proc-macro2",
159 "quote",
160 "unicode-xid",
161]
162
163[[package]]
164name = "text-size"
165version = "1.1.0"
166source = "registry+https://github.com/rust-lang/crates.io-index"
167checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a"
168
169[[package]]
170name = "unicode-xid"
171version = "0.2.2"
172source = "registry+https://github.com/rust-lang/crates.io-index"
173checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
174
175[[package]]
176name = "yansi"
177version = "0.5.0"
178source = "registry+https://github.com/rust-lang/crates.io-index"
179checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71"
diff --git a/lib/Cargo.toml b/lib/Cargo.toml
index 49e2e49..e371c5d 100644
--- a/lib/Cargo.toml
+++ b/lib/Cargo.toml
@@ -6,3 +6,7 @@ edition = "2018"
6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 7
8[dependencies] 8[dependencies]
9rnix = "0.9.0"
10if_chain = "1.0"
11macros = { path = "../macros" }
12lazy_static = "1.0"
diff --git a/lib/src/lib.rs b/lib/src/lib.rs
index 31e1bb2..537f4b3 100644
--- a/lib/src/lib.rs
+++ b/lib/src/lib.rs
@@ -1,7 +1,47 @@
1#[cfg(test)] 1pub mod lints;
2mod tests { 2
3 #[test] 3use rnix::{SyntaxElement, SyntaxKind, TextRange};
4 fn it_works() { 4use std::ops::Deref;
5 assert_eq!(2 + 2, 4); 5
6pub trait Rule {
7 fn validate(&self, node: &SyntaxElement) -> Option<Diagnostic>;
8}
9
10#[derive(Debug)]
11pub struct Diagnostic {
12 pub at: TextRange,
13 pub message: String,
14}
15
16impl Diagnostic {
17 pub fn new(at: TextRange, message: String) -> Self {
18 Self { at, message }
6 } 19 }
7} 20}
21
22pub trait Metadata {
23 fn name(&self) -> &str;
24 fn note(&self) -> &str;
25 fn match_with(&self, with: &SyntaxKind) -> bool;
26}
27
28pub trait Lint: Metadata + Rule + Send + Sync {}
29
30// #[macro_export]
31// macro_rules! lint_map {
32// ($($s:ident),*,) => {
33// lint_map($($s),*);
34// }
35// ($($s:ident),*) => {
36// use ::std::collections::HashMap;
37// use rnix::SyntaxKind;
38// $(
39// mod $s;
40// )*
41// ::lazy_static::lazy_static! {
42// pub static ref RULES: HashMap<SyntaxKind, &'static Box<dyn $crate::Lint>> = {
43// vec![$(&*$s::LINT,)*]
44// }
45// }
46// }
47// }
diff --git a/lib/src/lints.rs b/lib/src/lints.rs
new file mode 100644
index 0000000..b0df71b
--- /dev/null
+++ b/lib/src/lints.rs
@@ -0,0 +1,2 @@
1pub mod bool_comparison;
2pub mod with_list;
diff --git a/lib/src/lints/bool_comparison.rs b/lib/src/lints/bool_comparison.rs
new file mode 100644
index 0000000..4476b31
--- /dev/null
+++ b/lib/src/lints/bool_comparison.rs
@@ -0,0 +1,78 @@
1use crate::{Diagnostic, Lint, Metadata, Rule};
2
3use if_chain::if_chain;
4use macros::lint;
5use rnix::{
6 types::{BinOp, BinOpKind, Ident, TokenWrapper, TypedNode},
7 NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode,
8};
9
10#[lint(
11 name = "bool_comparison",
12 note = "Unnecessary comparison with boolean",
13 match_with = "SyntaxKind::NODE_BIN_OP"
14)]
15struct BoolComparison;
16
17impl Rule for BoolComparison {
18 fn validate(&self, node: &SyntaxElement) -> Option<Diagnostic> {
19 if_chain! {
20 if let NodeOrToken::Node(bin_op_node) = node;
21 if let Some(bin_expr) = BinOp::cast(bin_op_node.clone());
22 if let Some(lhs) = bin_expr.lhs();
23 if let Some(rhs) = bin_expr.rhs();
24
25 if let BinOpKind::Equal | BinOpKind::NotEqual = bin_expr.operator();
26 let (non_bool_side, bool_side) = if is_boolean_ident(&lhs) {
27 (rhs, lhs)
28 } else if is_boolean_ident(&rhs) {
29 (lhs, rhs)
30 } else {
31 return None
32 };
33 then {
34 let at = node.text_range();
35 let message = format!(
36 "Comparing `{}` with boolean literal `{}`",
37 non_bool_side,
38 bool_side
39 );
40 dbg!(Some(Diagnostic::new(at, message)))
41 } else {
42 None
43 }
44 }
45 }
46}
47
48// not entirely accurate, underhanded nix programmers might write `true = false`
49fn is_boolean_ident(node: &SyntaxNode) -> bool {
50 if let Some(ident_expr) = Ident::cast(node.clone()) {
51 ident_expr.as_str() == "true" || ident_expr.as_str() == "false"
52 } else {
53 false
54 }
55}
56
57// #[cfg(test)]
58// mod tests {
59// use super::*;
60// use rnix::{parser, WalkEvent};
61//
62// #[test]
63// fn trivial() {
64// let src = r#"
65// a == true
66// "#;
67// let parsed = rnix::parse(src).as_result().ok().unwrap();
68// let _ = parsed
69// .node()
70// .preorder_with_tokens()
71// .filter_map(|event| match event {
72// WalkEvent::Enter(t) => Some(t),
73// _ => None,
74// })
75// .map(|node| BoolComparison.validate(&node))
76// .collect::<Vec<_>>();
77// }
78// }