@@ -17,17 +17,17 @@ namespace Semmle.BuildAnalyser
1717 internal partial class FileContent
1818 {
1919 private readonly ProgressMonitor progressMonitor ;
20- private readonly TemporaryDirectory packageDirectory ;
20+ private readonly IUnsafeFileReader unsafeFileReader ;
2121 private readonly Func < IEnumerable < string > > getFiles ;
22+ private readonly Func < HashSet < string > > getAlreadyDownloadedPackages ;
2223 private readonly HashSet < string > notYetDownloadedPackages = new HashSet < string > ( ) ;
23-
24- private bool IsInitialized { get ; set ; } = false ;
24+ private Initializer Initialize { get ; init ; }
2525
2626 public HashSet < string > NotYetDownloadedPackages
2727 {
2828 get
2929 {
30- Initialize ( ) ;
30+ Initialize . Run ( ) ;
3131 return notYetDownloadedPackages ;
3232 }
3333 }
@@ -45,18 +45,30 @@ public bool UseAspNetDlls
4545 {
4646 get
4747 {
48- Initialize ( ) ;
48+ Initialize . Run ( ) ;
4949 return useAspNetDlls ;
5050 }
5151 }
5252
53- public FileContent ( TemporaryDirectory packageDirectory , ProgressMonitor progressMonitor , Func < IEnumerable < string > > getFiles )
53+ internal FileContent ( Func < HashSet < string > > getAlreadyDownloadedPackages ,
54+ ProgressMonitor progressMonitor ,
55+ Func < IEnumerable < string > > getFiles ,
56+ IUnsafeFileReader unsafeFileReader )
5457 {
58+ this . getAlreadyDownloadedPackages = getAlreadyDownloadedPackages ;
5559 this . progressMonitor = progressMonitor ;
56- this . packageDirectory = packageDirectory ;
5760 this . getFiles = getFiles ;
61+ this . unsafeFileReader = unsafeFileReader ;
62+ Initialize = new Initializer ( DoInitialize ) ;
5863 }
5964
65+
66+ public FileContent ( TemporaryDirectory packageDirectory , ProgressMonitor progressMonitor , Func < IEnumerable < string > > getFiles ) : this ( ( ) => Directory . GetDirectories ( packageDirectory . DirInfo . FullName )
67+ . Select ( d => Path . GetFileName ( d )
68+ . ToLowerInvariant ( ) )
69+ . ToHashSet ( ) , progressMonitor , getFiles , new UnsafeFileReader ( ) )
70+ { }
71+
6072 private static string GetGroup ( ReadOnlySpan < char > input , ValueMatch valueMatch , string groupPrefix )
6173 {
6274 var match = input . Slice ( valueMatch . Index , valueMatch . Length ) ;
@@ -87,21 +99,14 @@ private static bool IsGroupMatch(ReadOnlySpan<char> line, Regex regex, string gr
8799 return false ;
88100 }
89101
90- private void Initialize ( )
102+ private void DoInitialize ( )
91103 {
92- if ( IsInitialized )
93- {
94- return ;
95- }
96-
97- var alreadyDownloadedPackages = Directory . GetDirectories ( packageDirectory . DirInfo . FullName ) . Select ( d => Path . GetFileName ( d ) . ToLowerInvariant ( ) ) . ToHashSet ( ) ;
104+ var alreadyDownloadedPackages = getAlreadyDownloadedPackages ( ) ;
98105 foreach ( var file in getFiles ( ) )
99106 {
100107 try
101108 {
102- using var sr = new StreamReader ( file ) ;
103- ReadOnlySpan < char > line ;
104- while ( ( line = sr . ReadLine ( ) ) != null )
109+ foreach ( ReadOnlySpan < char > line in unsafeFileReader . ReadLines ( file ) )
105110 {
106111
107112 // Find the not yet downloaded packages.
@@ -122,15 +127,13 @@ private void Initialize()
122127 IsGroupMatch ( line , ProjectSdk ( ) , "Sdk" , "Microsoft.NET.Sdk.Web" ) ||
123128 IsGroupMatch ( line , FrameworkReference ( ) , "Include" , "Microsoft.AspNetCore.App" ) ;
124129 }
125-
126130 }
127131 }
128132 catch ( Exception ex )
129133 {
130134 progressMonitor . FailedToReadFile ( file , ex ) ;
131135 }
132136 }
133- IsInitialized = true ;
134137 }
135138
136139 [ GeneratedRegex ( "<PackageReference.*\\ sInclude=\" (.*?)\" .*/?>" , RegexOptions . IgnoreCase | RegexOptions . Compiled | RegexOptions . Singleline ) ]
@@ -142,4 +145,22 @@ private void Initialize()
142145 [ GeneratedRegex ( "<(.*\\ s)?Project.*\\ sSdk=\" (.*?)\" .*/?>" , RegexOptions . IgnoreCase | RegexOptions . Compiled | RegexOptions . Singleline ) ]
143146 private static partial Regex ProjectSdk ( ) ;
144147 }
148+ }
149+
150+ internal interface IUnsafeFileReader
151+ {
152+ IEnumerable < string > ReadLines ( string file ) ;
153+ }
154+
155+ internal class UnsafeFileReader : IUnsafeFileReader
156+ {
157+ public IEnumerable < string > ReadLines ( string file )
158+ {
159+ using var sr = new StreamReader ( file ) ;
160+ string ? line ;
161+ while ( ( line = sr . ReadLine ( ) ) != null )
162+ {
163+ yield return line ;
164+ }
165+ }
145166}
0 commit comments