예제 #1
0
        private string TransformTemplate(CompileFile assemblyFile)
        {
            // 读取文件,解析其语法树。
            var originalText = File.ReadAllText(assemblyFile.FullName);
            var syntaxTree   = CSharpSyntaxTree.ParseText(originalText);

            var visitor = new PlaceholderVisitor();

            visitor.Visit(syntaxTree.GetRoot());

            var builder             = new StringBuilder();
            var currentTextPosition = 0;

            var placeholders = visitor.Placeholders;

            foreach (var placeholder in placeholders)
            {
                var actualText = placeholder.Execute(_compilingContext);

                builder.Append(originalText.Substring(currentTextPosition, placeholder.Span.Start));
                builder.Append(actualText);
                currentTextPosition = placeholder.Span.End;
            }

            builder.Append(originalText.Substring(currentTextPosition, originalText.Length - currentTextPosition));
            builder.Replace("[CompileTimeTemplate]", "");
            builder.Replace("using dotnetCampus.SourceFusion;", "");

            var targetText = builder.ToString();
            var fileName   = Path.GetFileNameWithoutExtension(assemblyFile.FullName);
            var targetFile = Path.Combine(_generatedCodeFolder, $"{fileName}.g.cs");

            File.WriteAllText(targetFile, targetText);

            return(assemblyFile.FullName);
        }
예제 #2
0
        private string TransformTemplate(CompileFile assemblyFile)
        {
            // 读取文件,去掉非期望字符。
            var originalText = File.ReadAllText(assemblyFile.FullName);

            originalText = originalText.Replace("[CompileTimeTemplate]", AssemblyInfo.GeneratedCodeAttribute);
            originalText = _usingRegex.Replace(originalText, "");
            foreach (Match match in _projectPropertyRegex.Matches(originalText))
            {
                var propertyName  = match.Groups["propertyName"].Value;
                var propertyValue = _context.GetProperty(propertyName);
                originalText = originalText.Replace(match.Value, propertyValue);
            }

            // 解析其语法树。
            var symbols    = _context.PreprocessorSymbols.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            var syntaxTree = CSharpSyntaxTree.ParseText(originalText, new CSharpParseOptions(
                                                            LanguageVersion.Latest, DocumentationMode.None, SourceCodeKind.Regular, symbols));

            // 访问语法节点。
            var visitor = new PlaceholderVisitor();

            visitor.Visit(syntaxTree.GetRoot());

            // 初始化字符串。
            var builder             = new StringBuilder(AssemblyInfo.GeneratedCodeComment);
            var namespaceIndex      = builder.Length;
            var currentTextPosition = 0;

            // 替换占位符。
            var placeholders = visitor.Placeholders;

            foreach (var placeholder in placeholders)
            {
                var actualText = placeholder.Fill(_compilingContext);

                builder.Append(
                    originalText.Substring(currentTextPosition, placeholder.Span.Start - currentTextPosition));
                builder.Append(actualText);
                currentTextPosition = placeholder.Span.End;
            }

            // 把文件剩余的部分拼接起来。
            builder.Append(originalText.Substring(currentTextPosition));

            // 去掉原来的命名空间,添加上新补充的命名空间。
            var requiredNamespaces = string.Join(Environment.NewLine, placeholders
                                                 .SelectMany(x => x.RequiredNamespaces)
                                                 .Union(visitor.Namespaces.Select(x => x.@namespace))
                                                 .Distinct()
                                                 .OrderBy(s => s, new SystemFirstNamespaceComparer())
                                                 .Select(x => $"using {x};"));
            var namespaceStart = visitor.Namespaces.Min(x => x.span.Start);
            var namespaceEnd   = visitor.Namespaces.Max(x => x.span.End);

            builder.Remove(namespaceIndex, namespaceEnd - namespaceStart);
            builder.Insert(namespaceIndex, requiredNamespaces);

            // 将新的代码写入到文件。
            var targetText = builder.ToString();
            var fileName   = Path.GetFileNameWithoutExtension(assemblyFile.FullName);
            var targetFile = Path.Combine(_generatedCodeFolder, $"{fileName}.g.cs");

            File.WriteAllText(targetFile, targetText);

            return(assemblyFile.FullName);
        }