Ejemplo n.º 1
0
 internal TemplateTransformer(string workingFolder, string generatedCodeFolder, CompileAssembly assembly)
 {
     _workingFolder       = workingFolder;
     _generatedCodeFolder = generatedCodeFolder;
     _assembly            = assembly;
     _compilingContext    = new CompilingContext(assembly);
 }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 5
0
        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());
        }
Ejemplo n.º 6
0
 /// <summary>
 /// 初始化 <see cref="CompilingContext"/> 的新实例。
 /// </summary>
 /// <param name="assembly">当前程序集的编译期信息。</param>
 public CompilingContext(CompileAssembly assembly)
 {
     _assembly = assembly;
 }
Ejemplo n.º 7
0
 /// <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;
 }