public async Task GenerateFiles(Entity rootEntity, string generator, string output, bool outputDefined, ChangeObservable observable) { IEnumerable <Entity> generatableEntities = rootEntity.Hierarchy(); HashSet <VirtualFile> generatedFiles = new HashSet <VirtualFile>(); HashSet <VirtualDirectory> rootDirectories = new HashSet <VirtualDirectory>(); foreach (Entity generatableEntity in generatableEntities) { await GenerateFilesForEntity(generatableEntity).ConfigureAwait(false); } Exception e = rootEntity.GetCodeExceptions(); if (e != null) { e.CompleteCodeExceptions(fileSystem.GetDirectory(rootEntity.Path)); throw e; } foreach (VirtualDirectory rootDirectory in rootDirectories) { DeleteRedundantFiles(rootDirectory); } void DeleteRedundantFiles(VirtualDirectory rootDirectory) { foreach (VirtualFile file in rootDirectory.Files(searchRecursive:true).Where(f => !generatedFiles.Contains(f)).ToArray()) { VirtualDirectory current = file.Parent; file.Delete(); while (current != null && !current.Entries.Any()) { VirtualDirectory next = current.Parent; current.Delete(); current = next; } } } async Task GenerateFilesForEntity(Entity generatableEntity) { TemplateDescription template = generatableEntity.Template(); if (template == null) { return; } foreach (templateGeneratedFile file in template.GeneratedFile ?? Enumerable.Empty <templateGeneratedFile>()) { if (generator != "all" && !file.generator.Equals(generator, StringComparison.OrdinalIgnoreCase)) { continue; } if (!string.IsNullOrEmpty(file.condition)) { string condition = await resolver.ResolveAsync(file.condition, generatableEntity).ConfigureAwait(false); if (condition.Equals("false", StringComparison.OrdinalIgnoreCase)) { continue; } } (string content, Encoding encoding) = await GetResolvedTemplateContent(generatableEntity, file, template).ConfigureAwait(false); VirtualDirectory baseDirectory = GetBaseDirectory(file); VirtualFile destination = await GetFile(generatableEntity, file, true, baseDirectory.FullName, template).ConfigureAwait(false); rootDirectories.Add(baseDirectory); generatedFiles.Add(destination); observable.OnNext(new Change(() => destination.Restore(), $"Generated the file {destination.FullName}.")); using (Stream fileStream = destination.OpenComparingWriteStream()) using (StreamWriter writer = new StreamWriter(fileStream, encoding)) { await writer.WriteAsync(content).ConfigureAwait(false); } } VirtualDirectory GetBaseDirectory(templateGeneratedFile file) { string generatorPath = output; if (!outputDefined) { generatorPath = Path.Combine(Constants.IntermediateFolderName, file.generator.ToLowerInvariant()); } else if (generator == "all") { generatorPath = Path.Combine(generatorPath, file.generator.ToLowerInvariant()); } return(fileSystem.GetDirectory(generatorPath, rootEntity.Path)); } } }