Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions SysManager/SysManager.Tests/ArchitectureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1844,9 +1844,13 @@ public void EveryModelProperty_IsEitherWrittenOrShown()
}
}

Assert.True(checkedProperties >= 40,
$"only {checkedProperties} model properties were inspected — the detection is probably no "
+ "longer matching the [ObservableProperty] declarations.");
// Measured: 187 today. The floor is set just under that rather than at a token value, because the
// defect it has to catch is precisely a pattern that still matches MOST declarations — the previous
// prefix saw 164 of these 187 and its floor of 40 reported nothing wrong for as long as it shipped.
Assert.True(checkedProperties >= 180,
$"only {checkedProperties} model properties were inspected, out of 187 measured — the detection "
+ "is no longer matching every [ObservableProperty] declaration. A pattern that matches most of "
+ "them still leaves the rest unguarded, so fix this before trusting a pass.");

Assert.True(dead.Count == 0,
"these model properties are never written and never shown, so they can only ever present an "
Expand All @@ -1858,7 +1862,22 @@ public void EveryModelProperty_IsEitherWrittenOrShown()
private static partial Regex TypeDeclaration();

/// <summary>An <c>[ObservableProperty]</c> backing field, capturing the field name without its underscore.</summary>
[GeneratedRegex(@"\[ObservableProperty\][^\n]*\n?\s*(?:private|internal)\s+[\w\?<>,\[\]\. ]+?\s+_(\w+)\s*[;=]",
/// <remarks>
/// The prefix was <c>[^\n]*\n?</c>, which is wrong in both directions.
/// <para>It let the match run to the end of the attribute's own line and then across ONE newline, so for
/// the single-line form followed by a plain field —
/// <c>[ObservableProperty] private string _label = "";</c> then <c>private string? _target;</c> — it walked
/// past <c>_label</c> and captured <c>_target</c>, a field that is not observable at all. Four such
/// mis-captures exist in <c>ViewModels/</c> today.</para>
/// <para>And one newline is not enough for the multi-attribute form, so every property carrying a
/// <c>[NotifyPropertyChangedFor]</c> beside it was invisible: 23 of the 187 properties in
/// <c>Models/</c>, including six on <c>DiskHealthReport</c> alone. The guard's floor of 40 could never
/// reveal that, since 164 clears it comfortably.</para>
/// <para>Now: optional whitespace, then any number of further attributes, then the field. Nothing on the
/// attribute's own line can be skipped over.</para>
/// </remarks>
[GeneratedRegex(@"\[ObservableProperty\]\s*(?:\[[^\]]*\]\s*)*(?:private|internal)\s+"
+ @"[\w\?<>,\[\]\. ]+?\s+_(\w+)\s*[;=]",
RegexOptions.Compiled)]
private static partial Regex ObservablePropertyField();

Expand Down
4 changes: 3 additions & 1 deletion SysManager/SysManager.Tests/DiskAnalyzerViewModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ private static DiskAnalyzerViewModel NewVm()
[Fact]
public void Constructor_InitialState_IsCorrect()
{
// TotalFolders was asserted here too. It was computed from a full recursive
// Entries.Sum(e => e.FolderCount) on every scan and read by nothing — no binding, no other
// code — and this assertion on its default value is what made it look exercised.
var vm = NewVm();
Assert.False(vm.IsBusy);
Assert.Equal(0, vm.TotalSize);
Assert.Equal(0, vm.TotalFiles);
Assert.Equal(0, vm.TotalFolders);
Assert.Equal(0, vm.EntryCount);
Assert.Empty(vm.Entries);
Assert.Contains("Select", vm.ScanSummary);
Expand Down
6 changes: 0 additions & 6 deletions SysManager/SysManager/ViewModels/DiskAnalyzerViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ public sealed partial class DiskAnalyzerViewModel : ViewModelBase
public bool HasTrend => !string.IsNullOrEmpty(TrendSummary);
[ObservableProperty] private long _totalSize;
[ObservableProperty] private int _totalFiles;
[ObservableProperty] private int _totalFolders;
[ObservableProperty] private int _entryCount;
[ObservableProperty] private string _currentFolder = "";

// Distinguishes the un-run state from a completed zero-result scan so the big empty-state overlay
// doesn't tell the user to "pick a folder and analyze" right after they did exactly that. Set true
Expand Down Expand Up @@ -153,7 +151,6 @@ private async Task AnalyzeAsync()
Entries.Clear();
TotalSize = 0;
TotalFiles = 0;
TotalFolders = 0;
EntryCount = 0;

UpdateDriveInfo();
Expand All @@ -162,7 +159,6 @@ private async Task AnalyzeAsync()
{
var progress = new Progress<DiskAnalyzerService.AnalysisProgress>(p =>
{
CurrentFolder = p.CurrentFolder;
StatusMessage = $"Scanning folder {p.FoldersScanned}: {p.CurrentFolder}";
});

Expand All @@ -173,7 +169,6 @@ private async Task AnalyzeAsync()
EntryCount = Entries.Count;
TotalSize = Entries.Sum(e => e.SizeBytes);
TotalFiles = Entries.Sum(e => e.FileCount);
TotalFolders = Entries.Sum(e => e.FolderCount);

ScanSummary = EntryCount == 0
? "No subfolders found."
Expand Down Expand Up @@ -201,7 +196,6 @@ private async Task AnalyzeAsync()
{
IsBusy = false;
IsProgressIndeterminate = false;
CurrentFolder = "";
}
}

Expand Down
1 change: 0 additions & 1 deletion SysManager/SysManager/ViewModels/SpeedTestViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ public sealed partial class SpeedTestViewModel : ViewModelBase
"New York, US (ID: 10390)",
};
[ObservableProperty] private int _speedProgress;
[ObservableProperty] private string _speedStatus = "";
[ObservableProperty] private string _httpStatus = "";
[ObservableProperty] private string _ooklaStatus = "";
[ObservableProperty] private bool _isSpeedTesting;
Expand Down