11use clippy_utils:: diagnostics:: span_lint_and_sugg;
2+ use clippy_utils:: numeric_literal:: { NumericLiteral , Radix } ;
23use clippy_utils:: source:: { snippet_opt, snippet_with_applicability} ;
34use clippy_utils:: { match_def_path, paths} ;
5+ use rustc_ast:: LitKind ;
46use rustc_errors:: Applicability ;
57use rustc_hir:: { Expr , ExprKind } ;
68use rustc_lint:: { LateContext , LateLintPass } ;
@@ -39,6 +41,24 @@ declare_clippy_lint! {
3941
4042declare_lint_pass ! ( NonOctalUnixPermissions => [ NON_OCTAL_UNIX_PERMISSIONS ] ) ;
4143
44+ fn check_binary_unix_permissions ( lit_kind : & LitKind , snip : & str ) -> bool {
45+ // support binary unix permissions
46+ if let Some ( num_lit) = NumericLiteral :: from_lit_kind ( snip, lit_kind) {
47+ if num_lit. radix != Radix :: Binary {
48+ return false ;
49+ }
50+
51+ let group_sizes: Vec < usize > = num_lit. integer . split ( '_' ) . map ( str:: len) . collect ( ) ;
52+ // check whether is binary format unix permissions
53+ if group_sizes. len ( ) != 3 {
54+ return false ;
55+ }
56+ group_sizes. iter ( ) . all ( |len| * len == 3 )
57+ } else {
58+ false
59+ }
60+ }
61+
4262impl < ' tcx > LateLintPass < ' tcx > for NonOctalUnixPermissions {
4363 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > ) {
4464 match & expr. kind {
@@ -51,26 +71,22 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
5171 ) )
5272 || ( path. ident . name == sym ! ( set_mode)
5373 && cx. tcx . is_diagnostic_item ( sym:: FsPermissions , adt. did ( ) ) ) )
54- && let ExprKind :: Lit ( _ ) = param. kind
74+ && let ExprKind :: Lit ( lit_kind ) = param. kind
5575 && param. span . eq_ctxt ( expr. span )
76+ && let Some ( snip) = snippet_opt ( cx, param. span )
77+ && !( snip. starts_with ( "0o" ) || check_binary_unix_permissions ( & lit_kind. node , & snip) )
5678 {
57- let Some ( snip) = snippet_opt ( cx, param. span ) else {
58- return ;
59- } ;
60-
61- if !snip. starts_with ( "0o" ) {
62- show_error ( cx, param) ;
63- }
79+ show_error ( cx, param) ;
6480 }
6581 } ,
6682 ExprKind :: Call ( func, [ param] ) => {
6783 if let ExprKind :: Path ( ref path) = func. kind
6884 && let Some ( def_id) = cx. qpath_res ( path, func. hir_id ) . opt_def_id ( )
6985 && match_def_path ( cx, def_id, & paths:: PERMISSIONS_FROM_MODE )
70- && let ExprKind :: Lit ( _ ) = param. kind
86+ && let ExprKind :: Lit ( lit_kind ) = param. kind
7187 && param. span . eq_ctxt ( expr. span )
7288 && let Some ( snip) = snippet_opt ( cx, param. span )
73- && !snip. starts_with ( "0o" )
89+ && !( snip. starts_with ( "0o" ) || check_binary_unix_permissions ( & lit_kind . node , & snip ) )
7490 {
7591 show_error ( cx, param) ;
7692 }
0 commit comments