-
Notifications
You must be signed in to change notification settings - Fork 401
Perf improvements part 6: startup time #1654
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
790646f
7b15e52
e084081
e950bf0
465e150
4f7cc72
59b1941
0ed5532
fb76e42
bd44fb2
0a82102
3de63b1
2127b1e
1d7aff7
692f045
54e26d4
0d072bd
511d6d0
5f475cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,73 @@ | ||
// Copyright (c) .NET Foundation and contributors. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System.Linq; | ||
|
||
namespace System.CommandLine.Binding | ||
{ | ||
internal abstract class ArgumentConversionResult | ||
internal sealed class ArgumentConversionResult | ||
{ | ||
private protected ArgumentConversionResult(Argument argument) | ||
internal readonly Argument Argument; | ||
internal readonly object? Value; | ||
internal readonly string? ErrorMessage; | ||
internal ArgumentConversionResultType Result; | ||
|
||
private ArgumentConversionResult(Argument argument, string error, ArgumentConversionResultType failure) | ||
{ | ||
Argument = argument ?? throw new ArgumentNullException(nameof(argument)); | ||
ErrorMessage = error ?? throw new ArgumentNullException(nameof(error)); | ||
Result = failure; | ||
} | ||
|
||
private ArgumentConversionResult(Argument argument, object? value) | ||
{ | ||
Argument = argument ?? throw new ArgumentNullException(nameof(argument)); | ||
Value = value; | ||
Result = ArgumentConversionResultType.Successful; | ||
} | ||
|
||
private ArgumentConversionResult(Argument argument) | ||
{ | ||
Argument = argument ?? throw new ArgumentNullException(nameof(argument)); | ||
Result = ArgumentConversionResultType.NoArgument; | ||
} | ||
|
||
internal ArgumentConversionResult( | ||
Argument argument, | ||
Type expectedType, | ||
string value, | ||
LocalizationResources localizationResources) : | ||
this(argument, FormatErrorMessage(argument, expectedType, value, localizationResources), ArgumentConversionResultType.FailedType) | ||
{ | ||
} | ||
|
||
public Argument Argument { get; } | ||
internal static ArgumentConversionResult Failure(Argument argument, string error, ArgumentConversionResultType reason) => new(argument, error, reason); | ||
|
||
public static ArgumentConversionResult Success(Argument argument, object? value) => new(argument, value); | ||
|
||
internal string? ErrorMessage { get; set; } | ||
internal static ArgumentConversionResult None(Argument argument) => new(argument); | ||
|
||
internal static FailedArgumentConversionResult Failure(Argument argument, string error) => new(argument, error); | ||
private static string FormatErrorMessage( | ||
Argument argument, | ||
Type expectedType, | ||
string value, | ||
LocalizationResources localizationResources) | ||
{ | ||
if (argument.FirstParent?.Symbol is IdentifierSymbol identifierSymbol && | ||
argument.FirstParent.Next is null) | ||
{ | ||
var alias = identifierSymbol.Aliases.First(); | ||
|
||
public static SuccessfulArgumentConversionResult Success(Argument argument, object? value) => new(argument, value); | ||
switch (identifierSymbol) | ||
{ | ||
case Command _: | ||
return localizationResources.ArgumentConversionCannotParseForCommand(value, alias, expectedType); | ||
case Option _: | ||
return localizationResources.ArgumentConversionCannotParseForOption(value, alias, expectedType); | ||
} | ||
} | ||
|
||
internal static NoArgumentConversionResult None(Argument argument) => new(argument); | ||
return localizationResources.ArgumentConversionCannotParse(value, expectedType); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright (c) .NET Foundation and contributors. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace System.CommandLine.Binding | ||
{ | ||
internal enum ArgumentConversionResultType | ||
{ | ||
NoArgument, // NoArgumentConversionResult | ||
Successful, // SuccessfulArgumentConversionResult | ||
Failed, // FailedArgumentConversionResult | ||
FailedArity, // FailedArgumentConversionArityResult | ||
FailedType, // FailedArgumentTypeConversionResult | ||
FailedTooManyArguments, // TooManyArgumentsConversionResult | ||
FailedMissingArgument, // MissingArgumentConversionResult | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,6 @@ | |
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Runtime.Serialization; | ||
|
||
|
@@ -13,10 +12,7 @@ namespace System.CommandLine.Binding; | |
internal static partial class ArgumentConverter | ||
{ | ||
#if NET6_0_OR_GREATER | ||
private static readonly Lazy<ConstructorInfo> _listCtor = | ||
new(() => typeof(List<>) | ||
.GetConstructors() | ||
.SingleOrDefault(c => c.GetParameters().Length == 0)!); | ||
private static ConstructorInfo? _listCtor; | ||
#endif | ||
|
||
private static Array CreateEmptyArray(Type itemType, int capacity = 0) | ||
|
@@ -25,14 +21,19 @@ private static Array CreateEmptyArray(Type itemType, int capacity = 0) | |
private static IList CreateEmptyList(Type listType) | ||
{ | ||
#if NET6_0_OR_GREATER | ||
var ctor = (ConstructorInfo)listType.GetMemberWithSameMetadataDefinitionAs(_listCtor.Value); | ||
ConstructorInfo? listCtor = _listCtor; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there reflection-based argument conversions used with the source generator support? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Source generator support is still pending. The original source generator work we did was superseded by improvements we've made to support trimming. |
||
|
||
if (listCtor is null) | ||
{ | ||
_listCtor = listCtor = typeof(List<>).GetConstructor(Type.EmptyTypes)!; | ||
} | ||
|
||
var ctor = (ConstructorInfo)listType.GetMemberWithSameMetadataDefinitionAs(listCtor); | ||
#else | ||
var ctor = listType | ||
.GetConstructors() | ||
.SingleOrDefault(c => c.GetParameters().Length == 0); | ||
var ctor = listType.GetConstructor(Type.EmptyTypes); | ||
#endif | ||
|
||
return (IList)ctor.Invoke(new object[] { }); | ||
return (IList)ctor.Invoke(null); | ||
} | ||
|
||
private static IList CreateEnumerable(Type type, Type itemType, int capacity = 0) | ||
|
Uh oh!
There was an error while loading. Please reload this page.