Skip to content
Merged
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
5 changes: 4 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
<Deterministic>true</Deterministic>
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
<ArtifactsPath>$(MSBuildThisFileDirectory)artifacts\</ArtifactsPath>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>

<PropertyGroup>
<!--
DCL101: 命令行库自己的警告,是为了给库的用户报告的;而本仓库要测这些,所以不能放一堆警告破窗。
NU1507: 没有指定包源映射
-->
<NoWarn>$(NoWarn);DCL101</NoWarn>
<NoWarn>$(NoWarn);DCL101;NU1507</NoWarn>
<!--
CA1416: 平台兼容性警告
-->
Expand Down
17 changes: 17 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project>
<ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.15.2" />
<PackageVersion Include="dotnetCampus.LatestCSharpFeatures" Version="13.0.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.11.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="MSTest.TestAdapter" Version="3.10.3" />
<PackageVersion Include="MSTest.TestFramework" Version="3.10.3" />
<PackageVersion Include="MSTestEnhancer" Version="2.2.2" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageVersion Include="System.Memory" Version="4.5.5" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions DotNetCampus.CommandLine.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{2AC77BF2
LICENSE = LICENSE
README.md = README.md
build\Version.props = build\Version.props
Directory.Packages.props = Directory.Packages.props
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetCampus.CommandLine.Analyzer", "src\DotNetCampus.CommandLine.Analyzer\DotNetCampus.CommandLine.Analyzer.csproj", "{8AD0FEAB-2E36-4EBB-9E32-C4394FC6DC86}"
Expand Down
4 changes: 2 additions & 2 deletions build/Version.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<Project>
<PropertyGroup>
<Version>4.0.0-alpha01</Version>
<Version>0.0.1-alpha.1</Version>
</PropertyGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="dotnetCampus.LatestCSharpFeatures" Version="12.0.1" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PackageReference Include="dotnetCampus.LatestCSharpFeatures" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.11.0" />
<PackageReference Include="System.Collections.Immutable" Version="8.0.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
<PackageReference Include="System.Collections.Immutable" />
</ItemGroup>

<ItemGroup>
Expand Down
7 changes: 7 additions & 0 deletions src/DotNetCampus.CommandLine/CommandLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,14 @@ private CommandLine(IReadOnlyList<string> arguments, CommandLineParsingOptions?
[Pure]
public static CommandLine Parse(IReadOnlyList<string> args, CommandLineParsingOptions? parsingOptions = null)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(args);
#else
if (args is null)
{
throw new ArgumentNullException(nameof(args));
}
#endif
return args.Count is 0
? new CommandLine()
: new CommandLine(args, parsingOptions);
Expand Down
4 changes: 1 addition & 3 deletions src/DotNetCampus.CommandLine/CommandLineParsingOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Collections.Immutable;

namespace DotNetCampus.Cli;

/// <summary>
Expand Down Expand Up @@ -104,5 +102,5 @@ public readonly record struct CommandLineParsingOptions()
/// myapp://open/file.txt?temporary=true # open 是谓词,file.txt 是位置参数;或 open 和 file.txt 都是位置参数
/// </code>
/// </remarks>
public ImmutableArray<string> SchemeNames { get; init; } = [];
public IReadOnlyList<string> SchemeNames { get; init; } = [];
}
37 changes: 34 additions & 3 deletions src/DotNetCampus.CommandLine/CommandLinePropertyValue.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using DotNetCampus.Cli.Exceptions;
#if NETCOREAPP3_1_OR_GREATER
using System.Collections.Immutable;
#endif

namespace DotNetCampus.Cli;

Expand Down Expand Up @@ -155,6 +157,7 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
$"Value [{values[0]}] is not a valid uint value."),
};

#if NET5_0_OR_GREATER
/// <summary>
/// 将从命令行解析出来的属性值转换为 <see cref="nint"/>。
/// </summary>
Expand All @@ -166,7 +169,9 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
: throw new CommandLineParseValueException(
$"Value [{values[0]}] is not a valid nint value."),
};
#endif

#if NET5_0_OR_GREATER
/// <summary>
/// 将从命令行解析出来的属性值转换为 <see cref="nuint"/>。
/// </summary>
Expand All @@ -178,6 +183,7 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
: throw new CommandLineParseValueException(
$"Value [{values[0]}] is not a valid unint value."),
};
#endif

/// <summary>
/// 将从命令行解析出来的属性值转换为 <see cref="long"/>。
Expand Down Expand Up @@ -237,8 +243,13 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
{
MultiValueHandling.First => values[0],
MultiValueHandling.Last => values[^1],
#if NETCOREAPP3_1_OR_GREATER
MultiValueHandling.SpaceAll => string.Join(' ', values),
MultiValueHandling.SlashAll => string.Join('/', values),
#else
MultiValueHandling.SpaceAll => string.Join(" ", values),
MultiValueHandling.SlashAll => string.Join("/", values),
#endif
_ => values[0],
},
};
Expand All @@ -252,23 +263,37 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
{ } values => [..SplitValues(values)],
};

