diff options
Diffstat (limited to 'lib/src/lib.rs')
-rw-r--r-- | lib/src/lib.rs | 76 |
1 files changed, 52 insertions, 24 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; | |||
6 | use rnix::{SyntaxElement, SyntaxKind, TextRange}; | 6 | use rnix::{SyntaxElement, SyntaxKind, TextRange}; |
7 | use std::{default::Default, convert::Into}; | 7 | use std::{default::Default, convert::Into}; |
8 | 8 | ||
9 | pub trait Rule { | 9 | /// Report generated by a lint |
10 | fn validate(&self, node: &SyntaxElement) -> Option<Report>; | 10 | #[derive(Debug, Default)] |
11 | pub 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 | |||
20 | impl 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)] |
14 | pub struct Diagnostic { | 45 | pub struct Diagnostic { |
15 | pub at: TextRange, | 46 | pub at: TextRange, |
@@ -18,14 +49,18 @@ pub struct Diagnostic { | |||
18 | } | 49 | } |
19 | 50 | ||
20 | impl Diagnostic { | 51 | impl 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)] |
30 | pub struct Suggestion { | 65 | pub struct Suggestion { |
31 | pub at: TextRange, | 66 | pub at: TextRange, |
@@ -33,6 +68,7 @@ pub struct Suggestion { | |||
33 | } | 68 | } |
34 | 69 | ||
35 | impl Suggestion { | 70 | impl 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, |
45 | pub struct Report { | 81 | /// look at the `lint` attribute macro instead for implementing rules |
46 | pub diagnostics: Vec<Diagnostic>, | 82 | pub trait Rule { |
47 | pub note: &'static str | 83 | fn validate(&self, node: &SyntaxElement) -> Option<Report>; |
48 | } | ||
49 | |||
50 | impl 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 | ||
68 | pub trait Metadata { | 88 | pub 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. | ||
75 | pub trait Lint: Metadata + Rule + Send + Sync {} | 99 | pub 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] |
78 | macro_rules! lint_map { | 106 | macro_rules! lint_map { |
79 | ($($s:ident),*,) => { | 107 | ($($s:ident),*,) => { |