@@ -87,7 +87,7 @@ public static ExitCode Run(string[] args)
8787 var pathTransformer = new PathTransformer ( canonicalPathCache ) ;
8888
8989 using var analyser = new NonStandaloneAnalyser ( new LogProgressMonitor ( logger ) , logger , options . AssemblySensitiveTrap , pathTransformer ) ;
90- using var references = new BlockingCollection < MetadataReference > ( ) ;
90+
9191 try
9292 {
9393 var compilerVersion = new CompilerVersion ( options ) ;
@@ -120,80 +120,7 @@ public static ExitCode Run(string[] args)
120120 return ExitCode . Ok ;
121121 }
122122
123- var referenceTasks = ResolveReferences ( compilerArguments , analyser , canonicalPathCache , references ) ;
124-
125- var syntaxTrees = new List < SyntaxTree > ( ) ;
126- var syntaxTreeTasks = ReadSyntaxTrees (
127- compilerArguments . SourceFiles .
128- Select ( src => canonicalPathCache . GetCanonicalPath ( src . Path ) ) ,
129- analyser ,
130- compilerArguments . ParseOptions ,
131- compilerArguments . Encoding ,
132- syntaxTrees ) ;
133-
134- var sw1 = new Stopwatch ( ) ;
135- sw1 . Start ( ) ;
136-
137- Parallel . Invoke (
138- new ParallelOptions { MaxDegreeOfParallelism = options . Threads } ,
139- referenceTasks . Interleave ( syntaxTreeTasks ) . ToArray ( ) ) ;
140-
141- if ( syntaxTrees . Count == 0 )
142- {
143- logger . Log ( Severity . Error , " No source files" ) ;
144- ++ analyser . CompilationErrors ;
145- return ExitCode . Failed ;
146- }
147-
148- // csc.exe (CSharpCompiler.cs) also provides CompilationOptions
149- // .WithMetadataReferenceResolver(),
150- // .WithXmlReferenceResolver() and
151- // .WithSourceReferenceResolver().
152- // These would be needed if we hadn't explicitly provided the source/references
153- // already.
154- var compilation = CSharpCompilation . Create (
155- compilerArguments . CompilationName ,
156- syntaxTrees ,
157- references ,
158- compilerArguments . CompilationOptions .
159- WithAssemblyIdentityComparer ( DesktopAssemblyIdentityComparer . Default ) .
160- WithStrongNameProvider ( new DesktopStrongNameProvider ( compilerArguments . KeyFileSearchPaths ) )
161- ) ;
162-
163- analyser . EndInitialize ( compilerArguments , options , compilation ) ;
164- analyser . AnalyseCompilation ( ) ;
165- analyser . AnalyseReferences ( ) ;
166-
167- foreach ( var tree in compilation . SyntaxTrees )
168- {
169- analyser . AnalyseTree ( tree ) ;
170- }
171-
172- var currentProcess = Process . GetCurrentProcess ( ) ;
173- var cpuTime1 = currentProcess . TotalProcessorTime ;
174- var userTime1 = currentProcess . UserProcessorTime ;
175- sw1 . Stop ( ) ;
176- logger . Log ( Severity . Info , " Models constructed in {0}" , sw1 . Elapsed ) ;
177-
178- var sw2 = new Stopwatch ( ) ;
179- sw2 . Start ( ) ;
180- analyser . PerformExtraction ( options . Threads ) ;
181- sw2 . Stop ( ) ;
182- var cpuTime2 = currentProcess . TotalProcessorTime ;
183- var userTime2 = currentProcess . UserProcessorTime ;
184-
185- var performance = new Entities . PerformanceMetrics ( )
186- {
187- Frontend = new Entities . Timings ( ) { Elapsed = sw1 . Elapsed , Cpu = cpuTime1 , User = userTime1 } ,
188- Extractor = new Entities . Timings ( ) { Elapsed = sw2 . Elapsed , Cpu = cpuTime2 - cpuTime1 , User = userTime2 - userTime1 } ,
189- Total = new Entities . Timings ( ) { Elapsed = stopwatch . Elapsed , Cpu = cpuTime2 , User = userTime2 } ,
190- PeakWorkingSet = currentProcess . PeakWorkingSet64
191- } ;
192-
193- analyser . LogPerformance ( performance ) ;
194- logger . Log ( Severity . Info , " Extraction took {0}" , sw2 . Elapsed ) ;
195-
196- return analyser . TotalErrors == 0 ? ExitCode . Ok : ExitCode . Errors ;
123+ return AnalyseNonStandalone ( analyser , compilerArguments , options , canonicalPathCache , stopwatch ) ;
197124 }
198125 catch ( Exception ex ) // lgtm[cs/catch-of-all-exceptions]
199126 {
@@ -321,73 +248,175 @@ public static void ExtractStandalone(
321248 ILogger logger ,
322249 CommonOptions options )
323250 {
251+ var stopwatch = new Stopwatch ( ) ;
252+ stopwatch . Start ( ) ;
253+
324254 var canonicalPathCache = CanonicalPathCache . Create ( logger , 1000 ) ;
325255 var pathTransformer = new PathTransformer ( canonicalPathCache ) ;
326256
327257 using var analyser = new StandaloneAnalyser ( pm , logger , false , pathTransformer ) ;
328- using var references = new BlockingCollection < MetadataReference > ( ) ;
329258 try
330259 {
331- var referenceTasks = referencePaths . Select < string , Action > ( path => ( ) =>
332- {
333- var reference = MetadataReference . CreateFromFile ( path ) ;
334- references . Add ( reference ) ;
335- } ) ;
260+ AnalyseStandalone ( analyser , sources , referencePaths , options , pm , stopwatch ) ;
261+ }
262+ catch ( Exception ex ) // lgtm[cs/catch-of-all-exceptions]
263+ {
264+ analyser . Logger . Log ( Severity . Error , " Unhandled exception: {0}" , ex ) ;
265+ }
266+ }
336267
337- var syntaxTrees = new List < SyntaxTree > ( ) ;
338- var syntaxTreeTasks = ReadSyntaxTrees ( sources , analyser , null , null , syntaxTrees ) ;
268+ private static ExitCode Analyse ( Stopwatch stopwatch , Analyser analyser , CommonOptions options ,
269+ Func < BlockingCollection < MetadataReference > , IEnumerable < Action > > getResolvedReferenceTasks ,
270+ Func < Analyser , List < SyntaxTree > , IEnumerable < Action > > getSyntaxTreeTasks ,
271+ Func < IEnumerable < SyntaxTree > , IEnumerable < MetadataReference > , CSharpCompilation > getCompilation ,
272+ Action < CSharpCompilation , CommonOptions > initializeAnalyser ,
273+ Action analyseCompilation ,
274+ Action < Entities . PerformanceMetrics > logPerformance ,
275+ Action postProcess )
276+ {
277+ using var references = new BlockingCollection < MetadataReference > ( ) ;
278+ var referenceTasks = getResolvedReferenceTasks ( references ) ;
339279
340- var sw = new Stopwatch ( ) ;
341- sw . Start ( ) ;
280+ var syntaxTrees = new List < SyntaxTree > ( ) ;
281+ var syntaxTreeTasks = getSyntaxTreeTasks ( analyser , syntaxTrees ) ;
342282
343- Parallel . Invoke (
344- new ParallelOptions { MaxDegreeOfParallelism = options . Threads } ,
345- referenceTasks . Interleave ( syntaxTreeTasks ) . ToArray ( ) ) ;
283+ var sw = new Stopwatch ( ) ;
284+ sw . Start ( ) ;
346285
347- if ( syntaxTrees . Count == 0 )
286+ Parallel . Invoke (
287+ new ParallelOptions { MaxDegreeOfParallelism = options . Threads } ,
288+ referenceTasks . Interleave ( syntaxTreeTasks ) . ToArray ( ) ) ;
289+
290+ if ( syntaxTrees . Count == 0 )
291+ {
292+ analyser . Logger . Log ( Severity . Error , " No source files" ) ;
293+ ++ analyser . CompilationErrors ;
294+ if ( analyser is NonStandaloneAnalyser )
348295 {
349- analyser . Logger . Log ( Severity . Error , " No source files" ) ;
350- ++ analyser . CompilationErrors ;
296+ return ExitCode . Failed ;
351297 }
298+ }
352299
353- var compilation = CSharpCompilation . Create (
354- "csharp.dll" ,
355- syntaxTrees ,
356- references
357- ) ;
300+ var compilation = getCompilation ( syntaxTrees , references ) ;
358301
359- analyser . InitializeStandalone ( compilation , options ) ;
360- analyser . AnalyseReferences ( ) ;
302+ initializeAnalyser ( compilation , options ) ;
303+ analyseCompilation ( ) ;
304+ analyser . AnalyseReferences ( ) ;
361305
362- foreach ( var tree in compilation . SyntaxTrees )
363- {
364- analyser . AnalyseTree ( tree ) ;
365- }
306+ foreach ( var tree in compilation . SyntaxTrees )
307+ {
308+ analyser . AnalyseTree ( tree ) ;
309+ }
366310
367- sw . Stop ( ) ;
368- analyser . Logger . Log ( Severity . Info , " Models constructed in {0}" , sw . Elapsed ) ;
311+ sw . Stop ( ) ;
312+ analyser . Logger . Log ( Severity . Info , " Models constructed in {0}" , sw . Elapsed ) ;
313+ var elapsed = sw . Elapsed ;
369314
370- sw . Restart ( ) ;
371- analyser . PerformExtraction ( options . Threads ) ;
372- sw . Stop ( ) ;
373- analyser . Logger . Log ( Severity . Info , " Extraction took {0}" , sw . Elapsed ) ;
315+ var currentProcess = Process . GetCurrentProcess ( ) ;
316+ var cpuTime1 = currentProcess . TotalProcessorTime ;
317+ var userTime1 = currentProcess . UserProcessorTime ;
374318
375- foreach ( var type in analyser . MissingNamespaces )
319+ sw . Restart ( ) ;
320+ analyser . PerformExtraction ( options . Threads ) ;
321+ sw . Stop ( ) ;
322+ var cpuTime2 = currentProcess . TotalProcessorTime ;
323+ var userTime2 = currentProcess . UserProcessorTime ;
324+
325+ var performance = new Entities . PerformanceMetrics ( )
326+ {
327+ Frontend = new Entities . Timings ( ) { Elapsed = elapsed , Cpu = cpuTime1 , User = userTime1 } ,
328+ Extractor = new Entities . Timings ( ) { Elapsed = sw . Elapsed , Cpu = cpuTime2 - cpuTime1 , User = userTime2 - userTime1 } ,
329+ Total = new Entities . Timings ( ) { Elapsed = stopwatch . Elapsed , Cpu = cpuTime2 , User = userTime2 } ,
330+ PeakWorkingSet = currentProcess . PeakWorkingSet64
331+ } ;
332+
333+ logPerformance ( performance ) ;
334+ analyser . Logger . Log ( Severity . Info , " Extraction took {0}" , sw . Elapsed ) ;
335+
336+ postProcess ( ) ;
337+
338+ return analyser . TotalErrors == 0 ? ExitCode . Ok : ExitCode . Errors ;
339+ }
340+
341+ private static void AnalyseStandalone (
342+ StandaloneAnalyser analyser ,
343+ IEnumerable < string > sources ,
344+ IEnumerable < string > referencePaths ,
345+ CommonOptions options ,
346+ IProgressMonitor progressMonitor ,
347+ Stopwatch stopwatch )
348+ {
349+ Analyse ( stopwatch , analyser , options ,
350+ references => GetResolvedReferencesStandalone ( referencePaths , references ) ,
351+ ( analyser , syntaxTrees ) => ReadSyntaxTrees ( sources , analyser , null , null , syntaxTrees ) ,
352+ ( syntaxTrees , references ) => CSharpCompilation . Create ( "csharp.dll" , syntaxTrees , references ) ,
353+ ( compilation , options ) => analyser . InitializeStandalone ( compilation , options ) ,
354+ ( ) => { } ,
355+ _ => { } ,
356+ ( ) =>
376357 {
377- pm . MissingNamespace ( type ) ;
378- }
358+ foreach ( var type in analyser . MissingNamespaces )
359+ {
360+ progressMonitor . MissingNamespace ( type ) ;
361+ }
362+
363+ foreach ( var type in analyser . MissingTypes )
364+ {
365+ progressMonitor . MissingType ( type ) ;
366+ }
379367
380- foreach ( var type in analyser . MissingTypes )
368+ progressMonitor . MissingSummary ( analyser . MissingTypes . Count ( ) , analyser . MissingNamespaces . Count ( ) ) ;
369+ } ) ;
370+ }
371+
372+ private static ExitCode AnalyseNonStandalone (
373+ NonStandaloneAnalyser analyser ,
374+ CSharpCommandLineArguments compilerArguments ,
375+ Options options ,
376+ CanonicalPathCache canonicalPathCache ,
377+ Stopwatch stopwatch )
378+ {
379+ return Analyse ( stopwatch , analyser , options ,
380+ references => ResolveReferences ( compilerArguments , analyser , canonicalPathCache , references ) ,
381+ ( analyser , syntaxTrees ) =>
381382 {
382- pm . MissingType ( type ) ;
383- }
383+ return ReadSyntaxTrees (
384+ compilerArguments . SourceFiles . Select ( src => canonicalPathCache . GetCanonicalPath ( src . Path ) ) ,
385+ analyser ,
386+ compilerArguments . ParseOptions ,
387+ compilerArguments . Encoding ,
388+ syntaxTrees ) ;
389+ } ,
390+ ( syntaxTrees , references ) =>
391+ {
392+ // csc.exe (CSharpCompiler.cs) also provides CompilationOptions
393+ // .WithMetadataReferenceResolver(),
394+ // .WithXmlReferenceResolver() and
395+ // .WithSourceReferenceResolver().
396+ // These would be needed if we hadn't explicitly provided the source/references
397+ // already.
398+ return CSharpCompilation . Create (
399+ compilerArguments . CompilationName ,
400+ syntaxTrees ,
401+ references ,
402+ compilerArguments . CompilationOptions .
403+ WithAssemblyIdentityComparer ( DesktopAssemblyIdentityComparer . Default ) .
404+ WithStrongNameProvider ( new DesktopStrongNameProvider ( compilerArguments . KeyFileSearchPaths ) )
405+ ) ;
406+ } ,
407+ ( compilation , options ) => analyser . EndInitialize ( compilerArguments , options , compilation ) ,
408+ ( ) => analyser . AnalyseCompilation ( ) ,
409+ performance => analyser . LogPerformance ( performance ) ,
410+ ( ) => { } ) ;
411+ }
384412
385- pm . MissingSummary ( analyser . MissingTypes . Count ( ) , analyser . MissingNamespaces . Count ( ) ) ;
386- }
387- catch ( Exception ex ) // lgtm[cs/catch-of-all-exceptions]
413+ private static IEnumerable < Action > GetResolvedReferencesStandalone ( IEnumerable < string > referencePaths , BlockingCollection < MetadataReference > references )
414+ {
415+ return referencePaths . Select < string , Action > ( path => ( ) =>
388416 {
389- analyser . Logger . Log ( Severity . Error , " Unhandled exception: {0}" , ex ) ;
390- }
417+ var reference = MetadataReference . CreateFromFile ( path ) ;
418+ references . Add ( reference ) ;
419+ } ) ;
391420 }
392421
393422 /// <summary>
0 commit comments