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

Fix nullable issues #636

Merged
merged 10 commits into from
Oct 23, 2022
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
4 changes: 3 additions & 1 deletion System.Linq.Dynamic.Core.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EF/@EntryIndexedValue">EF</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IL/@EntryIndexedValue">IL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UTC/@EntryIndexedValue">UTC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WASM/@EntryIndexedValue">WASM</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Formattable/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Formattable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=renamer/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Copyright>Copyright © ZZZ Projects</Copyright>
<DefaultLanguage>en-us</DefaultLanguage>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<LangVersion>latest</LangVersion>
<LangVersion>10</LangVersion>
<Nullable>enable</Nullable>
<PackageIcon>logo.png</PackageIcon>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
#pragma warning disable CS1591
using JetBrains.Annotations;
using System.Text.RegularExpressions;

Expand Down
50 changes: 26 additions & 24 deletions src/System.Linq.Dynamic.Core/Compatibility/ExpressionVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ protected ExpressionVisitor()
protected virtual Expression Visit(Expression exp)
{
if (exp == null)
{
return exp;
}

switch (exp.NodeType)
{
Expand Down Expand Up @@ -103,7 +105,7 @@ protected virtual MemberBinding VisitBinding(MemberBinding binding)

protected virtual ElementInit VisitElementInitializer(ElementInit initializer)
{
ReadOnlyCollection<Expression> arguments = this.VisitExpressionList(initializer.Arguments);
ReadOnlyCollection<Expression> arguments = VisitExpressionList(initializer.Arguments);
if (arguments != initializer.Arguments)
{
return Expression.ElementInit(initializer.AddMethod, arguments);
Expand All @@ -127,13 +129,15 @@ protected virtual Expression VisitBinary(BinaryExpression b)
{
Expression left = Visit(b.Left);
Expression right = Visit(b.Right);
Expression conversion = Visit(b.Conversion);
Expression conversion = Visit(b.Conversion!);
if (left != b.Left || right != b.Right || conversion != b.Conversion)
{
if (b.NodeType == ExpressionType.Coalesce && b.Conversion != null)
{
return Expression.Coalesce(left, right, conversion as LambdaExpression);
else
return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method);
}

return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method);
}

return b;
Expand Down Expand Up @@ -186,8 +190,8 @@ protected virtual Expression VisitMemberAccess(MemberExpression m)

protected virtual Expression VisitMethodCall(MethodCallExpression m)
{
Expression obj = Visit(m.Object);
IEnumerable<Expression> args = this.VisitExpressionList(m.Arguments);
Expression obj = Visit(m.Object!);
IEnumerable<Expression> args = VisitExpressionList(m.Arguments);
if (obj != m.Object || args != m.Arguments)
{
return Expression.Call(obj, m.Method, args);
Expand All @@ -198,10 +202,10 @@ protected virtual Expression VisitMethodCall(MethodCallExpression m)

protected virtual ReadOnlyCollection<Expression> VisitExpressionList(ReadOnlyCollection<Expression> original)
{
List<Expression> list = null;
List<Expression>? list = null;
for (int i = 0, n = original.Count; i < n; i++)
{
Expression p = this.Visit(original[i]);
Expression p = Visit(original[i]);
if (list != null)
{
list.Add(p);
Expand Down Expand Up @@ -239,7 +243,7 @@ protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assign

protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding)
{
IEnumerable<MemberBinding> bindings = this.VisitBindingList(binding.Bindings);
IEnumerable<MemberBinding> bindings = VisitBindingList(binding.Bindings);
if (bindings != binding.Bindings)
{
return Expression.MemberBind(binding.Member, bindings);
Expand All @@ -250,7 +254,7 @@ protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBindi

protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding)
{
IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(binding.Initializers);
IEnumerable<ElementInit> initializers = VisitElementInitializerList(binding.Initializers);
if (initializers != binding.Initializers)
{
return Expression.ListBind(binding.Member, initializers);
Expand All @@ -261,10 +265,10 @@ protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding bin

protected virtual IEnumerable<MemberBinding> VisitBindingList(ReadOnlyCollection<MemberBinding> original)
{
List<MemberBinding> list = null;
List<MemberBinding>? list = null;
for (int i = 0, n = original.Count; i < n; i++)
{
MemberBinding b = this.VisitBinding(original[i]);
MemberBinding b = VisitBinding(original[i]);
if (list != null)
{
list.Add(b);
Expand All @@ -288,10 +292,10 @@ protected virtual IEnumerable<MemberBinding> VisitBindingList(ReadOnlyCollection

protected virtual IEnumerable<ElementInit> VisitElementInitializerList(ReadOnlyCollection<ElementInit> original)
{
List<ElementInit> list = null;
List<ElementInit>? list = null;
for (int i = 0, n = original.Count; i < n; i++)
{
ElementInit init = this.VisitElementInitializer(original[i]);
ElementInit init = VisitElementInitializer(original[i]);
if (list != null)
{
list.Add(init);
Expand Down Expand Up @@ -326,7 +330,7 @@ protected virtual Expression VisitLambda(LambdaExpression lambda)

protected virtual NewExpression VisitNew(NewExpression nex)
{
IEnumerable<Expression> args = this.VisitExpressionList(nex.Arguments);
IEnumerable<Expression> args = VisitExpressionList(nex.Arguments);
if (args != nex.Arguments)
{
if (nex.Members != null)
Expand All @@ -341,7 +345,7 @@ protected virtual NewExpression VisitNew(NewExpression nex)
protected virtual Expression VisitMemberInit(MemberInitExpression init)
{
NewExpression n = VisitNew(init.NewExpression);
IEnumerable<MemberBinding> bindings = this.VisitBindingList(init.Bindings);
IEnumerable<MemberBinding> bindings = VisitBindingList(init.Bindings);
if (n != init.NewExpression || bindings != init.Bindings)
{
return Expression.MemberInit(n, bindings);
Expand All @@ -353,7 +357,7 @@ protected virtual Expression VisitMemberInit(MemberInitExpression init)
protected virtual Expression VisitListInit(ListInitExpression init)
{
NewExpression n = VisitNew(init.NewExpression);
IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(init.Initializers);
IEnumerable<ElementInit> initializers = VisitElementInitializerList(init.Initializers);
if (n != init.NewExpression || initializers != init.Initializers)
{
return Expression.ListInit(n, initializers);
Expand All @@ -364,25 +368,23 @@ protected virtual Expression VisitListInit(ListInitExpression init)

protected virtual Expression VisitNewArray(NewArrayExpression na)
{
IEnumerable<Expression> exprs = this.VisitExpressionList(na.Expressions);
IEnumerable<Expression> exprs = VisitExpressionList(na.Expressions);
if (exprs != na.Expressions)
{
if (na.NodeType == ExpressionType.NewArrayInit)
{
return Expression.NewArrayInit(na.Type.GetElementType(), exprs);
}
else
{
return Expression.NewArrayBounds(na.Type.GetElementType(), exprs);
return Expression.NewArrayInit(na.Type.GetElementType()!, exprs);
}

return Expression.NewArrayBounds(na.Type.GetElementType()!, exprs);
}

return na;
}

protected virtual Expression VisitInvocation(InvocationExpression iv)
{
IEnumerable<Expression> args = this.VisitExpressionList(iv.Arguments);
IEnumerable<Expression> args = VisitExpressionList(iv.Arguments);
Expression expr = Visit(iv.Expression);
if (args != iv.Arguments || expr != iv.Expression)
{
Expand Down
39 changes: 39 additions & 0 deletions src/System.Linq.Dynamic.Core/Compatibility/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// ReSharper disable once CheckNamespace
namespace System;

internal static class StringExtensions
{
/// <summary>
/// Indicates whether a specified string is null, empty, or consists only of white-space
/// characters.
///
/// Recreates the same functionality as System.String.IsNullOrWhiteSpace but included here
/// for compatibility with net35.
/// </summary>
/// <param name="value">The string to test.</param>
/// <returns>
/// true if the value parameter is null or System.String.Empty, or if value consists
/// exclusively of white-space characters.
/// </returns>
public static bool IsNullOrWhiteSpace(this string? value)
{
#if !NET35
return string.IsNullOrWhiteSpace(value);
#else
if (value == null)
{
return true;
}

for (int i = 0; i < value.Length; i++)
{
if (!char.IsWhiteSpace(value[i]))
{
return false;
}
}

return true;
#endif
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq.Dynamic.Core.Validation;
using System.Reflection;

Expand All @@ -15,7 +14,7 @@ public abstract class AbstractDynamicLinqCustomTypeProvider
/// </summary>
/// <param name="assemblies">The assemblies to process.</param>
/// <returns><see cref="IEnumerable{Type}" /></returns>
protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute([NotNull] IEnumerable<Assembly> assemblies)
protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
{
Check.NotNull(assemblies, nameof(assemblies));
#if !NET35
Expand All @@ -30,7 +29,7 @@ protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute([NotNull
/// <param name="assemblies">The assemblies to inspect.</param>
/// <param name="typeName">The typename to resolve.</param>
/// <returns>A resolved <see cref="Type"/> or null when not found.</returns>
protected Type ResolveType([NotNull] IEnumerable<Assembly> assemblies, [NotNull] string typeName)
protected Type? ResolveType(IEnumerable<Assembly> assemblies, string typeName)
{
Check.NotNull(assemblies, nameof(assemblies));
Check.NotEmpty(typeName, nameof(typeName));
Expand All @@ -53,19 +52,19 @@ protected Type ResolveType([NotNull] IEnumerable<Assembly> assemblies, [NotNull]
/// <param name="assemblies">The assemblies to inspect.</param>
/// <param name="simpleTypeName">The simple typename to resolve.</param>
/// <returns>A resolved <see cref="Type"/> or null when not found.</returns>
protected Type ResolveTypeBySimpleName([NotNull] IEnumerable<Assembly> assemblies, [NotNull] string simpleTypeName)
protected Type? ResolveTypeBySimpleName(IEnumerable<Assembly> assemblies, string simpleTypeName)
{
Check.NotNull(assemblies, nameof(assemblies));
Check.NotEmpty(simpleTypeName, nameof(simpleTypeName));

foreach (var assembly in assemblies)
{
var fullNames = assembly.GetTypes().Select(t => t.FullName).Distinct();
var fullNames = assembly.GetTypes().Select(t => t.FullName!).Distinct();
var firstMatchingFullname = fullNames.FirstOrDefault(fn => fn.EndsWith($".{simpleTypeName}"));

if (firstMatchingFullname != null)
{
Type resolvedType = assembly.GetType(firstMatchingFullname, false, true);
var resolvedType = assembly.GetType(firstMatchingFullname, false, true);
if (resolvedType != null)
{
return resolvedType;
Expand All @@ -82,13 +81,13 @@ protected Type ResolveTypeBySimpleName([NotNull] IEnumerable<Assembly> assemblie
/// </summary>
/// <param name="assemblies">The assemblies to process.</param>
/// <returns><see cref="IEnumerable{Type}" /></returns>
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute([NotNull] IEnumerable<Assembly> assemblies)
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
{
Check.NotNull(assemblies, nameof(assemblies));

foreach (var assembly in assemblies)
{
Type[] definedTypes = null;
Type[]? definedTypes = null;

try
{
Expand Down Expand Up @@ -118,13 +117,13 @@ protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute([NotNul
/// </summary>
/// <param name="assemblies">The assemblies to process.</param>
/// <returns><see cref="IEnumerable{Type}" /></returns>
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute([NotNull] IEnumerable<Assembly> assemblies)
protected IEnumerable<Type> GetAssemblyTypesWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
{
Check.NotNull(assemblies, nameof(assemblies));

foreach (var assembly in assemblies.Where(a => !a.GlobalAssemblyCache)) // Skip System DLL's
{
Type[] definedTypes = null;
Type[]? definedTypes = null;

try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace System.Linq.Dynamic.Core.CustomTypeProviders
{
/// <summary>
/// The default implementation for <see cref="IDynamicLinkCustomTypeProvider"/>.
/// The default implementation for <see cref="DefaultDynamicLinqCustomTypeProvider"/>.
///
/// Scans the current AppDomain for all types marked with <see cref="DynamicLinqTypeAttribute"/>, and adds them as custom Dynamic Link types.
///
Expand All @@ -19,8 +19,8 @@ public class DefaultDynamicLinqCustomTypeProvider : AbstractDynamicLinqCustomTyp
private readonly IAssemblyHelper _assemblyHelper = new DefaultAssemblyHelper();
private readonly bool _cacheCustomTypes;

private HashSet<Type> _cachedCustomTypes;
private Dictionary<Type, List<MethodInfo>> _cachedExtensionMethods;
private HashSet<Type>? _cachedCustomTypes;
private Dictionary<Type, List<MethodInfo>>? _cachedExtensionMethods;

/// <summary>
/// Initializes a new instance of the <see cref="DefaultDynamicLinqCustomTypeProvider"/> class.
Expand Down Expand Up @@ -64,7 +64,7 @@ public Dictionary<Type, List<MethodInfo>> GetExtensionMethods()
}

/// <inheritdoc cref="IDynamicLinqCustomTypeProvider.ResolveType"/>
public Type ResolveType(string typeName)
public Type? ResolveType(string typeName)
{
Check.NotEmpty(typeName, nameof(typeName));

Expand All @@ -73,7 +73,7 @@ public Type ResolveType(string typeName)
}

/// <inheritdoc cref="IDynamicLinqCustomTypeProvider.ResolveTypeBySimpleName"/>
public Type ResolveTypeBySimpleName(string simpleTypeName)
public Type? ResolveTypeBySimpleName(string simpleTypeName)
{
Check.NotEmpty(simpleTypeName, nameof(simpleTypeName));

Expand Down Expand Up @@ -106,4 +106,4 @@ private Dictionary<Type, List<MethodInfo>> GetExtensionMethodsInternal()
return list.GroupBy(x => x.Item1, tuple => tuple.Item2).ToDictionary(key => key.Key, methods => methods.ToList());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ public interface IDynamicLinqCustomTypeProvider
/// </summary>
/// <param name="typeName">The typename to resolve.</param>
/// <returns>A resolved <see cref="Type"/> or null when not found.</returns>
Type ResolveType([NotNull] string typeName);
Type? ResolveType(string typeName);

/// <summary>
/// Resolve any type by the simple name which is registered in the current application domain.
/// </summary>
/// <param name="simpleTypeName">The typename to resolve.</param>
/// <returns>A resolved <see cref="Type"/> or null when not found.</returns>
Type ResolveTypeBySimpleName([NotNull] string simpleTypeName);
Type? ResolveTypeBySimpleName(string simpleTypeName);
}
}
}
Loading