diff --git a/.editorconfig b/.editorconfig index 9a7532823..d44c44ec7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -477,6 +477,9 @@ dotnet_style_require_accessibility_modifiers = for_non_interface_members # 'using' directive preferences csharp_using_directive_placement = outside_namespace:warning +# CS8625: Cannot convert null literal to non-nullable reference type. +dotnet_diagnostic.CS8625.severity = error + ########################################## # Disable various diagnostics diff --git a/Directory.Packages.props b/Directory.Packages.props index 0308a6631..185fbe651 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -31,7 +31,7 @@ - + @@ -45,10 +45,10 @@ - - - - + + + + diff --git a/apps/AppConsolePg/Db.cs b/apps/AppConsolePg/Db.cs index d2496b935..2ca1b2399 100644 --- a/apps/AppConsolePg/Db.cs +++ b/apps/AppConsolePg/Db.cs @@ -5,7 +5,6 @@ using Jeebs.Data; using Jeebs.Logging; using Microsoft.Extensions.Options; -using Wrap.Extensions; namespace AppConsolePg; diff --git a/src/Jeebs.Data/Query/FluentQuery.Sort.cs b/src/Jeebs.Data/Query/FluentQuery.Sort.cs index 9a4f751d6..1d157c734 100644 --- a/src/Jeebs.Data/Query/FluentQuery.Sort.cs +++ b/src/Jeebs.Data/Query/FluentQuery.Sort.cs @@ -30,6 +30,6 @@ public IFluentQuery Sort(Expression> aliasSelector.GetPropertyInfo() .Match( some: x => Sort(x.Name, order), - none: this + none: () => this ); } diff --git a/src/Jeebs.Data/Query/FluentQuery.Where.cs b/src/Jeebs.Data/Query/FluentQuery.Where.cs index 6b92c1625..b705f2175 100644 --- a/src/Jeebs.Data/Query/FluentQuery.Where.cs +++ b/src/Jeebs.Data/Query/FluentQuery.Where.cs @@ -72,7 +72,7 @@ public IFluentQuery Where(Expression aliasSelector.GetPropertyInfo() .Match( some: x => Where(x.Name, compare, value), - none: this + none: () => this ); /// @@ -105,7 +105,7 @@ public IFluentQuery WhereIn(Expression WhereIn(x.Name, values), - none: this + none: () => this ); /// @@ -124,6 +124,6 @@ public IFluentQuery WhereNotIn(Expression WhereNotIn(x.Name, values), - none: this + none: () => this ); } diff --git a/src/Jeebs.Logging.Serilog.MySql/MySqlLogger.cs b/src/Jeebs.Logging.Serilog.MySql/MySqlLogger.cs index 6434a4547..7040748b3 100644 --- a/src/Jeebs.Logging.Serilog.MySql/MySqlLogger.cs +++ b/src/Jeebs.Logging.Serilog.MySql/MySqlLogger.cs @@ -40,7 +40,7 @@ public MySqlLogger(string name) => public bool IsEnabled(MySqlConnectorLogLevel level) => LevelF.ConvertToSerilogLevel(level).Match( some: Logger.IsEnabled, - none: false + none: () => false ); /// diff --git a/src/Jeebs/Config/App/AppConfig.cs b/src/Jeebs/Config/App/AppConfig.cs index 52282fd09..9808a4588 100644 --- a/src/Jeebs/Config/App/AppConfig.cs +++ b/src/Jeebs/Config/App/AppConfig.cs @@ -2,7 +2,6 @@ // Copyright (c) bfren - licensed under https://mit.bfren.dev/2013 using System; -using Jeebs.Functions; using Microsoft.Extensions.Options; namespace Jeebs.Config.App; @@ -32,7 +31,7 @@ public sealed record class AppConfig : IOptions /// otherwise simply . /// public string FullName => - StringF.Format("{0}/", Suite, string.Empty) + Name; + F.Format("{0}/", Suite, string.Empty) + Name; /// /// Application Version. diff --git a/src/Jeebs/Extensions/String/StringExtensions.FormatWith.cs b/src/Jeebs/Extensions/String/StringExtensions.FormatWith.cs index 7fcd16faf..d1d2aa515 100644 --- a/src/Jeebs/Extensions/String/StringExtensions.FormatWith.cs +++ b/src/Jeebs/Extensions/String/StringExtensions.FormatWith.cs @@ -1,13 +1,11 @@ // Jeebs Rapid Application Development // Copyright (c) bfren - licensed under https://mit.bfren.dev/2013 -using Jeebs.Functions; - namespace Jeebs; public static partial class StringExtensions { - /// + /// public static string FormatWith(this string @this, T source) => - Modify(@this, () => StringF.Format(@this, source)); + Modify(@this, () => F.Format(@this, source)); } diff --git a/src/Jeebs/Functions/String/StringF.Format.cs b/src/Jeebs/Functions/String/StringF.Format.cs deleted file mode 100644 index df886d744..000000000 --- a/src/Jeebs/Functions/String/StringF.Format.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Jeebs Rapid Application Development -// Copyright (c) bfren - licensed under https://mit.bfren.dev/2013 - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text.RegularExpressions; - -namespace Jeebs.Functions; - -public static partial class StringF -{ - /// - /// If is not null, use string.Format() - - /// otherwise, return . - /// - /// Object type. - /// Format string. - /// Object (nullable). - /// String to use when is null. - /// Formatted string. - public static string Format(string formatString, T obj, string? ifNull) => - obj switch - { - T x => - string.Format(F.DefaultCulture, formatString, x), - - _ => - ifNull ?? formatString - }; - - /// - /// Works like string.Format() but with named as well as numbered placeholders. - /// Source is Array: values will be inserted in order (regardless of placeholder values). - /// Source is Object: property names must match placeholders or they will be left in place. - /// - /// - /// Inspired by http://james.newtonking.com/archive/2008/03/29/formatwith-2-0-string-formatting-with-named-variables, - /// (significantly) altered to work without requiring DataBinder. - /// - /// Source type. - /// String to format. - /// Source object to use for template values. - /// Formatted string. - public static string Format(string formatString, T source) - { - // Return original if source is null or if it is an empty array - if (source is null) - { - return formatString; - } - else if (source is Array arr && arr.Length == 0) - { - return formatString; - } - - // Thanks James Newton-King! - var r = TemplateMatcherRegex(); - - var values = new List(); - var replaceIndex = 0; // keeps track of replace loop so we can match named template values with an array source - var rewrittenFormat = r.Replace(formatString, (m) => - { - var startGroup = m.Groups["start"]; - var templateGroup = m.Groups["template"]; - var formatGroup = m.Groups["format"]; - var endGroup = m.Groups["end"]; - - // This is the value inside the braces, e.g. "0" in "{0}" or "A" in "{A}" - // Remove any @ symbols from the start - used by Serilog to denote an object format - // but breaks the following - var template = templateGroup.Value.TrimStart('@'); - - // Switch on the source type, using variety of methods to get this template's value - var flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance; - var value = source switch - { - // Source array - get next item in array - Array arr when replaceIndex < arr.Length && arr.GetValue(replaceIndex++) is object val => - val, - - // Source object - get matching property value - { } obj when typeof(T).GetProperty(template, flags)?.GetValue(obj) is object val => - val, - - // Nothing has matched yet so to be safe put the template back - _ => - $"{{{template}}}" - }; - - values.Add(value); - - // Recreate format using zero-based string - return new string('{', startGroup.Captures.Count) - + (values.Count - 1) - + formatGroup.Value - + new string('}', endGroup.Captures.Count); - }); - - return string.Format(F.DefaultCulture, rewrittenFormat, [.. values]); - } - - [GeneratedRegex("(?\\{)+(?