Skip to content

Commit

Permalink
output loading
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidVollmers committed May 3, 2024
1 parent 694adc2 commit b33bee9
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 29 deletions.
33 changes: 10 additions & 23 deletions src/Doki.CommandLine/Commands/GenerateCommand.Outputs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ namespace Doki.CommandLine.Commands;

internal partial class GenerateCommand
{
private readonly SourceRepository _nuget = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
private readonly SourceCacheContext _cacheContext = new();

private async Task<IOutput?> LoadOutputAsync(DirectoryInfo workingDirectory,
private async Task<Type?> LoadOutputAsync(DirectoryInfo workingDirectory,
DokiConfig.DokiConfigOutput output, bool allowPreview, CancellationToken cancellationToken)
{
var outputContext = new OutputContext(workingDirectory, output.Options);
Expand All @@ -29,13 +26,13 @@ internal partial class GenerateCommand

return fileInfo.Extension.ToLower() switch
{
".csproj" => await LoadOutputFromProjectAsync(fileInfo, output, outputContext, cancellationToken),
".dll" => LoadOutputFromAssembly(fileInfo.FullName, output, outputContext),
".csproj" => await LoadOutputFromProjectAsync(fileInfo, output, cancellationToken),
".dll" => LoadOutputFromAssembly(fileInfo.FullName, output),
_ => null
};
}

private async Task<IOutput?> LoadOutputFromNuGetAsync(DokiConfig.DokiConfigOutput output,
private async Task<Type?> LoadOutputFromNuGetAsync(DokiConfig.DokiConfigOutput output,
OutputContext outputContext, bool allowPreview, CancellationToken cancellationToken)
{
_logger.LogDebug("Loading output from NuGet: {PackageId}", output.Type);
Expand All @@ -47,11 +44,11 @@ internal partial class GenerateCommand
var assemblyPath =
await nugetLoader.LoadPackageAsync(output.Type, nugetFolder, allowPreview, cancellationToken);

return LoadOutputFromAssembly(assemblyPath, output, outputContext);
return LoadOutputFromAssembly(assemblyPath, output);
}

private async Task<IOutput?> LoadOutputFromProjectAsync(FileInfo fileInfo, DokiConfig.DokiConfigOutput output,
OutputContext outputContext, CancellationToken cancellationToken)
private async Task<Type?> LoadOutputFromProjectAsync(FileInfo fileInfo, DokiConfig.DokiConfigOutput output,
CancellationToken cancellationToken)
{
_logger.LogDebug("Loading output from project: {ProjectFileName}", fileInfo.Name);

Expand All @@ -61,27 +58,17 @@ internal partial class GenerateCommand
var assemblyPath = Path.Combine(fileInfo.DirectoryName!, "bin", "Release", "net8.0",
$"{fileInfo.Name[..^fileInfo.Extension.Length]}.dll");

return LoadOutputFromAssembly(assemblyPath, output, outputContext);
return LoadOutputFromAssembly(assemblyPath, output);
}

private IOutput? LoadOutputFromAssembly(string path, DokiConfig.DokiConfigOutput output,
OutputContext outputContext)
private Type? LoadOutputFromAssembly(string path, DokiConfig.DokiConfigOutput output)
{
_logger.LogDebug("Loading output from assembly: {AssemblyPath}", path);

var assembly = Assembly.LoadFrom(path);

var outputType = assembly.GetType(output.Type) ?? assembly
return assembly.GetType(output.Type) ?? assembly
.GetExportedTypes()
.FirstOrDefault(t => t.GetCustomAttribute<DokiOutputAttribute>()?.Name == output.Type);

// ReSharper disable once InvertIf
if (outputType == null)
{
_logger.LogError("Could not find output type: {OutputType}", output.Type);
return null;
}

return Activator.CreateInstance(outputType, outputContext) as IOutput;
}
}
22 changes: 17 additions & 5 deletions src/Doki.CommandLine/Commands/GenerateCommand.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Diagnostics;
using System.Reflection;
using System.Text.Json;
using System.Xml.XPath;
using Doki.Output;
using Microsoft.Extensions.FileSystemGlobbing;
using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -207,19 +209,29 @@ private async Task<int> LoadOutputsAsync(GenerateContext context, CancellationTo
{
if (string.IsNullOrWhiteSpace(output.Type))
{
_logger.LogError("No type configured.");
_logger.LogError("No output type configured.");
return -1;
}

var instance = await LoadOutputAsync(context.Directory, output, context.AllowPreview, cancellationToken);
var outputType = await LoadOutputAsync(context.Directory, output, context.AllowPreview, cancellationToken);

if (instance == null)
if (outputType == null)
{
_logger.LogError("Could not load output.");
_logger.LogError("Could not load output: {OutputType}", output.Type);
return -1;
}

context.Generator.AddOutput(instance);
_logger.LogDebug("Adding output: {OutputType}", outputType);

var outputAttribute = outputType.GetCustomAttribute<DokiOutputAttribute>();

var methodName = outputAttribute?.Scoped == true
? nameof(DocumentationGenerator.AddScopedOutput)
: nameof(DocumentationGenerator.AddOutput);

var genericMethod = typeof(DocumentationGenerator).GetMethod(methodName)!.MakeGenericMethod(outputType);

genericMethod.Invoke(context.Generator, []);
}

return 0;
Expand Down
2 changes: 2 additions & 0 deletions src/Doki.Output.Abstractions/DokiOutputAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public sealed class DokiOutputAttribute : Attribute
/// </summary>
public string Name { get; }

public bool Scoped { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="DokiOutputAttribute"/> class.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Doki.Output.ClassLibrary/ClassLibraryOutput.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Doki.Output.ClassLibrary;

[DokiOutput("Doki.Output.ClassLibrary")]
[DokiOutput("Doki.Output.ClassLibrary", Scoped = true)]
public sealed class ClassLibraryOutput(OutputContext context) : OutputBase<ClassLibraryOutputOptions>(context)
{
public override async Task WriteAsync(ContentList contentList, CancellationToken cancellationToken = default)

Check warning on line 6 in src/Doki.Output.ClassLibrary/ClassLibraryOutput.cs

View workflow job for this annotation

GitHub Actions / Test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 6 in src/Doki.Output.ClassLibrary/ClassLibraryOutput.cs

View workflow job for this annotation

GitHub Actions / Test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

Check warning on line 6 in src/Doki.Output.ClassLibrary/ClassLibraryOutput.cs

View workflow job for this annotation

GitHub Actions / Test

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
Expand Down
5 changes: 5 additions & 0 deletions src/Doki/DocumentationGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ public void AddOutput(IOutput output)

_serviceCollection.AddSingleton(typeof(IOutput), output);
}

public void AddOutput<T>() where T : IOutput
{
_serviceCollection.AddSingleton(typeof(IOutput), typeof(T));
}

public void AddScopedOutput<T>() where T : IOutput
{
Expand Down

0 comments on commit b33bee9

Please sign in to comment.