From 92b213ea2a1ff71501dde1746b1f1376d4893a72 Mon Sep 17 00:00:00 2001 From: Olmo del Corral Date: Mon, 5 Aug 2019 18:00:10 +0200 Subject: [PATCH] update Nullable Reference Types VS 16.2 --- Signum.Engine/BulkInserter.cs | 2 +- .../DynamicQuery/ExpressionContainer.cs | 6 +- Signum.Engine/Engine/Synchronizer.cs | 6 +- .../DbExpressionNominator.cs | 3 + .../ExpressionVisitor/DbExpressionVisitor.cs | 2 +- .../Linq/ExpressionVisitor/QueryBinder.cs | 4 +- .../SchemaBuilder/SchemaBuilderSettings.cs | 5 +- Signum.Engine/Signum.Engine.csproj | 2 +- .../Tokens/ExtensionDictionaryToken.cs | 2 +- .../EntityStructuralEqualityComparer.cs | 2 +- Signum.Entities/Signum.Entities.csproj | 8 +- Signum.Entities/TimeZoneManager.cs | 4 +- Signum.Entities/Validator.cs | 4 +- .../PublishProfiles/FolderProfile.pubxml | 12 --- .../Properties/launchSettings.json | 2 +- Signum.MSBuildTask/Signum.MSBuildTask.csproj | 6 +- Signum.React/Signum.React.csproj | 4 +- .../EntityDeclarationGenerator.cs | 17 +++- Signum.TSGenerator/Signum.TSGenerator.csproj | 2 +- Signum.Test/Signum.Test.csproj | 6 +- Signum.Utilities/ConsoleSwitch.cs | 2 +- .../DataStructures/DirectedEdgedGraph.cs | 4 +- .../DataStructures/DirectedGraph.cs | 2 +- .../DataStructures/ImmutableStack.cs | 4 +- .../ExpressionTrees/ExpressionEvaluator.cs | 2 +- .../Extensions/DictionaryExtensions.cs | 12 +-- .../Extensions/EnumerableExtensions.cs | 9 +- Signum.Utilities/Extensions/Extensions.cs | 9 +- .../Extensions/RegexExtensions.cs | 4 +- .../Extensions/StringExtensions.cs | 3 +- Signum.Utilities/NotNullAttributes.cs | 96 ++++++++++++------- Signum.Utilities/Polymorphic.cs | 22 ++--- .../Reflection/ReflectionTools.cs | 60 ++++++++++++ Signum.Utilities/Signum.Utilities.csproj | 4 +- 34 files changed, 216 insertions(+), 116 deletions(-) delete mode 100644 Signum.MSBuildTask/Properties/PublishProfiles/FolderProfile.pubxml diff --git a/Signum.Engine/BulkInserter.cs b/Signum.Engine/BulkInserter.cs index daefa1eef8..40f180b9c6 100644 --- a/Signum.Engine/BulkInserter.cs +++ b/Signum.Engine/BulkInserter.cs @@ -59,7 +59,7 @@ public static int BulkInsertQueryIds(this IEnumerable entities, int? timeout = null, string? message = null) where T : Entity - where K : object + where K : notnull { using (HeavyProfiler.Log(nameof(BulkInsertQueryIds), () => typeof(T).TypeName())) using (Transaction tr = new Transaction()) diff --git a/Signum.Engine/DynamicQuery/ExpressionContainer.cs b/Signum.Engine/DynamicQuery/ExpressionContainer.cs index add5c24e7e..ba997d27e8 100644 --- a/Signum.Engine/DynamicQuery/ExpressionContainer.cs +++ b/Signum.Engine/DynamicQuery/ExpressionContainer.cs @@ -108,7 +108,7 @@ public ExtensionDictionaryInfo RegisterDictionary( Expression> valueSelector, ResetLazy>? allKeys = null) where T : Entity - where K : object + where K : notnull { var mei = new ExtensionDictionaryInfo(collectionSelector, keySelector, valueSelector, allKeys ?? GetAllKeysLazy(collectionSelector, keySelector)); @@ -126,7 +126,7 @@ public ExtensionDictionaryInfo RegisterDictionaryInEmbedded>? allKeys = null) where T : Entity where M : ModifiableEntity - where K : object + where K : notnull { var mei = new ExtensionDictionaryInfo(collectionSelector, keySelector, valueSelector, allKeys ?? GetAllKeysLazy(CombineSelectors(embeddedSelector, collectionSelector), keySelector)); @@ -173,7 +173,7 @@ public interface IExtensionDictionaryInfo } public class ExtensionDictionaryInfo : IExtensionDictionaryInfo - where K : object + where K : notnull { public ResetLazy> AllKeys; diff --git a/Signum.Engine/Engine/Synchronizer.cs b/Signum.Engine/Engine/Synchronizer.cs index 0477426729..f61fbbce68 100644 --- a/Signum.Engine/Engine/Synchronizer.cs +++ b/Signum.Engine/Engine/Synchronizer.cs @@ -14,7 +14,7 @@ public static void Synchronize( Action? createNew, Action? removeOld, Action? merge) - where K : object + where K : notnull { HashSet keys = new HashSet(); keys.UnionWith(oldDictionary.Keys); @@ -48,7 +48,7 @@ public static void SynchronizeProgressForeach( Action? merge, bool showProgress = true, bool transactional = true) - where K : object + where K : notnull { HashSet keys = new HashSet(); keys.UnionWith(oldDictionary.Keys); @@ -120,7 +120,7 @@ public static void SynchronizeReplacing( Func? mergeBoth) where O : class where N : class - where K : object + where K : notnull { return newDictionary.OuterJoinDictionaryCC(oldDictionary, (key, newVal, oldVal) => { diff --git a/Signum.Engine/Linq/ExpressionVisitor/DbExpressionNominator.cs b/Signum.Engine/Linq/ExpressionVisitor/DbExpressionNominator.cs index 9162e972b4..f2ce5855a5 100644 --- a/Signum.Engine/Linq/ExpressionVisitor/DbExpressionNominator.cs +++ b/Signum.Engine/Linq/ExpressionVisitor/DbExpressionNominator.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Linq.Expressions; @@ -61,6 +62,7 @@ static internal HashSet Nominate(Expression? expression, out Express return n.candidates; } + [return: NotNullIfNotNull("expression")] static internal Expression? FullNominate(Expression? expression) { DbExpressionNominator n = new DbExpressionNominator { isFullNominate = true }; @@ -69,6 +71,7 @@ static internal HashSet Nominate(Expression? expression, out Express return result; } + [return: NotNullIfNotNull("expression")] static internal Expression? FullNominateNotNullable(Expression? expression) { DbExpressionNominator n = new DbExpressionNominator { isFullNominate = true, isNotNullRoot = expression }; diff --git a/Signum.Engine/Linq/ExpressionVisitor/DbExpressionVisitor.cs b/Signum.Engine/Linq/ExpressionVisitor/DbExpressionVisitor.cs index d78cfdd03f..9a395c191e 100644 --- a/Signum.Engine/Linq/ExpressionVisitor/DbExpressionVisitor.cs +++ b/Signum.Engine/Linq/ExpressionVisitor/DbExpressionVisitor.cs @@ -99,7 +99,7 @@ protected internal virtual Expression VisitTypeEntity(TypeEntityExpression typeF [DebuggerStepThrough] protected static ReadOnlyDictionary Visit(ReadOnlyDictionary dictionary, Func newValue) - where K : object + where K : notnull where V : class { Dictionary? alternate = null; diff --git a/Signum.Engine/Linq/ExpressionVisitor/QueryBinder.cs b/Signum.Engine/Linq/ExpressionVisitor/QueryBinder.cs index 5e661e31b8..f23f1efac5 100644 --- a/Signum.Engine/Linq/ExpressionVisitor/QueryBinder.cs +++ b/Signum.Engine/Linq/ExpressionVisitor/QueryBinder.cs @@ -1324,7 +1324,7 @@ private ProjectionExpression GetTableValuedFunctionProjection(MethodCallExpressi var functionName = mce.Method.GetCustomAttribute().Name ?? mce.Method.Name; - var argumens = mce.Arguments.Select(DbExpressionNominator.FullNominate).ToList(); + var argumens = mce.Arguments.Select(a => DbExpressionNominator.FullNominate(a)!).ToList(); SqlTableValuedFunctionExpression tableExpression = new SqlTableValuedFunctionExpression(functionName, table, tableAlias, argumens); @@ -2425,7 +2425,7 @@ public void FillColumnAssigments(List assignments, ParameterEx private Exception InvalidBody() { - throw new InvalidOperationException("The only allowed expressions on UnsafeInsert are: object initializers, calling method 'SetMixin', or or calling 'Administrator.SetReadonly'"); + throw new InvalidOperationException("The only allowed expressions on UnsafeInsert are: notnull initializers, calling method 'SetMixin', or or calling 'Administrator.SetReadonly'"); } private ColumnAssignment[] AdaptAssign(Expression colExpression, Expression exp) diff --git a/Signum.Engine/Schema/SchemaBuilder/SchemaBuilderSettings.cs b/Signum.Engine/Schema/SchemaBuilder/SchemaBuilderSettings.cs index 7d04f1a3f8..fb5e1788cc 100644 --- a/Signum.Engine/Schema/SchemaBuilder/SchemaBuilderSettings.cs +++ b/Signum.Engine/Schema/SchemaBuilder/SchemaBuilderSettings.cs @@ -13,6 +13,7 @@ using System.Collections.Concurrent; using Signum.Utilities.ExpressionTrees; using System.Runtime.CompilerServices; +using Signum.Utilities.Reflection; namespace Signum.Engine.Maps { @@ -224,8 +225,8 @@ private IsNullable GetIsNullablePrivate(PropertyRoute propertyRoute) if (propertyRoute.Type.IsValueType) return propertyRoute.Type.IsNullable() ? IsNullable.Yes : IsNullable.No; - var nullable = FieldAttribute(propertyRoute); - if (nullable != null && nullable.IsNullableMain == true) + var nullable = propertyRoute.FieldInfo?.IsNullable(); + if (nullable == true) return IsNullable.Yes; return IsNullable.No; diff --git a/Signum.Engine/Signum.Engine.csproj b/Signum.Engine/Signum.Engine.csproj index d6e04d9b4d..779d5ce128 100644 --- a/Signum.Engine/Signum.Engine.csproj +++ b/Signum.Engine/Signum.Engine.csproj @@ -4,7 +4,7 @@ netcoreapp2.2 preview true - enable + enable true x64;x86;AnyCPU diff --git a/Signum.Entities/DynamicQuery/Tokens/ExtensionDictionaryToken.cs b/Signum.Entities/DynamicQuery/Tokens/ExtensionDictionaryToken.cs index d2b329a907..13091a8195 100644 --- a/Signum.Entities/DynamicQuery/Tokens/ExtensionDictionaryToken.cs +++ b/Signum.Entities/DynamicQuery/Tokens/ExtensionDictionaryToken.cs @@ -8,7 +8,7 @@ namespace Signum.Entities.DynamicQuery { [Serializable] public class ExtensionDictionaryToken : QueryToken - where K : object + where K : notnull { QueryToken parent; public override QueryToken? Parent => parent; diff --git a/Signum.Entities/Reflection/EntityStructuralEqualityComparer.cs b/Signum.Entities/Reflection/EntityStructuralEqualityComparer.cs index f135462dac..cea4443458 100644 --- a/Signum.Entities/Reflection/EntityStructuralEqualityComparer.cs +++ b/Signum.Entities/Reflection/EntityStructuralEqualityComparer.cs @@ -97,7 +97,7 @@ public override int GetHashCode(T obj) } public class ClassStructuralEqualityComparer : EqualityComparer, ICompletableComparer - where T: object + where T: notnull { public Dictionary> Properties; diff --git a/Signum.Entities/Signum.Entities.csproj b/Signum.Entities/Signum.Entities.csproj index a7f9114b4f..c075124641 100644 --- a/Signum.Entities/Signum.Entities.csproj +++ b/Signum.Entities/Signum.Entities.csproj @@ -2,13 +2,17 @@ netcoreapp2.2 - 8.0 + preview true - enable + enable true x64;x86;AnyCPU + + On + + diff --git a/Signum.Entities/TimeZoneManager.cs b/Signum.Entities/TimeZoneManager.cs index c77deff774..879e5a25ff 100644 --- a/Signum.Entities/TimeZoneManager.cs +++ b/Signum.Entities/TimeZoneManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using Signum.Utilities; namespace Signum.Entities @@ -29,7 +29,7 @@ public static void IncrementOverridenNow(TimeSpan ts) if (OverrideNowVariable.Value == null) throw new InvalidOperationException("OverridenNow is not set"); - OverrideNowVariable.Value += ts; + OverrideNowVariable.Value = OverrideNowVariable.Value!.Value + ts; } diff --git a/Signum.Entities/Validator.cs b/Signum.Entities/Validator.cs index 3bb9a54054..1fa7771a0f 100644 --- a/Signum.Entities/Validator.cs +++ b/Signum.Entities/Validator.cs @@ -164,8 +164,8 @@ internal PropertyValidator(PropertyInfo pi) this.Validators = pi.GetCustomAttributes(typeof(ValidatorAttribute), false).OfType().OrderBy(va => va.Order).ThenBy(va => va.GetType().Name).ToList(); - var nullable = pi.GetCustomAttribute(); - if (nullable != null && nullable.IsNullableMain == false && !this.Validators.Any(v => v is NotNullValidatorAttribute)) + var nullable = pi.IsNullable(); + if (nullable == false && !this.Validators.Any(v => v is NotNullValidatorAttribute)) this.Validators.Add(new NotNullValidatorAttribute()); this.GetValue = ReflectionTools.CreateGetter(pi)!; diff --git a/Signum.MSBuildTask/Properties/PublishProfiles/FolderProfile.pubxml b/Signum.MSBuildTask/Properties/PublishProfiles/FolderProfile.pubxml deleted file mode 100644 index b98b8ff76a..0000000000 --- a/Signum.MSBuildTask/Properties/PublishProfiles/FolderProfile.pubxml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - FileSystem - Release - netstandard2.0 - D:\Signum\southwind\Framework\Signum.MSBuildTask\Binaries\ - - \ No newline at end of file diff --git a/Signum.MSBuildTask/Properties/launchSettings.json b/Signum.MSBuildTask/Properties/launchSettings.json index 4d8f56e29e..68dc1ebea7 100644 --- a/Signum.MSBuildTask/Properties/launchSettings.json +++ b/Signum.MSBuildTask/Properties/launchSettings.json @@ -1,7 +1,7 @@ { "profiles": { "Signum.Test": { - "commandName": "Project", + "commandName": "Signum.Test", "commandLineArgs": "\"obj\\Debug\\netcoreapp2.2\\Signum.Test.dll\" \"D:\\Signum\\Southwind\\Framework\\Signum.Test\\obj\\SignumReferences.txt\"", "workingDirectory": "D:\\Signum\\Southwind\\Framework\\Signum.Test\\" } diff --git a/Signum.MSBuildTask/Signum.MSBuildTask.csproj b/Signum.MSBuildTask/Signum.MSBuildTask.csproj index 1ea25065bc..3ab122cb29 100644 --- a/Signum.MSBuildTask/Signum.MSBuildTask.csproj +++ b/Signum.MSBuildTask/Signum.MSBuildTask.csproj @@ -8,7 +8,7 @@ true true latest - x64 + x64;AnyCPU Signum.MSBuildTask.nuspec 1.0.3 @@ -16,9 +16,5 @@ - - - - \ No newline at end of file diff --git a/Signum.React/Signum.React.csproj b/Signum.React/Signum.React.csproj index 3441d098db..783a406c51 100644 --- a/Signum.React/Signum.React.csproj +++ b/Signum.React/Signum.React.csproj @@ -3,9 +3,9 @@ netcoreapp2.2 3.5 - 8.0 + preview true - enable + enable true Library diff --git a/Signum.TSGenerator/EntityDeclarationGenerator.cs b/Signum.TSGenerator/EntityDeclarationGenerator.cs index 3f0c855dbd..d99d35bd53 100644 --- a/Signum.TSGenerator/EntityDeclarationGenerator.cs +++ b/Signum.TSGenerator/EntityDeclarationGenerator.cs @@ -334,10 +334,13 @@ private static string EntityInTypeScript(TypeDefinition type, Options options) var properties = GetProperties(type); + var defaultNullableCustomAttribute = type.NullableContextAttribute(); + + foreach (var prop in properties) { string context = $"By type {type.Name} and property {prop.Name}"; - var propertyType = TypeScriptNameInternal(prop.PropertyType, type, options, context) + (prop.GetTypescriptNull() ? " | null" : ""); + var propertyType = TypeScriptNameInternal(prop.PropertyType, type, options, context) + (prop.GetTypescriptNull(defaultNullableCustomAttribute) ? " | null" : ""); var undefined = prop.GetTypescriptUndefined() ? "?" : ""; @@ -348,6 +351,13 @@ private static string EntityInTypeScript(TypeDefinition type, Options options) return sb.ToString(); } + static CustomAttribute NullableContextAttribute(this TypeDefinition type) + { + return type.CustomAttributes.SingleOrDefault(a => a.AttributeType.Name == "NullableContextAttribute") ?? type.DeclaringType?.NullableContextAttribute(); + } + + + static bool IsModifiableEntity(TypeDefinition t) { if (t.IsValueType || t.IsInterface) @@ -465,7 +475,7 @@ public static bool GetTypescriptUndefined(this PropertyDefinition p) return (bool?)inTSAttr?.Properties.SingleOrDefault(a => a.Name == "Undefined").Argument.Value; } - public static bool GetTypescriptNull(this PropertyDefinition p) + public static bool GetTypescriptNull(this PropertyDefinition p, CustomAttribute defaultCustomAttribute) { var inTSAttr = p.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == Cache.InTypeScriptAttribute.FullName); @@ -479,6 +489,9 @@ public static bool GetTypescriptNull(this PropertyDefinition p) { var nullableAttr = p.CustomAttributes.SingleOrDefault(a => a.AttributeType.Name == "NullableAttribute"); + if (nullableAttr == null) + nullableAttr = defaultCustomAttribute; + if (nullableAttr == null) return false; diff --git a/Signum.TSGenerator/Signum.TSGenerator.csproj b/Signum.TSGenerator/Signum.TSGenerator.csproj index 001eb55b14..0d8f4aa63c 100644 --- a/Signum.TSGenerator/Signum.TSGenerator.csproj +++ b/Signum.TSGenerator/Signum.TSGenerator.csproj @@ -8,7 +8,7 @@ true true latest - x64 + x64;AnyCPU 2.0.2 diff --git a/Signum.Test/Signum.Test.csproj b/Signum.Test/Signum.Test.csproj index 799602acaf..a332dcd0cc 100644 --- a/Signum.Test/Signum.Test.csproj +++ b/Signum.Test/Signum.Test.csproj @@ -2,10 +2,10 @@ netcoreapp2.2 - 8.0 + preview SignumTest true - enable + enable true x64;x86;AnyCPU @@ -19,7 +19,7 @@ - + diff --git a/Signum.Utilities/ConsoleSwitch.cs b/Signum.Utilities/ConsoleSwitch.cs index 3655611882..2684ab834f 100644 --- a/Signum.Utilities/ConsoleSwitch.cs +++ b/Signum.Utilities/ConsoleSwitch.cs @@ -6,7 +6,7 @@ namespace Signum.Utilities { public class ConsoleSwitch : IEnumerable>> - where K : object + where K : notnull where V : class { readonly Dictionary> dictionary = new Dictionary>(StringComparer.InvariantCultureIgnoreCase); diff --git a/Signum.Utilities/DataStructures/DirectedEdgedGraph.cs b/Signum.Utilities/DataStructures/DirectedEdgedGraph.cs index 490c81fe7f..c65552d32d 100644 --- a/Signum.Utilities/DataStructures/DirectedEdgedGraph.cs +++ b/Signum.Utilities/DataStructures/DirectedEdgedGraph.cs @@ -7,7 +7,7 @@ namespace Signum.Utilities.DataStructures { public class DirectedEdgedGraph : IEnumerable - where T: object + where T: notnull { Dictionary> adjacency; public IEqualityComparer Comparer { get; private set; } @@ -609,7 +609,7 @@ public override string ToString() public static class DirectedEdgedGraphExtensions { public static E GetOrCreate(this DirectedEdgedGraph graph, T from, T to) - where T : object + where T : notnull where E : new() { var dic = graph.TryRelatedTo(from); diff --git a/Signum.Utilities/DataStructures/DirectedGraph.cs b/Signum.Utilities/DataStructures/DirectedGraph.cs index f37cbf16f7..c3aaa0ebba 100644 --- a/Signum.Utilities/DataStructures/DirectedGraph.cs +++ b/Signum.Utilities/DataStructures/DirectedGraph.cs @@ -7,7 +7,7 @@ namespace Signum.Utilities.DataStructures { public class DirectedGraph : IEnumerable - where T : object + where T : notnull { readonly Dictionary> adjacency; public IEqualityComparer Comparer { get; private set; } diff --git a/Signum.Utilities/DataStructures/ImmutableStack.cs b/Signum.Utilities/DataStructures/ImmutableStack.cs index 579561525b..fbd3f09e29 100644 --- a/Signum.Utilities/DataStructures/ImmutableStack.cs +++ b/Signum.Utilities/DataStructures/ImmutableStack.cs @@ -51,12 +51,12 @@ internal ImmutableStack() { } public static class ImmutableStackExtensions { - public static ImmutableStack Reverse(this ImmutableStack stack) where T : object + public static ImmutableStack Reverse(this ImmutableStack stack) where T : notnull { return Reverse(stack, ImmutableStack.Empty); } - public static ImmutableStack Reverse(this ImmutableStack stack, ImmutableStack initial) where T : object + public static ImmutableStack Reverse(this ImmutableStack stack, ImmutableStack initial) where T : notnull { ImmutableStack r = initial; for (ImmutableStack f = stack; !f.IsEmpty; f = f.Pop()) diff --git a/Signum.Utilities/ExpressionTrees/ExpressionEvaluator.cs b/Signum.Utilities/ExpressionTrees/ExpressionEvaluator.cs index 85b2ea34ab..4e1bc6d318 100644 --- a/Signum.Utilities/ExpressionTrees/ExpressionEvaluator.cs +++ b/Signum.Utilities/ExpressionTrees/ExpressionEvaluator.cs @@ -203,7 +203,7 @@ public override int GetHashCode() { return cachedStaticGetters.GetOrAdd((type: mi.DeclaringType, name: mi.Name), _ => { - return Expression.Lambda>(Expression.Convert(Expression.MakeMemberAccess(null, mi), typeof(object?))).Compile(); + return Expression.Lambda>(Expression.Convert(Expression.MakeMemberAccess(null, mi), typeof(object))).Compile(); }); } diff --git a/Signum.Utilities/Extensions/DictionaryExtensions.cs b/Signum.Utilities/Extensions/DictionaryExtensions.cs index d83e9bac89..7bd47753ed 100644 --- a/Signum.Utilities/Extensions/DictionaryExtensions.cs +++ b/Signum.Utilities/Extensions/DictionaryExtensions.cs @@ -55,7 +55,7 @@ public static V TryGet(this IReadOnlyDictionary dictionary, K key, V } public static V GetOrAdd(this ConcurrentDictionary dictionary, K key) - where K : object + where K : notnull where V : new() { return dictionary.GetOrAdd(key, k => new V()); @@ -98,21 +98,21 @@ public static V GetOrThrow(this IDictionary dictionary, K key, Func< return result; } - public static V GetOrThrow(this IDictionary dictionary, K key, string messageWithFormat) where K : object + public static V GetOrThrow(this IDictionary dictionary, K key, string messageWithFormat) where K : notnull { if (!dictionary.TryGetValue(key, out V result)) throw new KeyNotFoundException(messageWithFormat.FormatWith(key)); return result; } - public static V GetOrThrow(this IDictionary dictionary, K key) where K : object + public static V GetOrThrow(this IDictionary dictionary, K key) where K : notnull { if (!dictionary.TryGetValue(key, out V result)) throw new KeyNotFoundException("Key '{0}' ({1}) not found on {2}".FormatWith(key, key.GetType().TypeName(), dictionary.GetType().TypeName())); return result; } - public static void AddOrThrow(this IDictionary dictionary, K key, V value, string messageWithFormat) where K : object + public static void AddOrThrow(this IDictionary dictionary, K key, V value, string messageWithFormat) where K : notnull { if (dictionary.ContainsKey(key)) throw new ArgumentException(messageWithFormat.FormatWith(key)); @@ -471,14 +471,14 @@ public static Dictionary Extract(this IDictionary dictionary, } - public static V Extract(this IDictionary dictionary, K key) where K : object + public static V Extract(this IDictionary dictionary, K key) where K : notnull { V value = dictionary.GetOrThrow(key); dictionary.Remove(key); return value; } - public static V Extract(this IDictionary dictionary, K key, string messageWithFormat) where K : object + public static V Extract(this IDictionary dictionary, K key, string messageWithFormat) where K : notnull { V value = dictionary.GetOrThrow(key, messageWithFormat); dictionary.Remove(key); diff --git a/Signum.Utilities/Extensions/EnumerableExtensions.cs b/Signum.Utilities/Extensions/EnumerableExtensions.cs index d2a7e9ba1c..38f82ddc60 100644 --- a/Signum.Utilities/Extensions/EnumerableExtensions.cs +++ b/Signum.Utilities/Extensions/EnumerableExtensions.cs @@ -7,11 +7,11 @@ using System.Collections.ObjectModel; using System.ComponentModel; using System.Data; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; -using System.Runtime.CompilerServices; using System.Text; namespace Signum.Utilities @@ -400,12 +400,13 @@ public Expression Expand(Expression instance, Expression[] arguments, MethodInfo } } - public static bool IsNullOrEmpty([NotNullWhenFalse]this IEnumerable? collection) + + public static bool IsNullOrEmpty([NotNullWhen(false)]this IEnumerable? collection) { return collection == null || collection.IsEmpty(); } - public static bool HasItems([NotNullWhenTrue]this IEnumerable? collection) + public static bool HasItems([NotNullWhen(true)]this IEnumerable? collection) { return collection != null && collection.Any(); } @@ -967,7 +968,7 @@ public static IEnumerable SelectAggregate(this IEnumerable collectio } public static IEnumerable> CartesianProduct(this IEnumerable> sequences) - where T : object + where T : notnull { IEnumerable> emptyProduct = new[] { ImmutableStack.Empty }; var result = sequences.Aggregate( diff --git a/Signum.Utilities/Extensions/Extensions.cs b/Signum.Utilities/Extensions/Extensions.cs index 0f40af3861..0ba8fcb24c 100644 --- a/Signum.Utilities/Extensions/Extensions.cs +++ b/Signum.Utilities/Extensions/Extensions.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; @@ -262,7 +263,7 @@ public static int NotFound(this int value, int defaultValue) return value == -1 ? defaultValue : value; } - public static T ThrowIfNull([EnsuresNotNull]this T? t, string message) + public static T ThrowIfNull([NotNull]this T? t, string message) where T : struct { if (t == null) @@ -270,7 +271,7 @@ public static T ThrowIfNull([EnsuresNotNull]this T? t, string message) return t.Value; } - public static T ThrowIfNull([EnsuresNotNull]this T? t, string message) + public static T ThrowIfNull([NotNull]this T? t, string message) where T : class { if (t == null) @@ -279,7 +280,7 @@ public static T ThrowIfNull([EnsuresNotNull]this T? t, string message) } - public static T ThrowIfNull([EnsuresNotNull]this T? t, Func message) + public static T ThrowIfNull([NotNull]this T? t, Func message) where T : struct { if (t == null) @@ -287,7 +288,7 @@ public static T ThrowIfNull([EnsuresNotNull]this T? t, Func message) return t.Value; } - public static T ThrowIfNull([EnsuresNotNull]this T? t, Func message) + public static T ThrowIfNull([NotNull]this T? t, Func message) where T : class { if (t == null) diff --git a/Signum.Utilities/Extensions/RegexExtensions.cs b/Signum.Utilities/Extensions/RegexExtensions.cs index b36766a9b0..f52dd6e445 100644 --- a/Signum.Utilities/Extensions/RegexExtensions.cs +++ b/Signum.Utilities/Extensions/RegexExtensions.cs @@ -44,8 +44,8 @@ public static IEnumerable JoinSimilar(this List outer, List in Func outerKeySelector, Func innerKeySelector, Func resultSelector) - where T : object - where S : object + where T : notnull + where S : notnull { StringDistance sd = new StringDistance(); Dictionary, int> distances = (from o in outer diff --git a/Signum.Utilities/Extensions/StringExtensions.cs b/Signum.Utilities/Extensions/StringExtensions.cs index d11c8f9b23..8667b80b11 100644 --- a/Signum.Utilities/Extensions/StringExtensions.cs +++ b/Signum.Utilities/Extensions/StringExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; @@ -16,7 +17,7 @@ public static class StringExtensions static readonly Expression> HasTextExpression = str => (str ?? "").Length > 0; #pragma warning restore IDE0052 // Remove unread private members [ExpressionField("HasTextExpression")] - public static bool HasText([NotNullWhenTrue]this string? str) + public static bool HasText([NotNullWhen(true)]this string? str) { return !string.IsNullOrEmpty(str); } diff --git a/Signum.Utilities/NotNullAttributes.cs b/Signum.Utilities/NotNullAttributes.cs index 308553f626..fd96ef4328 100644 --- a/Signum.Utilities/NotNullAttributes.cs +++ b/Signum.Utilities/NotNullAttributes.cs @@ -6,57 +6,89 @@ namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] - public class NullableAttribute : Attribute + public class NullableContextAttribute : Attribute { - public NullableAttribute(byte b) + //0 : Dont't know + //1 : Not nullable + //2 : nullable + public readonly byte[] NullableFlags; + public NullableContextAttribute(byte flag) { - B = b; + NullableFlags = new byte[] { flag }; } - - public NullableAttribute(byte[] bs) + public NullableContextAttribute(byte[] flags) { - Bs = bs; + NullableFlags = flags; } + } - public bool? IsNullableMain + [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] + public class NullableAttribute : Attribute + { + //0 : Dont't know + //1 : Not nullable + //2 : nullable + public readonly byte[] NullableFlags; + public NullableAttribute(byte flag) + { + NullableFlags = new byte[] { flag }; + } + public NullableAttribute(byte[] flags) { - get - { - var first = B ?? Bs![0]; - - return first == 1 ? (bool?)false : - first == 2 ? (bool?)true : - null; - } + NullableFlags = flags; } + } +} +namespace System.Diagnostics.CodeAnalysis +{ + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] + public class AllowNullAttribute : Attribute + { + } - public byte? B { get; } - public byte[]? Bs { get; } + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] + public class DisallowNullAttribute : Attribute + { } - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] - public class AssertsTrueAttribute : Attribute + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false)] + public class MaybeNullAttribute : Attribute { - public AssertsTrueAttribute() { } } - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] - public class AssertsFalseAttribute : Attribute + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false)] + public class NotNullAttribute : Attribute { - public AssertsFalseAttribute() { } } - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] - public class EnsuresNotNullAttribute : Attribute + + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false)] + public class MaybeNullWhenAttribute : Attribute { - public EnsuresNotNullAttribute() { } + public bool ReturnValue { get; private set; } + public MaybeNullWhenAttribute(bool returnValue) + { + this.ReturnValue = returnValue; + } } - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] - public class NotNullWhenFalseAttribute : Attribute + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false)] + public class NotNullWhenAttribute : Attribute { - public NotNullWhenFalseAttribute() { } + public bool ReturnValue { get; private set; } + public NotNullWhenAttribute(bool returnValue) + { + this.ReturnValue = returnValue; + } } - [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] - public class NotNullWhenTrueAttribute : Attribute + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false)] + public class NotNullIfNotNullAttribute : Attribute { - public NotNullWhenTrueAttribute() { } + public string Name { get; private set; } + public NotNullIfNotNullAttribute(string name) + { + this.Name = name; + } } } diff --git a/Signum.Utilities/Polymorphic.cs b/Signum.Utilities/Polymorphic.cs index 08c25abf04..93adb19abe 100644 --- a/Signum.Utilities/Polymorphic.cs +++ b/Signum.Utilities/Polymorphic.cs @@ -46,7 +46,7 @@ public static class PolymorphicMerger } public static Dictionary? InheritDictionaryInterfaces(KeyValuePair?> currentValue, KeyValuePair?> baseValue, List?>> newInterfacesValues) - where K : Object + where K : notnull { if (currentValue.Value == null && baseValue.Value == null && newInterfacesValues.All(a => a.Value == null)) return null; @@ -287,31 +287,31 @@ public static void Register(this Polymorphic(this Polymorphic> polymorphic, T instance) where T : object + public static void Invoke(this Polymorphic> polymorphic, T instance) where T : notnull { var action = polymorphic.GetValue(instance.GetType()); action(instance); } - public static void Invoke(this Polymorphic> polymorphic, T instance, P0 p0) where T : object + public static void Invoke(this Polymorphic> polymorphic, T instance, P0 p0) where T : notnull { var action = polymorphic.GetValue(instance.GetType()); action(instance, p0); } - public static void Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1) where T : object + public static void Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1) where T : notnull { var action = polymorphic.GetValue(instance.GetType()); action(instance, p0, p1); } - public static void Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1, P2 p2) where T : object + public static void Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1, P2 p2) where T : notnull { var action = polymorphic.GetValue(instance.GetType()); action(instance, p0, p1, p2); } - public static void Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1, P2 p2, P3 p3) where T : object + public static void Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1, P2 p2, P3 p3) where T : notnull { var action = polymorphic.GetValue(instance.GetType()); action(instance, p0, p1, p2, p3); @@ -319,31 +319,31 @@ public static void Invoke(this Polymorphic(this Polymorphic> polymorphic, T instance) where T : object + public static R Invoke(this Polymorphic> polymorphic, T instance) where T : notnull { var func = polymorphic.GetValue(instance.GetType()); return func(instance); } - public static R Invoke(this Polymorphic> polymorphic, T instance, P0 p0) where T : object + public static R Invoke(this Polymorphic> polymorphic, T instance, P0 p0) where T : notnull { var func = polymorphic.GetValue(instance.GetType()); return func(instance, p0); } - public static R Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1) where T : object + public static R Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1) where T : notnull { var func = polymorphic.GetValue(instance.GetType()); return func(instance, p0, p1); } - public static R Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1, P2 p2) where T : object + public static R Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1, P2 p2) where T : notnull { var func = polymorphic.GetValue(instance.GetType()); return func(instance, p0, p1, p2); } - public static R Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1, P2 p2, P3 p3) where T : object + public static R Invoke(this Polymorphic> polymorphic, T instance, P0 p0, P1 p1, P2 p2, P3 p3) where T : notnull { var func = polymorphic.GetValue(instance.GetType()); return func(instance, p0, p1, p2, p3); diff --git a/Signum.Utilities/Reflection/ReflectionTools.cs b/Signum.Utilities/Reflection/ReflectionTools.cs index 75625d332d..c02aa221d6 100644 --- a/Signum.Utilities/Reflection/ReflectionTools.cs +++ b/Signum.Utilities/Reflection/ReflectionTools.cs @@ -5,11 +5,71 @@ using System.Collections; using System.ComponentModel; using System.Globalization; +using System.Runtime.CompilerServices; namespace Signum.Utilities.Reflection { public static class ReflectionTools { + public static bool? IsNullable(this FieldInfo fi, int position = 0) + { + var result = fi.GetCustomAttribute(); + + if (result != null) + return result.GetNullable(position); + + if (fi.FieldType.IsValueType) + return null; + + return fi.DeclaringType.IsNullableFromContext(position); + } + + public static bool? IsNullable(this PropertyInfo pi, int position = 0) + { + var result = pi.GetCustomAttribute(); + + if (result != null) + return result.GetNullable(position); + + if (pi.PropertyType.IsValueType) + return null; + + return pi.DeclaringType.IsNullableFromContext(); + } + + public static bool? IsNullableFromContext(this Type ti, int position = 0) + { + var result = ti.GetCustomAttribute(); + if (result != null) + return result.GetNullable(position); + + return ti.DeclaringType?.IsNullableFromContext(position); + } + + public static bool? GetNullable(this NullableContextAttribute attr, int position = 0) + { + if (position > 0 && attr.NullableFlags.Length == 1) + position = 0; + + var first = attr.NullableFlags[position]; + + return first == 1 ? (bool?)false : + first == 2 ? (bool?)true : + null; + } + + public static bool? GetNullable(this NullableAttribute attr, int position = 0) + { + if (position > 0 && attr.NullableFlags.Length == 1) + position = 0; + + var first = attr.NullableFlags[position]; + + return first == 1 ? (bool?)false : + first == 2 ? (bool?)true : + null; + } + public static bool FieldEquals(FieldInfo f1, FieldInfo f2) { return MemeberEquals(f1, f2); diff --git a/Signum.Utilities/Signum.Utilities.csproj b/Signum.Utilities/Signum.Utilities.csproj index 056850f3b3..970dc179f1 100644 --- a/Signum.Utilities/Signum.Utilities.csproj +++ b/Signum.Utilities/Signum.Utilities.csproj @@ -2,9 +2,9 @@ netcoreapp2.2 - 8.0 + preview true - enable + enable true x64;x86;AnyCPU