Skip to content

Commit 24e5d4d

Browse files
authored
Merge pull request #7 from code-of-chaos/Rework
Rework
2 parents a9fbe0e + 4e0687d commit 24e5d4d

File tree

57 files changed

+1056
-981
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1056
-981
lines changed

CodeOfChaos.CliArgsParser.sln

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "example", "example", "{91B4
1616
EndProject
1717
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeOfChaos.CliArgsParser.Generators", "src\CodeOfChaos.CliArgsParser.Generators\CodeOfChaos.CliArgsParser.Generators.csproj", "{80E6494A-B679-4DDA-877C-F4639D4C60A8}"
1818
EndProject
19-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeOfChaos.CliArgsParser.Generators.Sample", "src\CodeOfChaos.CliArgsParser.Generators.Sample\CodeOfChaos.CliArgsParser.Generators.Sample.csproj", "{5791637A-68E9-4B82-9C2C-E295D0C3E94C}"
19+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.CodeOfChaos.CliArgsParser", "src\Sample.CodeOfChaos.CliArgsParser\Sample.CodeOfChaos.CliArgsParser.csproj", "{5791637A-68E9-4B82-9C2C-E295D0C3E94C}"
2020
EndProject
2121
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests.CodeOfChaos.CliArgsParser", "tests\Tests.CodeOfChaos.CliArgsParser\Tests.CodeOfChaos.CliArgsParser.csproj", "{181DA4AF-50BA-4C90-B678-EE394B22BFED}"
2222
EndProject
23+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeOfChaos.CliArgsParser.Contracts", "src\CodeOfChaos.CliArgsParser.Contracts\CodeOfChaos.CliArgsParser.Contracts.csproj", "{0B047200-48C2-4A8F-BAB2-51E387F9541E}"
24+
EndProject
2325
Global
2426
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2527
Debug|Any CPU = Debug|Any CPU
@@ -50,6 +52,10 @@ Global
5052
{181DA4AF-50BA-4C90-B678-EE394B22BFED}.Debug|Any CPU.Build.0 = Debug|Any CPU
5153
{181DA4AF-50BA-4C90-B678-EE394B22BFED}.Release|Any CPU.ActiveCfg = Release|Any CPU
5254
{181DA4AF-50BA-4C90-B678-EE394B22BFED}.Release|Any CPU.Build.0 = Release|Any CPU
55+
{0B047200-48C2-4A8F-BAB2-51E387F9541E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56+
{0B047200-48C2-4A8F-BAB2-51E387F9541E}.Debug|Any CPU.Build.0 = Debug|Any CPU
57+
{0B047200-48C2-4A8F-BAB2-51E387F9541E}.Release|Any CPU.ActiveCfg = Release|Any CPU
58+
{0B047200-48C2-4A8F-BAB2-51E387F9541E}.Release|Any CPU.Build.0 = Release|Any CPU
5359
EndGlobalSection
5460
GlobalSection(NestedProjects) = preSolution
5561
{64B26DED-68C3-47FF-B409-1C8FAD4F9176} = {197E72AD-DEAB-4350-AFC3-A3BB38720BF5}
@@ -58,5 +64,6 @@ Global
5864
{80E6494A-B679-4DDA-877C-F4639D4C60A8} = {197E72AD-DEAB-4350-AFC3-A3BB38720BF5}
5965
{5791637A-68E9-4B82-9C2C-E295D0C3E94C} = {91B440FF-0570-4FF5-9AE9-5DD272DFD139}
6066
{181DA4AF-50BA-4C90-B678-EE394B22BFED} = {8DD280D4-1E14-4D5E-AFE6-58DD8F079DCC}
67+
{0B047200-48C2-4A8F-BAB2-51E387F9541E} = {197E72AD-DEAB-4350-AFC3-A3BB38720BF5}
6168
EndGlobalSection
6269
EndGlobal
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<RootNamespace>CodeOfChaos.CliArgsParser</RootNamespace>
8+
9+
<!-- Main package name -->
10+
<PackageId>CodeOfChaos.CliArgsParser.Contracts</PackageId>
11+
<Version>4.10.0</Version>
12+
<Authors>Anna Sas</Authors>
13+
<Description>CliArgsParser is a library built around Dependency Injection to allow you to create CLI tools with ease</Description>
14+
<PackageProjectUrl>https://github.com/code-of-chaos/cs-code_of_chaos-cli_args_parser/</PackageProjectUrl>
15+
<PackageTags>cli args cliparser input argsparser</PackageTags>
16+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
17+
<PublishRepositoryUrl>true</PublishRepositoryUrl>
18+
<IncludeSymbols>true</IncludeSymbols>
19+
<DebugType>embedded</DebugType>
20+
<PackageLicenseFile>LICENSE</PackageLicenseFile>
21+
<PackageReadmeFile>README.md</PackageReadmeFile>
22+
<PackageIcon>icon.png</PackageIcon>
23+
</PropertyGroup>
24+
25+
<ItemGroup>
26+
<None Include="../../LICENSE" Pack="true" PackagePath="" Visible="false" />
27+
<None Include="../../README.md" Pack="true" PackagePath="" Visible="false" />
28+
<None Include="../../assets/icon.png" Pack="true" PackagePath="" Visible="false" />
29+
</ItemGroup>
30+
31+
</Project>
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
// ---------------------------------------------------------------------------------------------------------------------
2-
// Imports
3-
// ---------------------------------------------------------------------------------------------------------------------
4-
namespace CodeOfChaos.CliArgsParser;
5-
// ---------------------------------------------------------------------------------------------------------------------
6-
// Code
7-
// ---------------------------------------------------------------------------------------------------------------------
8-
public interface ICommand<in T> :
9-
// Ah blessed be the workarounds.
10-
INonGenericCommandInterfaces
11-
where T : struct, IParameters {
12-
Task ExecuteAsync(T parameters);
13-
}
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
namespace CodeOfChaos.CliArgsParser;
5+
6+
// ---------------------------------------------------------------------------------------------------------------------
7+
// Code
8+
// ---------------------------------------------------------------------------------------------------------------------
9+
public interface ICliArgsParserBuilder {
10+
ICliArgsParserBuilder AddServices(IServiceProvider provider);
11+
ICliArgsParserBuilder AddServices(Func<IServiceProvider> provider);
12+
13+
ICliParser Build();
14+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
namespace CodeOfChaos.CliArgsParser;
5+
6+
// ---------------------------------------------------------------------------------------------------------------------
7+
// Code
8+
// ---------------------------------------------------------------------------------------------------------------------
9+
public interface ICliCommand<in TParameter> : ICliCommand
10+
where TParameter : ICliParameters
11+
{
12+
ValueTask ExecuteAsync(TParameter parameters, CancellationToken ct = default);
13+
}
14+
15+
public interface ICliCommand {
16+
ValueTask StartExecution(IParameterDictionary parameters, CancellationToken ct = default);
17+
}

src/CodeOfChaos.CliArgsParser/Contracts/IHasCommandData.cs renamed to src/CodeOfChaos.CliArgsParser.Contracts/ICliParameters.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
// Imports
33
// ---------------------------------------------------------------------------------------------------------------------
44
namespace CodeOfChaos.CliArgsParser;
5+
56
// ---------------------------------------------------------------------------------------------------------------------
67
// Code
78
// ---------------------------------------------------------------------------------------------------------------------
8-
public interface IHasCommandData {
9-
CommandData CommandData { get; }
9+
public interface ICliParameters {
10+
1011
}

src/CodeOfChaos.CliArgsParser/Contracts/CommandData.cs renamed to src/CodeOfChaos.CliArgsParser.Contracts/ICliParser.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
// Imports
33
// ---------------------------------------------------------------------------------------------------------------------
44
namespace CodeOfChaos.CliArgsParser;
5+
56
// ---------------------------------------------------------------------------------------------------------------------
67
// Code
78
// ---------------------------------------------------------------------------------------------------------------------
8-
public record struct CommandData(
9-
string Name,
10-
string? Description,
11-
Type Type
12-
);
9+
public interface ICliParser {
10+
ValueTask ExecuteAsync(string[] args, CancellationToken ct = default);
11+
ValueTask ExecuteAsync(string args, CancellationToken ct = default);
12+
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
// ---------------------------------------------------------------------------------------------------------------------
2-
// Imports
3-
// ---------------------------------------------------------------------------------------------------------------------
4-
namespace CodeOfChaos.CliArgsParser;
5-
// ---------------------------------------------------------------------------------------------------------------------
6-
// Code
7-
// ---------------------------------------------------------------------------------------------------------------------
8-
public interface IParameters {
9-
T NewFromRegistry<T>(IUserInputRegistry registry) where T : struct, IParameters;
10-
}
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
using System.Diagnostics.CodeAnalysis;
5+
6+
namespace CodeOfChaos.CliArgsParser;
7+
8+
// ---------------------------------------------------------------------------------------------------------------------
9+
// Code
10+
// ---------------------------------------------------------------------------------------------------------------------
11+
public interface ICommandProvider {
12+
bool TryGetCommand(string name, [NotNullWhen(true)] out Type? commandType);
13+
}

src/CodeOfChaos.CliArgsParser/Contracts/IUserInputRegistry.cs renamed to src/CodeOfChaos.CliArgsParser.Contracts/IUserInputRegistry.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ namespace CodeOfChaos.CliArgsParser;
55
// ---------------------------------------------------------------------------------------------------------------------
66
// Code
77
// ---------------------------------------------------------------------------------------------------------------------
8-
public interface IUserInputRegistry : IDisposable {
9-
void IngestString(IEnumerable<string> input);
10-
void IngestString(string[] input);
11-
void IngestString(string input);
12-
8+
public interface IParameterDictionary {
139
T GetParameterByPossibleNames<T>(string name, string shortName);
1410
T? GetOptionalParameterByPossibleNames<T>(string name, string shortName);
1511

src/CodeOfChaos.CliArgsParser.Generators.Sample/Example.cs

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/CodeOfChaos.CliArgsParser.Generators/CodeOfChaos.CliArgsParser.Generators.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,16 @@
3232
</ItemGroup>
3333

3434
<ItemGroup>
35+
<PackageReference Include="IndexRange" Version="1.0.3" />
3536
<PackageReference Include="IsExternalInit" Version="1.0.3">
3637
<PrivateAssets>all</PrivateAssets>
3738
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3839
</PackageReference>
40+
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
3941
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all" />
4042
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.13.0" PrivateAssets="all" />
4143
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" PrivateAssets="all" />
42-
<PackageReference Include="CodeOfChaos.GeneratorTools" Version="1.7.1" Pack="true" GeneratePathProperty="true" PrivateAssets="all" />
44+
<PackageReference Include="CodeOfChaos.GeneratorTools" Version="1.8.0" Pack="true" GeneratePathProperty="true" PrivateAssets="all" />
4345
</ItemGroup>
4446
<ItemGroup>
4547
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// ---------------------------------------------------------------------------------------------------------------------
2+
// Imports
3+
// ---------------------------------------------------------------------------------------------------------------------
4+
using CodeOfChaos.CliArgsParser.Generators.Helpers;
5+
using CodeOfChaos.GeneratorTools;
6+
using JetBrains.Annotations;
7+
using Microsoft.CodeAnalysis;
8+
using System;
9+
using System.Collections.Immutable;
10+
using System.Linq;
11+
12+
namespace CodeOfChaos.CliArgsParser.Generators;
13+
// ---------------------------------------------------------------------------------------------------------------------
14+
// Code
15+
// ---------------------------------------------------------------------------------------------------------------------
16+
public record CommandDto(
17+
[UsedImplicitly] INamedTypeSymbol Symbol,
18+
ITypeSymbol ParameterType
19+
) {
20+
public string ClassName { get; } = Symbol.Name;
21+
public string NameSpace { get; } = Symbol.ContainingNamespace.ToDisplayString();
22+
public string Accessibility { get; } = Symbol.GetAccessibility();
23+
public string TypeKeyword { get; } = Symbol.GetTypeKind();
24+
25+
public ParameterDto[] Parameters => GetParameters(ParameterType);
26+
public string ParameterTypeDisplayString { get; } = ParameterType.ToDisplayString();
27+
28+
public string Name { get; } = GetName(Symbol).ToQuotedString();
29+
public string ShortName { get; } = GetShortName(Symbol).ToQuotedString();
30+
// -----------------------------------------------------------------------------------------------------------------
31+
// Methods
32+
// -----------------------------------------------------------------------------------------------------------------
33+
private static string GetName(INamedTypeSymbol symbol) {
34+
ImmutableArray<AttributeData> attributes = symbol.GetAttributes();
35+
AttributeData? cliDataAttribute = attributes.FirstOrDefault(attr => attr.IsDisplayName(TypeNames.CliDataAttribute));
36+
37+
if (cliDataAttribute?.ConstructorArguments.ElementAtOrDefault(0).Value is string cliDataName) return cliDataName;
38+
return attributes.Any(attr => attr.IsDisplayName(TypeNames.AutoNameAttribute))
39+
? symbol.Name.ToKebabCase()
40+
: "UNDEFINED";
41+
}
42+
43+
private static string GetShortName(INamedTypeSymbol symbol) {
44+
ImmutableArray<AttributeData> attributes = symbol.GetAttributes();
45+
AttributeData? cliDataAttribute = attributes.FirstOrDefault(attr => attr.IsDisplayName(TypeNames.CliDataAttribute));
46+
47+
if (cliDataAttribute?.ConstructorArguments.ElementAtOrDefault(1).Value is string cliDataName) return cliDataName;
48+
return attributes.Any(attr => attr.IsDisplayName(TypeNames.AutoNameAttribute))
49+
? string.Join("", symbol.Name.ToKebabCase().Split('-').Select(s => s[0]))
50+
: "UNDEFINED";
51+
}
52+
53+
public static CommandDto? TryCreate(INamedTypeSymbol symbol) {
54+
if (!symbol.HasAttributeWithDisplayName(TypeNames.CliDataAttribute)) return null;
55+
56+
ImmutableArray<INamedTypeSymbol> interfaces = symbol.AllInterfaces;
57+
ITypeSymbol? parameterType = interfaces
58+
.Where(i => i.IsGenericType && i.ConstructedFrom.IsDisplayName(TypeNames.ICliCommandGenericInterface))
59+
.Select(i => i.TypeArguments[0])
60+
.FirstOrDefault();
61+
62+
if (parameterType is null) return null;
63+
64+
return new CommandDto(symbol, parameterType);
65+
66+
}
67+
68+
private ParameterDto[] GetParameters(ITypeSymbol symbol) {
69+
return symbol.GetMembers()
70+
.Where(member => member is IPropertySymbol propertySymbol
71+
&& propertySymbol.HasAttributeWithDisplayName(TypeNames.CliDataAttribute))
72+
.Select(member => new ParameterDto((member as IPropertySymbol)!))
73+
.ToArray();
74+
}
75+
76+
public void CreatePartialClass(GeneratorStringBuilder builder) {
77+
builder.AppendUsings(
78+
"System",
79+
"System.Threading",
80+
"System.Threading.Tasks",
81+
"CodeOfChaos.CliArgsParser"
82+
);
83+
builder.AppendNamespace(NameSpace);
84+
builder.AppendLine();
85+
builder.AppendNullableEnable();
86+
builder.AppendLine($"public partial {TypeKeyword} {ClassName} {{");
87+
builder.Indent(b => {
88+
b.AppendLine("public ValueTask StartExecution(IParameterDictionary parameterDictionary, CancellationToken ct = default){");
89+
b.Indent(b1 => {
90+
b1.AppendLine($"var parameters = new {ParameterTypeDisplayString}(){{");
91+
b1.ForEachAppendLineIndented(Parameters, parameterDto => $"{parameterDto.PropertyName} = {parameterDto.GetWithPropertyDictionary()},");
92+
b1.AppendLine("};");
93+
b1.AppendLine("return ExecuteAsync(parameters, ct);");
94+
});
95+
b.AppendLine("}");
96+
});
97+
builder.AppendLine("}");
98+
}
99+
}

0 commit comments

Comments
 (0)