public void BasicTest() { TestFileSystem fileSystem = new TestFileSystem(); fileSystem.AddFile("A\\table1.cs", TestTable1Text); var generated = ExistingCodeExplorer .EnumerateTableDescriptorsModelAttributes("A", fileSystem) .ParseAttribute(true) .CreateAnalysis() .Select(meta => ModelClassGenerator.Generate(meta, "Org", "", true, ModelType.ImmutableClass, fileSystem, out _).SyntaxTree) .ToList(); var trees = new List <SyntaxTree>(); foreach (var syntaxTree in generated) { trees.Add(CSharpSyntaxTree.ParseText(syntaxTree.ToString())); } trees.Add(CSharpSyntaxTree.ParseText(TestTable1Text)); var compilation = CSharpCompilation.Create("SqModels", trees, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: NullableContextOptions.Enable)); compilation = compilation.AddReferences( MetadataReference.CreateFromFile(Assembly.Load("netstandard, Version=2.0.0.0").Location), MetadataReference.CreateFromFile(typeof(object).Assembly.GetAssemblyLocation()), MetadataReference.CreateFromFile(Assembly .Load("System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") .Location), MetadataReference.CreateFromFile(typeof(SqQueryBuilder).Assembly.GetAssemblyLocation())); MemoryStream ms = new MemoryStream(); var emitResult = compilation.Emit(ms); if (!emitResult.Success) { Diagnostic first = emitResult.Diagnostics.First(); var sourceCode = first.Location.SourceTree?.ToString(); var s = sourceCode?.Substring(first.Location.SourceSpan.Start, first.Location.SourceSpan.Length); Console.WriteLine(sourceCode); Assert.Fail(first.GetMessage() + (string.IsNullOrEmpty(s)?null:$" \"{s}\"")); } var assembly = Assembly.Load(ms.ToArray()); var allTypes = assembly.GetTypes(); Assert.AreEqual(21, allTypes.Length); }
public static async Task RunGenTablesOptions(GenTablesOptions options) { ILogger logger = new DefaultLogger(Console.Out, options.Verbosity); logger.LogMinimal("Table proxy classes generation is running..."); string directory = EnsureDirectory(options.OutputDir, logger, "Output", true); if (string.IsNullOrEmpty(options.ConnectionString)) { throw new SqExpressCodeGenException("Connection string cannot be empty"); } logger.LogNormal("Checking existing code..."); IReadOnlyDictionary <TableRef, ClassDeclarationSyntax> existingCode = ExistingCodeExplorer.FindTableDescriptors(directory); if (logger.IsNormalOrHigher) { logger.LogNormal(existingCode.Count > 0 ? $"Found {existingCode.Count} already existing table descriptor classes." : "No table descriptor classes found."); } var sqlManager = CreateDbManager(options); logger.LogNormal("Connecting to database..."); var connectionTest = await sqlManager.TryOpenConnection(); if (!string.IsNullOrEmpty(connectionTest)) { throw new SqExpressCodeGenException(connectionTest); } logger.LogNormal("Success!"); var tables = await sqlManager.SelectTables(); if (logger.IsNormalOrHigher) { logger.LogNormal(tables.Count > 0 ? $"Found {tables.Count} tables." : "No tables found in the database."); if (logger.IsDetailed) { foreach (var tableModel in tables) { Console.WriteLine($"{tableModel.DbName} ({tableModel.Name})"); foreach (var tableModelColumn in tableModel.Columns) { Console.WriteLine($"- {tableModelColumn.DbName.Name} {tableModelColumn.ColumnType.GetType().Name}{(tableModelColumn.Pk.HasValue ? " (PK)":null)}{(tableModelColumn.Fk != null ? $" (FK: {string.Join(';', tableModelColumn.Fk.Select(f=>f.ToString()))})" : null)}"); } } } } logger.LogNormal("Code generation..."); IReadOnlyDictionary <TableRef, TableModel> tableMap = tables.ToDictionary(t => t.DbName); var tableClassGenerator = new TableClassGenerator(tableMap, options.Namespace, existingCode); foreach (var table in tables) { string filePath = Path.Combine(directory, $"{table.Name}.cs"); if (logger.IsDetailed) { logger.LogDetailed($"{table.DbName} to \"{filePath}\"."); } var text = tableClassGenerator.Generate(table, out var existing).ToFullString(); await File.WriteAllTextAsync(filePath, text); if (logger.IsDetailed) { logger.LogDetailed(existing ? "Existing file updated." : "New file created."); } } var allTablePath = Path.Combine(directory, "AllTables.cs"); if (logger.IsDetailed) { logger.LogDetailed($"AllTables to \"{allTablePath}\"."); } await File.WriteAllTextAsync(allTablePath, TableListClassGenerator.Generate(allTablePath, tables, options.Namespace, options.TableClassPrefix).ToFullString()); logger.LogMinimal("Table proxy classes generation successfully completed!"); }
private static async Task RunGenModelsOptions(GenModelsOptions options) { ILogger logger = new DefaultLogger(Console.Out, options.Verbosity); logger.LogMinimal("Model classes generation is running..."); string inDirectory = EnsureDirectory(options.InputDir, logger, "Input", false); string outDirectory = EnsureDirectory(options.OutputDir, logger, "Output", true); var analysis = ExistingCodeExplorer .EnumerateTableDescriptorsModelAttributes(inDirectory) .ParseAttribute(options.NullRefTypes) .CreateAnalysis(); if (analysis.Count < 1) { logger.LogNormal("No model attributes detected in the input directory."); } else { logger.LogNormal($"Found {analysis.Count} models in the input directory."); } if (logger.IsDetailed) { foreach (var model in analysis) { logger.LogDetailed(model.Name); foreach (var property in model.Properties) { logger.LogDetailed( $" -{property.Type} {property.Name}"); foreach (var col in property.Column) { logger.LogDetailed( $" ={(property.CastType != null ? $"({property.CastType})" : null)}{col.TableRef.TableTypeName}.{col.ColumnName}"); } } } } logger.LogNormal("Code generation..."); foreach (var meta in analysis) { string path = Path.Combine(outDirectory, $"{meta.Name}.cs"); if (logger.IsDetailed) { logger.LogDetailed(path); } await File.WriteAllTextAsync(path, ModelClassGenerator.Generate(meta, options.Namespace, path, out var existing).ToFullString()); if (logger.IsDetailed) { logger.LogDetailed(existing ? "Existing file updated." : "New file created."); } } logger.LogMinimal("Model classes generation successfully completed!"); }
private static async Task RunGenModelsOptions(GenModelsOptions options) { ILogger logger = new DefaultLogger(Console.Out, options.Verbosity); logger.LogMinimal("Model classes generation is running..."); string inDirectory = EnsureDirectory(options.InputDir, logger, "Input", false); string outDirectory = EnsureDirectory(options.OutputDir, logger, "Output", true); var analysis = ExistingCodeExplorer .EnumerateTableDescriptorsModelAttributes(inDirectory, DefaultFileSystem.Instance) .ParseAttribute(options.NullRefTypes) .CreateAnalysis(); if (analysis.Count < 1) { logger.LogNormal("No model attributes detected in the input directory."); } else { logger.LogNormal($"Found {analysis.Count} models in the input directory."); } if (logger.IsDetailed) { foreach (var model in analysis) { logger.LogDetailed(model.Name); foreach (var property in model.Properties) { logger.LogDetailed( $" -{property.Type} {property.Name}"); foreach (var col in property.Column) { logger.LogDetailed( $" ={(property.CastType != null ? $"({property.CastType})" : null)}{col.TableRef.TableTypeName}.{col.ColumnName}"); } } } } logger.LogNormal("Code generation..."); foreach (var meta in analysis) { string path = Path.Combine(outDirectory, $"{meta.Name}.cs"); if (logger.IsDetailed) { logger.LogDetailed(path); } await File.WriteAllTextAsync(path, ModelClassGenerator.Generate(meta, options.Namespace, path, options.RwClasses, options.ModelType, DefaultFileSystem.Instance, out var existing).ToFullString()); if (logger.IsDetailed) { logger.LogDetailed(existing ? "Existing file updated." : "New file created."); } } if (options.CleanOutput) { var modelFiles = analysis.Select(meta => $"{meta.Name}.cs").ToHashSet(StringComparer.InvariantCultureIgnoreCase); var toRemove = Directory.EnumerateFiles(outDirectory).Where(p => !modelFiles.Contains(Path.GetFileName(p))).ToList(); foreach (var delPath in toRemove) { File.Delete(delPath); if (logger.IsNormalOrHigher) { logger.LogNormal($"File {Path.GetFileName(delPath)} has been removed since it does not contain any model class"); } } } logger.LogMinimal("Model classes generation successfully completed!"); }