|
| 1 | +# REFACTOR-001 Implementation Plan |
| 2 | + |
| 3 | +## Analysis Summary |
| 4 | + |
| 5 | +### Issue 1: File Reading Pattern Duplication |
| 6 | + |
| 7 | +**Originally estimated**: 3 locations |
| 8 | +**Actually found**: 6 locations (+ 3 additional in config.analyzer.ts) |
| 9 | + |
| 10 | +| Module | Pattern | Return on Error | |
| 11 | +|--------|---------|-----------------| |
| 12 | +| ignore.parser.ts | readFile → catch → return empty | `{ patterns: [], source: null }` | |
| 13 | +| context.loader.ts (loadContextFile) | readFile → catch → return null | `null` | |
| 14 | +| context.loader.ts (getAllFiles) | readdir → catch → skip | (continues) | |
| 15 | +| code.sampler.ts | stat + readFile → catch → skip | (continues) | |
| 16 | +| package.analyzer.ts | readFile → catch → return null | `null` | |
| 17 | +| config.analyzer.ts | readFile → catch → skip (×3) | (continues) | |
| 18 | + |
| 19 | +**Key observation**: None check for ENOENT specifically. All use bare `catch` blocks. |
| 20 | + |
| 21 | +### Issue 2: Path Matching Logic Duplication |
| 22 | + |
| 23 | +| Pattern Type | Location | Approach | |
| 24 | +|--------------|----------|----------| |
| 25 | +| Path separator handling | code.sampler.ts | Check both `/` and `\` manually | |
| 26 | +| Path separator handling | ignore.parser.ts | Normalize `\` to `/` upfront | |
| 27 | +| Wildcard matching | config.analyzer.ts | Simple `*` → `.*` regex | |
| 28 | +| Glob pattern matching | ignore.parser.ts | Full gitignore-style (**, !, anchors) | |
| 29 | +| Directory in path check | code.sampler.ts | Custom `pathContainsDir()` helper | |
| 30 | +| Directory in path check | directory.analyzer.ts | Inline string checks | |
| 31 | + |
| 32 | +--- |
| 33 | + |
| 34 | +## Implementation Plan |
| 35 | + |
| 36 | +### Phase 1: Create Shared File Utilities |
| 37 | + |
| 38 | +**Goal**: Consolidate file reading patterns into reusable utilities |
| 39 | + |
| 40 | +**New module**: `src/shared/file.utils.ts` |
| 41 | + |
| 42 | +**Functions to create**: |
| 43 | + |
| 44 | +1. `safeReadFile(path): Promise<string | null>` |
| 45 | + - Returns file content or null if not found |
| 46 | + - Throws on permission/other errors |
| 47 | + |
| 48 | +2. `safeReadFileWithFallback<T>(path, fallback): Promise<T>` |
| 49 | + - Returns parsed content or fallback value |
| 50 | + - Useful for config files with default empty objects |
| 51 | + |
| 52 | +3. `tryReadFile(path): Promise<string | undefined>` |
| 53 | + - Silent failure variant for skip-on-error patterns |
| 54 | + |
| 55 | +**Refactoring targets** (6 files): |
| 56 | +- `src/config/ignore.parser.ts` |
| 57 | +- `src/config/context.loader.ts` |
| 58 | +- `src/analyzer/code.sampler.ts` |
| 59 | +- `src/analyzer/package.analyzer.ts` |
| 60 | +- `src/analyzer/config.analyzer.ts` |
| 61 | + |
| 62 | +### Phase 2: Create Shared Path Utilities |
| 63 | + |
| 64 | +**Goal**: Unify path matching approaches |
| 65 | + |
| 66 | +**New module**: `src/shared/path.utils.ts` |
| 67 | + |
| 68 | +**Functions to create**: |
| 69 | + |
| 70 | +1. `normalizePath(path): string` |
| 71 | + - Converts all `\` to `/` |
| 72 | + - Single source of truth for path normalization |
| 73 | + |
| 74 | +2. `pathContainsSegment(path, segment): boolean` |
| 75 | + - Checks if path contains a directory segment |
| 76 | + - Replaces manual `/dir/` and `\dir\` checks |
| 77 | + |
| 78 | +3. `matchesGlobPattern(path, pattern): boolean` |
| 79 | + - Wrapper around existing `patternToRegex` in ignore.parser.ts |
| 80 | + - Reusable for config.analyzer.ts wildcard matching |
| 81 | + |
| 82 | +**Refactoring targets** (3 files): |
| 83 | +- `src/analyzer/code.sampler.ts` |
| 84 | +- `src/analyzer/config.analyzer.ts` |
| 85 | +- `src/analyzer/directory.analyzer.ts` |
| 86 | + |
| 87 | +--- |
| 88 | + |
| 89 | +## Execution Order |
| 90 | + |
| 91 | +``` |
| 92 | +Step 1: Create src/shared/file.utils.ts + tests |
| 93 | + ↓ |
| 94 | +Step 2: Refactor config/ modules to use file.utils |
| 95 | + ↓ |
| 96 | +Step 3: Refactor analyzer/ modules to use file.utils |
| 97 | + ↓ |
| 98 | +Step 4: Create src/shared/path.utils.ts + tests |
| 99 | + ↓ |
| 100 | +Step 5: Refactor analyzer/ modules to use path.utils |
| 101 | + ↓ |
| 102 | +Step 6: Run full test suite, verify 269+ tests pass |
| 103 | +``` |
| 104 | + |
| 105 | +--- |
| 106 | + |
| 107 | +## Risk Mitigation |
| 108 | + |
| 109 | +| Risk | Mitigation | |
| 110 | +|------|------------| |
| 111 | +| Breaking error handling behavior | Keep same return types (null, empty object, skip) | |
| 112 | +| Missing edge cases | Existing tests cover current behavior | |
| 113 | +| Import cycle | shared/ has no dependencies on config/ or analyzer/ | |
| 114 | + |
| 115 | +--- |
| 116 | + |
| 117 | +## Success Metrics |
| 118 | + |
| 119 | +- [ ] `safeReadFile` pattern used in all 6 locations |
| 120 | +- [ ] `normalizePath` used consistently for path operations |
| 121 | +- [ ] No duplicate file reading try-catch blocks remain |
| 122 | +- [ ] No duplicate path separator handling remains |
| 123 | +- [ ] All 269 existing tests pass |
| 124 | +- [ ] New utility functions have dedicated test coverage |
| 125 | + |
| 126 | +--- |
| 127 | + |
| 128 | +## Estimated Scope |
| 129 | + |
| 130 | +| Item | Count | |
| 131 | +|------|-------| |
| 132 | +| New files | 4 (2 utils + 2 spec files) | |
| 133 | +| Modified files | 6 | |
| 134 | +| New functions | 5-6 | |
| 135 | +| Risk level | Low | |
0 commit comments