Skip to content

feat: Phase 5.4 migrate MockFileSystem.AddDrive to WithDrive#13

Merged
vbreuss merged 2 commits into
mainfrom
feat/phase-5.4-adddrive
May 15, 2026
Merged

feat: Phase 5.4 migrate MockFileSystem.AddDrive to WithDrive#13
vbreuss merged 2 commits into
mainfrom
feat/phase-5.4-adddrive

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented May 15, 2026

Rewrites fs.AddDrive(name, new MockDriveData { TotalSize = X, IsReady = Y, ... }) to fs.WithDrive(name, d => d.SetTotalSize(X).SetIsReady(Y)...).

Mappable initializer properties (1:1 with IStorageDrive setters):

  • TotalSize -> SetTotalSize
  • IsReady -> SetIsReady
  • DriveFormat -> SetDriveFormat
  • DriveType -> SetDriveType

AvailableFreeSpace, TotalFreeSpace and VolumeLabel have no IStorageDrive setter equivalent — the rewrite bails for any initializer that touches them so the user can address them by hand.

Gating:

  • Receiver must be the concrete TestableIO MockFileSystem (the rewrite emits WithDrive, which is Testably-only).
  • Second argument must be a new MockDriveData() (explicit or target- typed new()) with no ctor arguments — the copy ctor and captured references fall through to manual review.

Other notes:

  • Empty initializer collapses to the single-argument fs.WithDrive(name) overload (no lambda).
  • Lambda parameter name is chosen fresh from ["d", "drive", "driveBuilder", d1, d2, ...] to avoid shadowing identifiers in the initializer RHS.
  • The fix swaps the using directive to Testably.Abstractions.Testing, matching the constructor-fix pattern, because WithDrive doesn't exist on TestableIO.

Playground gains two AddDrive parity samples; analyzer + code-fix tests cover empty/single/multi-property/target-typed rewrites and the four HasNoFix cases (interface receiver, non-literal data, unsupported initializer property, copy ctor).

Rewrites `fs.AddDrive(name, new MockDriveData { TotalSize = X, IsReady = Y, ... })`
to `fs.WithDrive(name, d => d.SetTotalSize(X).SetIsReady(Y)...)`.

Mappable initializer properties (1:1 with IStorageDrive setters):
- TotalSize    -> SetTotalSize
- IsReady      -> SetIsReady
- DriveFormat  -> SetDriveFormat
- DriveType    -> SetDriveType

AvailableFreeSpace, TotalFreeSpace and VolumeLabel have no IStorageDrive
setter equivalent — the rewrite bails for any initializer that touches
them so the user can address them by hand.

Gating:
- Receiver must be the concrete TestableIO MockFileSystem (the rewrite
  emits WithDrive, which is Testably-only).
- Second argument must be a `new MockDriveData()` (explicit or target-
  typed `new()`) with no ctor arguments — the copy ctor and captured
  references fall through to manual review.

Other notes:
- Empty initializer collapses to the single-argument `fs.WithDrive(name)`
  overload (no lambda).
- Lambda parameter name is chosen fresh from ["d", "drive", "driveBuilder",
  d1, d2, ...] to avoid shadowing identifiers in the initializer RHS.
- The fix swaps the using directive to Testably.Abstractions.Testing,
  matching the constructor-fix pattern, because WithDrive doesn't exist
  on TestableIO.

Playground gains two AddDrive parity samples; analyzer + code-fix tests
cover empty/single/multi-property/target-typed rewrites and the four
HasNoFix cases (interface receiver, non-literal data, unsupported
initializer property, copy ctor).
@vbreuss vbreuss self-assigned this May 15, 2026
Copilot AI review requested due to automatic review settings May 15, 2026 06:59
@vbreuss vbreuss added the enhancement New feature or request label May 15, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds analyzer/code-fix support for migrating MockFileSystem.AddDrive usages from System.IO.Abstractions.TestingHelpers to Testably’s WithDrive API.

Changes:

  • Adds a new MockFileSystem.AddDrive analyzer pattern.
  • Implements a code fix that rewrites supported MockDriveData initializers into WithDrive calls and swaps the testing namespace.
  • Adds analyzer, code-fix, and playground coverage for supported and unsupported AddDrive migration cases.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Source/Testably.Abstractions.Migration.Analyzers/SystemIOAbstractionsAnalyzer.cs Flags AddDrive invocations for migration.
Source/Testably.Abstractions.Migration.Analyzers/Patterns.cs Adds the AddDrive migration pattern constant.
Source/Testably.Abstractions.Migration.Analyzers.CodeFixers/SystemIOAbstractionsCodeFixProvider.cs Adds the AddDrive-to-WithDrive rewrite logic.
Tests/Testably.Abstractions.Migration.Tests/SystemIOAbstractionsAnalyzerTests.cs Adds analyzer coverage for AddDrive detection.
Tests/Testably.Abstractions.Migration.Tests/SystemIOAbstractionsCodeFixProviderTests.AccessorMethodTests.cs Adds code-fix coverage for supported rewrites and no-fix cases.
Tests/Testably.Abstractions.Migration.SystemIOAbstractionsPlayground/AccessorMethodTests.cs Adds playground AddDrive samples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 15, 2026

Test Results

  6 files  ± 0    6 suites  ±0   1m 19s ⏱️ -5s
124 tests +14  124 ✅ +14  0 💤 ±0  0 ❌ ±0 
372 runs  +42  370 ✅ +42  2 💤 ±0  0 ❌ ±0 

Results for commit 36442e6. ± Comparison against base commit c837ba9.

♻️ This comment has been updated with latest results.

The Phase 5.4 gate only checked the receiver's semantic type, so the fix
was still offered when the receiver's declared type syntax was alias- or
fully-qualified — e.g. `System.IO.Abstractions.TestingHelpers.MockFileSystem fs`
or `using TestableIo = ...; TestableIo.MockFileSystem fs`. In those cases
the using-swap leaves the declaration untouched, so after the rewrite
`fs` still binds to TestableIO MockFileSystem and `fs.WithDrive(...)`
fails to compile.

Add a syntactic gate IsRetargetableMockFileSystemReceiver that inspects
the declaration of the receiver symbol (local, parameter, field,
property or method return type) and only accepts unqualified type syntax
(IdentifierNameSyntax, optionally wrapped in NullableTypeSyntax). Direct
constructions reuse the existing HasUnqualifiedMockFileSystemTypeName
gate. Anything else (qualified, alias-qualified, missing source
declaration) falls through to manual review.

Tests added for the fully-qualified and alias-qualified receiver shapes.
@sonarqubecloud
Copy link
Copy Markdown

@vbreuss vbreuss merged commit e934b74 into main May 15, 2026
9 checks passed
@vbreuss vbreuss deleted the feat/phase-5.4-adddrive branch May 15, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants