1+ use crate :: problem:: npv_169;
2+ use crate :: ratchet:: RatchetState ;
13use relative_path:: RelativePath ;
24use relative_path:: RelativePathBuf ;
5+
6+ use rnix:: SyntaxKind ;
7+ use rowan:: ast:: AstNode ;
38use std:: collections:: BTreeMap ;
49use std:: path:: Path ;
510
@@ -8,50 +13,62 @@ use crate::validation::ResultIteratorExt;
813use crate :: validation:: Validation :: Success ;
914use crate :: { nix_file, ratchet, structure, validation} ;
1015
11- /// Runs check on all Nix files, returning a ratchet result for each
16+ fn find_invalid_withs ( syntax : & rnix:: SyntaxNode ) -> Option < rnix:: SyntaxNode > {
17+ syntax
18+ . descendants ( )
19+ . filter ( |node| node. kind ( ) == rnix:: SyntaxKind :: NODE_WITH )
20+ . filter ( |node| {
21+ node. descendants ( )
22+ . map ( |child| {
23+ if child == * node {
24+ return None ;
25+ }
26+ match child. kind ( ) {
27+ SyntaxKind :: NODE_WITH => Some ( node) ,
28+ SyntaxKind :: NODE_LET_IN => Some ( node) ,
29+ SyntaxKind :: NODE_ATTR_SET => Some ( node) ,
30+ _ => None ,
31+ }
32+ } )
33+ . any ( |node| node. is_some ( ) )
34+ } )
35+ . take ( 1 )
36+ . last ( )
37+ }
38+
1239pub fn check_files (
1340 nixpkgs_path : & Path ,
1441 nix_file_store : & mut NixFileStore ,
1542) -> validation:: Result < BTreeMap < RelativePathBuf , ratchet:: File > > {
16- process_nix_files ( nixpkgs_path, nix_file_store, |_nix_file| {
17- // Noop for now, only boilerplate to make it easier to add future file-based checks
18- Ok ( Success ( ratchet:: File { } ) )
43+ process_nix_files ( nixpkgs_path, nix_file_store, |nix_file| {
44+ Ok ( Success ( ratchet:: File {
45+ top_level_with : check_files_top_level_with_lib ( nixpkgs_path, nix_file) ,
46+ } ) )
1947 } )
2048}
2149
22- /// Processes all Nix files in a Nixpkgs directory according to a given function `f`, collecting the
23- /// results into a mapping from each file to a ratchet value.
24- fn process_nix_files (
50+ fn check_files_top_level_with_lib (
2551 nixpkgs_path : & Path ,
26- nix_file_store : & mut NixFileStore ,
27- f : impl Fn ( & nix_file:: NixFile ) -> validation:: Result < ratchet:: File > ,
28- ) -> validation:: Result < BTreeMap < RelativePathBuf , ratchet:: File > > {
29- // Get all Nix files
30- let files = {
31- let mut files = vec ! [ ] ;
32- collect_nix_files ( nixpkgs_path, & RelativePathBuf :: new ( ) , & mut files) ?;
33- files
34- } ;
35-
36- let results = files
37- . into_iter ( )
38- . map ( |path| {
39- // Get the (optionally-cached) parsed Nix file
40- let nix_file = nix_file_store. get ( & path. to_path ( nixpkgs_path) ) ?;
41- let result = f ( nix_file) ?;
42- let val = result. map ( |ratchet| ( path, ratchet) ) ;
43- Ok :: < _ , anyhow:: Error > ( val)
44- } )
45- . collect_vec ( ) ?;
46-
47- Ok ( validation:: sequence ( results) . map ( |entries| {
48- // Convert the Vec to a BTreeMap
49- entries. into_iter ( ) . collect ( )
50- } ) )
52+ nix_file : & nix_file:: NixFile ,
53+ ) -> RatchetState < ratchet:: DoesNotIntroduceToplevelWiths > {
54+ if let Some ( open_scope_with_lib) = find_invalid_withs ( nix_file. syntax_root . syntax ( ) ) {
55+ RatchetState :: Loose (
56+ {
57+ npv_169:: TopLevelWithMayShadowVariablesAndBreakStaticChecks :: new (
58+ RelativePathBuf :: from_path (
59+ nix_file. path . clone ( ) . strip_prefix ( nixpkgs_path) . unwrap ( ) ,
60+ )
61+ . unwrap ( ) ,
62+ open_scope_with_lib. to_string ( ) ,
63+ )
64+ }
65+ . into ( ) ,
66+ )
67+ } else {
68+ RatchetState :: Tight
69+ }
5170}
5271
53- /// Recursively collects all Nix files in the relative `dir` within `base`
54- /// into the `files` `Vec`.
5572fn collect_nix_files (
5673 base : & Path ,
5774 dir : & RelativePath ,
@@ -63,7 +80,6 @@ fn collect_nix_files(
6380
6481 let absolute_path = entry. path ( ) ;
6582
66- // We'll get to every file based on directory recursion, no need to follow symlinks.
6783 if absolute_path. is_symlink ( ) {
6884 continue ;
6985 }
@@ -75,3 +91,26 @@ fn collect_nix_files(
7591 }
7692 Ok ( ( ) )
7793}
94+
95+ fn process_nix_files < F : Fn ( & nix_file:: NixFile ) -> validation:: Result < ratchet:: File > > (
96+ nixpkgs_path : & Path ,
97+ nix_file_store : & mut NixFileStore ,
98+ f : F ,
99+ ) -> validation:: Result < BTreeMap < RelativePathBuf , ratchet:: File > > {
100+ let files = {
101+ let mut files = vec ! [ ] ;
102+ collect_nix_files ( nixpkgs_path, & RelativePathBuf :: new ( ) , & mut files) ?;
103+ files
104+ } ;
105+
106+ let file_results: Vec < validation:: Validation < ( RelativePathBuf , ratchet:: File ) > > = files
107+ . into_iter ( )
108+ . map ( |path| {
109+ let nix_file = nix_file_store. get ( & path. to_path ( nixpkgs_path) ) ?;
110+ let val = f ( nix_file) ?. map ( |file| ( path, file) ) ;
111+ Ok :: < _ , anyhow:: Error > ( val)
112+ } )
113+ . collect_vec ( ) ?;
114+
115+ Ok ( validation:: sequence ( file_results) . map ( |entries| entries. into_iter ( ) . collect ( ) ) )
116+ }
0 commit comments