1
1
use crate :: core:: { Edition , Feature , Features , Manifest , Package } ;
2
2
use crate :: { CargoResult , GlobalContext } ;
3
- use annotate_snippets:: { Level , Snippet } ;
3
+ use annotate_snippets:: { AnnotationKind , Group , Level , Snippet } ;
4
4
use cargo_util_schemas:: manifest:: { TomlLintLevel , TomlToolLints } ;
5
5
use pathdiff:: diff_paths;
6
6
use std:: fmt:: Display ;
@@ -133,78 +133,69 @@ fn verify_feature_enabled(
133
133
dash_feature_name
134
134
) ;
135
135
136
- let message = if let Some ( span) =
137
- get_span ( manifest. document ( ) , & [ "lints" , "cargo" , lint_name] , false )
136
+ let ( contents , path , span ) = if let Some ( span) =
137
+ get_key_value_span ( manifest. document ( ) , & [ "lints" , "cargo" , lint_name] )
138
138
{
139
- Level :: Error
140
- . title ( & title)
141
- . snippet (
142
- Snippet :: source ( manifest. contents ( ) )
143
- . origin ( & manifest_path)
144
- . annotation ( Level :: Error . span ( span) . label ( & label) )
145
- . fold ( true ) ,
146
- )
147
- . footer ( Level :: Help . title ( & help) )
139
+ ( manifest. contents ( ) , manifest_path, span)
140
+ } else if let Some ( lint_span) =
141
+ get_key_value_span ( ws_document, & [ "workspace" , "lints" , "cargo" , lint_name] )
142
+ {
143
+ ( ws_contents, ws_path, lint_span)
148
144
} else {
149
- let lint_span = get_span (
150
- ws_document,
151
- & [ "workspace" , "lints" , "cargo" , lint_name] ,
152
- false ,
153
- )
154
- . unwrap_or_else ( || {
155
- panic ! ( "could not find `cargo::{lint_name}` in `[lints]`, or `[workspace.lints]` " )
156
- } ) ;
145
+ panic ! ( "could not find `cargo::{lint_name}` in `[lints]`, or `[workspace.lints]` " )
146
+ } ;
157
147
158
- let inherited_note = if let ( Some ( inherit_span_key) , Some ( inherit_span_value) ) = (
159
- get_span ( manifest. document ( ) , & [ "lints" , "workspace" ] , false ) ,
160
- get_span ( manifest. document ( ) , & [ "lints" , "workspace" ] , true ) ,
161
- ) {
162
- Level :: Note . title ( & second_title) . snippet (
148
+ let mut report = Vec :: new ( ) ;
149
+ report. push (
150
+ Group :: with_title ( Level :: ERROR . primary_title ( title) )
151
+ . element (
152
+ Snippet :: source ( contents)
153
+ . path ( path)
154
+ . annotation ( AnnotationKind :: Primary . span ( span. key ) . label ( label) ) ,
155
+ )
156
+ . element ( Level :: HELP . message ( help) ) ,
157
+ ) ;
158
+
159
+ if let Some ( inherit_span) = get_key_value_span ( manifest. document ( ) , & [ "lints" , "workspace" ] )
160
+ {
161
+ report. push (
162
+ Group :: with_title ( Level :: NOTE . secondary_title ( second_title) ) . element (
163
163
Snippet :: source ( manifest. contents ( ) )
164
- . origin ( & manifest_path)
164
+ . path ( manifest_path)
165
165
. annotation (
166
- Level :: Note . span ( inherit_span_key. start ..inherit_span_value. end ) ,
167
- )
168
- . fold ( true ) ,
169
- )
170
- } else {
171
- Level :: Note . title ( & second_title)
172
- } ;
173
-
174
- Level :: Error
175
- . title ( & title)
176
- . snippet (
177
- Snippet :: source ( ws_contents)
178
- . origin ( & ws_path)
179
- . annotation ( Level :: Error . span ( lint_span) . label ( & label) )
180
- . fold ( true ) ,
181
- )
182
- . footer ( inherited_note)
183
- . footer ( Level :: Help . title ( & help) )
184
- } ;
166
+ AnnotationKind :: Context
167
+ . span ( inherit_span. key . start ..inherit_span. value . end ) ,
168
+ ) ,
169
+ ) ,
170
+ ) ;
171
+ }
185
172
186
173
* error_count += 1 ;
187
- gctx. shell ( ) . print_message ( message ) ?;
174
+ gctx. shell ( ) . print_report ( & report ) ?;
188
175
}
189
176
Ok ( ( ) )
190
177
}
191
178
192
- pub fn get_span (
179
+ #[ derive( Clone ) ]
180
+ pub struct TomlSpan {
181
+ pub key : Range < usize > ,
182
+ pub value : Range < usize > ,
183
+ }
184
+
185
+ pub fn get_key_value_span (
193
186
document : & toml:: Spanned < toml:: de:: DeTable < ' static > > ,
194
187
path : & [ & str ] ,
195
- get_value : bool ,
196
- ) -> Option < Range < usize > > {
188
+ ) -> Option < TomlSpan > {
197
189
let mut table = document. get_ref ( ) ;
198
190
let mut iter = path. into_iter ( ) . peekable ( ) ;
199
191
while let Some ( key) = iter. next ( ) {
200
192
let key_s: & str = key. as_ref ( ) ;
201
193
let ( key, item) = table. get_key_value ( key_s) ?;
202
194
if iter. peek ( ) . is_none ( ) {
203
- return if get_value {
204
- Some ( item. span ( ) )
205
- } else {
206
- Some ( key. span ( ) )
207
- } ;
195
+ return Some ( TomlSpan {
196
+ key : key. span ( ) ,
197
+ value : item. span ( ) ,
198
+ } ) ;
208
199
}
209
200
if let Some ( next_table) = item. get_ref ( ) . as_table ( ) {
210
201
table = next_table;
@@ -213,7 +204,10 @@ pub fn get_span(
213
204
if let Some ( array) = item. get_ref ( ) . as_array ( ) {
214
205
let next = iter. next ( ) . unwrap ( ) ;
215
206
return array. iter ( ) . find_map ( |item| match item. get_ref ( ) {
216
- toml:: de:: DeValue :: String ( s) if s == next => Some ( item. span ( ) ) ,
207
+ toml:: de:: DeValue :: String ( s) if s == next => Some ( TomlSpan {
208
+ key : key. span ( ) ,
209
+ value : item. span ( ) ,
210
+ } ) ,
217
211
_ => None ,
218
212
} ) ;
219
213
}
@@ -337,12 +331,12 @@ impl LintLevel {
337
331
self == & LintLevel :: Forbid || self == & LintLevel :: Deny
338
332
}
339
333
340
- pub fn to_diagnostic_level ( self ) -> Level {
334
+ pub fn to_diagnostic_level ( self ) -> Level < ' static > {
341
335
match self {
342
336
LintLevel :: Allow => unreachable ! ( "allow does not map to a diagnostic level" ) ,
343
- LintLevel :: Warn => Level :: Warning ,
344
- LintLevel :: Deny => Level :: Error ,
345
- LintLevel :: Forbid => Level :: Error ,
337
+ LintLevel :: Warn => Level :: WARNING ,
338
+ LintLevel :: Deny => Level :: ERROR ,
339
+ LintLevel :: Forbid => Level :: ERROR ,
346
340
}
347
341
}
348
342
}
@@ -455,19 +449,17 @@ pub fn check_im_a_teapot(
455
449
let manifest_path = rel_cwd_manifest_path ( path, gctx) ;
456
450
let emitted_reason = IM_A_TEAPOT . emitted_source ( lint_level, reason) ;
457
451
458
- let key_span = get_span ( manifest. document ( ) , & [ "package" , "im-a-teapot" ] , false ) . unwrap ( ) ;
459
- let value_span = get_span ( manifest. document ( ) , & [ "package" , "im-a-teapot" ] , true ) . unwrap ( ) ;
460
- let message = level
461
- . title ( IM_A_TEAPOT . desc )
462
- . snippet (
452
+ let span = get_key_value_span ( manifest. document ( ) , & [ "package" , "im-a-teapot" ] ) . unwrap ( ) ;
453
+
454
+ let report = & [ Group :: with_title ( level. primary_title ( IM_A_TEAPOT . desc ) )
455
+ . element (
463
456
Snippet :: source ( manifest. contents ( ) )
464
- . origin ( & manifest_path)
465
- . annotation ( level. span ( key_span. start ..value_span. end ) )
466
- . fold ( true ) ,
457
+ . path ( & manifest_path)
458
+ . annotation ( AnnotationKind :: Primary . span ( span. key . start ..span. value . end ) ) ,
467
459
)
468
- . footer ( Level :: Note . title ( & emitted_reason) ) ;
460
+ . element ( Level :: NOTE . message ( & emitted_reason) ) ] ;
469
461
470
- gctx. shell ( ) . print_message ( message ) ?;
462
+ gctx. shell ( ) . print_report ( report ) ?;
471
463
}
472
464
Ok ( ( ) )
473
465
}
@@ -535,64 +527,48 @@ fn output_unknown_lints(
535
527
let help =
536
528
matching. map ( |( name, kind) | format ! ( "there is a {kind} with a similar name: `{name}`" ) ) ;
537
529
538
- let mut footers = Vec :: new ( ) ;
530
+ let ( contents, path, span) = if let Some ( span) =
531
+ get_key_value_span ( manifest. document ( ) , & [ "lints" , "cargo" , lint_name] )
532
+ {
533
+ ( manifest. contents ( ) , manifest_path, span)
534
+ } else if let Some ( lint_span) =
535
+ get_key_value_span ( ws_document, & [ "workspace" , "lints" , "cargo" , lint_name] )
536
+ {
537
+ ( ws_contents, ws_path, lint_span)
538
+ } else {
539
+ panic ! ( "could not find `cargo::{lint_name}` in `[lints]`, or `[workspace.lints]` " )
540
+ } ;
541
+
542
+ let mut report = Vec :: new ( ) ;
543
+ let mut group = Group :: with_title ( level. clone ( ) . primary_title ( title) ) . element (
544
+ Snippet :: source ( contents)
545
+ . path ( path)
546
+ . annotation ( AnnotationKind :: Primary . span ( span. key ) ) ,
547
+ ) ;
539
548
if emitted_source. is_none ( ) {
540
549
emitted_source = Some ( UNKNOWN_LINTS . emitted_source ( lint_level, reason) ) ;
541
- footers . push ( Level :: Note . title ( emitted_source. as_ref ( ) . unwrap ( ) ) ) ;
550
+ group = group . element ( Level :: NOTE . message ( emitted_source. as_ref ( ) . unwrap ( ) ) ) ;
542
551
}
552
+ if let Some ( help) = help. as_ref ( ) {
553
+ group = group. element ( Level :: HELP . message ( help) ) ;
554
+ }
555
+ report. push ( group) ;
543
556
544
- let mut message = if let Some ( span) =
545
- get_span ( manifest. document ( ) , & [ "lints" , "cargo" , lint_name] , false )
557
+ if let Some ( inherit_span) = get_key_value_span ( manifest. document ( ) , & [ "lints" , "workspace" ] )
546
558
{
547
- level. title ( & title) . snippet (
548
- Snippet :: source ( manifest. contents ( ) )
549
- . origin ( & manifest_path)
550
- . annotation ( Level :: Error . span ( span) )
551
- . fold ( true ) ,
552
- )
553
- } else {
554
- let lint_span = get_span (
555
- ws_document,
556
- & [ "workspace" , "lints" , "cargo" , lint_name] ,
557
- false ,
558
- )
559
- . unwrap_or_else ( || {
560
- panic ! ( "could not find `cargo::{lint_name}` in `[lints]`, or `[workspace.lints]` " )
561
- } ) ;
562
-
563
- let inherited_note = if let ( Some ( inherit_span_key) , Some ( inherit_span_value) ) = (
564
- get_span ( manifest. document ( ) , & [ "lints" , "workspace" ] , false ) ,
565
- get_span ( manifest. document ( ) , & [ "lints" , "workspace" ] , true ) ,
566
- ) {
567
- Level :: Note . title ( & second_title) . snippet (
559
+ report. push (
560
+ Group :: with_title ( Level :: NOTE . secondary_title ( second_title) ) . element (
568
561
Snippet :: source ( manifest. contents ( ) )
569
- . origin ( & manifest_path)
562
+ . path ( manifest_path)
570
563
. annotation (
571
- Level :: Note . span ( inherit_span_key. start ..inherit_span_value. end ) ,
572
- )
573
- . fold ( true ) ,
574
- )
575
- } else {
576
- Level :: Note . title ( & second_title)
577
- } ;
578
- footers. push ( inherited_note) ;
579
-
580
- level. title ( & title) . snippet (
581
- Snippet :: source ( ws_contents)
582
- . origin ( & ws_path)
583
- . annotation ( Level :: Error . span ( lint_span) )
584
- . fold ( true ) ,
585
- )
586
- } ;
587
-
588
- if let Some ( help) = help. as_ref ( ) {
589
- footers. push ( Level :: Help . title ( help) ) ;
590
- }
591
- for footer in footers {
592
- message = message. footer ( footer) ;
564
+ AnnotationKind :: Context
565
+ . span ( inherit_span. key . start ..inherit_span. value . end ) ,
566
+ ) ,
567
+ ) ,
568
+ ) ;
593
569
}
594
570
595
- gctx. shell ( ) . print_message ( message ) ?;
571
+ gctx. shell ( ) . print_report ( & report ) ?;
596
572
}
597
573
598
574
Ok ( ( ) )
0 commit comments