#if NETCOREAPP3_1_OR_GREATER
/// <summary>
/// 将从命令行解析出来的属性值转换为不可变字符串数组。
/// </summary>
public static implicit operator ImmutableArray<string>(CommandLinePropertyValue propertyValue) => propertyValue._values switch
{
#if NET8_0_OR_GREATER
{ Count: 0 } => [],
{ } values => [..SplitValues(values)],
#else
{ Count: 0 } => ImmutableArray<string>.Empty,
{ } values => SplitValues(values).ToImmutableArray(),
#endif
};
#endif

#if NETCOREAPP3_1_OR_GREATER
/// <summary>
/// 将从命令行解析出来的属性值转换为不可变字符串哈希集合。
/// </summary>
public static implicit operator ImmutableHashSet<string>(CommandLinePropertyValue propertyValue) => propertyValue._values switch
{
#if NET8_0_OR_GREATER
{ Count: 0 } => [],
{ } values => [..SplitValues(values)],
#else
{ Count: 0 } => ImmutableHashSet<string>.Empty,
{ } values => SplitValues(values).ToImmutableHashSet(),
#endif
};
#endif

/// <summary>
/// 将从命令行解析出来的属性值转换为字符串集合。
Expand Down Expand Up @@ -300,7 +325,7 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
public T ToEnum<T>() where T : unmanaged, Enum => _values switch
{
{ Count: 0 } => default,
{ } values => Enum.TryParse(typeof(T), values[0], true, out var result) ? (T)result : default!,
{ } values => Enum.TryParse<T>(values[0], true, out var result) ? result : default!,
};

