public string Process(string templateFile, string[] referenceList, string projectFile) { var options = new Options { TemplateFileName = templateFile, CurrentNamespace = Path.GetFileNameWithoutExtension(templateFile), CurrentAssembly = Path.GetFileNameWithoutExtension(projectFile).Replace(".React", ".Entities"), AssemblyReferences = (from r in referenceList where r.Contains(".Entities") let reactDirectory = ReactDirectoryCache.GetOrAdd(r, FindReactDirectory) select new AssemblyReference { AssemblyName = Path.GetFileNameWithoutExtension(r), AssemblyFullPath = r, ReactDirectory = reactDirectory, AllTypescriptFiles = AllFilesCache.GetOrAdd(reactDirectory, GetAllTypescriptFiles), }).ToDictionary(a => a.AssemblyName), AllReferences = referenceList.ToDictionary(a => Path.GetFileNameWithoutExtension(a)), }; PreloadingAssemblyResolver resolver = new PreloadingAssemblyResolver(referenceList); return(EntityDeclarationGenerator.Process(options, resolver)); }
public static int Main(string[] args) { Stopwatch sw = Stopwatch.StartNew(); string intermediateAssembly = args[0]; string[] references = File.ReadAllLines(args[1]); string[] content = File.ReadAllLines(args[2]); var log = Console.Out; log.WriteLine("Starting SignumTSGenerator"); bool hasPdb = File.Exists(Path.ChangeExtension(intermediateAssembly, ".pdb")); AssemblyDefinition reactAssembly = AssemblyDefinition.ReadAssembly(intermediateAssembly, new ReaderParameters { ReadingMode = ReadingMode.Deferred, ReadSymbols = hasPdb, InMemory = true, SymbolReaderProvider = hasPdb ? new PdbReaderProvider() : null }); if (AlreadyProcessed(reactAssembly)) { log.WriteLine("SignumTSGenerator already processed: {0}", intermediateAssembly); return(0); } PreloadingAssemblyResolver resolver = new PreloadingAssemblyResolver(references); var assemblyReferences = (from r in references where r.Contains(".Entities") let reactDirectory = FindReactDirectory(r) select new AssemblyReference { AssemblyName = Path.GetFileNameWithoutExtension(r), AssemblyFullPath = r, ReactDirectory = reactDirectory, AllTypescriptFiles = GetAllTypescriptFiles(reactDirectory), }).ToDictionary(a => a.AssemblyName); var entitiesAssembly = Path.GetFileNameWithoutExtension(intermediateAssembly).Replace(".React", ".Entities"); var entitiesAssemblyReference = assemblyReferences.GetOrThrow(entitiesAssembly); var entitiesModule = ModuleDefinition.ReadModule(entitiesAssemblyReference.AssemblyFullPath, new ReaderParameters { AssemblyResolver = resolver }); var options = new AssemblyOptions { CurrentAssembly = entitiesAssembly, AssemblyReferences = assemblyReferences, AllReferences = references.ToDictionary(a => Path.GetFileNameWithoutExtension(a)), ModuleDefinition = entitiesModule, Resolver = resolver, }; var currentDir = Directory.GetCurrentDirectory(); var files = content .Where(file => Path.GetExtension(file) == ".t4s") .Select(file => Path.Combine(currentDir, file)) .ToList(); bool hasErrors = false; foreach (var file in files) { try { string result = EntityDeclarationGenerator.Process(options, file, Path.GetFileNameWithoutExtension(file)); var targetFile = Path.ChangeExtension(file, ".ts"); if (File.Exists(targetFile) && File.ReadAllText(targetFile) == result) { log.WriteLine($"Skipping {targetFile} (Up to date)"); } else { log.WriteLine($"Writing {targetFile}"); File.WriteAllText(targetFile, result); } } catch (Exception ex) { hasErrors = true; log.WriteLine($"Error in {file}"); log.WriteLine(ex.Message); } } MarkAsProcessed(reactAssembly, resolver); reactAssembly.Write(intermediateAssembly, new WriterParameters { WriteSymbols = hasPdb, SymbolWriterProvider = hasPdb ? new PdbWriterProvider() : null }); log.WriteLine($"SignumTSGenerator finished in {sw.ElapsedMilliseconds.ToString()}ms"); Console.WriteLine(); return(hasErrors ? -1 : 0); }
internal static string Process(Options options, PreloadingAssemblyResolver resolver) { StringBuilder sb = new StringBuilder(); var module = ModuleDefinition.ReadModule(options.CurrentAssemblyReference.AssemblyFullPath, new ReaderParameters { AssemblyResolver = resolver }); var entities = resolver.SignumEntities; Cache = new TypeCache(entities); GetNamespaceReference(options, Cache.ModifiableEntity); var exportedTypes = module.Types.Where(a => a.Namespace == options.CurrentNamespace).ToList(); if (exportedTypes.Count == 0) { throw new InvalidOperationException($"Assembly '{options.CurrentAssembly}' has not types in namespace '{options.CurrentNamespace}'"); } var imported = module.Assembly.CustomAttributes.Where(at => at.AttributeType.FullName == Cache.ImportInTypeScriptAttribute.FullName) .Where(at => (string)at.ConstructorArguments[1].Value == options.CurrentNamespace) .Select(at => ((TypeReference)at.ConstructorArguments[0].Value).Resolve()) .ToList(); var importedMessage = imported.Where(a => a.Name.EndsWith("Message")).ToList(); var importedEnums = imported.Except(importedMessage).ToList(); var entityResults = (from type in exportedTypes where !type.IsValueType && (type.InTypeScript() ?? IsModifiableEntity(type)) select new { ns = type.Namespace, type, text = EntityInTypeScript(type, options), }).ToList(); var interfacesResults = (from type in exportedTypes where type.IsInterface && (type.InTypeScript() ?? AllInterfaces(type).Any(i => i.FullName == Cache.IEntity.FullName)) select new { ns = type.Namespace, type, text = EntityInTypeScript(type, options), }).ToList(); var usedEnums = (from type in entityResults.Select(a => a.type) from p in GetAllProperties(type) let pt = (p.PropertyType.ElementType() ?? p.PropertyType).UnNullify() let def = pt.Resolve() where def != null && def.IsEnum select def).Distinct().ToList(); var symbolResults = (from type in exportedTypes where !type.IsValueType && type.IsStaticClass() && type.ContainsAttribute("AutoInitAttribute") && (type.InTypeScript() ?? true) select new { ns = type.Namespace, type, text = SymbolInTypeScript(type, options), }).ToList(); var enumResult = (from type in exportedTypes where type.IsEnum && (type.InTypeScript() ?? usedEnums.Contains(type)) select new { ns = type.Namespace, type, text = EnumInTypeScript(type, options), }).ToList(); var externalEnums = (from type in usedEnums.Where(options.IsExternal).Concat(importedEnums) select new { ns = options.CurrentNamespace + ".External", type, text = EnumInTypeScript(type, options), }).ToList(); var externalMessages = (from type in importedMessage select new { ns = options.CurrentNamespace + ".External", type, text = MessageInTypeScript(type, options), }).ToList(); var messageResults = (from type in exportedTypes where type.IsEnum && type.Name.EndsWith("Message") select new { ns = type.Namespace, type, text = MessageInTypeScript(type, options), }).ToList(); var queryResult = (from type in exportedTypes where type.IsEnum && type.Name.EndsWith("Query") select new { ns = type.Namespace, type, text = QueryInTypeScript(type, options), }).ToList(); var namespaces = entityResults .Concat(interfacesResults) .Concat(enumResult) .Concat(messageResults) .Concat(queryResult) .Concat(symbolResults) .Concat(externalEnums) .Concat(externalMessages) .GroupBy(a => a.ns) .OrderBy(a => a.Key); foreach (var ns in namespaces) { var key = RemoveNamespace(ns.Key.ToString(), options.CurrentNamespace); if (key.Length == 0) { foreach (var item in ns.OrderBy(a => a.type.Name)) { sb.AppendLine(item.text); } } else { sb.AppendLine("export namespace " + key + " {"); sb.AppendLine(); foreach (var item in ns.OrderBy(a => a.type.Name)) { foreach (var line in item.text.Split(new[] { "\r\n" }, StringSplitOptions.None)) { sb.AppendLine(" " + line); } } sb.AppendLine("}"); sb.AppendLine(); } } var code = sb.ToString(); return(WriteFillFile(options, code)); }
public static int Main(string[] args) { var log = Console.Out; Stopwatch sw = Stopwatch.StartNew(); string intermediateAssembly = args[0]; string[] references = File.ReadAllLines(args[1]); string[] content = File.ReadAllLines(args[2]); log.WriteLine("Starting SignumTSGenerator"); var assemblyReferences = (from r in references where r.Contains(".Entities") let reactDirectory = FindReactDirectory(r) select new AssemblyReference { AssemblyName = Path.GetFileNameWithoutExtension(r), AssemblyFullPath = r, ReactDirectory = reactDirectory, AllTypescriptFiles = GetAllTypescriptFiles(reactDirectory), }).ToDictionary(a => a.AssemblyName); var entitiesAssembly = Path.GetFileNameWithoutExtension(intermediateAssembly).Replace(".React", ".Entities"); var entitiesAssemblyReference = assemblyReferences.GetOrThrow(entitiesAssembly); var currentDir = Directory.GetCurrentDirectory(); var files = content .Where(file => Path.GetExtension(file) == ".t4s") .Select(file => Path.Combine(currentDir, file)) .ToList(); var upToDateContent = string.Join("\r\n", new[] { entitiesAssemblyReference.AssemblyFullPath } .Concat(files) .OrderBy(a => a) .Select(f => File.GetLastWriteTimeUtc(f).ToString("o") + " " + Path.GetFileName(f))); var signumUpToDatePath = Path.Combine(Path.GetDirectoryName(args[1]), "SignumUpToDate.txt"); if (File.Exists(signumUpToDatePath) && File.ReadAllText(signumUpToDatePath) == upToDateContent) { log.WriteLine($"SignumTSGenerator already processed ({sw.ElapsedMilliseconds.ToString()}ms)"); return(0); } var entityResolver = new PreloadingAssemblyResolver(references); var entitiesModule = ModuleDefinition.ReadModule(entitiesAssemblyReference.AssemblyFullPath, new ReaderParameters { AssemblyResolver = entityResolver }); var options = new AssemblyOptions { CurrentAssembly = entitiesAssembly, AssemblyReferences = assemblyReferences, AllReferences = references.ToDictionary(a => Path.GetFileNameWithoutExtension(a)), ModuleDefinition = entitiesModule, Resolver = entityResolver, }; bool hasErrors = false; foreach (var file in files) { try { string result = EntityDeclarationGenerator.Process(options, file, Path.GetFileNameWithoutExtension(file)); var targetFile = Path.ChangeExtension(file, ".ts"); if (File.Exists(targetFile) && File.ReadAllText(targetFile) == result) { log.WriteLine($"Skipping {targetFile} (Up to date)"); } else { log.WriteLine($"Writing {targetFile}"); File.WriteAllText(targetFile, result); } } catch (Exception ex) { hasErrors = true; log.WriteLine($"{file}:error STSG0001:{ex.Message}"); log.WriteLine(ex.Message); } } if (hasErrors) { log.WriteLine($"SignumTSGenerator finished with errors ({sw.ElapsedMilliseconds.ToString()}ms)"); Console.WriteLine(); return(0); } else { File.WriteAllText(signumUpToDatePath, upToDateContent); log.WriteLine($"SignumTSGenerator finished ({sw.ElapsedMilliseconds.ToString()}ms)"); Console.WriteLine(); return(0); } }