Implemented add-module to project (initial, will be refactored).

pull/1466/head^2
Halil ibrahim Kalkan 7 years ago
parent 803f3b8701
commit c8bf413cfe

@ -17,6 +17,7 @@
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
<PackageReference Include="System.Security.Permissions" Version="4.5.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.0.0" />
</ItemGroup>
<ItemGroup>

@ -22,7 +22,7 @@ namespace Volo.Abp.Cli
{
options.Commands["help"] = typeof(HelpCommand);
options.Commands["new"] = typeof(NewCommand);
options.Commands["add"] = typeof(AddCommand);
options.Commands["add-module"] = typeof(AddModuleCommand);
options.Commands["login"] = typeof(LoginCommand);
options.Commands["logout"] = typeof(LogoutCommand);
});

@ -13,7 +13,10 @@ namespace Volo.Abp.Cli
{
public class CliService : ITransientDependency
{
public static string Version => typeof(AbpCliCoreModule).Assembly.GetFileVersion();
//public static string Version => typeof(AbpCliCoreModule).Assembly
// .GetFileVersion()
// .RemovePostFix(".0");
public static string Version => "0.17.0.0";
public ILogger<CliService> Logger { get; set; }

@ -7,16 +7,16 @@ using Volo.Abp.ProjectModification;
namespace Volo.Abp.Cli.Commands
{
public class AddCommand : IConsoleCommand, ITransientDependency
public class AddModuleCommand : IConsoleCommand, ITransientDependency
{
public ILogger<AddCommand> Logger { get; set; }
public ILogger<AddModuleCommand> Logger { get; set; }
protected ModuleAdder ModuleAdder { get; }
public AddCommand(ModuleAdder moduleAdder)
public AddModuleCommand(ModuleAdder moduleAdder)
{
ModuleAdder = moduleAdder;
Logger = NullLogger<AddCommand>.Instance;
Logger = NullLogger<AddModuleCommand>.Instance;
}
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Volo.Abp.ProjectModification
{
public class AbpModuleFinder
{
public List<string> Find(string csprojFilePath)
{
var modules = new List<string>();
var csFiles = GetAllCsFilesUnderDirectory(Path.GetDirectoryName(csprojFilePath), new List<string>());
foreach (var csFile in csFiles)
{
try
{
var root = CSharpSyntaxTree.ParseText(File.ReadAllText(csFile)).GetRoot();
var namespaceSyntaxs = root.DescendantNodes().OfType<NamespaceDeclarationSyntax>();
foreach (var namespaceSyntax in namespaceSyntaxs)
{
var classDeclarationSyntaxs = namespaceSyntax.DescendantNodes().OfType<ClassDeclarationSyntax>();
var syntaxsArray = classDeclarationSyntaxs as ClassDeclarationSyntax[] ?? classDeclarationSyntaxs.ToArray();
foreach (var classDeclaration in syntaxsArray)
{
var classDerivedFromAbpModule = classDeclaration.BaseList?.Types.FirstOrDefault(t => t.ToString().Contains("AbpModule"));
if (classDerivedFromAbpModule != null)
{
modules.Add(csFile);
}
}
}
}
catch (Exception)
{
//ignored!
}
}
return modules;
}
private static List<string> GetAllCsFilesUnderDirectory(string path, List<string> allCsFileList)
{
var directory = new DirectoryInfo(path);
var files = directory.GetFiles("*.cs").Select(f => f.DirectoryName + "\\" + f.Name).ToList();
foreach (var s in files)
{
allCsFileList.Add(s);
}
var directories = directory.GetDirectories().Select(d => path + "\\" + d.Name).ToList();
foreach (var subDirectory in directories)
{
allCsFileList = GetAllCsFilesUnderDirectory(subDirectory, allCsFileList);
}
return allCsFileList;
}
}
}

@ -0,0 +1,45 @@
using System;
using System.IO;
using System.Linq;
namespace Volo.Abp.ProjectModification
{
public class DependsOnAdder
{
public void Add(string path, string module)
{
ParseModuleNameAndNameSpace(module, out var nameSpace, out var moduleName);
var file = File.ReadAllText(path);
var indexOfEndingPublicClass = file.IndexOf("public class", StringComparison.Ordinal);
var dependsOnAttribute = "[DependsOn(" + moduleName + ")]" + Environment.NewLine + " ";
file = file.Insert(indexOfEndingPublicClass, dependsOnAttribute);
file = file.Insert(0, GetUsingStatement(nameSpace) + Environment.NewLine); //TODO: Add as the last item in the using list!
File.WriteAllText(path, file);
}
private void ParseModuleNameAndNameSpace(string module, out string nameSpace, out string moduleName)
{
var words = module?.Split('.');
if (words == null || words.Length <= 1)
{
nameSpace = null;
moduleName = module;
return;
}
moduleName = words[words.Length - 1];
nameSpace = string.Join(".", words.Take(words.Length - 1));
}
private string GetUsingStatement(string nameSpace)
{
return "using " + nameSpace + ";";
}
}
}

@ -15,12 +15,12 @@ namespace Volo.Abp.ProjectModification
{
public ILogger<ModuleAdder> Logger { get; set; }
protected ProjectModuleAdder ProjectModuleAdder { get; }
protected ProjectNugetPackageAdder ProjectNugetPackageAdder { get; }
protected SolutionModuleAdder SolutionModuleAdder { get; }
public ModuleAdder(ProjectModuleAdder projectModuleAdder, SolutionModuleAdder solutionModuleAdder)
public ModuleAdder(ProjectNugetPackageAdder projectNugetPackageAdder, SolutionModuleAdder solutionModuleAdder)
{
ProjectModuleAdder = projectModuleAdder;
ProjectNugetPackageAdder = projectNugetPackageAdder;
SolutionModuleAdder = solutionModuleAdder;
Logger = NullLogger<ModuleAdder>.Instance;
@ -43,7 +43,7 @@ namespace Volo.Abp.ProjectModification
if (!args.ProjectFile.IsNullOrEmpty())
{
await ProjectModuleAdder.AddAsync(args.ProjectFile, args.ModuleName);
await ProjectNugetPackageAdder.AddAsync(args.ProjectFile, args.ModuleName);
}
if (!args.SolutionFile.IsNullOrEmpty())

@ -0,0 +1,11 @@
namespace Volo.Abp.ProjectModification
{
public class NpmPackageInfo
{
public string Name { get; set; }
public int ApplicationType { get; set; } //TODO: Enum?
public bool IsPro { get; set; }
}
}

@ -0,0 +1,13 @@
namespace Volo.Abp.ProjectModification
{
public class NugetPackageInfo
{
public string Name { get; set; }
public string ModuleClass { get; set; }
public int Target { get; set; } //TODO: Enum?
public NpmPackageInfo DependedNpmPackage { get; set; }
}
}

@ -1,13 +0,0 @@
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.ProjectModification
{
public class ProjectModuleAdder : ITransientDependency
{
public async Task AddAsync(string projectFile, string moduleName)
{
}
}
}

@ -0,0 +1,42 @@
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.ProjectModification
{
public class ProjectNpmPackageAdder : ITransientDependency
{
public ILogger<ProjectNpmPackageAdder> Logger { get; set; }
public ProjectNpmPackageAdder()
{
Logger = NullLogger<ProjectNpmPackageAdder>.Instance;
}
public Task AddAsync(string directory, NpmPackageInfo npmPackage)
{
var packageJsonFilePath = Path.Combine(directory, "package.json");
if (!File.Exists(packageJsonFilePath))
{
return Task.CompletedTask;
}
Logger.LogInformation($"Installing '{npmPackage.Name}' package to the project '{packageJsonFilePath}'...");
Logger.LogInformation("yarn add " + npmPackage.Name + "...");
var procStartInfo = new ProcessStartInfo("cmd.exe", "/C yarn add " + npmPackage.Name);
procStartInfo.WindowStyle = ProcessWindowStyle.Normal;
Process.Start(procStartInfo).WaitForExit();
Logger.LogInformation("gulp...");
procStartInfo = new ProcessStartInfo("cmd.exe", "/C gulp");
procStartInfo.WindowStyle = ProcessWindowStyle.Normal;
Process.Start(procStartInfo).WaitForExit();
return Task.CompletedTask;
}
}
}

@ -0,0 +1,81 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace Volo.Abp.ProjectModification
{
public class ProjectNugetPackageAdder : ITransientDependency
{
public ILogger<ProjectNugetPackageAdder> Logger { get; set; }
protected IJsonSerializer JsonSerializer { get; }
protected ProjectNpmPackageAdder NpmPackageAdder { get; }
public ProjectNugetPackageAdder(
IJsonSerializer jsonSerializer,
ProjectNpmPackageAdder npmPackageAdder)
{
JsonSerializer = jsonSerializer;
NpmPackageAdder = npmPackageAdder;
Logger = NullLogger<ProjectNugetPackageAdder>.Instance;
}
public async Task AddAsync(string projectFile, string packageName)
{
var packageInfo = await FindNugetPackageInfoAsync(packageName);
if (packageInfo == null)
{
return;
}
Logger.LogInformation($"Installing '{packageName}' package to the project '{Path.GetFileNameWithoutExtension(projectFile)}'...");
var procStartInfo = new ProcessStartInfo("dotnet", "add package " + packageName);
Process.Start(procStartInfo).WaitForExit();
var moduleFile = new AbpModuleFinder().Find(projectFile).First();
new DependsOnAdder().Add(moduleFile, packageInfo.ModuleClass);
if (packageInfo.DependedNpmPackage != null)
{
await NpmPackageAdder.AddAsync(Path.GetDirectoryName(projectFile), packageInfo.DependedNpmPackage);
}
Logger.LogInformation("Successfully installed.");
}
private async Task<NugetPackageInfo> FindNugetPackageInfoAsync(string moduleName)
{
using (var client = new HttpClient())
{
var url = "https://localhost:44328/api/app/nugetPackage/byName/?name=" + moduleName;
var response = await client.GetAsync(url);
if (!response.IsSuccessStatusCode)
{
if (response.StatusCode == HttpStatusCode.NotFound)
{
Logger.LogError($"ERROR: '{moduleName}' module could not be found.");
}
else
{
Logger.LogError($"ERROR: Remote server returns '{response.StatusCode}'");
}
return null;
}
var responseContent = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<NugetPackageInfo>(responseContent);
}
}
}
}
Loading…
Cancel
Save