using System.Collections.Generic; using System.IO; using System.Linq; using Semmle.Util; using Semmle.Util.Logging; namespace Semmle.Extraction.CSharp.DependencyFetching { internal class ImplicitUsingsGenerator : SourceGeneratorBase { private readonly FileContent fileContent; public ImplicitUsingsGenerator(FileContent fileContent, ILogger logger, TemporaryDirectory tempWorkingDirectory) : base(logger, tempWorkingDirectory) { this.fileContent = fileContent; } protected override bool IsEnabled() => true; protected override IEnumerable Run() { var usings = new HashSet(); if (!fileContent.UseImplicitUsings) { logger.LogDebug("Skipping implicit usings generation"); return []; } // Hardcoded values from https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#implicit-using-directives usings.UnionWith([ "System", "System.Collections.Generic", "System.IO", "System.Linq", "System.Net.Http", "System.Threading", "System.Threading.Tasks" ]); if (fileContent.UseAspNetCoreDlls) { usings.UnionWith([ "System.Net.Http.Json", "Microsoft.AspNetCore.Builder", "Microsoft.AspNetCore.Hosting", "Microsoft.AspNetCore.Http", "Microsoft.AspNetCore.Routing", "Microsoft.Extensions.Configuration", "Microsoft.Extensions.DependencyInjection", "Microsoft.Extensions.Hosting", "Microsoft.Extensions.Logging" ]); } if (fileContent.UseWindowsForms) { usings.UnionWith(["System.Drawing", "System.Windows.Forms"]); } usings.UnionWith(fileContent.CustomImplicitUsings); logger.LogInfo($"Generating source file for implicit usings. Namespaces: {string.Join(", ", usings.OrderBy(u => u))}"); if (usings.Count > 0) { var tempDir = GetTemporaryWorkingDirectory("implicitUsings"); var path = Path.Combine(tempDir, "GlobalUsings.g.cs"); using (var writer = new StreamWriter(path)) { writer.WriteLine("// "); writer.WriteLine(""); foreach (var u in usings.OrderBy(u => u)) { writer.WriteLine($"global using global::{u};"); } } return [path]; } return []; } } }