internal TemplateTransformer(string workingFolder, string generatedCodeFolder, CompileAssembly assembly) { _workingFolder = workingFolder; _generatedCodeFolder = generatedCodeFolder; _assembly = assembly; _compilingContext = new CompilingContext(assembly); }
internal ProjectCompilingContext(Options options) { // 初始化基础属性。 WorkingFolder = Path.GetFullPath(options.WorkingDirectory); ToolsFolder = FullPath(options.ToolFolder); GeneratedCodeFolder = FullPath(options.GeneratedCodeFolder); PreprocessorSymbols = options.PreprocessorSymbols; // 初始化项目属性。 _projectProperties = Deserialize(FullPath(options.ProjectPropertyFile)); // 初始化编译文件和引用。 // filterFiles 是仅需扫描的文件,用 compilingFiles 取一下交集,可以避免被移除的文件也加入编译范围。 var compilingFiles = GetItems("Compile").Select(FullPath).ToArray(); var filterFiles = GetItems("PrecompileFilter").Select(FullPath).ToArray(); var filteredCompilingFiles = filterFiles.Any() ? compilingFiles.Intersect(filterFiles).ToArray() : compilingFiles; var referencingFiles = GetItems("ReferencePath").Select(FullPath).ToArray(); CompilingFiles = filteredCompilingFiles; References = referencingFiles; // 初始化编译程序集。 Assembly = new CompileAssembly(CompilingFiles, References, PreprocessorSymbols); }
private static int Run(Options options, ILogger logger) { // Initialize basic command options. //Parser.Default.ParseArguments<Options>(args) // .WithParsed(options => // { try { var(workingFolder, intermediateFolder, generatedCodeFolder, compilingFiles) = DeconstructPaths(options); var rebuildRequired = options.RebuildRequired; var cachedExcludesListFile = Path.Combine(intermediateFolder, "Excludes.txt"); // 如果可以差量编译,那么检测之前已经生成的文件,然后将其直接输出。 if (!rebuildRequired && File.Exists(cachedExcludesListFile)) { var cachedExcludeLines = File.ReadAllLines(cachedExcludesListFile, Encoding.UTF8); foreach (var exclude in cachedExcludeLines) { logger.Message(exclude); } return(0); } var assembly = new CompileAssembly(compilingFiles); // 分析 IPlainCodeTransformer。 var transformer = new CodeTransformer(workingFolder, generatedCodeFolder, assembly); var excludes = transformer.Transform(); // 分析 CompileTimeTemplate。 var templateTransformer = new TemplateTransformer(workingFolder, generatedCodeFolder, assembly); var templateExcludes = templateTransformer.Transform(); var toExcludes = excludes.Union(templateExcludes) .Select(x => PathEx.MakeRelativePath(workingFolder, x)).ToArray(); foreach (var exclude in toExcludes) { logger.Message(exclude); } File.WriteAllLines(cachedExcludesListFile, toExcludes, Encoding.UTF8); } catch (CompilingException ex) { foreach (var error in ex.Errors) { logger.Error($"error:{error}"); } } catch (Exception ex) { logger.Error($"error:{ex}"); } //}) //.WithNotParsed(errorList => { }); return(0); }
internal ProjectCompilingContext(Options options) { // 初始化基础属性。 if (string.IsNullOrEmpty(options.WorkingDirectory)) { throw new ArgumentNullException(nameof(options.WorkingDirectory) + $" CommandLine: {Environment.CommandLine}"); } if (string.IsNullOrEmpty(options.ToolFolder)) { throw new ArgumentNullException(nameof(options.ToolFolder) + $" CommandLine: {Environment.CommandLine}"); } if (string.IsNullOrEmpty(options.GeneratedCodeFolder)) { throw new ArgumentNullException(nameof(options.GeneratedCodeFolder) + $" CommandLine: {Environment.CommandLine}"); } WorkingFolder = Path.GetFullPath(options.WorkingDirectory); ToolsFolder = FullPath(options.ToolFolder); GeneratedCodeFolder = FullPath(options.GeneratedCodeFolder); PreprocessorSymbols = options.PreprocessorSymbols; // 初始化项目属性。 _projectProperties = Deserialize(FullPath(options.ProjectPropertyFile)); // 初始化编译文件和引用。 // filterFiles 是仅需扫描的文件,用 compilingFiles 取一下交集,可以避免被移除的文件也加入编译范围。 var compilingFiles = GetItems("Compile").Select(FullPath).ToArray(); var filterFiles = GetItems("PrecompileFilter").Select(FullPath).ToArray(); var filteredCompilingFiles = filterFiles.Any() ? compilingFiles.Intersect(filterFiles).ToArray() : compilingFiles; var referencingFiles = GetItems("ReferencePath").Select(FullPath).ToArray(); CompilingFiles = filteredCompilingFiles; References = referencingFiles; // 初始化编译程序集。 Assembly = new CompileAssembly(CompilingFiles, References, PreprocessorSymbols); }
private static string GenerateAttributedTypesExportCode(CompileAssembly assembly) { // 从 AssemblyInfo.cs 中找出设置的导出类信息。 var markedExports = assembly.Files .SelectMany(x => x.AssemblyAttributes) .Where(x => x.Match("MarkExport")) .OfType <CompileAttribute>() .Select(x => new { BaseClassOrInterfaceName = GuessTypeNameByTypeOfSyntax(x[0]), AttributeName = GuessTypeNameByTypeOfSyntax(x[1]) }) .ToList(); // 未标记任何导出,于是不生成类型。 if (markedExports.Count == 0) { return(""); } // 寻找并导出所有类,加入到接口列表/方法列表中,并生成类。 var exportedInterfaces = markedExports.Select(x => $@"ICompileTimeAttributedTypesExporter<{x.BaseClassOrInterfaceName}, {x.AttributeName}>"); var exportedMethodCodes = markedExports.Select(x => BuildExplicitMethodImplementation( assembly.Files.SelectMany(x => x.Types).OfType <CompileType>(), x.BaseClassOrInterfaceName, x.AttributeName)); var exportedFileUsings = assembly.Files .SelectMany(x => x.Types) .Where(x => markedExports.FindIndex(m => x.Attributes.Any(x => x.Match(m.AttributeName))) >= 0) .SelectMany(x => x.UsingNamespaceList) .Concat(assembly.Files .Where(x => x.AssemblyAttributes.Any(x => x.Match("MarkExport"))) .SelectMany(x => x.UsingNamespaceList)) .Distinct(StringComparer.Ordinal) .Where(x => !x.Contains('=')) .OrderBy(x => x); var exportedClass = BuildClassImplementation(exportedInterfaces, exportedMethodCodes, exportedFileUsings); return(exportedClass.Trim()); }
/// <summary> /// 初始化 <see cref="CompilingContext"/> 的新实例。 /// </summary> /// <param name="assembly">当前程序集的编译期信息。</param> public CompilingContext(CompileAssembly assembly) { _assembly = assembly; }
/// <summary> /// 创建用于转换源码的 <see cref="CodeTransformer"/>。 /// </summary> /// <param name="workingFolder">转换源码的工作路径。</param> /// <param name="generatedCodeFolder">中间文件的生成路径(文件夹,相对路径)。</param> /// <param name="assembly">需要分析源码转换的程序集。</param> internal CodeTransformer(string workingFolder, string generatedCodeFolder, CompileAssembly assembly) { _workingFolder = workingFolder; _generatedCodeFolder = generatedCodeFolder; _assembly = assembly; }