aboutsummaryrefslogtreecommitdiff
path: root/lib/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/src')
-rw-r--r--lib/src/lib.rs76
-rw-r--r--lib/src/lints/bool_comparison.rs6
2 files changed, 54 insertions, 28 deletions
diff --git a/lib/src/lib.rs b/lib/src/lib.rs
index 0f92d0d..93792d4 100644
--- a/lib/src/lib.rs
+++ b/lib/src/lib.rs
@@ -6,10 +6,41 @@ pub use lints::LINTS;
6use rnix::{SyntaxElement, SyntaxKind, TextRange}; 6use rnix::{SyntaxElement, SyntaxKind, TextRange};
7use std::{default::Default, convert::Into}; 7use std::{default::Default, convert::Into};
8 8
9pub trait Rule { 9/// Report generated by a lint
10 fn validate(&self, node: &SyntaxElement) -> Option<Report>; 10#[derive(Debug, Default)]
11pub struct Report {
12 /// General information about this lint and where it applies.
13 pub note: &'static str,
14 /// An error code to uniquely identify this lint
15 pub code: u32,
16 /// Collection of diagnostics raised by this lint
17 pub diagnostics: Vec<Diagnostic>,
18}
19
20impl Report {
21 /// Construct a report. Do not invoke manually, see `lint` macro
22 pub fn new(note: &'static str, code: u32) -> Self {
23 Self {
24 note,
25 code,
26 ..Default::default()
27 }
28 }
29 /// Add a diagnostic to this report
30 pub fn diagnostic(mut self, at: TextRange, message: String) -> Self {
31 self.diagnostics.push(Diagnostic::new(at, message));
32 self
33 }
34 /// Add a diagnostic with a fix to this report
35 pub fn suggest(mut self, at: TextRange, message: String, suggestion: Suggestion) -> Self {
36 self.diagnostics.push(Diagnostic::suggest(at, message, suggestion));
37 self
38 }
39
11} 40}
12 41
42/// Mapping from a bytespan to an error message.
43/// Can optionally suggest a fix.
13#[derive(Debug)] 44#[derive(Debug)]
14pub struct Diagnostic { 45pub struct Diagnostic {
15 pub at: TextRange, 46 pub at: TextRange,
@@ -18,14 +49,18 @@ pub struct Diagnostic {
18} 49}
19 50
20impl Diagnostic { 51impl Diagnostic {
52 /// Construct a diagnostic.
21 pub fn new(at: TextRange, message: String) -> Self { 53 pub fn new(at: TextRange, message: String) -> Self {
22 Self { at, message, suggestion: None } 54 Self { at, message, suggestion: None }
23 } 55 }
56 /// Construct a diagnostic with a fix.
24 pub fn suggest(at: TextRange, message: String, suggestion: Suggestion) -> Self { 57 pub fn suggest(at: TextRange, message: String, suggestion: Suggestion) -> Self {
25 Self { at, message, suggestion: Some(suggestion) } 58 Self { at, message, suggestion: Some(suggestion) }
26 } 59 }
27} 60}
28 61
62/// Suggested fix for a diagnostic, the fix is provided as a syntax element.
63/// Look at `make.rs` to construct fixes.
29#[derive(Debug)] 64#[derive(Debug)]
30pub struct Suggestion { 65pub struct Suggestion {
31 pub at: TextRange, 66 pub at: TextRange,
@@ -33,6 +68,7 @@ pub struct Suggestion {
33} 68}
34 69
35impl Suggestion { 70impl Suggestion {
71 /// Construct a suggestion.
36 pub fn new<E: Into<SyntaxElement>>(at: TextRange, fix: E) -> Self { 72 pub fn new<E: Into<SyntaxElement>>(at: TextRange, fix: E) -> Self {
37 Self { 73 Self {
38 at, 74 at,
@@ -41,39 +77,31 @@ impl Suggestion {
41 } 77 }
42} 78}
43 79
44#[derive(Debug, Default)] 80/// Lint logic is defined via this trait. Do not implement manually,
45pub struct Report { 81/// look at the `lint` attribute macro instead for implementing rules
46 pub diagnostics: Vec<Diagnostic>, 82pub trait Rule {
47 pub note: &'static str 83 fn validate(&self, node: &SyntaxElement) -> Option<Report>;
48}
49
50impl Report {
51 pub fn new(note: &'static str) -> Self {
52 Self {
53 note,
54 ..Default::default()
55 }
56 }
57 pub fn diagnostic(mut self, at: TextRange, message: String) -> Self {
58 self.diagnostics.push(Diagnostic::new(at, message));
59 self
60 }
61 pub fn suggest(mut self, at: TextRange, message: String, suggestion: Suggestion) -> Self {
62 self.diagnostics.push(Diagnostic::suggest(at, message, suggestion));
63 self
64 }
65
66} 84}
67 85
86/// Contains information about the lint itself. Do not implement manually,
87/// look at the `lint` attribute macro instead for implementing rules
68pub trait Metadata { 88pub trait Metadata {
69 fn name() -> &'static str where Self: Sized; 89 fn name() -> &'static str where Self: Sized;
70 fn note() -> &'static str where Self: Sized; 90 fn note() -> &'static str where Self: Sized;
91 fn code() -> u32 where Self: Sized;
92 fn report() -> Report where Self: Sized;
71 fn match_with(&self, with: &SyntaxKind) -> bool; 93 fn match_with(&self, with: &SyntaxKind) -> bool;
72 fn match_kind(&self) -> SyntaxKind; 94 fn match_kind(&self) -> SyntaxKind;
73} 95}
74 96
97/// Combines Rule and Metadata, do not implement manually, this is derived by
98/// the `lint` macro.
75pub trait Lint: Metadata + Rule + Send + Sync {} 99pub trait Lint: Metadata + Rule + Send + Sync {}
76 100
101/// Helper utility to take lints from modules and insert them into a map for efficient
102/// access. Mapping is from a SyntaxKind to a list of lints that apply on that Kind.
103///
104/// See `lints.rs` for usage.
77#[macro_export] 105#[macro_export]
78macro_rules! lint_map { 106macro_rules! lint_map {
79 ($($s:ident),*,) => { 107 ($($s:ident),*,) => {
diff --git a/lib/src/lints/bool_comparison.rs b/lib/src/lints/bool_comparison.rs
index f869e17..d23a4b0 100644
--- a/lib/src/lints/bool_comparison.rs
+++ b/lib/src/lints/bool_comparison.rs
@@ -10,6 +10,7 @@ use rnix::{
10#[lint( 10#[lint(
11 name = "bool_comparison", 11 name = "bool_comparison",
12 note = "Unnecessary comparison with boolean", 12 note = "Unnecessary comparison with boolean",
13 code = 1,
13 match_with = SyntaxKind::NODE_BIN_OP 14 match_with = SyntaxKind::NODE_BIN_OP
14)] 15)]
15struct BoolComparison; 16struct BoolComparison;
@@ -70,10 +71,7 @@ impl Rule for BoolComparison {
70 non_bool_side, 71 non_bool_side,
71 bool_side 72 bool_side
72 ); 73 );
73 Some( 74 Some(Self::report().suggest(at, message, Suggestion::new(at, replacement)))
74 Report::new(Self::note())
75 .suggest(at, message, Suggestion::new(at, replacement))
76 )
77 } else { 75 } else {
78 None 76 None
79 } 77 }