From aaee2ef41fd3c551898bc3415ee2c26bbc49ab85 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Thu, 16 May 2019 10:38:21 +0300 Subject: [PATCH] CLI can configure Entity Framework after installing a module cont. --- .../DbContextFileBuilderConfigureAdder.cs | 45 +++++++++++-- .../ProjectModification/DerivedClassFinder.cs | 55 ++++++++++++++-- .../ModuleClassDependcyAdder.cs | 44 +++---------- .../SolutionModuleAdder.cs | 2 +- .../UsingStatementAdder.cs | 65 +++++++++++++++++++ 5 files changed, 160 insertions(+), 51 deletions(-) create mode 100644 framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/UsingStatementAdder.cs diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DbContextFileBuilderConfigureAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DbContextFileBuilderConfigureAdder.cs index 8f4d48adfa..b8af0ed471 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DbContextFileBuilderConfigureAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DbContextFileBuilderConfigureAdder.cs @@ -1,23 +1,42 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Text; +using System.Linq; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Cli.ProjectModification { public class DbContextFileBuilderConfigureAdder : ITransientDependency { + protected UsingStatementAdder UsingStatementAdder { get; } + public ILogger Logger { get; set; } + + public DbContextFileBuilderConfigureAdder(UsingStatementAdder usingStatementAdder) + { + UsingStatementAdder = usingStatementAdder; + Logger = NullLogger.Instance; + } + public void Add(string path, string moduleConfiguration) { var file = File.ReadAllText(path); - var indexToInsert = FindIndexToInsert(file); + file = UsingStatementAdder.Add(file, GetNamespace(moduleConfiguration)); + var stringToAdd = GetLineToAdd(moduleConfiguration); + if (!file.Contains(stringToAdd)) + { + var indexToInsert = FindIndexToInsert(file); - stringToAdd = " " + stringToAdd + Environment.NewLine; + if (indexToInsert <= 0 || indexToInsert >= file.Length) + { + Logger.LogWarning($"\"OnModelCreating(ModelBuilder builder)\" method couldn't be found in {path}"); + return; + } + file = file.Insert(indexToInsert, " " + stringToAdd + Environment.NewLine + " "); + } - file = file.Insert(indexToInsert, stringToAdd); File.WriteAllText(path, file); } @@ -30,9 +49,15 @@ namespace Volo.Abp.Cli.ProjectModification var stack = 1; var index = indexOfOpeningBracket; - while (stack > 0 || index < file.Length) + while (stack > 0) { index++; + + if (index >= file.Length) + { + break; + } + if (file[index] == '{') { stack++; @@ -42,12 +67,18 @@ namespace Volo.Abp.Cli.ProjectModification stack--; } } + return index; } protected string GetLineToAdd(string moduleConfiguration) { - return "builder.Configure" + moduleConfiguration + "();"; + return "builder." + moduleConfiguration.Split('.').Last() + "();"; + } + + protected string GetNamespace(string moduleConfiguration) + { + return string.Join(".", moduleConfiguration.Split('.').Reverse().Skip(2)); } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs index bf11e0af65..db39a660ce 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/DerivedClassFinder.cs @@ -1,42 +1,83 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Cli.ProjectModification { public class DerivedClassFinder : ITransientDependency { + public ILogger Logger { get; set; } + + public DerivedClassFinder() + { + Logger = NullLogger.Instance; + } + public virtual List Find(string csprojFilePath, string baseClass) { var moduleFilePaths = new List(); + var csprojFileDirectory = Path.GetDirectoryName(csprojFilePath); + var binFile = Path.Combine(csprojFileDirectory, "bin"); + var objFile = Path.Combine(csprojFileDirectory, "obj"); + - var csFiles = new DirectoryInfo(Path.GetDirectoryName(csprojFilePath)) + var csFiles = new DirectoryInfo(csprojFileDirectory) .GetFiles("*.cs", SearchOption.AllDirectories) + .Where(f => !f.DirectoryName.StartsWith(binFile)) + .Where(f => !f.DirectoryName.StartsWith(objFile)) .Select(f => f.FullName) .ToList(); foreach (var csFile in csFiles) { - if (IsDerivedFromAbpModule(csFile, baseClass)) + try { - moduleFilePaths.Add(csFile); + if (IsDerived(csFile, baseClass)) + { + moduleFilePaths.Add(csFile); + } + } + catch (Exception) + { + Logger.LogDebug($"Couldn't parse {csFile}."); } } return moduleFilePaths; } - protected bool IsDerivedFromAbpModule(string csFile, string baseClass) + protected bool IsDerived(string csFile, string baseClass) { + Logger.LogDebug(csFile); var root = CSharpSyntaxTree.ParseText(File.ReadAllText(csFile)).GetRoot(); var namespaceSyntax = root.DescendantNodes().OfType().First(); var classDeclaration = (namespaceSyntax.DescendantNodes().OfType()).First(); + var baseTypeList = classDeclaration.BaseList?.Types.Select(t => t.ToString()).ToList(); + + if (baseTypeList == null) + { + return false; + } + + foreach (var baseType in baseTypeList) + { + if (baseType.Contains('<') && baseType.Substring(0, baseType.IndexOf('<')) == baseClass) + { + return true; + } + if (baseType == baseClass) + { + return true; + } + } - return classDeclaration.BaseList?.Types - .Any(t => t.ToString().Equals(baseClass)) ?? false; + return false; } } } diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ModuleClassDependcyAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ModuleClassDependcyAdder.cs index 594c77e5fa..9388ce42fe 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ModuleClassDependcyAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/ModuleClassDependcyAdder.cs @@ -7,16 +7,20 @@ namespace Volo.Abp.Cli.ProjectModification { public class ModuleClassDependcyAdder : ITransientDependency { + protected UsingStatementAdder UsingStatementAdder { get; } + + public ModuleClassDependcyAdder(UsingStatementAdder usingStatementAdder) + { + UsingStatementAdder = usingStatementAdder; + } + public virtual void Add(string path, string module) { ParseModuleNameAndNameSpace(module, out var nameSpace, out var moduleName); var file = File.ReadAllText(path); - if (!file.Contains(GetUsingStatement(nameSpace)) ) - { - file = InsertUsingStatement(file, nameSpace); - } + file = UsingStatementAdder.Add(file, nameSpace); if (!file.Contains(moduleName) ) { @@ -34,38 +38,6 @@ namespace Volo.Abp.Cli.ProjectModification return file.Insert(indexOfPublicClassDeclaration, dependsOnAttribute); } - protected virtual string InsertUsingStatement(string file, string nameSpace) - { - var indexOfTheEndOfTheLastUsingStatement = GetIndexOfTheEndOfTheLastUsingStatement(file); - - return file.Insert(indexOfTheEndOfTheLastUsingStatement, Environment.NewLine + GetUsingStatement(nameSpace)); - } - - protected virtual int GetIndexOfTheEndOfTheLastUsingStatement(string file) - { - var indexOfPublicClassDeclaration = GetIndexOfWhereDependsOnWillBeAdded(file); - file = file.Substring(0, indexOfPublicClassDeclaration); - - var indexOfTheStartOfLastUsingStatement = - file.LastIndexOf("using ", StringComparison.Ordinal); - - if (indexOfTheStartOfLastUsingStatement < 0) - { - return 0; - } - - var indexOfFirstSemiColonAfterLastUsingStatement = - file.Substring(indexOfTheStartOfLastUsingStatement).IndexOf(';'); - - if (indexOfFirstSemiColonAfterLastUsingStatement < 0) - { - return 0; - } - - return indexOfTheStartOfLastUsingStatement - + indexOfFirstSemiColonAfterLastUsingStatement + 1; - } - protected virtual int GetIndexOfWhereDependsOnWillBeAdded(string file) { var indexOfPublicClassDeclaration = file.IndexOf("public class", StringComparison.Ordinal); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs index 6048338b10..c62beeacc1 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/SolutionModuleAdder.cs @@ -97,7 +97,7 @@ namespace Volo.Abp.Cli.ProjectModification } var dbMigrationsProject = projectFiles.FirstOrDefault(p => p.EndsWith(".DbMigrations.csproj")); - + if (dbMigrationsProject == null) { Logger.LogDebug("Solution doesn't have a \".DbMigrations\" project."); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/UsingStatementAdder.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/UsingStatementAdder.cs new file mode 100644 index 0000000000..fd6a95fb10 --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectModification/UsingStatementAdder.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Cli.ProjectModification +{ + public class UsingStatementAdder : ITransientDependency + { + public string Add(string fileContent, string nameSpace) + { + if (fileContent.Contains(nameSpace)) + { + return fileContent; + } + + var index = GetIndexOfTheEndOfTheLastUsingStatement(fileContent); + + if (index < 0 || index >= fileContent.Length) + { + index = 0; + } + + var usingStatement = GetUsingStatement(nameSpace); + + return fileContent.Insert(index, usingStatement); + } + + protected string GetUsingStatement(string nameSpace) + { + return Environment.NewLine + "using " + nameSpace + ";"; + } + + protected virtual int GetIndexOfTheEndOfTheLastUsingStatement(string fileContent) + { + var indexOfNamespaceDeclaration = fileContent.IndexOf("namespace", StringComparison.Ordinal); + + if (indexOfNamespaceDeclaration < 0) + { + return 0; + } + + fileContent = fileContent.Substring(0, indexOfNamespaceDeclaration); + + var indexOfTheStartOfLastUsingStatement = + fileContent.LastIndexOf("using ", StringComparison.Ordinal); + + if (indexOfTheStartOfLastUsingStatement < 0) + { + return 0; + } + + var indexOfFirstSemiColonAfterLastUsingStatement = + fileContent.Substring(indexOfTheStartOfLastUsingStatement).IndexOf(';'); + + if (indexOfFirstSemiColonAfterLastUsingStatement < 0) + { + return 0; + } + + return indexOfTheStartOfLastUsingStatement + + indexOfFirstSemiColonAfterLastUsingStatement + 1; + } + } +}