From 6a854914a8a8dd26596d87a36aa3f8127c8510bc Mon Sep 17 00:00:00 2001 From: helto4real Date: Sat, 26 Dec 2020 23:33:52 +0100 Subject: [PATCH] dotnet 5 anayzer continues --- .../DaemonRunner/DaemonRunner.csproj | 6 +++ .../Config/NetDaemonConsoleThemes.cs | 34 +++++++------- .../Config/SerilogConfigurator.cs | 13 +++++- .../DaemonRunner/NetDaemonExtensions.cs | 12 +++-- .../DaemonRunner/Service/API/WsHandler.cs | 15 ++++-- .../DaemonRunner/Service/ApiService.cs | 9 +--- .../DaemonRunner/Service/App/CodeGenerator.cs | 24 ++++------ .../Service/App/DaemonAppCompiler.cs | 6 ++- .../Service/App/DaemonCompiler.cs | 46 ++++++++----------- .../DaemonRunner/Service/RunnerService.cs | 11 ++++- .../NetDaemon.Fakes/DaemonHostTestBase.cs | 13 ++---- .../FakesTests/FakeTests.cs | 2 +- 12 files changed, 104 insertions(+), 87 deletions(-) diff --git a/src/DaemonRunner/DaemonRunner/DaemonRunner.csproj b/src/DaemonRunner/DaemonRunner/DaemonRunner.csproj index 271cfec80..b33d4e45f 100644 --- a/src/DaemonRunner/DaemonRunner/DaemonRunner.csproj +++ b/src/DaemonRunner/DaemonRunner/DaemonRunner.csproj @@ -33,6 +33,10 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + @@ -42,5 +46,7 @@ ..\..\..\.linting\roslynator.ruleset + true + AllEnabledByDefault \ No newline at end of file diff --git a/src/DaemonRunner/DaemonRunner/Infrastructure/Config/NetDaemonConsoleThemes.cs b/src/DaemonRunner/DaemonRunner/Infrastructure/Config/NetDaemonConsoleThemes.cs index fc8fe7146..9c491ab7a 100644 --- a/src/DaemonRunner/DaemonRunner/Infrastructure/Config/NetDaemonConsoleThemes.cs +++ b/src/DaemonRunner/DaemonRunner/Infrastructure/Config/NetDaemonConsoleThemes.cs @@ -8,22 +8,22 @@ public static class NetDaemonConsoleThemes { private static SystemConsoleTheme SystemTheme { get; } = new(new Dictionary { - [ConsoleThemeStyle.Text] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Gray}, - [ConsoleThemeStyle.SecondaryText] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.DarkGray}, - [ConsoleThemeStyle.TertiaryText] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.DarkGray}, - [ConsoleThemeStyle.Invalid] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Yellow}, - [ConsoleThemeStyle.Null] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Green}, - [ConsoleThemeStyle.Name] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Green}, - [ConsoleThemeStyle.String] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Green}, - [ConsoleThemeStyle.Number] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Green}, - [ConsoleThemeStyle.Boolean] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Green}, - [ConsoleThemeStyle.Scalar] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Green}, - [ConsoleThemeStyle.LevelVerbose] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Gray}, - [ConsoleThemeStyle.LevelDebug] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.DarkYellow}, - [ConsoleThemeStyle.LevelInformation] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.DarkGreen}, - [ConsoleThemeStyle.LevelWarning] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Yellow}, - [ConsoleThemeStyle.LevelError] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.Red}, - [ConsoleThemeStyle.LevelFatal] = new SystemConsoleThemeStyle {Foreground = ConsoleColor.DarkRed}, + [ConsoleThemeStyle.Text] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Gray }, + [ConsoleThemeStyle.SecondaryText] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.DarkGray }, + [ConsoleThemeStyle.TertiaryText] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.DarkGray }, + [ConsoleThemeStyle.Invalid] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Yellow }, + [ConsoleThemeStyle.Null] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Green }, + [ConsoleThemeStyle.Name] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Green }, + [ConsoleThemeStyle.String] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Green }, + [ConsoleThemeStyle.Number] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Green }, + [ConsoleThemeStyle.Boolean] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Green }, + [ConsoleThemeStyle.Scalar] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Green }, + [ConsoleThemeStyle.LevelVerbose] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Gray }, + [ConsoleThemeStyle.LevelDebug] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.DarkYellow }, + [ConsoleThemeStyle.LevelInformation] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.DarkGreen }, + [ConsoleThemeStyle.LevelWarning] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Yellow }, + [ConsoleThemeStyle.LevelError] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.Red }, + [ConsoleThemeStyle.LevelFatal] = new SystemConsoleThemeStyle { Foreground = ConsoleColor.DarkRed }, }); private static AnsiConsoleTheme AnsiTheme { get; } = new(new Dictionary @@ -48,7 +48,7 @@ public static class NetDaemonConsoleThemes public static ConsoleTheme GetThemeByType(string type) { - return string.Equals(type, "system", StringComparison.InvariantCultureIgnoreCase) ? SystemTheme : AnsiTheme; + return string.Equals(type, "system", StringComparison.OrdinalIgnoreCase) ? SystemTheme : AnsiTheme; } } } \ No newline at end of file diff --git a/src/DaemonRunner/DaemonRunner/Infrastructure/Config/SerilogConfigurator.cs b/src/DaemonRunner/DaemonRunner/Infrastructure/Config/SerilogConfigurator.cs index 1a5990592..e2f42b2b6 100644 --- a/src/DaemonRunner/DaemonRunner/Infrastructure/Config/SerilogConfigurator.cs +++ b/src/DaemonRunner/DaemonRunner/Infrastructure/Config/SerilogConfigurator.cs @@ -1,6 +1,8 @@ -using System.IO; +using System.Globalization; +using System.IO; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; +using NetDaemon.Common.Exceptions; using Serilog; using Serilog.Core; using Serilog.Events; @@ -13,6 +15,11 @@ public static class SerilogConfigurator public static LoggerConfiguration Configure(LoggerConfiguration loggerConfiguration, IHostEnvironment hostingEnvironment) { + _ = loggerConfiguration ?? + throw new NetDaemonArgumentNullException(nameof(loggerConfiguration)); + _ = hostingEnvironment ?? + throw new NetDaemonArgumentNullException(nameof(hostingEnvironment)); + var loggingConfiguration = GetLoggingConfiguration(hostingEnvironment); SetMinimumLogLevel(loggingConfiguration.MinimumLevel); @@ -40,7 +47,9 @@ private static LoggingConfiguration GetLoggingConfiguration(IHostEnvironment hos public static void SetMinimumLogLevel(string level) { - LevelSwitch.MinimumLevel = level.ToLower() switch + _ = level ?? + throw new NetDaemonArgumentNullException(nameof(level)); + LevelSwitch.MinimumLevel = level.ToLower(CultureInfo.InvariantCulture) switch { "info" => LogEventLevel.Information, "debug" => LogEventLevel.Debug, diff --git a/src/DaemonRunner/DaemonRunner/NetDaemonExtensions.cs b/src/DaemonRunner/DaemonRunner/NetDaemonExtensions.cs index 2804d4300..06b64eb7c 100644 --- a/src/DaemonRunner/DaemonRunner/NetDaemonExtensions.cs +++ b/src/DaemonRunner/DaemonRunner/NetDaemonExtensions.cs @@ -12,6 +12,8 @@ using Serilog; using NetDaemon.Infrastructure.Config; using NetDaemon.Common.Exceptions; +using System.Globalization; +using System.Diagnostics.CodeAnalysis; namespace NetDaemon { @@ -21,6 +23,9 @@ public static class NetDaemonExtensions public static IHostBuilder UseNetDaemon(this IHostBuilder hostBuilder) { + _ = hostBuilder ?? + throw new NetDaemonArgumentNullException(nameof(hostBuilder)); + if (File.Exists(HassioConfigPath)) ReadHassioConfig(); @@ -70,13 +75,14 @@ private static bool UseLocalAssemblyLoading() if (string.IsNullOrEmpty(appSource)) return true; - return appSource.EndsWith(".csproj") || appSource.EndsWith(".dll"); + return appSource.EndsWith(".csproj", true, CultureInfo.InvariantCulture) + || appSource.EndsWith(".dll", true, CultureInfo.InvariantCulture); } /// /// Reads the Home Assistant (hassio) configuration file /// - /// + [SuppressMessage("", "CA1031")] private static void ReadHassioConfig() { try @@ -98,7 +104,7 @@ private static void ReadHassioConfig() _ = hassAddOnSettings?.AppSource ?? throw new NetDaemonNullReferenceException("AppSource cannot be null"); - if (hassAddOnSettings.AppSource.StartsWith("/") || hassAddOnSettings.AppSource[1] == ':') + if (hassAddOnSettings.AppSource.StartsWith("/", true, CultureInfo.InvariantCulture) || hassAddOnSettings.AppSource[1] == ':') { // Hard codede path Environment.SetEnvironmentVariable("NETDAEMON__APPSOURCE", hassAddOnSettings.AppSource); diff --git a/src/DaemonRunner/DaemonRunner/Service/API/WsHandler.cs b/src/DaemonRunner/DaemonRunner/Service/API/WsHandler.cs index 7075530be..2efa208ab 100644 --- a/src/DaemonRunner/DaemonRunner/Service/API/WsHandler.cs +++ b/src/DaemonRunner/DaemonRunner/Service/API/WsHandler.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Net.WebSockets; @@ -42,6 +43,10 @@ public class ApiWebsocketMiddleware NetDaemonHost? host = null ) { + _ = netDaemonSettings ?? + throw new NetDaemonArgumentNullException(nameof(netDaemonSettings)); + _ = homeAssistantSettings ?? + throw new NetDaemonArgumentNullException(nameof(homeAssistantSettings)); _logger = loggerFactory.CreateLogger(); _host = host; _netdaemonSettings = netDaemonSettings.Value; @@ -67,11 +72,15 @@ private async Task NewEvent(ExternalEventBase ev) LastErrorMessage = n.IsEnabled ? n.RuntimeInfo.LastErrorMessage : null }) }; - await BroadCast(JsonSerializer.Serialize(eventMessage, _jsonOptions)).ConfigureAwait(false); + await BroadCast(JsonSerializer.Serialize(eventMessage, _jsonOptions)).ConfigureAwait(false); } } + + [SuppressMessage("", "CA1031")] public async Task Invoke(HttpContext context) { + _ = context ?? + throw new NetDaemonArgumentNullException(nameof(context)); if (!context.WebSockets.IsWebSocketRequest && context.Request.Path != "/api/ws") { await _next.Invoke(context).ConfigureAwait(false); @@ -115,7 +124,7 @@ public async Task Invoke(HttpContext context) }) }; - await BroadCast(JsonSerializer.Serialize(eventMessage, _jsonOptions)).ConfigureAwait(false); + await BroadCast(JsonSerializer.Serialize(eventMessage, _jsonOptions)).ConfigureAwait(false); break; case "settings": @@ -156,7 +165,7 @@ public async Task Invoke(HttpContext context) } if (command.IsEnabled is not null) { - if (command.IsEnabled ?? false) + if (command.IsEnabled.Value) { _host?.CallService("switch", "turn_on", new { entity_id = $"switch.netdaemon_{msg.App.ToSafeHomeAssistantEntityId()}" }); } diff --git a/src/DaemonRunner/DaemonRunner/Service/ApiService.cs b/src/DaemonRunner/DaemonRunner/Service/ApiService.cs index 56263cf82..0aa37a06d 100644 --- a/src/DaemonRunner/DaemonRunner/Service/ApiService.cs +++ b/src/DaemonRunner/DaemonRunner/Service/ApiService.cs @@ -1,20 +1,15 @@ -using System.Reflection; using JoySoftware.HomeAssistant.Client; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using NetDaemon.Daemon; using NetDaemon.Daemon.Storage; -using NetDaemon.Service; using Microsoft.Extensions.Options; using System.IO; using Microsoft.Extensions.Hosting; using NetDaemon.Common; using System; -using System.Net.WebSockets; -using Microsoft.AspNetCore.WebSockets; using NetDaemon.Service.Api; using NetDaemon.Common.Configuration; @@ -22,7 +17,7 @@ namespace NetDaemon.Service { public class ApiStartup { - private readonly bool _useAdmin = false; + private readonly bool _useAdmin; public ApiStartup(IConfiguration configuration) { @@ -42,7 +37,7 @@ public static void ConfigureServices(IServiceCollection services) Path.Combine( n.GetRequiredService>().Value.GetAppSourceDirectory() , ".storage"))); - services.AddTransient(); + services.AddTransient(); services.AddSingleton(); services.AddHttpClient(); } diff --git a/src/DaemonRunner/DaemonRunner/Service/App/CodeGenerator.cs b/src/DaemonRunner/DaemonRunner/Service/App/CodeGenerator.cs index ba0ef1c24..149e641ee 100644 --- a/src/DaemonRunner/DaemonRunner/Service/App/CodeGenerator.cs +++ b/src/DaemonRunner/DaemonRunner/Service/App/CodeGenerator.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; using JoySoftware.HomeAssistant.Client; @@ -30,9 +31,6 @@ public static class CodeGenerator ["camera"] = ("Camera", "ICamera"), ["media_player"] = ("MediaPlayer", "IMediaPlayer"), ["automation"] = ("Entity", "IEntity"), - // ["input_boolean"], - // ["remote"], - // ["climate"], }; public static string? GenerateCode(string nameSpace, IEnumerable entities) @@ -41,7 +39,7 @@ public static class CodeGenerator // Add Usings statements code = code.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(typeof(NetDaemonApp).Namespace!))); - code = code.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(typeof(NetDaemon.Common.Fluent.IMediaPlayer).Namespace!))); + code = code.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(typeof(Common.Fluent.IMediaPlayer).Namespace!))); // Add namespace var namespaceDeclaration = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(nameSpace)).NormalizeWhitespace(); @@ -53,9 +51,7 @@ public static class CodeGenerator SyntaxFactory.Token(SyntaxKind.StaticKeyword), SyntaxFactory.Token(SyntaxKind.PartialKeyword)); // Get all available domains, this is used to create the extensionmethods - var domains = GetDomainsFromEntities(entities); - - foreach (var domain in domains) + foreach (var domain in GetDomainsFromEntities(entities)) { if (_FluentApiMapper.ContainsKey(domain)) { @@ -85,10 +81,10 @@ public static class CodeGenerator }}"; var entityClass = CSharpSyntaxTree.ParseText(classDeclaration).GetRoot().ChildNodes().OfType().FirstOrDefault() ?? throw new NetDaemonNullReferenceException($"Parse class {nameof(NetDaemonApp)} failed"); - foreach (var entity in entities.Where(n => n.StartsWith(domain))) + foreach (var entity in entities.Where(n => n.StartsWith(domain, true, CultureInfo.InvariantCulture))) { var (fluent, fluentInterface) = _FluentApiMapper[domain]; - var name = entity[(entity.IndexOf(".") + 1)..]; + var name = entity[(entity.IndexOf(".", StringComparison.InvariantCultureIgnoreCase) + 1)..]; // Quick check to make sure the name is a valid C# identifier. Should really check to make // sure it doesn't collide with a reserved keyword as well. if (!char.IsLetter(name[0]) && (name[0] != '_')) @@ -121,7 +117,7 @@ public static class CodeGenerator code = code.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Linq"))); code = code.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(typeof(NetDaemonApp).Namespace!))); code = code.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(typeof(NetDaemonRxApp).Namespace!))); - code = code.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(typeof(NetDaemon.Common.Fluent.FluentExpandoObject).Namespace!))); + code = code.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(typeof(Common.Fluent.FluentExpandoObject).Namespace!))); // Add namespace var namespaceDeclaration = SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(nameSpace)).NormalizeWhitespace(); @@ -183,7 +179,7 @@ public static class CodeGenerator if (s.Service is null) continue; - var name = s.Service[(s.Service.IndexOf(".") + 1)..]; + var name = s.Service[(s.Service.IndexOf(".", StringComparison.InvariantCultureIgnoreCase) + 1)..]; if (Array.IndexOf(skipServices, name) >= 0) continue; @@ -236,9 +232,9 @@ public static class CodeGenerator }}"; var entityClass = CSharpSyntaxTree.ParseText(classDeclaration).GetRoot().ChildNodes().OfType().FirstOrDefault() ?? throw new NetDaemonNullReferenceException("Failed to parse entity class"); - foreach (var entity in entities.Where(n => n.StartsWith(domain))) + foreach (var entity in entities.Where(n => n.StartsWith(domain, StringComparison.InvariantCultureIgnoreCase))) { - var name = entity[(entity.IndexOf(".") + 1)..]; + var name = entity[(entity.IndexOf(".", StringComparison.InvariantCultureIgnoreCase) + 1)..]; // Quick check to make sure the name is a valid C# identifier. Should really check to make // sure it doesn't collide with a reserved keyword as well. if (!char.IsLetter(name[0]) && (name[0] != '_')) @@ -264,6 +260,6 @@ public static class CodeGenerator /// /// A list of entities internal static IEnumerable GetDomainsFromEntities(IEnumerable entities) => - entities.Select(n => n[0..n.IndexOf(".")]).Distinct(); + entities.Select(n => n[0..n.IndexOf(".", StringComparison.InvariantCultureIgnoreCase)]).Distinct(); } } \ No newline at end of file diff --git a/src/DaemonRunner/DaemonRunner/Service/App/DaemonAppCompiler.cs b/src/DaemonRunner/DaemonRunner/Service/App/DaemonAppCompiler.cs index 2cdb5d7da..175a27731 100644 --- a/src/DaemonRunner/DaemonRunner/Service/App/DaemonAppCompiler.cs +++ b/src/DaemonRunner/DaemonRunner/Service/App/DaemonAppCompiler.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Reflection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using NetDaemon.Common; using NetDaemon.Common.Configuration; +using NetDaemon.Common.Exceptions; using NetDaemon.Infrastructure.Extensions; namespace NetDaemon.Service.App @@ -15,9 +15,11 @@ public class DaemonAppCompiler : IDaemonAppCompiler { private readonly ILogger _logger; - private readonly string? _sourceFolder = null; + private readonly string? _sourceFolder; public DaemonAppCompiler(ILogger logger, IOptions netDaemonSettings) { + _ = netDaemonSettings ?? + throw new NetDaemonArgumentNullException(nameof(netDaemonSettings)); _logger = logger; NetDaemonSettings = netDaemonSettings; _sourceFolder = netDaemonSettings.Value.GetAppSourceDirectory(); diff --git a/src/DaemonRunner/DaemonRunner/Service/App/DaemonCompiler.cs b/src/DaemonRunner/DaemonRunner/Service/App/DaemonCompiler.cs index b2d3ae958..df7180e85 100644 --- a/src/DaemonRunner/DaemonRunner/Service/App/DaemonCompiler.cs +++ b/src/DaemonRunner/DaemonRunner/Service/App/DaemonCompiler.cs @@ -27,7 +27,7 @@ public CollectibleAssemblyLoadContext() : base(isCollectible: true) { } - protected override Assembly? Load(AssemblyName _) => null; + protected override Assembly? Load(AssemblyName assemblyName) => null; } /// @@ -108,16 +108,12 @@ private static List LoadSyntaxTree(string codeFolder) var result = new List(50); // Get the paths for all .cs files recursively in app folder - var csFiles = Directory.EnumerateFiles(codeFolder, "*.cs", SearchOption.AllDirectories); - - foreach (var csFile in csFiles) - { - using var fs = new FileStream(csFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - var sourceText = SourceText.From(fs, encoding: Encoding.UTF8, canBeEmbedded: true); - var syntaxTree = SyntaxFactory.ParseSyntaxTree(sourceText, path: csFile); - result.Add(syntaxTree); - } - + IEnumerable? csFiles = Directory.EnumerateFiles(codeFolder, "*.cs", SearchOption.AllDirectories); + result.AddRange(from csFile in csFiles + let fs = new FileStream(csFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + let sourceText = SourceText.From(fs, encoding: Encoding.UTF8, canBeEmbedded: true) + let syntaxTree = SyntaxFactory.ParseSyntaxTree(sourceText, path: csFile) + select syntaxTree); return result; } @@ -129,7 +125,7 @@ public static IEnumerable GetDefaultReferences() MetadataReference.CreateFromFile(typeof(System.Text.RegularExpressions.Regex).Assembly.Location), MetadataReference.CreateFromFile(typeof(Console).Assembly.Location), MetadataReference.CreateFromFile(typeof(System.ComponentModel.DataAnnotations.DisplayAttribute).Assembly.Location), - MetadataReference.CreateFromFile(typeof(System.Linq.Enumerable).Assembly.Location), + MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location), MetadataReference.CreateFromFile(typeof(System.ComponentModel.INotifyPropertyChanged).Assembly.Location), MetadataReference.CreateFromFile(typeof(System.Linq.Expressions.DynamicExpression).Assembly.Location), MetadataReference.CreateFromFile(typeof(Microsoft.Extensions.Logging.Abstractions.NullLogger).Assembly.Location), @@ -143,8 +139,7 @@ public static IEnumerable GetDefaultReferences() MetadataReference.CreateFromFile(typeof(System.Reactive.Linq.Observable).Assembly.Location), }; - var assembliesFromCurrentAppDomain = AppDomain.CurrentDomain.GetAssemblies(); - foreach (var assembly in assembliesFromCurrentAppDomain) + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (!assembly.IsDynamic && !string.IsNullOrEmpty(assembly.Location)) metaDataReference.Add(MetadataReference.CreateFromFile(assembly.Location)); @@ -209,9 +204,7 @@ private static void InterceptAppInfo(SyntaxTree syntaxTree, CSharpCompilation co { var semModel = compilation.GetSemanticModel(syntaxTree); - var classDeclarationExpressions = syntaxTree.GetRoot().DescendantNodes().OfType(); - - foreach (var classDeclaration in classDeclarationExpressions) + foreach (var classDeclaration in syntaxTree.GetRoot().DescendantNodes().OfType()) { var symbol = semModel?.GetDeclaredSymbol(classDeclaration); @@ -274,8 +267,8 @@ private static void WarnIfExecuteIsMissing(SyntaxTree syntaxTree, CSharpCompilat if (symbol is null) continue; - if (string.IsNullOrEmpty(symbol?.Name) || - !ExecuteWarningOnInvocationNames.Contains(symbol?.Name)) + if (string.IsNullOrEmpty(symbol.Name) || + !ExecuteWarningOnInvocationNames.Contains(symbol.Name)) { // The invocation name is empty or not in list of invocations // that needs to be closed with Execute or ExecuteAsync @@ -285,7 +278,7 @@ private static void WarnIfExecuteIsMissing(SyntaxTree syntaxTree, CSharpCompilat // Now find top invocation to match whole expression InvocationExpressionSyntax topInvocationExpression = invocationExpression; - if (symbol is not null && symbol.ContainingType.Name == "NetDaemonApp") + if (symbol.ContainingType.Name == "NetDaemonApp") { var disableLogging = false; @@ -295,12 +288,9 @@ private static void WarnIfExecuteIsMissing(SyntaxTree syntaxTree, CSharpCompilat while (parentInvocationExpression is not null) { - if (parentInvocationExpression is MethodDeclarationSyntax methodDeclarationSyntax) + if (parentInvocationExpression is MethodDeclarationSyntax methodDeclarationSyntax && ExpressionContainsDisableLogging(methodDeclarationSyntax)) { - if (ExpressionContainsDisableLogging(methodDeclarationSyntax)) - { - disableLogging = true; - } + disableLogging = true; } if (parentInvocationExpression is InvocationExpressionSyntax invocationExpressionSyntax) { @@ -330,7 +320,8 @@ private static void WarnIfExecuteIsMissing(SyntaxTree syntaxTree, CSharpCompilat private static bool ExpressionContainsDisableLogging(MethodDeclarationSyntax methodInvocationExpression) { var invocationString = methodInvocationExpression.ToFullString(); - return invocationString.Contains("[DisableLog") && invocationString.Contains("SupressLogType.MissingExecute"); + return invocationString.Contains("[DisableLog", StringComparison.InvariantCultureIgnoreCase) + && invocationString.Contains("SupressLogType.MissingExecute", StringComparison.InvariantCultureIgnoreCase); } // Todo: Refactor using something smarter than string match. In the future use Roslyn @@ -338,7 +329,8 @@ private static bool ExpressionContainsExecuteInvocations(InvocationExpressionSyn { var invocationString = invocation.ToFullString(); - return invocationString.Contains("ExecuteAsync()") || invocationString.Contains("Execute()"); + return invocationString.Contains("ExecuteAsync()", StringComparison.InvariantCultureIgnoreCase) + || invocationString.Contains("Execute()", StringComparison.InvariantCultureIgnoreCase); } } } \ No newline at end of file diff --git a/src/DaemonRunner/DaemonRunner/Service/RunnerService.cs b/src/DaemonRunner/DaemonRunner/Service/RunnerService.cs index c32fd3ae7..6b17fb3fc 100644 --- a/src/DaemonRunner/DaemonRunner/Service/RunnerService.cs +++ b/src/DaemonRunner/DaemonRunner/Service/RunnerService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Threading; @@ -36,9 +37,9 @@ public class RunnerService : BackgroundService private bool _entitiesGenerated; private IEnumerable? _loadedDaemonApps; - private string? _sourcePath = null; + private string? _sourcePath; - private bool _hasConnectedBefore = false; + private bool _hasConnectedBefore; public RunnerService( ILoggerFactory loggerFactory, @@ -49,6 +50,10 @@ public class RunnerService : BackgroundService IDaemonAppCompiler daemonAppCompiler ) { + _ = homeAssistantSettings ?? + throw new NetDaemonArgumentNullException(nameof(homeAssistantSettings)); + _ = netDaemonSettings ?? + throw new NetDaemonArgumentNullException(nameof(netDaemonSettings)); _logger = loggerFactory.CreateLogger(); _homeAssistantSettings = homeAssistantSettings.Value; _netDaemonSettings = netDaemonSettings.Value; @@ -63,6 +68,7 @@ public override async Task StopAsync(CancellationToken cancellationToken) await base.StopAsync(cancellationToken).ConfigureAwait(false); } + [SuppressMessage("", "CA1031")] protected override async Task ExecuteAsync(CancellationToken stoppingToken) { try @@ -105,6 +111,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) _logger.LogInformation("NetDaemon service exited!"); } + [SuppressMessage("", "CA1031")] private async Task Run(NetDaemonHost daemonHost, CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) diff --git a/src/Fakes/NetDaemon.Fakes/DaemonHostTestBase.cs b/src/Fakes/NetDaemon.Fakes/DaemonHostTestBase.cs index 0747678cc..48439367b 100644 --- a/src/Fakes/NetDaemon.Fakes/DaemonHostTestBase.cs +++ b/src/Fakes/NetDaemon.Fakes/DaemonHostTestBase.cs @@ -18,7 +18,7 @@ namespace NetDaemon.Daemon.Fakes /// /// Base class for test classes /// - public partial class DaemonHostTestBase : IAsyncLifetime + public class DaemonHostTestBase : IAsyncLifetime { private Task? _fakeConnectedDaemon; @@ -77,8 +77,7 @@ public Task DisposeAsync() /// The object to turn into dynamic public static dynamic GetDynamicDataObject(string testData = "testdata") { - var expandoObject = new ExpandoObject(); - dynamic dynamicData = expandoObject; + dynamic dynamicData = new ExpandoObject(); dynamicData.Test = testData; return dynamicData; } @@ -123,14 +122,12 @@ public void SetEntityState(HassState state) /// Area of entity public void SetEntityState(string entityId, dynamic? state = null, string? area = null) { - var entity = new EntityState + DefaultDaemonHost.InternalState[entityId] = new EntityState { EntityId = entityId, Area = area, State = state }; - - DefaultDaemonHost.InternalState[entityId] = entity; } /// @@ -355,7 +352,7 @@ public void VerifySetStateTimes(string entityId, Times times) /// /// Timeout (ms) of how long fake daemon will stay connected and process events /// True if running debug mode should not cancel on timeout - protected async Task InitializeFakeDaemon(short timeout = 300, bool overrideDebugNotCancel = false) + protected async Task InitializeFakeDaemon(short timeout = 50, bool overrideDebugNotCancel = false) { _fakeConnectedDaemon = await GetConnectedNetDaemonTask(timeout, overrideDebugNotCancel).ConfigureAwait(false); } @@ -363,7 +360,6 @@ protected async Task InitializeFakeDaemon(short timeout = 300, bool overrideDebu /// /// Runs the fake daemon service until timed out /// - /// protected async Task RunFakeDaemonUntilTimeout() { _ = _fakeConnectedDaemon ?? @@ -377,7 +373,6 @@ protected async Task RunFakeDaemonUntilTimeout() /// /// Timeout in milliseconds /// True to use timeout while debugging - /// private async Task GetConnectedNetDaemonTask(short milliSeconds = 100, bool overrideDebugNotCancel = false) { var cancelSource = Debugger.IsAttached && !overrideDebugNotCancel diff --git a/tests/NetDaemon.Daemon.Tests/FakesTests/FakeTests.cs b/tests/NetDaemon.Daemon.Tests/FakesTests/FakeTests.cs index 908177974..557581086 100644 --- a/tests/NetDaemon.Daemon.Tests/FakesTests/FakeTests.cs +++ b/tests/NetDaemon.Daemon.Tests/FakesTests/FakeTests.cs @@ -357,7 +357,7 @@ public async Task UsingEntityNewEventShouldNotCallFunction() [Fact] public async Task WhenStateStaysSameForTimeItShouldCallFunction() { - await InitializeFakeDaemon().ConfigureAwait(false); + await InitializeFakeDaemon(100).ConfigureAwait(false); bool isRun = false; using var ctx = DefaultDaemonRxApp.StateChanges