Skip to content

Commit 54bcb9d

Browse files
committed
Integrate todo items in prd
1 parent f746787 commit 54bcb9d

File tree

2 files changed

+172
-71
lines changed

2 files changed

+172
-71
lines changed

TODO.md

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +0,0 @@
1-
- Move all tests to integration tests and test only via front door (Assert)
2-
- Expose Assert(() => x => y) overload method in Sharp class to delegate to included PowerAssert directly
3-
- Review dynamic support - make sure that dynamic = {...} objects are properly formatted
4-
- Custom formatters
5-
- Custom comparisons
6-
7-
----
8-
9-
Dynamic - only implement (general/binary). Need to be tested/extended to work properly with objects/collections/expando
10-
```csharp
11-
dynamic json = JsonSerializer.Deserialize<dynamic>(jsonString);
12-
Console.WriteLine(json.user.name);
13-
```
14-
15-
```csharp
16-
dynamic person = new ExpandoObject();
17-
person.Name = "Yevhen";
18-
person.Age = 42;
19-
Console.WriteLine($"{person.Name} ({person.Age})");
20-
```
21-
22-
----
23-
24-
**External diff viewers** - this is important to implement.
25-
- Need proper research. In pycharm when pytest assert fails it shows nice diff right inside ide using native means.
26-
- It would be cool impl similar for large multiline strings, or maps, etc. Need to think where this could be useful.
27-
28-
----
29-
30-
**Debugging the Rewriter** - not sure what value this will bring and what changes these requires.
31-
To facilitate debugging, the rewrite task will support a diagnostic MSBuild property:
32-
33-
```xml
34-
<PropertyGroup>
35-
<SharpAssertEmitRewriteInfo>true</SharpAssertEmitRewriteInfo>
36-
</PropertyGroup>
37-
```
38-
39-
When enabled, the rewriter will output detailed logs of its analysis and decisions. This is crucial for troubleshooting unexpected rewrite behavior.
40-
41-
----
42-
43-
**Dependencies**
44-
- PowerAssert (current) — is not used anymore as automatic fallback for unsupported features (need to find all references to this fact and update)
45-
- DiffPlex — string & sequence diffs
46-
- Compare‑Net‑Objects — deep object diffs
47-
- Verify.* — external diff tooling
48-
49-
All these packages need to be properly attributed in README.md
50-
51-
----
52-
53-
**Rewriter Robustness & Fallback - pending**
54-
55-
- Wrap rewriter logic in try-catch
56-
- If analysis fails, leave original Assert call
57-
- Add diagnostic logging controlled by MSBuild property - this looks like 4.3
58-
- Test with edge cases and invalid code

prd.md

Lines changed: 172 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,107 @@
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
38147
SharpConfig.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

Comments
 (0)