Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/AbpHelper.Core/AbpHelperCoreConsts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace EasyAbp.AbpHelper.Core
{
internal static class AbpHelperCoreConsts
{
internal static readonly string TemplateResourcePathPrefix = "/Templates/";
}
}
23 changes: 23 additions & 0 deletions src/AbpHelper.Core/Commands/CommandOptionsBase.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.IO;
using EasyAbp.AbpHelper.Core.Attributes;
using EasyAbp.AbpHelper.Core.Extensions;

namespace EasyAbp.AbpHelper.Core.Commands
{
Expand All @@ -14,5 +16,26 @@ public abstract class CommandOptionsBase

[Option("exclude", Description = "Exclude directories when searching files, arguments can contain a combination of valid literal path and wildcard (* and ?) characters. Use double asterisk(**) to search all directories. Example: --exclude *Folder1 Folder2/Folder* **/*Folder? **/*Folder*")]
public virtual string[] Exclude { get; set; } = Array.Empty<string>();

[Option('t', "template-path", Description = "Prioritize loading template files in the path")]
public virtual string? TemplatePath { get; set; }

public virtual string MapTemplatePath(string subPath)
{
string resourcePathPrefix = AbpHelperCoreConsts.TemplateResourcePathPrefix;

if (string.IsNullOrWhiteSpace(TemplatePath))
{
return Path.Combine(new[] { resourcePathPrefix, subPath }).NormalizePath();
}

if (AbpHelperCoreConsts.TemplateResourcePathPrefix.StartsWith('/') ||
AbpHelperCoreConsts.TemplateResourcePathPrefix.StartsWith('\\'))
{
resourcePathPrefix = resourcePathPrefix.Substring(1);
}

return Path.Combine(new[] { TemplatePath!, resourcePathPrefix, subPath }).NormalizePath();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ protected override IActivityBuilder ConfigureBuild(ControllerCommandOption optio
step =>
{
step.VariableName = VariableNames.TemplateDirectory;
step.ValueExpression = new LiteralExpression<string>("/Templates/Controller");
step.ValueExpression = new LiteralExpression<string>(option.MapTemplatePath("Controller"));
})
.Then<IfElse>(
step => step.ConditionExpression = new JavaScriptExpression<bool>($"{OptionVariableName}.{nameof(ControllerCommandOption.SkipBuild)}"),
Expand Down
2 changes: 1 addition & 1 deletion src/AbpHelper.Core/Commands/Generate/Crud/CrudCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected override IActivityBuilder ConfigureBuild(CrudCommandOption option, IAc
step =>
{
step.VariableName = VariableNames.TemplateDirectory;
step.ValueExpression = new LiteralExpression<string>("/Templates/Crud");
step.ValueExpression = new LiteralExpression<string>(option.MapTemplatePath("Crud"));
})
.Then<FileFinderStep>(
step => { step.SearchFileName = new LiteralExpression(entityFileName); })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protected override IActivityBuilder ConfigureBuild(LocalizationCommandOption opt
step =>
{
step.VariableName = VariableNames.TemplateDirectory;
step.ValueExpression = new LiteralExpression<string>("/Templates/Localization");
step.ValueExpression = new LiteralExpression<string>(option.MapTemplatePath("Localization"));
})
.Then<SetModelVariableStep>()
/* Add localization */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ protected override IActivityBuilder ConfigureBuild(MethodsCommandOption option,
step =>
{
step.VariableName = VariableNames.TemplateDirectory;
step.ValueExpression = new LiteralExpression<string>("/Templates/Methods");
step.ValueExpression = new LiteralExpression<string>(option.MapTemplatePath("Methods"));
})
.Then<FileFinderStep>(
step =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected override IActivityBuilder ConfigureBuild(ServiceCommandOption option,
step =>
{
step.VariableName = VariableNames.TemplateDirectory;
step.ValueExpression = new LiteralExpression<string>("/Templates/Service");
step.ValueExpression = new LiteralExpression<string>(option.MapTemplatePath("Service"));
})
.Then<SetModelVariableStep>()
.Then<GroupGenerationStep>(
Expand Down
2 changes: 1 addition & 1 deletion src/AbpHelper.Core/Commands/Module/Add/AddCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ protected override IActivityBuilder ConfigureBuild(AddCommandOption option, IAct
step =>
{
step.VariableName = VariableNames.TemplateDirectory;
step.ValueExpression = new LiteralExpression<string>("/Templates/Module");
step.ValueExpression = new LiteralExpression<string>(option.MapTemplatePath("Module"));
})
.Then<SetVariable>(
step =>
Expand Down
2 changes: 1 addition & 1 deletion src/AbpHelper.Core/Commands/Module/Remove/RemoveCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ protected override IActivityBuilder ConfigureBuild(RemoveCommandOption option, I
step =>
{
step.VariableName = VariableNames.TemplateDirectory;
step.ValueExpression = new LiteralExpression<string>("/Templates/Module");
step.ValueExpression = new LiteralExpression<string>(option.MapTemplatePath("Module"));
})
.Then<SetVariable>(
step =>
Expand Down
53 changes: 53 additions & 0 deletions src/AbpHelper.Core/Extensions/FileProviderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.FileProviders;
using System.Linq;
using Volo.Abp.VirtualFileSystem;

namespace EasyAbp.AbpHelper.Core.Extensions
{
Expand All @@ -26,5 +28,56 @@ public static class FileProviderExtensions
}
}
}

public static IEnumerable<(string, IFileInfo)> GetFilesRecursively(this IVirtualFileProvider fileProvider, string dir)
{
Copy link

Copilot AI Jul 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GetTemplatePathMirror method duplicates logic from TemplateRootDirectoryMirror. Consider extracting the common path parsing logic into a shared private method to reduce code duplication.

Copilot uses AI. Check for mistakes.
var (virtualDirectory, physicalDirectory) = fileProvider.GetTemplateRootDirectoryMirror(dir);
var files = GetFilesRecursively((IFileProvider)fileProvider, virtualDirectory);
if (physicalDirectory == null)
{
return files;
}
var physicalFiles = new PhysicalFileProvider(physicalDirectory).GetFilesRecursively("").ToList();
var virtualFiles = files.ToList();
var physicalPaths = new HashSet<string>(physicalFiles.Select(p => p.Item1));
return physicalFiles.Concat(virtualFiles.Where(v => !physicalPaths.Contains(v.Item1)));
}

/// <summary>
/// If <paramref name="dir"/> is physical path try to get virtual directory path
/// </summary>
/// <param name="dir"></param>
/// <returns>(virtualDirectory, physicalDirectory)</returns>
public static (string, string?) GetTemplateRootDirectoryMirror(this IVirtualFileProvider fileProvider, string dir)
{
if (dir.StartsWith(AbpHelperCoreConsts.TemplateResourcePathPrefix)) return (dir, null);

var index = dir.IndexOf(AbpHelperCoreConsts.TemplateResourcePathPrefix);

if (index == -1) return (dir, null);

var virtualDirectory = dir.Substring(index);
var physicalDirectory = dir.Substring(0, index);

return (virtualDirectory, physicalDirectory);
}

/// <summary>
/// If <paramref name="dir"/> is physical path try to get virtual directory path
/// </summary>
/// <param name="dir"></param>
/// <returns>(virtualDirectory, physicalDirectory)</returns>
public static (string, string?) GetTemplatePathMirror(this IVirtualFileProvider fileProvider, string dir)
{
if (dir.StartsWith(AbpHelperCoreConsts.TemplateResourcePathPrefix)) return (dir, null);

var index = dir.IndexOf(AbpHelperCoreConsts.TemplateResourcePathPrefix);

if (index == -1) return (dir, null);

var virtualPath = dir.Substring(index);

return (virtualPath, dir);
}
}
}
18 changes: 15 additions & 3 deletions src/AbpHelper.Core/Generator/TemplateLoader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Threading.Tasks;
using System.IO;
using System.Threading.Tasks;
using EasyAbp.AbpHelper.Core.Extensions;
using Microsoft.Extensions.FileProviders;
using Scriban;
using Scriban.Parsing;
Expand All @@ -24,12 +26,22 @@ public string GetPath(TemplateContext context, SourceSpan callerSpan, string tem

public string Load(TemplateContext context, SourceSpan callerSpan, string templatePath)
{
return _virtualFileProvider.GetFileInfo(templatePath).ReadAsString();
var (v, p) = _virtualFileProvider.GetTemplatePathMirror(templatePath);
if (p != null && File.Exists(p))
{
return File.ReadAllText(p);
}
return _virtualFileProvider.GetFileInfo(v).ReadAsString();
}

public async ValueTask<string> LoadAsync(TemplateContext context, SourceSpan callerSpan, string templatePath)
{
return await _virtualFileProvider.GetFileInfo(templatePath).ReadAsStringAsync();
var (v, p) = _virtualFileProvider.GetTemplatePathMirror(templatePath);
if (p != null && File.Exists(p))
{
return await File.ReadAllTextAsync(p);
}
return await _virtualFileProvider.GetFileInfo(v).ReadAsStringAsync();
}
}
}
16 changes: 13 additions & 3 deletions src/AbpHelper.Core/Generator/TextGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,22 @@ public string GenerateByTemplateName(string templateDirectory, string templateNa
{
return GenerateByTemplateName(templateDirectory, templateName, model, out _);
}

public string GenerateByTemplateName(string templateDirectory, string templateName, object model, out TemplateContext context)
{
string path = Path.Combine(templateDirectory, templateName).NormalizePath();
var templateFile = _virtualFileProvider.GetFileInfo(path);
var templateText = templateFile.ReadAsString();
var templateText = string.Empty;
if (File.Exists(path))
{
templateText = File.ReadAllText(path);
}
else
{
var (virtualPath, _) = _virtualFileProvider.GetTemplateRootDirectoryMirror(path);

var templateFile = _virtualFileProvider.GetFileInfo(virtualPath);
templateText = templateFile.ReadAsString();
}
return GenerateByTemplateText(templateText, model, out context);
}

Expand Down
6 changes: 4 additions & 2 deletions src/AbpHelper.Core/Steps/Common/GroupGenerationStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public WorkflowExpression<string> TemplateDirectory
get => GetState<WorkflowExpression<string>>(() => new JavaScriptExpression<string>(VariableNames.TemplateDirectory));
set => SetState(value);
}

public string GroupName
{
get => GetState<string>();
Expand Down Expand Up @@ -80,10 +80,12 @@ protected override async Task<ActivityExecutionResult> OnExecuteAsync(WorkflowEx

private async Task GenerateFile(string groupDirectory, string targetDirectory, object model, bool overwrite)
{
var (virtualDirectory, physicalDirectory) = _virtualFileProvider.GetTemplateRootDirectoryMirror(groupDirectory);

foreach (var (path, file) in _virtualFileProvider.GetFilesRecursively(groupDirectory))
{
Logger.LogDebug($"Generating using template file: {path}");
var targetFilePathNameTemplate = path.Replace(groupDirectory, targetDirectory);
var targetFilePathNameTemplate = path.Replace(virtualDirectory, targetDirectory);
var targetFilePathName = _textGenerator.GenerateByTemplateText(targetFilePathNameTemplate, model);
if (File.Exists(targetFilePathName) && !overwrite)
{
Expand Down