/// <summary>
Expand All @@ -319,7 +344,13 @@ public static implicit operator bool(CommandLinePropertyValue propertyValue)
{
{ Count: 0 } => new Dictionary<string, string>(),
{ } values => values
.SelectMany(x => x.Split(';', StringSplitOptions.RemoveEmptyEntries))
.SelectMany(x => x.Split(
#if NETCOREAPP3_1_OR_GREATER
';'
#else
[";"]
#endif
, StringSplitOptions.RemoveEmptyEntries))
.Select(x =>
{
var parts = x.Split('=');
Expand Down
6 changes: 5 additions & 1 deletion src/DotNetCampus.CommandLine/CommandRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ namespace DotNetCampus.Cli;
/// </summary>
public class CommandRunner : ICommandRunnerBuilder, IAsyncCommandRunnerBuilder
{
private static ConcurrentDictionary<Type, CommandObjectCreationInfo> CommandObjectCreationInfos { get; } = new(ReferenceEqualityComparer.Instance);
private static ConcurrentDictionary<Type, CommandObjectCreationInfo> CommandObjectCreationInfos { get; } = new(
#if NET5_0_OR_GREATER
ReferenceEqualityComparer.Instance
#endif
);

private readonly CommandLine _commandLine;
private readonly DictionaryCommandHandlerCollection _dictionaryVerbHandlers = new();
Expand Down
22 changes: 17 additions & 5 deletions src/DotNetCampus.CommandLine/DotNetCampus.CommandLine.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0;net6.0</TargetFrameworks>
<!--
We add net8.0 to support collection expressions for Immutables.
We add net6.0 to support ArgumentNullException.ThrowIfNull().
We add net5.0 to support OperatingSystem.IsWindows()/IsLinux()/IsMacOS() methods.
We add netcoreapp3.1 to support basic string methods.
-->
<TargetFrameworks>net8.0;net6.0;net5.0;netcoreapp3.1;netstandard2.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<PackageId>DotNetCampus.CommandLine</PackageId>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
Expand All @@ -10,20 +16,26 @@
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<IsAotCompatible>true</IsAotCompatible>
<IsAotCompatible Condition="'$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net6.0'">false</IsAotCompatible>
<EmbedAllSources Condition="'$(Configuration)' != 'debug'">true</EmbedAllSources>
<WarningLevel Condition="'$(TargetFramework)' == 'net6.0'">0</WarningLevel>
</PropertyGroup>


<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<NoWarn>$(NoWarn);CS8767</NoWarn>
</PropertyGroup>

<ItemGroup>
<InternalsVisibleTo Include="DotNetCampus.CommandLine.Tests" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0">
<PackageReference Include="dotnetCampus.LatestCSharpFeatures" PrivateAssets="all" />
<PackageReference Include="Microsoft.SourceLink.GitHub">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Condition="'$(TargetFramework)' == 'net6.0'" Include="System.Collections.Immutable" Version="8.0.0" />
<PackageReference Condition="'$(TargetFramework)' == 'netstandard2.0'" Include="System.Memory" />
</ItemGroup>

<Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,10 @@ public static string MakeKebabCase(ReadOnlySpan<char> span)
{
return builder.ToString();
}
#if NETCOREAPP3_1_OR_GREATER
return new string(builder[..actualBuilderCount]);
#else
return builder[..actualBuilderCount].ToString();
#endif
}
}
7 changes: 3 additions & 4 deletions src/DotNetCampus.CommandLine/Utils/CommandLineConverter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Immutable;
using DotNetCampus.Cli.Utils.Parsers;
using DotNetCampus.Cli.Utils.Parsers;

namespace DotNetCampus.Cli.Utils;

Expand All @@ -17,7 +16,7 @@ internal static IReadOnlyList<string> SingleLineCommandLineArgsToArrayCommandLin
{
if (string.IsNullOrWhiteSpace(singleLineCommandLineArgs))
{
return ImmutableArray<string>.Empty;
return [];
}

List<Range> parts = [];
Expand Down Expand Up @@ -69,7 +68,7 @@ internal static IReadOnlyList<string> SingleLineCommandLineArgsToArrayCommandLin
public static (string? MatchedUrlScheme, CommandLineParsedResult Result) ParseCommandLineArguments(
IReadOnlyList<string> arguments, CommandLineParsingOptions? parsingOptions)
{
var matchedUrlScheme = arguments.Count is 1 && parsingOptions?.SchemeNames is { Length: > 0 } schemeNames
var matchedUrlScheme = arguments.Count is 1 && parsingOptions?.SchemeNames is { Count: > 0 } schemeNames
? schemeNames.FirstOrDefault(x => arguments[0].StartsWith($"{x}://", StringComparison.OrdinalIgnoreCase))
: null;

Expand Down
12 changes: 9 additions & 3 deletions src/DotNetCampus.CommandLine/Utils/Parsers/DotNetStyleParser.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Runtime.InteropServices;
using DotNetCampus.Cli.Exceptions;
using DotNetCampus.Cli.Utils.Collections;

Expand Down Expand Up @@ -105,9 +106,14 @@ internal readonly ref struct DotNetArgument(DotNetParsedType type)
public static DotNetArgument Parse(string argument, DotNetParsedType lastType)
{
var isPostPositionalArgument = lastType is DotNetParsedType.PositionalArgumentSeparator or DotNetParsedType.PostPositionalArgument;
var hasPrefix = OperatingSystem.IsWindows()
? argument.Length > 0 && (argument[0] is '-' or '/')
: argument.Length > 0 && argument[0] is '-';
var hasPrefix =
#if NET5_0_OR_GREATER
OperatingSystem.IsWindows()
#else
RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
#endif
? argument.Length > 0 && (argument[0] is '-' or '/')
: argument.Length > 0 && argument[0] is '-';

if (!isPostPositionalArgument && hasPrefix)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Runtime.InteropServices;
using DotNetCampus.Cli.Exceptions;
using DotNetCampus.Cli.Utils.Collections;

Expand Down Expand Up @@ -106,9 +107,14 @@ internal readonly ref struct FlexibleArgument(FlexibleParsedType type)
public static FlexibleArgument Parse(string argument, FlexibleParsedType lastType)
{
var isPostPositionalArgument = lastType is FlexibleParsedType.PositionalArgumentSeparator or FlexibleParsedType.PostPositionalArgument;
var hasPrefix = OperatingSystem.IsWindows()
? argument.Length > 0 && (argument[0] is '-' or '/')
: argument.Length > 0 && argument[0] is '-';
var hasPrefix =
#if NET5_0_OR_GREATER
OperatingSystem.IsWindows()
#else
RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
#endif
? argument.Length > 0 && (argument[0] is '-' or '/')
: argument.Length > 0 && argument[0] is '-';

if (!isPostPositionalArgument && hasPrefix)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System.Collections.Immutable;

namespace DotNetCampus.Cli.Utils.Parsers;
namespace DotNetCampus.Cli.Utils.Parsers;

internal interface ICommandLineParser
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,13 @@ public static PowerShellArgument Parse(string argument, PowerShellParsedType las
return new PowerShellArgument(PowerShellParsedType.PositionalArgumentSeparator);
}

if (!isPostPositionalArgument && argument.StartsWith('-') && argument.Length > 1 && !char.IsDigit(argument[1]))
if (!isPostPositionalArgument && argument.StartsWith(
#if NETCOREAPP3_1_OR_GREATER
'-'
#else
"-"
#endif
) && argument.Length > 1 && !char.IsDigit(argument[1]))
{
// PowerShell 风格的选项 (-ParameterName)
var optionSpan = argument.AsSpan(1);
Expand Down
6 changes: 5 additions & 1 deletion src/DotNetCampus.CommandLine/Utils/Parsers/UrlStyleParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,11 @@ private static UrlPart ReadNextParameterName(string url, ref int index)
index = endIndex;
return new UrlPart(UrlParsedType.ParameterName)
{
Name = OptionName.MakeKebabCase(value),
Name = OptionName.MakeKebabCase(value
#if !NETCOREAPP3_1_OR_GREATER
.AsSpan()
#endif
),
};
}

Expand Down
Loading
Loading