Skip to content

Commit bedf89f

Browse files
committed
采纳代码审查意见
1 parent ecd0ab4 commit bedf89f

15 files changed

+48
-34
lines changed

src/DotNetCampus.CommandLine.Analyzer/Analyzers/ConvertOptionProperty/FindOptionPropertyTypeAnalyzer.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@ namespace DotNetCampus.CommandLine.Analyzers.ConvertOptionProperty;
99
[DiagnosticAnalyzer(LanguageNames.CSharp)]
1010
public class FindOptionPropertyTypeAnalyzer : DiagnosticAnalyzer
1111
{
12-
private readonly ImmutableArray<string> _nonGenericTypeNames =
12+
private readonly ImmutableHashSet<string> _nonGenericTypeNames =
1313
[
1414
"String", "string", "Boolean", "bool", "Byte", "byte", "Int16", "short", "UInt16", "ushort", "Int32", "int", "UInt32", "uint", "Int64", "long",
1515
"UInt64", "ulong", "Single", "float", "Double", "double", "Decimal", "decimal", "IList", "ICollection", "IEnumerable",
1616
];
1717

18-
private readonly ImmutableArray<string> _oneGenericTypeNames =
18+
private readonly ImmutableHashSet<string> _oneGenericTypeNames =
1919
[
2020
"[]", "ImmutableArray", "List", "IList", "IReadOnlyList", "ImmutableHashSet", "Collection", "ICollection", "IReadOnlyCollection", "IEnumerable",
2121
];
2222

23-
private readonly ImmutableArray<string> _twoGenericTypeNames = ["ImmutableDictionary", "Dictionary", "IDictionary", "IReadOnlyDictionary", "KeyValuePair"];
24-
private readonly ImmutableArray<string> _genericKeyArgumentTypeNames = ["String", "string"];
25-
private readonly ImmutableArray<string> _genericArgumentTypeNames = ["String", "string"];
23+
private readonly ImmutableHashSet<string> _twoGenericTypeNames = ["ImmutableDictionary", "Dictionary", "IDictionary", "IReadOnlyDictionary", "KeyValuePair"];
24+
private readonly ImmutableHashSet<string> _genericKeyArgumentTypeNames = ["String", "string"];
25+
private readonly ImmutableHashSet<string> _genericArgumentTypeNames = ["String", "string"];
2626

2727
/// <summary>
2828
/// Supported diagnostics.

src/DotNetCampus.CommandLine.Analyzer/Analyzers/OptionLongNameMustBeKebabCaseAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class OptionLongNameMustBeKebabCaseAnalyzer : DiagnosticAnalyzer
1717
/// <summary>
1818
/// Recognize these attributes.
1919
/// </summary>
20-
private readonly IList<string> _attributeNames = new List<string> { "Option", "OptionAttribute" };
20+
private readonly ImmutableHashSet<string> _attributeNames = ["Option", "OptionAttribute"];
2121

2222
/// <summary>
2323
/// Supported diagnostics.

src/DotNetCampus.CommandLine.Analyzer/Analyzers/OptionLongNameMustBeKebabCaseCodeFixProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
5757
private async Task<Solution> MakeKebabCaseAsync(Document document, ExpressionSyntax expressionSyntax, CancellationToken cancellationToken)
5858
{
5959
var expression = expressionSyntax.ToString();
60+
// 去掉引号。
6061
var oldName = expression.Substring(1, expression.Length - 2);
6162
var newName = NamingHelper.MakeKebabCase(oldName);
6263

src/DotNetCampus.CommandLine.Analyzer/GeneratorInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace DotNetCampus.CommandLine;
55

66
internal static class GeneratorInfo
77
{
8-
public static string RootNamespace { get; } = typeof(GeneratorInfo).Namespace!;
8+
public static string RootNamespace => typeof(GeneratorInfo).Namespace!;
99

1010
public static string ToolName { get; } = typeof(GeneratorInfo).Assembly
1111
.GetCustomAttribute<AssemblyTitleAttribute>()?.Title ?? typeof(GeneratorInfo).Namespace!;

src/DotNetCampus.CommandLine.Analyzer/Generators/ModelProviding/CommandModelProvider.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,6 @@ public string GetDisplayCommandOption()
229229
var shortName = optionAttribute.ConstructorArguments.FirstOrDefault(x => x.Type?.SpecialType is SpecialType.System_Char).Value?.ToString();
230230
var caseSensitive = optionAttribute.NamedArguments.FirstOrDefault(a => a.Key == nameof(OptionAttribute.CaseSensitive)).Value.Value?.ToString();
231231
var exactSpelling = optionAttribute.NamedArguments.FirstOrDefault(a => a.Key == nameof(OptionAttribute.ExactSpelling)).Value.Value is true;
232-
if (exactSpelling)
233-
{
234-
throw new InvalidOperationException($"Property: {propertySymbol.Name}");
235-
}
236232
var aliases = optionAttribute.NamedArguments.FirstOrDefault(a => a.Key == nameof(OptionAttribute.Aliases)).Value switch
237233
{
238234
{ Kind: TypedConstantKind.Array } typedConstant => typedConstant.Values.Select(a => a.Value?.ToString())

src/DotNetCampus.CommandLine.Analyzer/Properties/Localizations.Designer.cs

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/DotNetCampus.CommandLine.Analyzer/Properties/Localizations.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@
141141
<value>Use 'string' type instead</value>
142142
</data>
143143
<data name="DCL202_Description" xml:space="preserve">
144-
<value>This property has the type '{0}' which is not built-in supported. It's recommended to use bool/string/IList&lt;string&gt; or other types that the code fix will suggest you change instead or add a custom converter on your Value or Option attribute.</value>
144+
<value>This property has the type '{0}' which is not built-in supported. It's recommended to use bool/string/IReadOnlyList&lt;string&gt; or other types that the code fix will suggest you change instead or add a custom converter on your Value or Option attribute.</value>
145145
</data>
146146
<data name="DCL202_Message" xml:space="preserve">
147147
<value>This property has the type '{0}' which is not built-in supported.</value>

src/DotNetCampus.CommandLine.Analyzer/Properties/Localizations.zh-hans-cn.resx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
<value>命令行选项:改为字典类型 (IReadOnlyDictionary&lt;string, string&gt;)</value>
2323
</data>
2424
<data name="DCL201_202_Fix_OptionTypeToDouble" xml:space="preserve">
25-
<value>命令行选项:改为小数类型 (double)</value>
26-
</data>
25+
<value>命令行选项:改为浮点数类型 (double)</value>
26+
</data>
2727
<data name="DCL201_202_Fix_OptionTypeToInt32" xml:space="preserve">
2828
<value>命令行选项:改为整数类型 (int)</value>
2929
</data>
@@ -34,8 +34,8 @@
3434
<value>命令行选项:改为字符串类型 (string)</value>
3535
</data>
3636
<data name="DCL202_Description" xml:space="preserve">
37-
<value>作为命令行选项,此属性的类型 {0} 不被内置支持。 建议使用 bool / string / IList&lt;string&gt; 或代码修复会建议您更改的其他类型,或者在 Value / Option 特性上添加自定义转换器。</value>
38-
</data>
37+
<value>作为命令行选项,此属性的类型 {0} 不被内置支持。 建议使用 bool / string / IReadOnlyList&lt;string&gt; 或代码修复会建议您更改的其他类型,或者在 Value / Option 特性上添加自定义转换器。</value>
38+
</data>
3939
<data name="DCL202_Message" xml:space="preserve">
4040
<value>作为命令行选项,此属性的类型 {0} 不被内置支持。</value>
4141
</data>

src/DotNetCampus.CommandLine.Analyzer/Utils/CodeAnalysis/AttributeExtensions.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ public static bool IsAttributeOf<TAttribute>(this AttributeSyntax attribute)
2828

2929
public static bool IsAttributeOf<TAttribute>(this INamedTypeSymbol attribute)
3030
{
31+
if (attribute.ContainingNamespace.ToString() != typeof(TAttribute).Namespace)
32+
{
33+
return false;
34+
}
35+
3136
var compareName = typeof(TAttribute).Name;
32-
if (attribute.Name == compareName)
37+
if (attribute.Name == typeof(TAttribute).Name)
3338
{
3439
return true;
3540
}

src/DotNetCampus.CommandLine/CommandLine.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ public override string ToString()
413413
{
414414
return MatchedUrlScheme is { } scheme
415415
? $"{scheme}://{string.Join("/", PositionalArguments)}?{string.Join("&", LongOptionValues.Select(x => $"{x.Key}={string.Join("&", x.Value)}"))}"
416-
: string.Join(" ", CommandLineArguments);
416+
: string.Join(" ", CommandLineArguments.Select(x => x.Contains(' ') ? $"\"{x}\"" : x));
417417
}
418418
}
419419

src/DotNetCampus.CommandLine/CommandLineParsingOptions.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,38 @@ namespace DotNetCampus.Cli;
55
/// <summary>
66
/// 在解析命令行参数时,指定命令行参数的解析方式。
77
/// </summary>
8-
public record CommandLineParsingOptions
8+
public readonly record struct CommandLineParsingOptions()
99
{
1010
/// <inheritdoc cref="CommandLineStyle.Flexible" />
11-
public static CommandLineParsingOptions Flexible { get; } = new CommandLineParsingOptions
11+
public static CommandLineParsingOptions Flexible => new CommandLineParsingOptions
1212
{
1313
Style = CommandLineStyle.Flexible,
1414
CaseSensitive = false,
1515
};
1616

1717
/// <inheritdoc cref="CommandLineStyle.GNU" />
18-
public static CommandLineParsingOptions GNU { get; } = new CommandLineParsingOptions
18+
public static CommandLineParsingOptions GNU => new CommandLineParsingOptions
1919
{
2020
Style = CommandLineStyle.GNU,
2121
CaseSensitive = true,
2222
};
2323

2424
/// <inheritdoc cref="CommandLineStyle.POSIX" />
25-
public static CommandLineParsingOptions POSIX { get; } = new CommandLineParsingOptions
25+
public static CommandLineParsingOptions POSIX => new CommandLineParsingOptions
2626
{
2727
Style = CommandLineStyle.POSIX,
2828
CaseSensitive = true,
2929
};
3030

3131
/// <inheritdoc cref="CommandLineStyle.DotNet" />
32-
public static CommandLineParsingOptions DotNet { get; } = new CommandLineParsingOptions
32+
public static CommandLineParsingOptions DotNet => new CommandLineParsingOptions
3333
{
3434
Style = CommandLineStyle.DotNet,
3535
CaseSensitive = false,
3636
};
3737

3838
/// <inheritdoc cref="CommandLineStyle.PowerShell" />
39-
public static CommandLineParsingOptions PowerShell { get; } = new CommandLineParsingOptions
39+
public static CommandLineParsingOptions PowerShell => new CommandLineParsingOptions
4040
{
4141
Style = CommandLineStyle.PowerShell,
4242
CaseSensitive = false,

src/DotNetCampus.CommandLine/CommandRunner.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class CommandRunner : ICommandRunnerBuilder, IAsyncCommandRunnerBuilder
1414

1515
private readonly CommandLine _commandLine;
1616
private readonly DictionaryCommandHandlerCollection _dictionaryVerbHandlers = new();
17-
private readonly List<ICommandHandlerCollection> _assemblyVerbHandlers = [];
17+
private readonly ConcurrentDictionary<ICommandHandlerCollection, ICommandHandlerCollection> _assemblyVerbHandlers = [];
1818

1919
internal CommandRunner(CommandLine commandLine)
2020
{
@@ -97,7 +97,8 @@ internal CommandRunner AddHandler<T>(Func<T, Task<int>> handler)
9797
internal CommandRunner AddHandlers<T>()
9898
where T : ICommandHandlerCollection, new()
9999
{
100-
_assemblyVerbHandlers.Add(new T());
100+
var c = new T();
101+
_assemblyVerbHandlers.TryAdd(c, c);
101102
return this;
102103
}
103104

@@ -114,7 +115,7 @@ internal CommandRunner AddHandlers<T>()
114115
// 其次寻找程序集中自动搜集到的处理器。
115116
foreach (var handler in _assemblyVerbHandlers)
116117
{
117-
if (handler.TryMatch(verbName, _commandLine) is { } h2)
118+
if (handler.Value.TryMatch(verbName, _commandLine) is { } h2)
118119
{
119120
return h2;
120121
}
@@ -127,7 +128,7 @@ internal CommandRunner AddHandlers<T>()
127128
}
128129
foreach (var handler in _assemblyVerbHandlers)
129130
{
130-
if (handler.TryMatch(null, _commandLine) is { } h4)
131+
if (handler.Value.TryMatch(null, _commandLine) is { } h4)
131132
{
132133
return h4;
133134
}

src/DotNetCampus.CommandLine/DotNetCampus.CommandLine.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414
<InternalsVisibleTo Include="DotNetCampus.CommandLine.Tests" />
1515
</ItemGroup>
1616

17+
<ItemGroup>
18+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0">
19+
<PrivateAssets>all</PrivateAssets>
20+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
21+
</PackageReference>
22+
</ItemGroup>
23+
1724
<Target Name="_IncludeAllDependencies" BeforeTargets="_GetPackageFiles">
1825
<ItemGroup>
1926
<None Include="$(RepositoryRoot)README.md" Pack="true" PackagePath="\" />

src/DotNetCampus.CommandLine/Utils/CommandLineValueConverter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,13 @@ internal static bool ArgumentStringsToBoolean(ImmutableArray<string>? arguments)
8282
}
8383
}
8484

85-
internal static T ArgumentStringsToEnum<T>(ImmutableArray<string>? arguments) where T : unmanaged, Enum => arguments switch
85+
private static T? ArgumentStringsToValue<T>(ImmutableArray<string>? arguments) where T : IParsable<T> => arguments switch
8686
{
8787
null or { Length: 0 } => default,
88-
{ } values => Enum.TryParse<T>(values[0], true, out var result)
88+
{ } values => T.TryParse(values[0], null, out var result)
8989
? result
9090
: throw new CommandLineParseValueException(
91-
$"Value [{values[0]}] is not a valid enum value for type {typeof(T).Name}."),
91+
$"Value [{values[0]}] is not a valid value for type {typeof(T).Name}."),
9292
};
9393

9494
internal static byte ArgumentStringsToByte(ImmutableArray<string>? arguments) => arguments switch

src/DotNetCampus.CommandLine/Utils/Handlers/DictionaryCommandHandlerCollection.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
using System.Collections.Concurrent;
12
using DotNetCampus.Cli.Compiler;
23

34
namespace DotNetCampus.Cli.Utils.Handlers;
45

56
internal sealed class DictionaryCommandHandlerCollection : ICommandHandlerCollection
67
{
78
private Func<CommandLine, ICommandHandler>? _defaultHandlerCreator;
8-
private readonly Dictionary<string, Func<CommandLine, ICommandHandler>> _verbHandlers = [];
9+
private readonly ConcurrentDictionary<string, Func<CommandLine, ICommandHandler>> _verbHandlers = [];
910

1011
public void AddHandler(string? verbName, Func<CommandLine, ICommandHandler> handlerCreator)
1112
{
@@ -19,7 +20,10 @@ public void AddHandler(string? verbName, Func<CommandLine, ICommandHandler> hand
1920
}
2021
else
2122
{
22-
_verbHandlers[verbName] = handlerCreator;
23+
if (!_verbHandlers.TryAdd(verbName, handlerCreator))
24+
{
25+
throw new InvalidOperationException($"Duplicate handler with verb {verbName}. Existed: {_verbHandlers}, new: {handlerCreator}");
26+
}
2327
}
2428
}
2529

0 commit comments

Comments
 (0)