diff --git a/bench/Libraries/Microsoft.Extensions.Telemetry.PerformanceTests/ModernCodeGen.cs b/bench/Libraries/Microsoft.Extensions.Telemetry.PerformanceTests/ModernCodeGen.cs index ee131405b0e..1d02fa9bfd9 100644 --- a/bench/Libraries/Microsoft.Extensions.Telemetry.PerformanceTests/ModernCodeGen.cs +++ b/bench/Libraries/Microsoft.Extensions.Telemetry.PerformanceTests/ModernCodeGen.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Globalization; + namespace Microsoft.Extensions.Telemetry.Bench; [global::System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Emulating generated code")] @@ -35,7 +37,7 @@ public static void RefTypes(global::Microsoft.Extensions.Logging.ILogger logger, var length = s.TagArray[3].Value ?? "(null)"; var flags = s.TagArray[2].Value ?? "(null)"; var other = s.TagArray[1].Value ?? "(null)"; - return global::System.FormattableString.Invariant($"Connection id '{connectionId}' received {type} frame for stream ID {streamId} with length {length} and flags {flags} and {other}"); + return string.Create(CultureInfo.InvariantCulture, $"Connection id '{connectionId}' received {type} frame for stream ID {streamId} with length {length} and flags {flags} and {other}"); }); state.Clear(); @@ -66,7 +68,7 @@ public static void ValueTypes(global::Microsoft.Extensions.Logging.ILogger logge var end = s.TagArray[3].Value; var options = s.TagArray[2].Value; var guid = s.TagArray[1].Value; - return global::System.FormattableString.Invariant($"Range [{start}..{end}], options {options}, guid {guid}"); + return string.Create(CultureInfo.InvariantCulture, $"Range [{start}..{end}], options {options}, guid {guid}"); }); state.Clear(); diff --git a/eng/Tools/.editorconfig b/eng/Tools/.editorconfig index 8b26ad2938d..3114fb9c808 100644 --- a/eng/Tools/.editorconfig +++ b/eng/Tools/.editorconfig @@ -2931,7 +2931,7 @@ dotnet_diagnostic.S1067.severity = warning # Title : Methods should not have too many parameters # Category : Major Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-107 -dotnet_diagnostic.S107.severity = warning +dotnet_diagnostic.S107.severity = none # Title : URIs should not be hardcoded # Category : Minor Code Smell @@ -3964,7 +3964,7 @@ dotnet_diagnostic.S3246.severity = warning # Title : Duplicate casts should not be made # Category : Minor Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-3247 -dotnet_diagnostic.S3247.severity = warning +dotnet_diagnostic.S3247.severity = none # Title : Classes directly extending "object" should not call "base" in "GetHashCode" or "Equals" # Category : Major Bug @@ -5084,7 +5084,7 @@ dotnet_diagnostic.S6585.severity = none # Title : Use the "UnixEpoch" field instead of creating "DateTime" instances that point to the beginning of the Unix epoch # Category : Minor Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-6588 -dotnet_diagnostic.S6588.severity = warning +dotnet_diagnostic.S6588.severity = none # Title : "Find" method should be used instead of the "FirstOrDefault" extension # Category : Minor Code Smell @@ -5146,6 +5146,21 @@ dotnet_diagnostic.S6618.severity = none # Help Link: https://rules.sonarsource.com/csharp/RSPEC-6640 dotnet_diagnostic.S6640.severity = warning +# Title : Generic logger injection should match enclosing type +# Category : Minor Code Smell +# Help Link: https://rules.sonarsource.com/csharp/RSPEC-6672 +dotnet_diagnostic.S6672.severity = none + +# Title : Awaitable method should be used +# Category : Code Smell +# Help Link: https://rules.sonarsource.com/csharp/RSPEC-6966 +dotnet_diagnostic.S6966.severity = none + +# Title : ModelState.IsValid should be called in controller actions +# Category : Code Smell +# Help Link: https://rules.sonarsource.com/csharp/RSPEC-6967 +dotnet_diagnostic.S6967.severity = none + # Title : Literal suffixes should be upper case # Category : Minor Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-818 diff --git a/eng/packages/General.props b/eng/packages/General.props index 4dafd30a2fa..44dc26c7c0e 100644 --- a/eng/packages/General.props +++ b/eng/packages/General.props @@ -46,7 +46,7 @@ - + diff --git a/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/AssemblyAnalysis.cs b/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/AssemblyAnalysis.cs index b29e34e2af0..94958d722ab 100644 --- a/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/AssemblyAnalysis.cs +++ b/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/AssemblyAnalysis.cs @@ -130,7 +130,7 @@ public void AnalyzeType(INamedTypeSymbol type) { var typeSignature = type.ToDisplayString(_format); var typeModifiersAndName = PrependModifiers(typeSignature, type); - var typeDef = Assembly.Types.FirstOrDefault(x => x.ModifiersAndName == typeModifiersAndName); + var typeDef = Array.Find(Assembly.Types, x => x.ModifiersAndName == typeModifiersAndName); if (typeDef == null) { @@ -218,7 +218,7 @@ and not MethodKind.EventAdd { var methodSignature = member.ToDisplayString(_formatNoVariance) + ";"; - var method = typeDef.Methods.FirstOrDefault(x => x.Member == methodSignature); + var method = Array.Find(typeDef.Methods, x => x.Member == methodSignature); if (method != null) { _ = MissingMethods.Remove(method); @@ -233,7 +233,7 @@ and not MethodKind.EventAdd { var propSignature = member.ToDisplayString(_formatNoVariance); - var prop = typeDef.Properties.FirstOrDefault(x => x.Member == propSignature); + var prop = Array.Find(typeDef.Properties, x => x.Member == propSignature); if (prop != null) { _ = MissingProperties.Remove(prop); @@ -255,7 +255,7 @@ and not MethodKind.EventAdd fieldSignature = "const " + t.ToDisplayString(_enumType) + " " + fieldSignature; } - var field = typeDef.Fields.FirstOrDefault(x => x.Member == fieldSignature); + var field = Array.Find(typeDef.Fields, x => x.Member == fieldSignature); if (field != null) { _ = MissingFields.Remove(field); diff --git a/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/Json/JsonObject.cs b/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/Json/JsonObject.cs index 54bc365173b..69fe95bd608 100644 --- a/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/Json/JsonObject.cs +++ b/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/Json/JsonObject.cs @@ -173,7 +173,7 @@ public KeyValuePair[] Keys } } - [DebuggerDisplay("{value.ToString(),nq}", Name = "{key}", Type = "JsonValue({Type})")] + [DebuggerDisplay("{_value,nq}", Name = "{_key}")] public sealed class KeyValuePair { [DebuggerBrowsable(DebuggerBrowsableState.Never)] diff --git a/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/Json/JsonValue.cs b/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/Json/JsonValue.cs index 93aa01236d5..ae2429be76d 100644 --- a/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/Json/JsonValue.cs +++ b/src/Analyzers/Microsoft.Analyzers.Local/ApiLifecycle/Json/JsonValue.cs @@ -270,7 +270,7 @@ public int AsInteger /// Gets this value as a system.DateTime. /// /// This value as a system.DateTime. - public DateTime? AsDateTime => IsString && DateTime.TryParse((string?)_reference ?? string.Empty, out var value) + public DateTime? AsDateTime => IsString && DateTime.TryParse((string?)_reference ?? string.Empty, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out var value) ? value : null; diff --git a/src/Generators/Microsoft.Gen.Logging/Parsing/Parser.cs b/src/Generators/Microsoft.Gen.Logging/Parsing/Parser.cs index ab4604ca1de..94996b7b1b3 100644 --- a/src/Generators/Microsoft.Gen.Logging/Parsing/Parser.cs +++ b/src/Generators/Microsoft.Gen.Logging/Parsing/Parser.cs @@ -251,7 +251,7 @@ public IReadOnlyList GetLogTypes(IEnumerable if (keepMethod && string.IsNullOrWhiteSpace(lm.Message) && !lm.EventId.HasValue && - lm.Parameters.All(x => x.IsLogger || x.IsLogLevel)) + lm.Parameters.TrueForAll(static x => x.IsLogger || x.IsLogLevel)) { if (!_failedMethod) { diff --git a/src/Generators/Shared/DiagDescriptorsBase.cs b/src/Generators/Shared/DiagDescriptorsBase.cs index ece15b7a446..12474c33dac 100644 --- a/src/Generators/Shared/DiagDescriptorsBase.cs +++ b/src/Generators/Shared/DiagDescriptorsBase.cs @@ -32,9 +32,7 @@ protected static DiagnosticDescriptor Make( category, defaultSeverity, isEnabledByDefault, - null, - string.Format(DiagnosticIds.UrlFormat, id), - Array.Empty()); + helpLinkUri: string.Format(DiagnosticIds.UrlFormat, id)); #pragma warning restore CS0436 // Type conflicts with imported type #pragma warning restore CA1863 // Use 'CompositeFormat' #pragma warning restore CA1305 // Specify IFormatProvider diff --git a/src/Libraries/.editorconfig b/src/Libraries/.editorconfig index e6feaee1f0f..e7f721ab42b 100644 --- a/src/Libraries/.editorconfig +++ b/src/Libraries/.editorconfig @@ -2968,7 +2968,7 @@ dotnet_diagnostic.S1067.severity = suggestion # Title : Methods should not have too many parameters # Category : Major Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-107 -dotnet_diagnostic.S107.severity = suggestion +dotnet_diagnostic.S107.severity = none # Title : URIs should not be hardcoded # Category : Minor Code Smell @@ -4001,7 +4001,7 @@ dotnet_diagnostic.S3246.severity = warning # Title : Duplicate casts should not be made # Category : Minor Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-3247 -dotnet_diagnostic.S3247.severity = warning +dotnet_diagnostic.S3247.severity = none # Title : Classes directly extending "object" should not call "base" in "GetHashCode" or "Equals" # Category : Major Bug @@ -5121,7 +5121,7 @@ dotnet_diagnostic.S6585.severity = none # Title : Use the "UnixEpoch" field instead of creating "DateTime" instances that point to the beginning of the Unix epoch # Category : Minor Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-6588 -dotnet_diagnostic.S6588.severity = warning +dotnet_diagnostic.S6588.severity = none # Title : "Find" method should be used instead of the "FirstOrDefault" extension # Category : Minor Code Smell @@ -5183,6 +5183,21 @@ dotnet_diagnostic.S6618.severity = warning # Help Link: https://rules.sonarsource.com/csharp/RSPEC-6640 dotnet_diagnostic.S6640.severity = warning +# Title : Generic logger injection should match enclosing type +# Category : Minor Code Smell +# Help Link: https://rules.sonarsource.com/csharp/RSPEC-6672 +dotnet_diagnostic.S6672.severity = none + +# Title : Awaitable method should be used +# Category : Code Smell +# Help Link: https://rules.sonarsource.com/csharp/RSPEC-6966 +dotnet_diagnostic.S6966.severity = none + +# Title : ModelState.IsValid should be called in controller actions +# Category : Code Smell +# Help Link: https://rules.sonarsource.com/csharp/RSPEC-6967 +dotnet_diagnostic.S6967.severity = none + # Title : Literal suffixes should be upper case # Category : Minor Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-818 diff --git a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/CleanCacheCommand.cs b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/CleanCacheCommand.cs index a3224e411cd..65c2ebe2ba4 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/CleanCacheCommand.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/CleanCacheCommand.cs @@ -37,7 +37,7 @@ await logger.ExecuteWithCatchAsync( if (storageRootDir is not null) { string storageRootPath = storageRootDir.FullName; - logger.LogInformation("Storage root path: {storageRootPath}", storageRootPath); + logger.LogInformation("Storage root path: {StorageRootPath}", storageRootPath); logger.LogInformation("Deleting expired cache entries..."); cacheProvider = new DiskBasedResponseCacheProvider(storageRootPath); @@ -46,7 +46,7 @@ await logger.ExecuteWithCatchAsync( } else if (endpointUri is not null) { - logger.LogInformation("Azure Storage endpoint: {endpointUri}", endpointUri); + logger.LogInformation("Azure Storage endpoint: {EndpointUri}", endpointUri); var fsClient = new DataLakeDirectoryClient(endpointUri, new DefaultAzureCredential()); cacheProvider = new AzureStorageResponseCacheProvider(fsClient); diff --git a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/CleanResultsCommand.cs b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/CleanResultsCommand.cs index ec5a8805424..008e5f69dff 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/CleanResultsCommand.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/CleanResultsCommand.cs @@ -42,7 +42,7 @@ await logger.ExecuteWithCatchAsync( if (storageRootDir is not null) { string storageRootPath = storageRootDir.FullName; - logger.LogInformation("Storage root path: {storageRootPath}", storageRootPath); + logger.LogInformation("Storage root path: {StorageRootPath}", storageRootPath); resultStore = new DiskBasedResultStore(storageRootPath); @@ -50,7 +50,7 @@ await logger.ExecuteWithCatchAsync( } else if (endpointUri is not null) { - logger.LogInformation("Azure Storage endpoint: {endpointUri}", endpointUri); + logger.LogInformation("Azure Storage endpoint: {EndpointUri}", endpointUri); var fsClient = new DataLakeDirectoryClient(endpointUri, new DefaultAzureCredential()); resultStore = new AzureStorageResultStore(fsClient); @@ -72,7 +72,7 @@ await resultStore.DeleteResultsAsync( else { logger.LogInformation( - "Deleting all results except the {lastN} most recent ones...", + "Deleting all results except the {LastN} most recent ones...", lastN); HashSet toPreserve = []; diff --git a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/ReportCommand.cs b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/ReportCommand.cs index cf2242eaac6..8e038ad5ae9 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/ReportCommand.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Commands/ReportCommand.cs @@ -52,7 +52,7 @@ await logger.ExecuteWithCatchAsync( if (storageRootDir is not null) { string storageRootPath = storageRootDir.FullName; - logger.LogInformation("Storage root path: {storageRootPath}", storageRootPath); + logger.LogInformation("Storage root path: {StorageRootPath}", storageRootPath); resultStore = new DiskBasedResultStore(storageRootPath); @@ -60,7 +60,7 @@ await logger.ExecuteWithCatchAsync( } else if (endpointUri is not null) { - logger.LogInformation("Azure Storage endpoint: {endpointUri}", endpointUri); + logger.LogInformation("Azure Storage endpoint: {EndpointUri}", endpointUri); var fsClient = new DataLakeDirectoryClient(endpointUri, new DefaultAzureCredential()); resultStore = new AzureStorageResultStore(fsClient); @@ -107,7 +107,7 @@ await logger.ExecuteWithCatchAsync( results.Add(result); logger.LogInformation( - "Execution: {executionName} Scenario: {scenarioName} Iteration: {iterationName}", + "Execution: {ExecutionName} Scenario: {ScenarioName} Iteration: {IterationName}", result.ExecutionName, result.ScenarioName, result.IterationName); @@ -131,7 +131,7 @@ await logger.ExecuteWithCatchAsync( }; await reportWriter.WriteReportAsync(results, cancellationToken).ConfigureAwait(false); - logger.LogInformation("Report: {outputFilePath} [{format}]", outputFilePath, format); + logger.LogInformation("Report: {OutputFilePath} [{Format}]", outputFilePath, format); // See the following issues for reasoning behind this check. We want to avoid opening the // report if this process is running as a service or in a CI pipeline. diff --git a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Telemetry/EnvironmentHelper.cs b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Telemetry/EnvironmentHelper.cs index 28942cb4eb1..af5717d1c54 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Telemetry/EnvironmentHelper.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Telemetry/EnvironmentHelper.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Linq; namespace Microsoft.Extensions.AI.Evaluation.Console.Telemetry; @@ -54,7 +53,7 @@ public static bool IsCIEnvironment() foreach (string[] variables in _mustNotBeNullCIVariables) { - if (variables.All(variable => !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(variable)))) + if (Array.TrueForAll(variables, static variable => !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(variable)))) { return true; } diff --git a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Telemetry/TelemetryHelper.cs b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Telemetry/TelemetryHelper.cs index f72822e150b..cc8a072100d 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Telemetry/TelemetryHelper.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Evaluation.Console/Telemetry/TelemetryHelper.cs @@ -113,7 +113,7 @@ internal void ReportEvent( } catch (Exception ex) { - _logger.LogWarning(ex, $"Failed to report event '{eventName}' in telemetry."); + _logger.LogWarning(ex, "Failed to report event '{EventName}' in telemetry.", eventName); } } diff --git a/src/Libraries/Microsoft.Extensions.AI.Evaluation/CompositeEvaluator.cs b/src/Libraries/Microsoft.Extensions.AI.Evaluation/CompositeEvaluator.cs index 07e2636d7f9..301dc4a0cf4 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Evaluation/CompositeEvaluator.cs +++ b/src/Libraries/Microsoft.Extensions.AI.Evaluation/CompositeEvaluator.cs @@ -163,6 +163,6 @@ async ValueTask EvaluateAsync(IEvaluator e) } IEnumerable> concurrentTasks = _evaluators.Select(EvaluateAsync); - return concurrentTasks.StreamResultsAsync(preserveOrder: false, cancellationToken); + return concurrentTasks.StreamResultsAsync(cancellationToken: cancellationToken); } } diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIChatExtensions.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIChatExtensions.cs index 40009005cb6..39556246e8b 100644 --- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIChatExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIChatExtensions.cs @@ -112,7 +112,7 @@ static IEnumerable ConvertAnnotations(IEnumerable AsOpenAIStre var toolCallUpdates = update.Contents.OfType().Select((fcc, index) => OpenAIChatModelFactory.StreamingChatToolCallUpdate( - index, fcc.CallId, ChatToolCallKind.Function, fcc.Name, - new(JsonSerializer.SerializeToUtf8Bytes(fcc.Arguments, AIJsonUtilities.DefaultOptions.GetTypeInfo(typeof(IDictionary)))))) + index, + fcc.CallId, + functionName: fcc.Name, + functionArgumentsUpdate: new(JsonSerializer.SerializeToUtf8Bytes(fcc.Arguments, AIJsonUtilities.DefaultOptions.GetTypeInfo(typeof(IDictionary)))))) .ToList(); yield return OpenAIChatModelFactory.StreamingChatCompletionUpdate( diff --git a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs index b8a09e59e4f..74f9bf554fa 100644 --- a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs +++ b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs @@ -751,7 +751,7 @@ private static (Dictionary? ToolMap, bool AnyRequireApproval) Cr /// Gets whether contains any or instances. /// private static bool HasAnyApprovalContent(List messages) => - messages.Any(static m => m.Contents.Any(static c => c is FunctionApprovalRequestContent or FunctionApprovalResponseContent)); + messages.Exists(static m => m.Contents.Any(static c => c is FunctionApprovalRequestContent or FunctionApprovalResponseContent)); /// Copies any from to . private static bool CopyFunctionCalls( @@ -925,7 +925,7 @@ select ProcessFunctionCallAsync( messages, options, toolMap, functionCallContents, iteration, callIndex, captureExceptions: true, isStreaming, cancellationToken))); - shouldTerminate = results.Any(r => r.Terminate); + shouldTerminate = results.Exists(static r => r.Terminate); } else { diff --git a/src/Libraries/Microsoft.Extensions.DataIngestion.Abstractions/Microsoft.Extensions.DataIngestion.Abstractions.csproj b/src/Libraries/Microsoft.Extensions.DataIngestion.Abstractions/Microsoft.Extensions.DataIngestion.Abstractions.csproj index f3f16874b4c..e22de778e06 100644 --- a/src/Libraries/Microsoft.Extensions.DataIngestion.Abstractions/Microsoft.Extensions.DataIngestion.Abstractions.csproj +++ b/src/Libraries/Microsoft.Extensions.DataIngestion.Abstractions/Microsoft.Extensions.DataIngestion.Abstractions.csproj @@ -12,7 +12,7 @@ 75 75 - $(NoWarn);S1694 + $(NoWarn);S1694;S2368 diff --git a/src/Libraries/Microsoft.Extensions.DataIngestion.MarkItDown/MarkItDownMcpReader.cs b/src/Libraries/Microsoft.Extensions.DataIngestion.MarkItDown/MarkItDownMcpReader.cs index e6a14bfbf17..753f0053b90 100644 --- a/src/Libraries/Microsoft.Extensions.DataIngestion.MarkItDown/MarkItDownMcpReader.cs +++ b/src/Libraries/Microsoft.Extensions.DataIngestion.MarkItDown/MarkItDownMcpReader.cs @@ -97,7 +97,7 @@ private async Task ConvertToMarkdownAsync(DataContent dataContent, Cance await using (transport.ConfigureAwait(false)) { // Create MCP client - McpClient client = await McpClient.CreateAsync(transport, _options, loggerFactory: null, cancellationToken).ConfigureAwait(false); + McpClient client = await McpClient.CreateAsync(transport, _options, cancellationToken: cancellationToken).ConfigureAwait(false); await using (client.ConfigureAwait(false)) { diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.ResourceUtilization/ResourceUtilizationHealthCheck.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.ResourceUtilization/ResourceUtilizationHealthCheck.cs index 072060c8fa3..0019a014bb9 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.ResourceUtilization/ResourceUtilizationHealthCheck.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.HealthChecks.ResourceUtilization/ResourceUtilizationHealthCheck.cs @@ -56,7 +56,7 @@ public static Task EvaluateHealthStatusAsync(double cpuUsedPe message = "Memory usage is above the limit"; } - return Task.FromResult(HealthCheckResult.Unhealthy(message, default, data)); + return Task.FromResult(HealthCheckResult.Unhealthy(message, data: data)); } bool cpuDegraded = cpuUsedPercentage > options.CpuThresholds.DegradedUtilizationPercentage; @@ -78,10 +78,10 @@ public static Task EvaluateHealthStatusAsync(double cpuUsedPe message = "Memory usage is close to the limit"; } - return Task.FromResult(HealthCheckResult.Degraded(message, default, data)); + return Task.FromResult(HealthCheckResult.Degraded(message, data: data)); } - return Task.FromResult(HealthCheckResult.Healthy(default, data)); + return Task.FromResult(HealthCheckResult.Healthy(data: data)); } #pragma warning restore EA0014 // The async method doesn't support cancellation diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/DiskStatsReader.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/DiskStatsReader.cs index a95506d40fe..2cf62935bfe 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/DiskStatsReader.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/Disk/DiskStatsReader.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; using Microsoft.Extensions.ObjectPool; using Microsoft.Shared.Pools; @@ -41,8 +40,7 @@ public DiskStats[] ReadAll(string[] skipDevicePrefixes) try { DiskStats stat = DiskStatsReader.ParseLine(line); - if (!skipDevicePrefixes.Any(prefix => - stat.DeviceName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))) + if (!Array.Exists(skipDevicePrefixes, prefix => stat.DeviceName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))) { diskStatsList.Add(stat); } diff --git a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationParserCgroupV2.cs b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationParserCgroupV2.cs index bbc664ea107..a7538eb5d3b 100644 --- a/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationParserCgroupV2.cs +++ b/src/Libraries/Microsoft.Extensions.Diagnostics.ResourceMonitoring/Linux/LinuxUtilizationParserCgroupV2.cs @@ -133,7 +133,7 @@ public string GetCgroupPath(string filename) // Extract the part after the last colon and cache it for future use ReadOnlySpan trimmedPath = fileContent[(colonIndex + 1)..]; - _cachedCgroupPath = "/sys/fs/cgroup" + trimmedPath.ToString().TrimEnd('/') + "/"; + _cachedCgroupPath = $"/sys/fs/cgroup{trimmedPath.TrimEnd('/')}/"; return $"{_cachedCgroupPath}{filename}"; } diff --git a/src/Libraries/Microsoft.Extensions.ServiceDiscovery.Dns/DnsServiceEndpointProviderBase.cs b/src/Libraries/Microsoft.Extensions.ServiceDiscovery.Dns/DnsServiceEndpointProviderBase.cs index 311c06f631a..eb76b4a8a30 100644 --- a/src/Libraries/Microsoft.Extensions.ServiceDiscovery.Dns/DnsServiceEndpointProviderBase.cs +++ b/src/Libraries/Microsoft.Extensions.ServiceDiscovery.Dns/DnsServiceEndpointProviderBase.cs @@ -119,11 +119,8 @@ protected void SetResult(List endpoints, TimeSpan validityPerio _hasEndpoints = false; } - if (validityPeriod <= TimeSpan.Zero) - { - validityPeriod = _nextRefreshPeriod; - } - else if (validityPeriod > _nextRefreshPeriod) + if (validityPeriod <= TimeSpan.Zero || + validityPeriod > _nextRefreshPeriod) { validityPeriod = _nextRefreshPeriod; } diff --git a/src/Libraries/Microsoft.Extensions.ServiceDiscovery.Dns/Resolver/DnsResolver.cs b/src/Libraries/Microsoft.Extensions.ServiceDiscovery.Dns/Resolver/DnsResolver.cs index 511e8fdb1c9..acf8baa47f0 100644 --- a/src/Libraries/Microsoft.Extensions.ServiceDiscovery.Dns/Resolver/DnsResolver.cs +++ b/src/Libraries/Microsoft.Extensions.ServiceDiscovery.Dns/Resolver/DnsResolver.cs @@ -619,7 +619,7 @@ internal static bool GetNegativeCacheExpiration(DateTime createdAt, List r.Type == QueryType.SOA); + DnsResourceRecord? soa = authorities.Find(r => r.Type == QueryType.SOA); if (soa != null && DnsPrimitives.TryReadSoa(soa.Value.Data, out _, out _, out _, out _, out _, out _, out uint minimum, out _)) { expiration = createdAt.AddSeconds(Math.Min(minimum, soa.Value.Ttl)); @@ -653,7 +653,7 @@ internal static SendQueryError ValidateResponse(QueryResponseCode responseCode, // another query for the same that resulted in // the cached negative response. // - if (!authorities.Any(r => r.Type == QueryType.NS) && GetNegativeCacheExpiration(createdAt, authorities, out DateTime newExpiration)) + if (!authorities.Exists(r => r.Type == QueryType.NS) && GetNegativeCacheExpiration(createdAt, authorities, out DateTime newExpiration)) { expiration = newExpiration; // _cache.TryAdd(name, queryType, expiration, Array.Empty()); diff --git a/src/Libraries/Microsoft.Extensions.Telemetry/Buffering/GlobalLogBufferManager.cs b/src/Libraries/Microsoft.Extensions.Telemetry/Buffering/GlobalLogBufferManager.cs index 449b12580fb..c544f7c3dc0 100644 --- a/src/Libraries/Microsoft.Extensions.Telemetry/Buffering/GlobalLogBufferManager.cs +++ b/src/Libraries/Microsoft.Extensions.Telemetry/Buffering/GlobalLogBufferManager.cs @@ -44,12 +44,22 @@ public override void Flush() public override bool TryEnqueue(IBufferedLogger bufferedLogger, in LogEntry logEntry) { string category = logEntry.Category; - GlobalBuffer buffer = Buffers.GetOrAdd(category, _ => new GlobalBuffer( +#if NET + GlobalBuffer buffer = Buffers.GetOrAdd(category, static (category, state) => new GlobalBuffer( + state.bufferedLogger, + category, + state._ruleSelector, + state._options, + state._timeProvider), + (bufferedLogger, _ruleSelector, _options, _timeProvider)); +#else + GlobalBuffer buffer = Buffers.GetOrAdd(category, category => new GlobalBuffer( bufferedLogger, category, _ruleSelector, _options, _timeProvider)); +#endif return buffer.TryEnqueue(logEntry); } } diff --git a/src/Shared/FxPolyfills/IPEndPoint.cs b/src/Shared/FxPolyfills/IPEndPoint.cs index 8571b675bb5..97ca789c91d 100644 --- a/src/Shared/FxPolyfills/IPEndPoint.cs +++ b/src/Shared/FxPolyfills/IPEndPoint.cs @@ -29,12 +29,9 @@ public static bool TryParse(ReadOnlySpan s, out IPEndPoint? result) // Look to see if this is an IPv6 address with a port. if (lastColonPos > 0) { - if (s[lastColonPos - 1] == ']') - { - addressLength = lastColonPos; - } // Look to see if this is IPv4 with a port (IPv6 will have another colon) - else if (s.Slice(0, lastColonPos).LastIndexOf(':') == -1) + if (s[lastColonPos - 1] == ']' || + s.Slice(0, lastColonPos).LastIndexOf(':') < 0) { addressLength = lastColonPos; } diff --git a/src/Shared/ServerSentEvents/SseItem.cs b/src/Shared/ServerSentEvents/SseItem.cs index 013d2fe9098..752589f4289 100644 --- a/src/Shared/ServerSentEvents/SseItem.cs +++ b/src/Shared/ServerSentEvents/SseItem.cs @@ -23,7 +23,7 @@ internal readonly struct SseItem /// Thrown when contains a line break. public SseItem(T data, string? eventType = null) { - if (eventType.AsSpan().ContainsLineBreaks() is true) + if (eventType.AsSpan().ContainsLineBreaks()) { ThrowHelper.ThrowArgumentException_CannotContainLineBreaks(nameof(eventType)); } @@ -45,7 +45,7 @@ public string? EventId get; init { - if (value.AsSpan().ContainsLineBreaks() is true) + if (value.AsSpan().ContainsLineBreaks()) { ThrowHelper.ThrowArgumentException_CannotContainLineBreaks(nameof(EventId)); } diff --git a/test/.editorconfig b/test/.editorconfig index e98d1472b6a..2d31ce90a29 100644 --- a/test/.editorconfig +++ b/test/.editorconfig @@ -2936,7 +2936,7 @@ dotnet_diagnostic.S1067.severity = warning # Title : Methods should not have too many parameters # Category : Major Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-107 -dotnet_diagnostic.S107.severity = warning +dotnet_diagnostic.S107.severity = none # Title : URIs should not be hardcoded # Category : Minor Code Smell @@ -3969,7 +3969,7 @@ dotnet_diagnostic.S3246.severity = warning # Title : Duplicate casts should not be made # Category : Minor Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-3247 -dotnet_diagnostic.S3247.severity = warning +dotnet_diagnostic.S3247.severity = none # Title : Classes directly extending "object" should not call "base" in "GetHashCode" or "Equals" # Category : Major Bug @@ -5089,7 +5089,7 @@ dotnet_diagnostic.S6585.severity = none # Title : Use the "UnixEpoch" field instead of creating "DateTime" instances that point to the beginning of the Unix epoch # Category : Minor Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-6588 -dotnet_diagnostic.S6588.severity = warning +dotnet_diagnostic.S6588.severity = none # Title : "Find" method should be used instead of the "FirstOrDefault" extension # Category : Minor Code Smell @@ -5151,6 +5151,21 @@ dotnet_diagnostic.S6618.severity = none # Help Link: https://rules.sonarsource.com/csharp/RSPEC-6640 dotnet_diagnostic.S6640.severity = warning +# Title : Generic logger injection should match enclosing type +# Category : Minor Code Smell +# Help Link: https://rules.sonarsource.com/csharp/RSPEC-6672 +dotnet_diagnostic.S6672.severity = none + +# Title : Awaitable method should be used +# Category : Code Smell +# Help Link: https://rules.sonarsource.com/csharp/RSPEC-6966 +dotnet_diagnostic.S6966.severity = none + +# Title : ModelState.IsValid should be called in controller actions +# Category : Code Smell +# Help Link: https://rules.sonarsource.com/csharp/RSPEC-6967 +dotnet_diagnostic.S6967.severity = none + # Title : Literal suffixes should be upper case # Category : Minor Code Smell # Help Link: https://rules.sonarsource.com/csharp/RSPEC-818 diff --git a/test/Generators/Microsoft.Gen.Logging/TestClasses/NonSensitiveRecordExtensions.cs b/test/Generators/Microsoft.Gen.Logging/TestClasses/NonSensitiveRecordExtensions.cs index 14a1bed0e58..890013c34c9 100644 --- a/test/Generators/Microsoft.Gen.Logging/TestClasses/NonSensitiveRecordExtensions.cs +++ b/test/Generators/Microsoft.Gen.Logging/TestClasses/NonSensitiveRecordExtensions.cs @@ -6,7 +6,7 @@ public static partial class NonSensitiveRecordExtensions { - internal record User() + internal record User { public int Id { get; set; } diff --git a/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/ChatCompletion/ChatResponseUpdateExtensionsTests.cs b/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/ChatCompletion/ChatResponseUpdateExtensionsTests.cs index 09f3600e522..59acc1c0991 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/ChatCompletion/ChatResponseUpdateExtensionsTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/ChatCompletion/ChatResponseUpdateExtensionsTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -803,9 +804,9 @@ await YieldAsync(updates).ToChatResponseAsync() : [MemberData(nameof(ToChatResponse_TimestampFolding_MemberData))] public async Task ToChatResponse_TimestampFolding(bool useAsync, string? timestamp1, string? timestamp2, string? expectedTimestamp) { - DateTimeOffset? first = timestamp1 is not null ? DateTimeOffset.Parse(timestamp1) : null; - DateTimeOffset? second = timestamp2 is not null ? DateTimeOffset.Parse(timestamp2) : null; - DateTimeOffset? expected = expectedTimestamp is not null ? DateTimeOffset.Parse(expectedTimestamp) : null; + DateTimeOffset? first = timestamp1 is not null ? DateTimeOffset.Parse(timestamp1, DateTimeFormatInfo.InvariantInfo) : null; + DateTimeOffset? second = timestamp2 is not null ? DateTimeOffset.Parse(timestamp2, DateTimeFormatInfo.InvariantInfo) : null; + DateTimeOffset? expected = expectedTimestamp is not null ? DateTimeOffset.Parse(expectedTimestamp, DateTimeFormatInfo.InvariantInfo) : null; ChatResponseUpdate[] updates = [ diff --git a/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Embeddings/BinaryEmbeddingTests.cs b/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Embeddings/BinaryEmbeddingTests.cs index c927a7ccf18..8f822e97d9e 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Embeddings/BinaryEmbeddingTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Embeddings/BinaryEmbeddingTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections; +using System.Globalization; using System.Linq; using System.Text.Json; using Xunit; @@ -40,7 +41,7 @@ public void Properties_Roundtrips() Assert.Equal("text-embedding-3-small", e.ModelId); Assert.Null(e.CreatedAt); - DateTimeOffset createdAt = DateTimeOffset.Parse("2022-01-01T00:00:00Z"); + DateTimeOffset createdAt = DateTimeOffset.Parse("2022-01-01T00:00:00Z", DateTimeFormatInfo.InvariantInfo); e.CreatedAt = createdAt; Assert.Equal(createdAt, e.CreatedAt); diff --git a/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Embeddings/EmbeddingTests.cs b/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Embeddings/EmbeddingTests.cs index c3809782006..eccdbf262bb 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Embeddings/EmbeddingTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Embeddings/EmbeddingTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Globalization; using System.Runtime.InteropServices; using System.Text.Json; using Xunit; @@ -16,7 +17,7 @@ public void Embedding_Ctor_Roundtrips() float[] floats = [1f, 2f, 3f]; AdditionalPropertiesDictionary props = []; - var createdAt = DateTimeOffset.Parse("2022-01-01T00:00:00Z"); + var createdAt = DateTimeOffset.Parse("2022-01-01T00:00:00Z", DateTimeFormatInfo.InvariantInfo); const string Model = "text-embedding-3-small"; Embedding e = new(floats) diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/DistributedCachingChatClientTest.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/DistributedCachingChatClientTest.cs index 64a83a35d7d..76e2493c24b 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/DistributedCachingChatClientTest.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/DistributedCachingChatClientTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization.Metadata; @@ -388,7 +389,7 @@ public async Task StreamingCoalescingPropagatesMetadataAsync() AdditionalProperties = new() { ["e"] = "f", ["g"] = "h" }, } ], - CreatedAt = DateTime.Parse("2024-10-11T19:23:36.0152137Z"), + CreatedAt = DateTime.Parse("2024-10-11T19:23:36.0152137Z", DateTimeFormatInfo.InvariantInfo), ResponseId = "12345", MessageId = "someMessageId123", AuthorName = "Someone", @@ -419,7 +420,7 @@ public async Task StreamingCoalescingPropagatesMetadataAsync() Assert.Equal("someMessageId123", item.MessageId); Assert.Equal("Someone", item.AuthorName); Assert.Equal(ChatFinishReason.Length, item.FinishReason); - Assert.Equal(DateTime.Parse("2024-10-11T19:23:36.0152137Z"), item.CreatedAt); + Assert.Equal(DateTime.Parse("2024-10-11T19:23:36.0152137Z", DateTimeFormatInfo.InvariantInfo), item.CreatedAt); var content = Assert.IsType(Assert.Single(item.Contents)); Assert.Equal("Hello world, how are you?", content.Text); diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/DistributedCachingEmbeddingGeneratorTest.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/DistributedCachingEmbeddingGeneratorTest.cs index b14d3de83a9..96218af5092 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/DistributedCachingEmbeddingGeneratorTest.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/DistributedCachingEmbeddingGeneratorTest.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Globalization; using System.Linq; using System.Text.Json; using System.Threading.Tasks; @@ -16,7 +17,7 @@ public class DistributedCachingEmbeddingGeneratorTest private readonly TestInMemoryCacheStorage _storage = new(); private readonly Embedding _expectedEmbedding = new(new float[] { 1.0f, 2.0f, 3.0f }) { - CreatedAt = DateTimeOffset.Parse("2024-08-01T00:00:00Z"), + CreatedAt = DateTimeOffset.Parse("2024-08-01T00:00:00Z", DateTimeFormatInfo.InvariantInfo), ModelId = "someModel", AdditionalProperties = new() { ["a"] = "b" }, }; @@ -88,7 +89,7 @@ public async Task SupportsPartiallyCachedBatchesAsync() Embedding[] expected = Enumerable.Range(0, 10).Select(i => new Embedding(new[] { 1.0f, 2.0f, 3.0f }) { - CreatedAt = DateTimeOffset.Parse("2024-08-01T00:00:00Z") + TimeSpan.FromHours(i), + CreatedAt = DateTimeOffset.Parse("2024-08-01T00:00:00Z", DateTimeFormatInfo.InvariantInfo) + TimeSpan.FromHours(i), ModelId = $"someModel{i}", AdditionalProperties = new() { [$"a{i}"] = $"b{i}" }, }).ToArray();