using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; namespace PCL.Core.SourceGenerators; [Generator(LanguageNames.CSharp)] public class EnvironmentInteropGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { var secretProvider = context.CompilationProvider.Select(static (_, _) => { // 判断 PCL_WRITE_SECRET 是否存在并遍历转换环境变量 // 打死也不会用 MSBuild Properties 这种非人类设计出来的垃圾 #pragma warning disable RS1035 var envs = Environment.GetEnvironmentVariables(); #pragma warning restore RS1035 var secretPairs = envs.Contains("PCL_WRITE_SECRET") ? ( from key in ( from key in envs.Keys.Cast() where !string.IsNullOrWhiteSpace(key) && key.StartsWith("PCL_") && key != "PCL_WRITE_SECRET" select key ) let value = envs[key]?.ToString() where !string.IsNullOrWhiteSpace(value) select (key.Substring(4), value) ) : []; return secretPairs; }); // 注册源代码输出 context.RegisterSourceOutput(secretProvider, static (spc, secretPairs) => _Execute(spc, secretPairs)); } private static void _Execute(SourceProductionContext context, IEnumerable<(string, string)> secretPairs) { var sb = new StringBuilder(); sb.AppendLine("// "); sb.AppendLine("// 此文件由 Source Generator 自动生成,请勿手动修改"); sb.AppendLine(); sb.AppendLine("#nullable enable"); sb.AppendLine(); sb.AppendLine("namespace PCL.Core.Utils.OS;"); sb.AppendLine(); sb.AppendLine("partial class EnvironmentInterop"); sb.AppendLine("{"); sb.AppendLine(" private static readonly System.Collections.Generic.Dictionary SecretDictionary = new()"); sb.AppendLine(" {"); foreach (var (key, value) in secretPairs) sb.AppendLine($" [\"{key}\"] = {_ToVerbatimString(value)},"); sb.AppendLine(" };"); sb.AppendLine("}"); context.AddSource("EnvironmentInterop.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8)); } private static string _ToVerbatimString(string text) { return "@\"" + text.Replace("\"", "\"\"") + "\""; } }