mirror of https://github.com/abpframework/abp.git
committed by
GitHub
8 changed files with 310 additions and 46 deletions
@ -0,0 +1,84 @@ |
|||||
|
using System; |
||||
|
using System.IO; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public class DbContextFileBuilderConfigureAdder : ITransientDependency |
||||
|
{ |
||||
|
public ILogger<DbContextFileBuilderConfigureAdder> Logger { get; set; } |
||||
|
|
||||
|
protected UsingStatementAdder UsingStatementAdder { get; } |
||||
|
|
||||
|
public DbContextFileBuilderConfigureAdder(UsingStatementAdder usingStatementAdder) |
||||
|
{ |
||||
|
UsingStatementAdder = usingStatementAdder; |
||||
|
Logger = NullLogger<DbContextFileBuilderConfigureAdder>.Instance; |
||||
|
} |
||||
|
|
||||
|
public void Add(string path, string moduleConfiguration) |
||||
|
{ |
||||
|
var file = File.ReadAllText(path); |
||||
|
|
||||
|
file = UsingStatementAdder.Add(file, GetNamespace(moduleConfiguration)); |
||||
|
|
||||
|
var stringToAdd = GetLineToAdd(moduleConfiguration); |
||||
|
if (!file.Contains(stringToAdd)) |
||||
|
{ |
||||
|
var indexToInsert = FindIndexToInsert(file); |
||||
|
|
||||
|
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.WriteAllText(path, file); |
||||
|
} |
||||
|
|
||||
|
protected int FindIndexToInsert(string file) |
||||
|
{ |
||||
|
var indexOfMethodDeclaration = file.IndexOf("OnModelCreating(", StringComparison.Ordinal); |
||||
|
var indexOfOpeningBracket = indexOfMethodDeclaration + file.Substring(indexOfMethodDeclaration).IndexOf('{'); |
||||
|
|
||||
|
var stack = 1; |
||||
|
var index = indexOfOpeningBracket; |
||||
|
|
||||
|
while (stack > 0) |
||||
|
{ |
||||
|
index++; |
||||
|
|
||||
|
if (index >= file.Length) |
||||
|
{ |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if (file[index] == '{') |
||||
|
{ |
||||
|
stack++; |
||||
|
} |
||||
|
else if (file[index] == '}') |
||||
|
{ |
||||
|
stack--; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return index; |
||||
|
} |
||||
|
|
||||
|
protected string GetLineToAdd(string moduleConfiguration) |
||||
|
{ |
||||
|
return "builder." + moduleConfiguration.Split(':')[1] + "();"; |
||||
|
} |
||||
|
|
||||
|
protected string GetNamespace(string moduleConfiguration) |
||||
|
{ |
||||
|
return string.Join(".", moduleConfiguration.Split(':')[0]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,42 +1,83 @@ |
|||||
using System.Collections.Generic; |
using System; |
||||
|
using System.Collections.Generic; |
||||
using System.IO; |
using System.IO; |
||||
using System.Linq; |
using System.Linq; |
||||
using Microsoft.CodeAnalysis.CSharp; |
using Microsoft.CodeAnalysis.CSharp; |
||||
using Microsoft.CodeAnalysis.CSharp.Syntax; |
using Microsoft.CodeAnalysis.CSharp.Syntax; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
namespace Volo.Abp.Cli.ProjectModification |
namespace Volo.Abp.Cli.ProjectModification |
||||
{ |
{ |
||||
public class DerivedClassFinder : ITransientDependency |
public class DerivedClassFinder : ITransientDependency |
||||
{ |
{ |
||||
|
public ILogger<DerivedClassFinder> Logger { get; set; } |
||||
|
|
||||
|
public DerivedClassFinder() |
||||
|
{ |
||||
|
Logger = NullLogger<DerivedClassFinder>.Instance; |
||||
|
} |
||||
|
|
||||
public virtual List<string> Find(string csprojFilePath, string baseClass) |
public virtual List<string> Find(string csprojFilePath, string baseClass) |
||||
{ |
{ |
||||
var moduleFilePaths = new List<string>(); |
var moduleFilePaths = new List<string>(); |
||||
|
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) |
.GetFiles("*.cs", SearchOption.AllDirectories) |
||||
|
.Where(f => !f.DirectoryName.StartsWith(binFile)) |
||||
|
.Where(f => !f.DirectoryName.StartsWith(objFile)) |
||||
.Select(f => f.FullName) |
.Select(f => f.FullName) |
||||
.ToList(); |
.ToList(); |
||||
|
|
||||
foreach (var csFile in csFiles) |
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; |
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 root = CSharpSyntaxTree.ParseText(File.ReadAllText(csFile)).GetRoot(); |
||||
var namespaceSyntax = root.DescendantNodes().OfType<NamespaceDeclarationSyntax>().First(); |
var namespaceSyntax = root.DescendantNodes().OfType<NamespaceDeclarationSyntax>().First(); |
||||
var classDeclaration = (namespaceSyntax.DescendantNodes().OfType<ClassDeclarationSyntax>()).First(); |
var classDeclaration = (namespaceSyntax.DescendantNodes().OfType<ClassDeclarationSyntax>()).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 |
return false; |
||||
.Any(t => t.ToString().Equals(baseClass)) ?? false; |
|
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,47 @@ |
|||||
|
using System; |
||||
|
using System.Diagnostics; |
||||
|
using System.IO; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public class EfCoreMigrationAdder : ITransientDependency |
||||
|
{ |
||||
|
public void AddMigration(string csprojFile, string module, bool updateDatabase = true) |
||||
|
{ |
||||
|
var moduleName = ParseModuleName(module); |
||||
|
var migrationName = "Added_" + moduleName + "_Module" + GetUniquePostFix(); |
||||
|
|
||||
|
var process = Process.Start("CMD.exe", "/C cd \"" + Path.GetDirectoryName(csprojFile) + "\" & dotnet ef migrations add " + migrationName); |
||||
|
process.WaitForExit(); |
||||
|
|
||||
|
if (updateDatabase) |
||||
|
{ |
||||
|
UpdateDatabase(csprojFile); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected void UpdateDatabase(string csprojFile) |
||||
|
{ |
||||
|
var process = Process.Start("CMD.exe", "/C cd \"" + Path.GetDirectoryName(csprojFile) + "\" & dotnet ef database update"); |
||||
|
process.WaitForExit(); |
||||
|
} |
||||
|
|
||||
|
protected virtual string ParseModuleName(string fullModuleName) |
||||
|
{ |
||||
|
var words = fullModuleName?.Split('.'); |
||||
|
|
||||
|
if (words == null || words.Length <= 1) |
||||
|
{ |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
return words[words.Length - 1]; |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetUniquePostFix() |
||||
|
{ |
||||
|
return "_" + new Random().Next(1,99999); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
using System; |
||||
|
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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue