From 672cd7150b469a53085c20021276925eddb0bd16 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Sat, 25 Apr 2026 19:19:55 -0400 Subject: [PATCH] Bump dependencies and clean up source warnings Dependencies: - Avalonia 11.3.12 -> 11.3.14 (DataGrid 11.3.13) - ModelContextProtocol + .AspNetCore 0.7.0-preview.1 -> 1.2.0 (GA) - Microsoft.NET.Test.Sdk 17.8.0 -> 18.4.0 - xunit 2.5.3 -> 2.9.3, xunit.runner.visualstudio 2.5.3 -> 3.1.5, coverlet.collector 6.0.0 -> 10.0.0 - Meziantou.Framework.Win32.CredentialManager 1.7.17 -> 1.7.18 - ScottPlot 5.1.57 -> 5.1.58, SkiaSharp.NativeAssets.Linux 3.119.0 -> 3.119.2 Closes 3 transitive vulnerabilities: Tmds.DBus.Protocol (GHSA-xrw6-gwf8-vvr9), System.Net.Http (GHSA-7jgj-8wvc-jh57), System.Text.RegularExpressions (GHSA-cmhx-cq75-c4mj). Source warnings: - PlanAnalyzer.cs: null-conditional on StatementText and PhysicalOp - QueryStoreHistoryWindow.cs: pattern-match ComboBoxItem; replace obsolete DataGridRow.GetIndex with .Index - WindowsCredentialService: [SupportedOSPlatform("windows5.1.2600")] - CredentialServiceFactory: switch to OperatingSystem.IsWindows/IsMacOS; pragma at the cross-platform bridge - CredentialCommand: explicit OperatingSystem.IsWindows guard + pragma 71/71 tests passing. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Controls/PlanViewerControl.axaml.cs | 2 -- .../Dialogs/QueryStoreHistoryWindow.axaml.cs | 7 +++--- src/PlanViewer.App/PlanViewer.App.csproj | 22 +++++++++---------- .../Commands/CredentialCommand.cs | 15 ++++++++----- src/PlanViewer.Core/PlanViewer.Core.csproj | 2 +- .../Services/CredentialServiceFactory.cs | 9 +++++--- src/PlanViewer.Core/Services/PlanAnalyzer.cs | 4 ++-- .../Services/WindowsCredentialService.cs | 2 ++ .../PlanViewer.Core.Tests.csproj | 8 +++---- 9 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/PlanViewer.App/Controls/PlanViewerControl.axaml.cs b/src/PlanViewer.App/Controls/PlanViewerControl.axaml.cs index 1b3dd71..fa0bf7f 100644 --- a/src/PlanViewer.App/Controls/PlanViewerControl.axaml.cs +++ b/src/PlanViewer.App/Controls/PlanViewerControl.axaml.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; using System.IO; using System.Linq; using System.Text.RegularExpressions; diff --git a/src/PlanViewer.App/Dialogs/QueryStoreHistoryWindow.axaml.cs b/src/PlanViewer.App/Dialogs/QueryStoreHistoryWindow.axaml.cs index b39825a..66f6706 100644 --- a/src/PlanViewer.App/Dialogs/QueryStoreHistoryWindow.axaml.cs +++ b/src/PlanViewer.App/Dialogs/QueryStoreHistoryWindow.axaml.cs @@ -7,7 +7,6 @@ using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Layout; using Avalonia.Media; using Avalonia.VisualTree; using PlanViewer.Core.Models; @@ -111,9 +110,9 @@ public QueryStoreHistoryWindow(string connectionString, string queryHash, // Select initial metric in the combo box var metricTag = initialMetricTag; - foreach (ComboBoxItem item in MetricSelector.Items) + foreach (var entry in MetricSelector.Items) { - if (item.Tag?.ToString() == metricTag) + if (entry is ComboBoxItem item && item.Tag?.ToString() == metricTag) { MetricSelector.SelectedItem = item; break; @@ -759,7 +758,7 @@ private void HighlightGridRows() private void OnHighlightLoadingRow(object? sender, DataGridRowEventArgs e) { - var idx = e.Row.GetIndex(); + var idx = e.Row.Index; if (_selectedRowIndices.Contains(idx)) { e.Row.Background = new SolidColorBrush(Avalonia.Media.Color.FromArgb(60, 79, 195, 247)); diff --git a/src/PlanViewer.App/PlanViewer.App.csproj b/src/PlanViewer.App/PlanViewer.App.csproj index f6091dd..a677f74 100644 --- a/src/PlanViewer.App/PlanViewer.App.csproj +++ b/src/PlanViewer.App/PlanViewer.App.csproj @@ -14,23 +14,23 @@ - + - - - - - + + + + + - + None All - - - + + + @@ -40,7 +40,7 @@ but the managed SkiaSharp 3.x requires native libs in the [119.0, 120.0) range. Without these pins, the old 2.88.x .so overwrites the correct one at publish time, causing a TypeInitializationException on Linux (GitHub issue #139). --> - + diff --git a/src/PlanViewer.Cli/Commands/CredentialCommand.cs b/src/PlanViewer.Cli/Commands/CredentialCommand.cs index e94e1f1..e49b9f1 100644 --- a/src/PlanViewer.Cli/Commands/CredentialCommand.cs +++ b/src/PlanViewer.Cli/Commands/CredentialCommand.cs @@ -77,12 +77,15 @@ private static Command CreateListCommand(ICredentialService credentialService) cmd.SetHandler(() => { - IReadOnlyList<(string ServerName, string Username)>? creds = credentialService switch - { - WindowsCredentialService win => win.ListAll(), - KeychainCredentialService mac => mac.ListAll(), - _ => null - }; + IReadOnlyList<(string ServerName, string Username)>? creds = null; + // CA1416: WindowsCredentialService is gated on OperatingSystem.IsWindows(). + // .NET 8 won't run below Windows 10, so the underlying "windows5.1.2600" requirement is always met. +#pragma warning disable CA1416 + if (OperatingSystem.IsWindows() && credentialService is WindowsCredentialService win) + creds = win.ListAll(); +#pragma warning restore CA1416 + if (OperatingSystem.IsMacOS() && credentialService is KeychainCredentialService mac) + creds = mac.ListAll(); if (creds == null) { diff --git a/src/PlanViewer.Core/PlanViewer.Core.csproj b/src/PlanViewer.Core/PlanViewer.Core.csproj index b91d4dc..c9f1aeb 100644 --- a/src/PlanViewer.Core/PlanViewer.Core.csproj +++ b/src/PlanViewer.Core/PlanViewer.Core.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/PlanViewer.Core/Services/CredentialServiceFactory.cs b/src/PlanViewer.Core/Services/CredentialServiceFactory.cs index 648ff53..cc60138 100644 --- a/src/PlanViewer.Core/Services/CredentialServiceFactory.cs +++ b/src/PlanViewer.Core/Services/CredentialServiceFactory.cs @@ -1,4 +1,3 @@ -using System.Runtime.InteropServices; using PlanViewer.Core.Interfaces; namespace PlanViewer.Core.Services; @@ -7,10 +6,14 @@ public static class CredentialServiceFactory { public static ICredentialService Create() { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + // CA1416: the underlying CredentialManager API declares "windows5.1.2600" (XP+); + // .NET 8 won't run on anything below Windows 10, so OperatingSystem.IsWindows() is sufficient. +#pragma warning disable CA1416 + if (OperatingSystem.IsWindows()) return new WindowsCredentialService(); +#pragma warning restore CA1416 - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + if (OperatingSystem.IsMacOS()) return new KeychainCredentialService(); // Linux and other platforms: use in-memory storage (credentials not persisted across sessions) diff --git a/src/PlanViewer.Core/Services/PlanAnalyzer.cs b/src/PlanViewer.Core/Services/PlanAnalyzer.cs index aae2d0e..5aa8f2e 100644 --- a/src/PlanViewer.Core/Services/PlanAnalyzer.cs +++ b/src/PlanViewer.Core/Services/PlanAnalyzer.cs @@ -403,7 +403,7 @@ private static void AnalyzeStatement(PlanStatement stmt, AnalyzerConfig cfg) if (unsnifffedParams.Count > 0) { - var hasRecompile = stmt.StatementText.Contains("RECOMPILE", StringComparison.OrdinalIgnoreCase); + var hasRecompile = stmt.StatementText?.Contains("RECOMPILE", StringComparison.OrdinalIgnoreCase) == true; if (!hasRecompile) { var names = string.Join(", ", unsnifffedParams.Select(p => p.Name)); @@ -1321,7 +1321,7 @@ _ when nonSargableReason.StartsWith("Function call") => // Rule 28: Row Count Spool — NOT IN with nullable column // Pattern: Row Count Spool with high rewinds, child scan has IS NULL predicate, // and statement text contains NOT IN - if (!cfg.IsRuleDisabled(28) && node.PhysicalOp.Contains("Row Count Spool")) + if (!cfg.IsRuleDisabled(28) && node.PhysicalOp?.Contains("Row Count Spool") == true) { var rewinds = node.HasActualStats ? (double)node.ActualRewinds : node.EstimateRewinds; if (rewinds > 10000 && HasNotInPattern(node, stmt)) diff --git a/src/PlanViewer.Core/Services/WindowsCredentialService.cs b/src/PlanViewer.Core/Services/WindowsCredentialService.cs index 99c96aa..645e567 100644 --- a/src/PlanViewer.Core/Services/WindowsCredentialService.cs +++ b/src/PlanViewer.Core/Services/WindowsCredentialService.cs @@ -1,8 +1,10 @@ +using System.Runtime.Versioning; using Meziantou.Framework.Win32; using PlanViewer.Core.Interfaces; namespace PlanViewer.Core.Services; +[SupportedOSPlatform("windows5.1.2600")] public class WindowsCredentialService : ICredentialService { private const string Prefix = "planview:"; diff --git a/tests/PlanViewer.Core.Tests/PlanViewer.Core.Tests.csproj b/tests/PlanViewer.Core.Tests/PlanViewer.Core.Tests.csproj index 3e468c0..5fd8768 100644 --- a/tests/PlanViewer.Core.Tests/PlanViewer.Core.Tests.csproj +++ b/tests/PlanViewer.Core.Tests/PlanViewer.Core.Tests.csproj @@ -10,10 +10,10 @@ - - - - + + + +