Skip to content
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

Make trimmable in net8.0 #913

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 15 additions & 16 deletions src/CommandLine/BaseAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information.

using System;
using System.Diagnostics.CodeAnalysis;

namespace CommandLine
{
Expand All @@ -14,6 +15,11 @@ public abstract class BaseAttribute : Attribute
private object @default;
private Infrastructure.LocalizableAttributeProperty helpText;
private string metaValue;

#if NET8_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods |
DynamicallyAccessedMemberTypes.PublicProperties)]
#endif
private Type resourceType;

/// <summary>
Expand All @@ -31,11 +37,7 @@ protected internal BaseAttribute()
/// <summary>
/// Gets or sets a value indicating whether a command line option is required.
/// </summary>
public bool Required
{
get;
set;
}
public bool Required { get; set; }

/// <summary>
/// When applied to <see cref="System.Collections.Generic.IEnumerable{T}"/> properties defines
Expand Down Expand Up @@ -81,18 +83,15 @@ public int Max
public object Default
{
get { return @default; }
set
{
@default = value;
}
set { @default = value; }
}

/// <summary>
/// Gets or sets a short description of this command line option. Usually a sentence summary.
/// </summary>
public string HelpText
{
get => helpText.Value??string.Empty;
get => helpText.Value ?? string.Empty;
set => helpText.Value = value ?? throw new ArgumentNullException("value");
}

Expand All @@ -116,22 +115,22 @@ public string MetaValue
/// <summary>
/// Gets or sets a value indicating whether a command line option is visible in the help text.
/// </summary>
public bool Hidden
{
get;
set;
}
public bool Hidden { get; set; }

/// <summary>
/// Gets or sets the <see cref="System.Type"/> that contains the resources for <see cref="HelpText"/>.
/// </summary>
#if NET8_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods |
DynamicallyAccessedMemberTypes.PublicProperties)]
#endif
public Type ResourceType
{
get { return resourceType; }
set
{
resourceType =
helpText.ResourceType = value;
helpText.ResourceType = value;
}
}
}
Expand Down
49 changes: 40 additions & 9 deletions src/CommandLine/CastExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;
#if NET8_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using System.Linq;
using System.Reflection;

Expand All @@ -9,11 +12,18 @@ internal static class CastExtensions
private const string ImplicitCastMethodName = "op_Implicit";
private const string ExplicitCastMethodName = "op_Explicit";

public static bool CanCast<T>(this Type baseType)
public static bool CanCast<T>(
#if NET8_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
#endif
this Type baseType)
{
return baseType.CanImplicitCast<T>() || baseType.CanExplicitCast<T>();
}

#if NET8_0_OR_GREATER
[UnconditionalSuppressMessage("Missing annotations on type", "IL2072")]
#endif
public static bool CanCast<T>(this object obj)
{
var objType = obj.GetType();
Expand All @@ -24,7 +34,7 @@ public static T Cast<T>(this object obj)
{
try
{
return (T) obj;
return (T)obj;
}
catch (InvalidCastException)
{
Expand All @@ -37,29 +47,48 @@ public static T Cast<T>(this object obj)
}
}

private static bool CanImplicitCast<T>(this Type baseType)
private static bool CanImplicitCast<T>(
#if NET8_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
#endif
this Type baseType)
{
return baseType.CanCast<T>(ImplicitCastMethodName);
}

#if NET8_0_OR_GREATER
[UnconditionalSuppressMessage("Missing annotations on type", "IL2072")]
#endif
private static bool CanImplicitCast<T>(this object obj)
{
var baseType = obj.GetType();
return baseType.CanImplicitCast<T>();
}

private static bool CanExplicitCast<T>(this Type baseType)
private static bool CanExplicitCast<T>(
#if NET8_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
#endif
this Type baseType)
{
return baseType.CanCast<T>(ExplicitCastMethodName);
}

#if NET8_0_OR_GREATER
[UnconditionalSuppressMessage("Missing annotations on type", "IL2072")]
#endif
private static bool CanExplicitCast<T>(this object obj)
{
var baseType = obj.GetType();
return baseType.CanExplicitCast<T>();
}

private static bool CanCast<T>(this Type baseType, string castMethodName)
private static bool CanCast<T>(
#if NET8_0_OR_GREATER
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)]
#endif
this Type baseType,
string castMethodName)
{
var targetType = typeof(T);
return baseType.GetMethods(BindingFlags.Public | BindingFlags.Static)
Expand All @@ -81,6 +110,9 @@ private static T ExplicitCast<T>(this object obj)
return obj.Cast<T>(ExplicitCastMethodName);
}

