1
1
use argh:: FromArgs ;
2
2
use rayon:: prelude:: * ;
3
- use serde :: Deserialize ;
4
- use std :: clone :: Clone ;
3
+ use select :: document :: Document ;
4
+ use select :: predicate :: { Class , Name , Predicate } ;
5
5
use std:: collections:: HashMap ;
6
+ use std:: fmt:: { self , Formatter } ;
6
7
use std:: fs;
7
8
use std:: path:: Path ;
8
9
use tokio:: runtime:: Runtime ;
9
10
10
11
use crate :: minify:: Minifier ;
11
12
use crate :: tasks:: Task ;
12
13
13
- const LINT_URL : & str = "https://rust-lang.github.io/rust-clippy/stable/lints.json " ;
14
- const LINTS_INDEX_PATH : & str = "../extension /index/lints.js" ;
14
+ const LINT_URL : & str = "https://rust-lang.github.io/rust-clippy/stable/index.html " ;
15
+ const LINTS_INDEX_PATH : & str = "../lib /index/lints.js" ;
15
16
16
17
/// Lint task
17
18
#[ derive( FromArgs ) ]
@@ -22,8 +23,7 @@ pub struct LintsTask {
22
23
dest_path : String ,
23
24
}
24
25
25
- #[ derive( Deserialize , Debug ) ]
26
- #[ serde( rename_all = "lowercase" ) ]
26
+ #[ derive( Debug ) ]
27
27
enum LintLevel {
28
28
Allow ,
29
29
Warn ,
@@ -32,27 +32,70 @@ enum LintLevel {
32
32
None ,
33
33
}
34
34
35
- impl ToString for LintLevel {
36
- fn to_string ( & self ) -> String {
35
+ impl fmt :: Display for LintLevel {
36
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt :: Result {
37
37
match self {
38
- Self :: Allow => "Allow" . to_string ( ) ,
39
- Self :: Warn => "Warn" . to_string ( ) ,
40
- Self :: Deny => "Deny" . to_string ( ) ,
41
- Self :: Deprecated => "Deprecated" . to_string ( ) ,
42
- Self :: None => "None" . to_string ( ) ,
38
+ Self :: Allow => write ! ( f , "Allow" ) ,
39
+ Self :: Warn => write ! ( f , "Warn" ) ,
40
+ Self :: Deny => write ! ( f , "Deny" ) ,
41
+ Self :: Deprecated => write ! ( f , "Deprecated" ) ,
42
+ Self :: None => write ! ( f , "None" ) ,
43
43
}
44
44
}
45
45
}
46
46
47
- #[ derive( Deserialize , Debug ) ]
48
47
struct Lint {
49
48
id : String ,
50
49
level : LintLevel ,
51
50
docs : Option < String > ,
52
51
}
53
52
54
53
async fn fetch_clippy_lints ( ) -> crate :: Result < Vec < Lint > > {
55
- let lints = reqwest:: get ( LINT_URL ) . await ?. json ( ) . await ?;
54
+ let html = reqwest:: get ( LINT_URL ) . await ?. text ( ) . await ?;
55
+ let document = Document :: from ( html. as_str ( ) ) ;
56
+
57
+ // Define custom predicate for articles that have panel class
58
+ let article_panel = Name ( "article" ) . and ( Class ( "panel" ) ) ;
59
+
60
+ let lints: Vec < Lint > = document
61
+ . find ( article_panel)
62
+ . filter_map ( |article| {
63
+ // Get lint ID from the panel-title-name span
64
+ let id = article
65
+ . find ( Class ( "panel-title-name" ) )
66
+ . next ( ) ?
67
+ . find ( Name ( "span" ) )
68
+ . next ( ) ?
69
+ . text ( )
70
+ . trim ( )
71
+ . to_string ( ) ;
72
+
73
+ // Get lint level from label-lint-level class
74
+ let level = article
75
+ . find ( Class ( "label-lint-level" ) )
76
+ . next ( ) ?
77
+ . text ( )
78
+ . trim ( )
79
+ . to_lowercase ( ) ;
80
+
81
+ let level = match level. as_str ( ) {
82
+ "allow" => LintLevel :: Allow ,
83
+ "warn" => LintLevel :: Warn ,
84
+ "deny" => LintLevel :: Deny ,
85
+ "deprecated" => LintLevel :: Deprecated ,
86
+ _ => LintLevel :: None ,
87
+ } ;
88
+
89
+ // Get full documentation from lint-doc-md class
90
+ let docs = article
91
+ . find ( Class ( "lint-doc-md" ) )
92
+ . next ( )
93
+ . map ( |doc| doc. text ( ) ) ;
94
+
95
+ Some ( Lint { id, level, docs } )
96
+ } )
97
+ . collect ( ) ;
98
+
56
99
Ok ( lints)
57
100
}
58
101
@@ -73,7 +116,7 @@ impl LintsTask {
73
116
if let Some ( docs) = lint
74
117
. docs
75
118
. as_ref ( )
76
- . and_then ( |d| d. trim ( ) . strip_prefix ( "### What it does" ) )
119
+ . and_then ( |d| d. trim ( ) . strip_prefix ( "What it does" ) )
77
120
{
78
121
let mut desc = docs. replace ( [ '`' , '#' ] , "" ) ;
79
122
desc. truncate ( 100 ) ;
@@ -90,7 +133,10 @@ impl LintsTask {
90
133
} )
91
134
. collect ( ) ;
92
135
93
- let contents = format ! ( "const lintsIndex={};export default lintsIndex;" , serde_json:: to_string( & lints) ?) ;
136
+ let contents = format ! (
137
+ "const lintsIndex={};export default lintsIndex;" ,
138
+ serde_json:: to_string( & lints) ?
139
+ ) ;
94
140
let path = Path :: new ( & self . dest_path ) ;
95
141
fs:: write ( path, Minifier :: minify_js ( & contents) ) ?;
96
142
println ! ( "\n Generate javascript lints index successful!" ) ;
0 commit comments