1+ use forge_lint:: { linter:: Lint , sol:: med:: REGISTERED_LINTS } ;
12use foundry_config:: { LintSeverity , LinterConfig } ;
23
34const CONTRACT : & str = r#"
@@ -53,6 +54,7 @@ warning[divide-before-multiply]: multiplication should occur before division to
535416 | (1 / 2) * 3;
5455 | -----------
5556 |
57+ = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply
5658
5759
5860"# ] ] ) ;
@@ -75,6 +77,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase
75776 | uint256 VARIABLE_MIXED_CASE_INFO;
7678 | ------------------------
7779 |
80+ = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable
7881
7982
8083"# ] ] ) ;
@@ -109,6 +112,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase
1091126 | uint256 VARIABLE_MIXED_CASE_INFO;
110113 | ------------------------
111114 |
115+ = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable
112116
113117
114118"# ] ] ) ;
@@ -134,6 +138,7 @@ warning[divide-before-multiply]: multiplication should occur before division to
13413816 | (1 / 2) * 3;
135139 | -----------
136140 |
141+ = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply
137142
138143
139144"# ] ] ) ;
@@ -160,8 +165,56 @@ warning[incorrect-shift]: the order of args in a shift operation is incorrect
16016513 | result = 8 >> localValue;
161166 | ---------------
162167 |
168+ = help: https://book.getfoundry.sh/reference/forge/forge-lint#incorrect-shift
163169
164170
165171"#
166172 ] ] ) ;
167173} ) ;
174+
175+ #[ tokio:: test]
176+ async fn ensure_lint_rule_docs ( ) {
177+ const FOUNDRY_BOOK_LINT_PAGE_URL : & str =
178+ "https://book.getfoundry.sh/reference/forge/forge-lint" ;
179+
180+ // Fetch the content of the lint reference
181+ let content = match reqwest:: get ( FOUNDRY_BOOK_LINT_PAGE_URL ) . await {
182+ Ok ( resp) => {
183+ if !resp. status ( ) . is_success ( ) {
184+ panic ! (
185+ "Failed to fetch Foundry Book lint page ({FOUNDRY_BOOK_LINT_PAGE_URL}). Status: {status}" ,
186+ status = resp. status( )
187+ ) ;
188+ }
189+ match resp. text ( ) . await {
190+ Ok ( text) => text,
191+ Err ( e) => {
192+ panic ! ( "Failed to read response text: {e}" ) ;
193+ }
194+ }
195+ }
196+ Err ( e) => {
197+ panic ! ( "Failed to fetch Foundry Book lint page ({FOUNDRY_BOOK_LINT_PAGE_URL}): {e}" , ) ;
198+ }
199+ } ;
200+
201+ // Ensure no missing lints
202+ let mut missing_lints = Vec :: new ( ) ;
203+ for lint in REGISTERED_LINTS {
204+ let selector = format ! ( "#{}" , lint. id( ) ) ;
205+ if !content. contains ( & selector) {
206+ missing_lints. push ( lint. id ( ) ) ;
207+ }
208+ }
209+
210+ if !missing_lints. is_empty ( ) {
211+ let mut msg = String :: from (
212+ "Foundry Book lint validation failed. The following lints must be added to the docs:\n " ,
213+ ) ;
214+ for lint in missing_lints {
215+ msg. push_str ( & format ! ( " - {lint}\n " ) ) ;
216+ }
217+ msg. push_str ( "Please open a PR: https://github.com/foundry-rs/book" ) ;
218+ panic ! ( "{msg}" ) ;
219+ }
220+ }
0 commit comments