#if NET8_0_OR_GREATER
[UnconditionalSuppressMessage("Reflection on object", "IL2075")]
#endif
private static T Cast<T>(this object obj, string castMethodName)
{
var objType = obj.GetType();
Expand All @@ -91,10 +123,9 @@ private static T Cast<T>(this object obj, string castMethodName)
ParameterInfo pi = mi.GetParameters().FirstOrDefault();
return pi != null && pi.ParameterType == objType;
});
if (conversionMethod != null)
return (T) conversionMethod.Invoke(null, new[] {obj});
else
throw new InvalidCastException($"No method to cast {objType.FullName} to {typeof(T).FullName}");
return conversionMethod != null
? (T)conversionMethod.Invoke(null, new[] { obj })
: throw new InvalidCastException($"No method to cast {objType.FullName} to {typeof(T).FullName}");
}
}
}
5 changes: 3 additions & 2 deletions src/CommandLine/CommandLine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<AssemblyName>CommandLine</AssemblyName>
<OutputType>Library</OutputType>
<TargetFrameworks>netstandard2.0;net40;net45;net461</TargetFrameworks>
<TargetFrameworks>netstandard2.0;net40;net45;net461;net8.0</TargetFrameworks>
<DefineConstants>$(DefineConstants);CSX_EITHER_INTERNAL;CSX_REM_EITHER_BEYOND_2;CSX_ENUM_INTERNAL;ERRH_INTERNAL;CSX_MAYBE_INTERNAL;CSX_REM_EITHER_FUNC;CSX_REM_CRYPTORAND;ERRH_ADD_MAYBE_METHODS</DefineConstants>
<DefineConstants Condition="'$(BuildTarget)' != 'fsharp'">$(DefineConstants);SKIP_FSHARP</DefineConstants>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand All @@ -24,9 +24,10 @@
<PackageTags>command line;commandline;argument;option;parser;parsing;library;syntax;shell</PackageTags>
<PackageReleaseNotes>https://github.com/commandlineparser/commandline/blob/master/CHANGELOG.md</PackageReleaseNotes>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<LangVersion>8.0</LangVersion>
<LangVersion>latest</LangVersion>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<TrimmerRemoveSymbols>true</TrimmerRemoveSymbols>
</PropertyGroup>

<ItemGroup Condition="'$(BuildTarget)' != 'fsharp'">
Expand Down
6 changes: 3 additions & 3 deletions src/CommandLine/Core/GetoptTokenizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,15 +147,15 @@ static class GetoptTokenizer
// But if there is no rest of the string, then instead we swallow the next argument
string chars = arg.Substring(1);
int len = chars.Length;
if (len > 0 && Char.IsDigit(chars[0]))
if (len > 0 && char.IsDigit(chars[0]))
{
// Assume it's a negative number
yield return Token.Value(arg);
yield break;
}
for (int i = 0; i < len; i++)
{
var s = new String(chars[i], 1);
var s = new string(chars[i], 1);
switch(nameLookup(s))
{
case NameLookupResult.OtherOptionFound:
Expand Down Expand Up @@ -196,7 +196,7 @@ static class GetoptTokenizer
string name = parts[0];
string value = (parts.Length > 1) ? parts[1] : null;
// A parameter like "--stringvalue=" is acceptable, and makes stringvalue be the empty string
if (String.IsNullOrWhiteSpace(name) || name.Contains(" "))
if (string.IsNullOrWhiteSpace(name) || name.Contains(" "))
{
onBadFormatToken(arg);
yield break;
Expand Down