public static CSharpCompilation Generate(Options options, Type[] types, ITestOutputHelper output = null) { // generate code from types var generator = new EntryCodeGenerator(options); generator.GenerateCode(types); var code = generator.CodeWriter.ToString(); if (output != null) { var typeInfo = string.Join(", ", types.Select(t => t.Name)); output.WriteLine($"***** Generated Code({typeInfo}) *****"); output.WriteLine(code); output.WriteLine(""); } // compile generated code output?.WriteLine($"***** Compile Code *****"); var parseOption = new CSharpParseOptions(LanguageVersion.CSharp6, DocumentationMode.Parse, SourceCodeKind.Regular); var syntaxTrees = new[] { CSharpSyntaxTree.ParseText(code, parseOption, "Generated.cs") }; var references = new[] { typeof(object), typeof(IInterfacedActor), typeof(InterfacedActor), typeof(IActorRef), typeof(IGreeter) } .Select(t => MetadataReference.CreateFromFile(t.Assembly.Location)); var compilation = CSharpCompilation.Create( "Generated.dll", syntaxTrees: syntaxTrees, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); using (var ms = new MemoryStream()) { var result = compilation.Emit(ms); if (!result.Success) { var failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); foreach (var diagnostic in failures) { var line = diagnostic.Location.GetLineSpan(); output?.WriteLine("{0}({1}): {2} {3}", line.Path, line.StartLinePosition.Line + 1, diagnostic.Id, diagnostic.GetMessage()); } } Assert.True(result.Success, "Build error!"); } return compilation; }
public EntryCodeGenerator(Options options) { Options = options; var settings = new CodeWriterSettings(CodeWriterSettings.CSharpDefault); settings.TranslationMapping["`"] = "\""; CodeWriter = new CodeWriter.CodeWriter(settings); GenerateHead(); }
private static int Process(Options options) { try { Console.WriteLine("Start Process!"); // Resolve options var basePath = Path.GetFullPath(options.Path ?? "."); var sources = options.Sources.Where(p => string.IsNullOrWhiteSpace(p) == false && FilterSource(options, p)).Select(p => MakeFullPath(p, basePath)).ToArray(); var references = options.References.Where(p => string.IsNullOrWhiteSpace(p) == false).Select(p => MakeFullPath(p, basePath)).ToArray(); var targetDefaultPath = options.UseSlimClient ? @".\Properties\Akka.Interfaced.CodeGen.Slim.cs" : @".\Properties\Akka.Interfaced.CodeGen.cs"; var targetPath = MakeFullPath(options.TargetFile ?? targetDefaultPath, basePath); // Build source and load assembly Console.WriteLine("- Build sources"); var assembly = AssemblyLoader.BuildAndLoad(sources, references, options.Defines.ToArray()); if (assembly == null) return 1; // Generate code Console.WriteLine("- Generate code"); var codeGenerator = new EntryCodeGenerator(options); var sourceTypes = GetTypesSafely(assembly).OrderBy(t => t.FullName).ToArray(); codeGenerator.GenerateCode(sourceTypes); // Save generated code Console.WriteLine("- Save code"); if (codeGenerator.CodeWriter.WriteAllText(targetPath, true) == false) Console.WriteLine("Nothing changed. Skip writing."); return 0; } catch (Exception e) { Console.WriteLine("Exception in processing:\n" + e); return 1; } }
private static bool FilterSource(Options options, string path) { if (path.ToLower().IndexOf("akka.interfaced.codegen") != -1) return false; foreach (var exclude in options.Excludes) { if (Regex.IsMatch(path, exclude, RegexOptions.IgnoreCase)) return false; } if (options.Includes.Any()) { foreach (var include in options.Includes) { if (Regex.IsMatch(path, include, RegexOptions.IgnoreCase)) return true; } return false; } return true; }