88
99** See [ CONSTITUTION.md] ( CONSTITUTION.md ) ** for the immutable architectural principles and core philosophy.
1010
11+ Key invariants:
12+ - Hybrid architecture: minimal rewriter, rich runtime
13+ - Never break the build (graceful fallback)
14+ - Single evaluation, single materialization
15+ - Simple API, rich diagnostics
16+ - Pay-on-failure performance
17+
18+ ---
19+
20+ ## Implementation Roadmap
21+
22+ ### High Priority (Polish & Correctness)
23+
24+ #### 1. Move All Tests to Integration Tests (Front Door Only)
25+ ** Goal:** Test only via public API ` Assert() ` , not internal methods.
26+
27+ ** Why:** Ensures we're testing user-facing behavior, catches integration issues.
28+
29+ ** Tasks:**
30+ - Move unit tests from ` SharpInternal.* ` direct calls to ` Sharp.Assert() ` calls
31+ - Keep tests focused on behavior, not implementation
32+ - Verify all edge cases still covered
33+
1134---
1235
13- ## Remaining Work
36+ #### 2. Enhanced Dynamic Support (Objects/Collections/ExpandoObject)
37+ ** Goal:** Make dynamic object comparisons work with proper formatting.
38+
39+ ** Current State:** Basic dynamic binary/general implemented but needs extension.
1440
15- ### Verify.* Integration (External Diff Viewers)
16- ** Status:** Not Started
17- ** Goal:** When string/object diffs are large, write ` .received ` /` .verified ` files and open configured diff tool.
41+ ** Test Cases:**
42+ ``` csharp
43+ // JSON deserialization
44+ dynamic json = JsonSerializer .Deserialize <dynamic >(jsonString );
45+ Assert (json .user .name == " expected" );
46+
47+ // ExpandoObject
48+ dynamic person = new ExpandoObject ();
49+ person .Name = " Yevhen" ;
50+ person .Age = 42 ;
51+ Assert (person .Age > 40 );
52+
53+ // Dynamic collections
54+ dynamic obj = new { Items = new [] { 1 , 2 , 3 } };
55+ Assert (obj .Items .Contains (5 )); // Should show collection contents
56+ ```
57+
58+ ** Tasks:**
59+ - Test dynamic objects with nested properties
60+ - Test dynamic with collections (arrays, lists)
61+ - Test ExpandoObject scenarios
62+ - Ensure proper formatting for dynamic objects in diagnostics
63+
64+ ---
65+
66+ #### 3. Rewriter Diagnostic Logging (` SharpAssertEmitRewriteInfo ` )
67+ ** Goal:** Support MSBuild property for troubleshooting rewriter behavior.
1868
1969** Implementation:**
20- - Integrate Verify.* packages (Verify.Xunit, Verify.NUnit, Verify.MSTest).
70+ ``` xml
71+ <PropertyGroup >
72+ <SharpAssertEmitRewriteInfo >true</SharpAssertEmitRewriteInfo >
73+ </PropertyGroup >
74+ ```
75+
76+ ** Tasks:**
77+ - Add logging infrastructure to rewriter task
78+ - Log: detected await/dynamic, chosen rewrite path, fallback reasons
79+ - Write logs to MSBuild diagnostic output
80+ - Document in README/troubleshooting guide
81+
82+ ---
83+
84+ #### 4. Documentation: Dependency Attribution
85+ ** Goal:** Properly credit all third-party dependencies in README.md.
86+
87+ ** Dependencies to attribute:**
88+ - ** DiffPlex** — string & sequence diffs
89+ - ** Compare-Net-Objects** — deep object diffs
90+ - ** PowerAssert** — optional alternative/fallback mode (clarify current usage)
91+
92+ ** Tasks:**
93+ - Add "Credits" or "Dependencies" section to README.md
94+ - Link to each package's repository
95+ - Clarify PowerAssert relationship (optional vs. fallback vs. not used)
96+ - Review all references to PowerAssert fallback behavior
97+
98+ ---
99+
100+ ### Medium Priority (New Features)
101+
102+ #### 5. External Diff Viewers (Verify.* Integration)
103+ ** Goal:** For large diffs, write ` .received ` /` .verified ` files and open configured diff tool.
104+
105+ ** Research Needed:**
106+ - How PyCharm/pytest shows inline diffs in IDE
107+ - What triggers "large diff" threshold
108+ - Best UI/UX for .NET developers
109+
110+ ** Implementation:**
111+ - Integrate Verify.* packages (Verify.Xunit, Verify.NUnit, Verify.MSTest)
21112- Write assertion failure artifacts to ` .received ` /` .verified ` files
22113- Open configured diff tool (VS Code, Beyond Compare, etc.)
23114- For NUnit/MSTest: attach files via ` TestContext.AddTestAttachment ` / ` AddResultFile `
@@ -29,22 +120,66 @@ dotnet add package Verify.Xunit # or NUnit/MSTest variants
29120
30121---
31122
32- ### Custom Formatter Registry
33- ** Status:** Not Started
123+ #### 6. Expose Direct PowerAssert Integration
124+ ** Goal:** Allow users to call PowerAssert directly via ` Sharp.Assert(() => ...) ` overload.
125+
126+ ** API:**
127+ ``` csharp
128+ // Current: Sharp.Assert(bool condition)
129+ // New: Sharp.Assert(Expression<Func<bool>> condition) // delegates to PowerAssert
130+ ```
131+
132+ ** Why:** Gives users escape hatch if they prefer PowerAssert diagnostics for specific assertions.
133+
134+ ** Tasks:**
135+ - Add overload that accepts ` Expression<Func<bool>> `
136+ - Delegate directly to PowerAssert.PAssert.IsTrue
137+ - Document when to use this overload
138+ - Test that it works alongside rewritten assertions
139+
140+ ---
141+
142+ #### 7. Custom Formatters Registry
34143** Goal:** Allow users to register custom formatters for domain types.
35144
36- ** Example API:**
145+ ** API:**
37146``` csharp
38147SharpConfig .RegisterFormatter <MyType >((value , context ) =>
39148{
40149 return $" MyType({value .Id }, {value .Name })" ;
41150});
42151```
43152
153+ ** Tasks:**
154+ - Design formatter API (signature, context object)
155+ - Implement formatter registry (thread-safe)
156+ - Integrate into diagnostic pipeline
157+ - Document with examples
158+
159+ ---
160+
161+ #### 8. Custom Comparers
162+ ** Goal:** Allow users to register custom equality comparers for types.
163+
164+ ** API:**
165+ ``` csharp
166+ SharpConfig .RegisterComparer <MyType >((left , right ) =>
167+ {
168+ return left .Id == right .Id ; // Custom equality logic
169+ });
170+ ```
171+
172+ ** Tasks:**
173+ - Design comparer API
174+ - Implement comparer registry (thread-safe)
175+ - Integrate into comparison logic
176+ - Document with examples
177+
44178---
45179
46- ### HTML Diff Emitter
47- ** Status:** Not Started
180+ ### Low Priority (Nice-to-Have)
181+
182+ #### 9. HTML Diff Emitter
48183** Goal:** Generate HTML diff artifacts for CI/CD pipelines.
49184
50185** Implementation:**
@@ -54,8 +189,7 @@ SharpConfig.RegisterFormatter<MyType>((value, context) =>
54189
55190---
56191
57- ### SourceLink-based Expression Embedding
58- ** Status:** Not Started
192+ #### 10. SourceLink-based Expression Embedding
59193** Goal:** Use SourceLink to embed original expression text without CallerArgumentExpression.
60194
61195** Rationale:**
@@ -66,6 +200,21 @@ SharpConfig.RegisterFormatter<MyType>((value, context) =>
66200
67201## Reference Documentation
68202
203+ ### Current Implementation Status
204+
205+ All core features are ** ✅ COMPLETED** :
206+ - Basic assertions with CallerArgumentExpression
207+ - Expression tree runtime with binary/logical operators
208+ - MSBuild rewriter with PowerAssert fallback
209+ - String diffs (DiffPlex)
210+ - Collection comparisons
211+ - Object deep diffs (Compare-Net-Objects)
212+ - LINQ operations (Contains/Any/All/SequenceEqual)
213+ - Async/await support
214+ - Dynamic type support (basic)
215+ - Nullable type support
216+ - Graceful rewriter fallback
217+
69218### API Reference
70219
71220** Public API:**
@@ -125,11 +274,21 @@ public static class SharpInternal
125274- CompareNETObjects (object deep diffs)
126275
127276** Optional:**
128- - PowerAssert (alternative mode)
277+ - PowerAssert (alternative mode via explicit overload - future )
129278- Verify.* (external diff viewers - future)
130279
131280---
132281
282+ ## Non-Goals
283+
284+ - Full AST explanation for async/dynamic beyond thunks
285+ - Expression trees for await/dynamic (C# limitation)
286+ - Rewriting outside test projects
287+ - IDE integration/plugins
288+ - Performance profiling tools
289+
290+ ---
291+
133292## Testing Commands
134293
135294** Fast development cycle:**
0 commit comments