@@ -12,6 +12,160 @@ use std::ops::Range;
12
12
use std:: path:: Path ;
13
13
use toml_edit:: ImDocument ;
14
14
15
+ const LINTS : & [ Lint ] = & [ IM_A_TEAPOT , IMPLICIT_FEATURES , UNUSED_OPTIONAL_DEPENDENCY ] ;
16
+
17
+ pub fn verify_lints (
18
+ pkg : & Package ,
19
+ path : & Path ,
20
+ pkg_lints : & TomlToolLints ,
21
+ ws_lints : Option < & TomlToolLints > ,
22
+ ws_contents : & str ,
23
+ ws_document : & ImDocument < String > ,
24
+ ws_path : & Path ,
25
+ gctx : & GlobalContext ,
26
+ ) -> CargoResult < ( ) > {
27
+ let mut error_count = 0 ;
28
+ let manifest = pkg. manifest ( ) ;
29
+ let manifest_path = rel_cwd_manifest_path ( path, gctx) ;
30
+ let ws_path = rel_cwd_manifest_path ( ws_path, gctx) ;
31
+
32
+ for lint_name in pkg_lints
33
+ . keys ( )
34
+ . chain ( ws_lints. map ( |l| l. keys ( ) ) . unwrap_or_default ( ) )
35
+ {
36
+ if let Some ( lint) = LINTS . iter ( ) . find ( |l| l. name == lint_name) {
37
+ let ( _, reason) = lint. level ( pkg_lints, ws_lints, manifest. edition ( ) ) ;
38
+ if let Some ( feature_gate) = lint. feature_gate {
39
+ feature_gated_lint (
40
+ lint. name ,
41
+ feature_gate,
42
+ reason,
43
+ manifest,
44
+ & manifest_path,
45
+ ws_contents,
46
+ ws_document,
47
+ & ws_path,
48
+ & mut error_count,
49
+ gctx,
50
+ ) ?;
51
+ }
52
+ }
53
+ }
54
+ if error_count > 0 {
55
+ Err ( anyhow:: anyhow!(
56
+ "encountered {error_count} errors(s) while verifying lints" ,
57
+ ) )
58
+ } else {
59
+ Ok ( ( ) )
60
+ }
61
+ }
62
+
63
+ fn feature_gated_lint (
64
+ lint_name : & str ,
65
+ feature_gate : & Feature ,
66
+ reason : LintLevelReason ,
67
+ manifest : & Manifest ,
68
+ manifest_path : & str ,
69
+ ws_contents : & str ,
70
+ ws_document : & ImDocument < String > ,
71
+ ws_path : & str ,
72
+ error_count : & mut usize ,
73
+ gctx : & GlobalContext ,
74
+ ) -> CargoResult < ( ) > {
75
+ if !manifest. unstable_features ( ) . is_enabled ( feature_gate) {
76
+ let dash_name = lint_name. replace ( "_" , "-" ) ;
77
+ let dash_feature_name = feature_gate. name . replace ( "_" , "-" ) ;
78
+ let title = format ! ( "use of unstable lint `{}`" , dash_name) ;
79
+ let label = format ! (
80
+ "this is behind `{}`, which is not enabled" ,
81
+ dash_feature_name
82
+ ) ;
83
+ let second_title = format ! ( "`cargo::{}` was inherited" , dash_name) ;
84
+ let help = format ! (
85
+ "consider adding `cargo-features = [\" {}\" ]` to the top of the manifest" ,
86
+ dash_feature_name
87
+ ) ;
88
+ let message = match reason {
89
+ LintLevelReason :: Package => {
90
+ let span = get_span (
91
+ manifest. document ( ) ,
92
+ & [ "lints" , "cargo" , dash_name. as_str ( ) ] ,
93
+ false ,
94
+ )
95
+ . or ( get_span (
96
+ manifest. document ( ) ,
97
+ & [ "lints" , "cargo" , lint_name] ,
98
+ false ,
99
+ ) )
100
+ . unwrap ( ) ;
101
+ Some (
102
+ Level :: Error
103
+ . title ( & title)
104
+ . snippet (
105
+ Snippet :: source ( manifest. contents ( ) )
106
+ . origin ( & manifest_path)
107
+ . annotation ( Level :: Error . span ( span) . label ( & label) )
108
+ . fold ( true ) ,
109
+ )
110
+ . footer ( Level :: Help . title ( & help) ) ,
111
+ )
112
+ }
113
+ LintLevelReason :: Workspace => {
114
+ let lint_span = get_span (
115
+ ws_document,
116
+ & [ "workspace" , "lints" , "cargo" , dash_name. as_str ( ) ] ,
117
+ false ,
118
+ )
119
+ . or ( get_span (
120
+ ws_document,
121
+ & [ "workspace" , "lints" , "cargo" , lint_name] ,
122
+ false ,
123
+ ) )
124
+ . unwrap ( ) ;
125
+ let inherit_span_key =
126
+ get_span ( manifest. document ( ) , & [ "lints" , "workspace" ] , false ) . unwrap ( ) ;
127
+ let inherit_span_value =
128
+ get_span ( manifest. document ( ) , & [ "lints" , "workspace" ] , true ) . unwrap ( ) ;
129
+ Some (
130
+ Level :: Error
131
+ . title ( & title)
132
+ . snippet (
133
+ Snippet :: source ( ws_contents)
134
+ . origin ( & ws_path)
135
+ . annotation ( Level :: Error . span ( lint_span) . label ( & label) )
136
+ . fold ( true ) ,
137
+ )
138
+ . footer (
139
+ Level :: Note . title ( & second_title) . snippet (
140
+ Snippet :: source ( manifest. contents ( ) )
141
+ . origin ( & manifest_path)
142
+ . annotation (
143
+ Level :: Note
144
+ . span ( inherit_span_key. start ..inherit_span_value. end ) ,
145
+ )
146
+ . fold ( true ) ,
147
+ ) ,
148
+ )
149
+ . footer ( Level :: Help . title ( & help) ) ,
150
+ )
151
+ }
152
+ _ => None ,
153
+ } ;
154
+
155
+ if let Some ( message) = message {
156
+ * error_count += 1 ;
157
+ let renderer = Renderer :: styled ( ) . term_width (
158
+ gctx. shell ( )
159
+ . err_width ( )
160
+ . diagnostic_terminal_width ( )
161
+ . unwrap_or ( annotate_snippets:: renderer:: DEFAULT_TERM_WIDTH ) ,
162
+ ) ;
163
+ writeln ! ( gctx. shell( ) . err( ) , "{}" , renderer. render( message) ) ?;
164
+ }
165
+ }
166
+ Ok ( ( ) )
167
+ }
168
+
15
169
fn get_span ( document : & ImDocument < String > , path : & [ & str ] , get_value : bool ) -> Option < Range < usize > > {
16
170
let mut table = document. as_item ( ) . as_table_like ( ) ?;
17
171
let mut iter = path. into_iter ( ) . peekable ( ) ;
@@ -122,12 +276,6 @@ impl Lint {
122
276
. map ( |( _, ( l, r, _) ) | ( l, r) )
123
277
. unwrap ( )
124
278
}
125
-
126
- /// Returns true if the lint is feature gated and the feature is not enabled
127
- fn is_feature_gated ( & self , manifest : & Manifest ) -> bool {
128
- self . feature_gate
129
- . map_or ( false , |f| !manifest. unstable_features ( ) . is_enabled ( f) )
130
- }
131
279
}
132
280
133
281
#[ derive( Copy , Clone , Debug , PartialEq ) ]
@@ -250,39 +398,6 @@ pub fn check_im_a_teapot(
250
398
let manifest_path = rel_cwd_manifest_path ( path, gctx) ;
251
399
let ( lint_level, reason) = IM_A_TEAPOT . level ( pkg_lints, ws_lints, manifest. edition ( ) ) ;
252
400
253
- if IM_A_TEAPOT . is_feature_gated ( manifest) {
254
- if reason == LintLevelReason :: Package || reason == LintLevelReason :: Workspace {
255
- * error_count += 1 ;
256
- let span = get_span (
257
- manifest. document ( ) ,
258
- & [ "lints" , "cargo" , "im-a-teapot" ] ,
259
- false ,
260
- )
261
- . or ( get_span (
262
- manifest. document ( ) ,
263
- & [ "lints" , "cargo" , "im_a_teapot" ] ,
264
- false ,
265
- ) )
266
- . unwrap ( ) ;
267
- let message = Level :: Error
268
- . title ( "use of unstable lint `im-a-teapot`" )
269
- . snippet (
270
- Snippet :: source ( manifest. contents ( ) )
271
- . origin ( & manifest_path)
272
- . annotation ( Level :: Error . span ( span) )
273
- . fold ( true ) ,
274
- ) ;
275
- let renderer = Renderer :: styled ( ) . term_width (
276
- gctx. shell ( )
277
- . err_width ( )
278
- . diagnostic_terminal_width ( )
279
- . unwrap_or ( annotate_snippets:: renderer:: DEFAULT_TERM_WIDTH ) ,
280
- ) ;
281
- writeln ! ( gctx. shell( ) . err( ) , "{}" , renderer. render( message) ) ?;
282
- }
283
- return Ok ( ( ) ) ;
284
- }
285
-
286
401
if lint_level == LintLevel :: Allow {
287
402
return Ok ( ( ) ) ;
288
403
}
0 commit comments