@@ -15,6 +15,7 @@ pub enum IgnoreKind {
1515pub struct Ignore {
1616 pub range : TextRange ,
1717 pub violation_names : HashSet < Rule > ,
18+ pub ignore_all : bool ,
1819 pub kind : IgnoreKind ,
1920}
2021
@@ -48,18 +49,22 @@ pub fn ignore_rule_info(token: &SyntaxToken) -> Option<(&str, TextRange, IgnoreK
4849 if let Some ( ( comment_body, range) ) = comment_body ( token) {
4950 let without_start = comment_body. trim_start ( ) ;
5051 let trim_start_size = comment_body. len ( ) - without_start. len ( ) ;
51- let trimmed_comment = without_start. trim_end ( ) ;
52- let trim_end_size = without_start. len ( ) - trimmed_comment. len ( ) ;
52+
53+ let without_end = without_start
54+ . find ( "--" )
55+ . map_or ( without_start, |idx| & without_start[ ..idx] )
56+ . trim_end ( ) ;
57+ let trim_end_size = without_start. len ( ) - without_end. len ( ) ;
5358
5459 for ( prefix, kind) in [
5560 ( IGNORE_FILE_TEXT , IgnoreKind :: File ) ,
5661 ( IGNORE_LINE_TEXT , IgnoreKind :: Line ) ,
5762 ] {
58- if let Some ( without_prefix) = trimmed_comment . strip_prefix ( prefix) {
59- let range = TextRange :: new (
60- range. start ( ) + TextSize :: new ( ( trim_start_size + prefix . len ( ) ) as u32 ) ,
61- range . end ( ) - TextSize :: new ( trim_end_size as u32 ) ,
62- ) ;
63+ if let Some ( without_prefix) = without_end . strip_prefix ( prefix) {
64+ let start = range . start ( ) + TextSize :: new ( ( trim_start_size + prefix . len ( ) ) as u32 ) ;
65+ let end = range. end ( ) - TextSize :: new ( trim_end_size as u32 ) ;
66+
67+ let range = TextRange :: new ( start , end ) ;
6368 return Some ( ( without_prefix, range, kind) ) ;
6469 }
6570 }
@@ -76,6 +81,10 @@ pub(crate) fn find_ignores(ctx: &mut Linter, file: &SyntaxNode) {
7681 if let Some ( ( rule_names, range, kind) ) = ignore_rule_info ( & token) {
7782 let mut set = HashSet :: new ( ) ;
7883 let mut offset = 0usize ;
84+ // We have a specific check instead of going off of empty
85+ // rules in case we have invalid rule names specified in the
86+ // ignore.
87+ let ignore_all = rule_names. trim ( ) . is_empty ( ) ;
7988
8089 // we need to keep track of our offset and report specific
8190 // ranges for any unknown names we encounter, which makes
@@ -109,6 +118,7 @@ pub(crate) fn find_ignores(ctx: &mut Linter, file: &SyntaxNode) {
109118 ctx. ignore ( Ignore {
110119 range,
111120 violation_names : set,
121+ ignore_all,
112122 kind,
113123 } ) ;
114124 }
@@ -506,4 +516,100 @@ alter table t2 drop column c2 cascade;
506516 ]
507517 " ) ;
508518 }
519+
520+ #[ test]
521+ fn file_ignore_with_invalid_rules ( ) {
522+ let mut linter = Linter :: with_all_rules ( ) ;
523+ let sql = r#"
524+ -- squawk-ignore-file ban-ban-ban-drop-column ignore-something hmm
525+ alter table t drop column c cascade;
526+ alter table t2 drop column c2 cascade;
527+ "# ;
528+
529+ let parse = squawk_syntax:: SourceFile :: parse ( sql) ;
530+ let errors = linter. lint ( & parse, sql) ;
531+ let errors: Vec < _ > = errors. iter ( ) . map ( |x| ( & x. code , & x. message ) ) . collect ( ) ;
532+
533+ assert_debug_snapshot ! ( errors, @r#"
534+ [
535+ (
536+ UnusedIgnore,
537+ "unknown name ban-ban-ban-drop-column ignore-something hmm",
538+ ),
539+ (
540+ RequireTimeoutSettings,
541+ "Missing `set lock_timeout` before potentially slow operations",
542+ ),
543+ (
544+ RequireTimeoutSettings,
545+ "Missing `set statement_timeout` before potentially slow operations",
546+ ),
547+ (
548+ BanDropColumn,
549+ "Dropping a column may break existing clients.",
550+ ),
551+ (
552+ PreferRobustStmts,
553+ "Missing `IF EXISTS`, the migration can't be rerun if it fails part way through.",
554+ ),
555+ (
556+ BanDropColumn,
557+ "Dropping a column may break existing clients.",
558+ ),
559+ (
560+ PreferRobustStmts,
561+ "Missing `IF EXISTS`, the migration can't be rerun if it fails part way through.",
562+ ),
563+ ]
564+ "# ) ;
565+ }
566+
567+ #[ test]
568+ fn file_ignore_with_trailing_comment ( ) {
569+ let mut linter = Linter :: with_all_rules ( ) ;
570+ let sql = r#"
571+ -- squawk-ignore-file ban-drop-column -- some comment here
572+ alter table t drop column c cascade;
573+ alter table t2 drop column c2 cascade;
574+ "# ;
575+
576+ let parse = squawk_syntax:: SourceFile :: parse ( sql) ;
577+ let errors: Vec < _ > = linter
578+ . lint ( & parse, sql)
579+ . into_iter ( )
580+ . map ( |x| x. code )
581+ . collect ( ) ;
582+
583+ assert_debug_snapshot ! ( errors, @"
584+ [
585+ RequireTimeoutSettings,
586+ RequireTimeoutSettings,
587+ PreferRobustStmts,
588+ PreferRobustStmts,
589+ ]
590+ " ) ;
591+ }
592+
593+ #[ test]
594+ fn line_ignore_with_trailing_comment ( ) {
595+ let mut linter = Linter :: with_all_rules ( ) ;
596+ let sql = r#"
597+ -- squawk-ignore ban-drop-column,prefer-robust-stmts -- drop is intentional
598+ alter table t drop column c cascade;
599+ "# ;
600+
601+ let parse = squawk_syntax:: SourceFile :: parse ( sql) ;
602+ let errors: Vec < _ > = linter
603+ . lint ( & parse, sql)
604+ . into_iter ( )
605+ . map ( |x| x. code )
606+ . collect ( ) ;
607+
608+ assert_debug_snapshot ! ( errors, @"
609+ [
610+ RequireTimeoutSettings,
611+ RequireTimeoutSettings,
612+ ]
613+ " ) ;
614+ }
509615}
0 commit comments