|
| 1 | +# Inflector Library Migration Plan |
| 2 | + |
| 3 | +## Goal |
| 4 | +Remove external `inflector` shard dependency by vendoring the library into our project and improving it to fix known issues while maintaining 100% backward compatibility. |
| 5 | + |
| 6 | +## Current State Analysis |
| 7 | + |
| 8 | +### External Dependency |
| 9 | +- **Library**: `phoffer/inflector.cr` (v0.1.8) |
| 10 | +- **Location**: External shard in `shard.yml` |
| 11 | +- **Usage**: Only 4 methods used from the library |
| 12 | + |
| 13 | +### Current Usage Points |
| 14 | +```crystal |
| 15 | +# In src/amber_cli/core/word_transformer.cr: |
| 16 | +Inflector.singularize(word) # Line 122 |
| 17 | +Inflector.pluralize(word) # Line 125 |
| 18 | +Inflector.classify(word) # Line 150 |
| 19 | +Inflector.foreign_key(word) # Line 157 |
| 20 | +``` |
| 21 | + |
| 22 | +### Known Issues to Fix |
| 23 | +1. **"foot" → "foots"** instead of "feet" (currently fixed with custom override) |
| 24 | +2. **Potential other irregular plurals** that need investigation |
| 25 | +3. **Performance improvements** using Crystal's built-in methods where possible |
| 26 | + |
| 27 | +### Test Coverage |
| 28 | +- **359 lines** of comprehensive tests in `spec/core/word_transformer_spec.cr` |
| 29 | +- **Edge cases covered**: empty strings, single chars, irregular plurals, acronyms |
| 30 | +- **Performance tests**: 1000 iterations for built-in methods |
| 31 | +- **Custom conventions**: Pattern overrides and fallbacks |
| 32 | + |
| 33 | +--- |
| 34 | + |
| 35 | +## Migration Plan |
| 36 | + |
| 37 | +### Phase 1: Research & Analysis ✅ |
| 38 | + |
| 39 | +#### 1.1 Clone and Analyze Source Code |
| 40 | +- [ ] Clone `phoffer/inflector.cr` repository |
| 41 | +- [ ] Analyze source code structure and implementation |
| 42 | +- [ ] Identify the 4 methods we actually use |
| 43 | +- [ ] Document current irregular plurals/singulars |
| 44 | +- [ ] Create list of known incorrect transformations |
| 45 | + |
| 46 | +#### 1.2 Identify Improvement Opportunities |
| 47 | +- [ ] Compare with Rails ActiveSupport::Inflector for reference |
| 48 | +- [ ] Research comprehensive lists of irregular English plurals |
| 49 | +- [ ] Identify performance bottlenecks in current implementation |
| 50 | +- [ ] Document Crystal built-in methods we can leverage |
| 51 | + |
| 52 | +### Phase 2: Setup Vendored Library ✅ |
| 53 | + |
| 54 | +#### 2.1 Create Vendor Directory |
| 55 | +- [ ] Create `src/amber_cli/vendor/` directory |
| 56 | +- [ ] Create `src/amber_cli/vendor/inflector/` subdirectory |
| 57 | +- [ ] Add appropriate README and license attribution |
| 58 | + |
| 59 | +#### 2.2 Extract Required Code |
| 60 | +- [ ] Copy only the required methods and dependencies |
| 61 | +- [ ] Rename module to `AmberCLI::Vendor::Inflector` |
| 62 | +- [ ] Remove unused methods to reduce code size |
| 63 | +- [ ] Maintain original method signatures for compatibility |
| 64 | + |
| 65 | +### Phase 3: Improve Implementation ✅ |
| 66 | + |
| 67 | +#### 3.1 Fix Known Issues |
| 68 | +- [ ] Fix "foot" → "feet" (remove need for custom override) |
| 69 | +- [ ] Add comprehensive irregular plurals list |
| 70 | +- [ ] Fix any other documented incorrect transformations |
| 71 | +- [ ] Add missing irregular singulars |
| 72 | + |
| 73 | +#### 3.2 Performance Improvements |
| 74 | +- [ ] Use Crystal's `String#camelcase` instead of custom implementation |
| 75 | +- [ ] Use Crystal's `String#underscore` instead of custom implementation |
| 76 | +- [ ] Optimize regex patterns for better performance |
| 77 | +- [ ] Add memoization for expensive operations if needed |
| 78 | + |
| 79 | +#### 3.3 Enhanced Irregular Words Database |
| 80 | +- [ ] Create comprehensive IRREGULAR_PLURALS hash |
| 81 | +- [ ] Create comprehensive IRREGULAR_SINGULARS hash |
| 82 | +- [ ] Add common programming-related words (e.g., "schema" → "schemas") |
| 83 | +- [ ] Include domain-specific terms relevant to web development |
| 84 | + |
| 85 | +### Phase 4: Testing & Validation ✅ |
| 86 | + |
| 87 | +#### 4.1 Maintain Backward Compatibility |
| 88 | +- [ ] Run existing test suite to ensure no regressions |
| 89 | +- [ ] Create comparison tests between old and new implementations |
| 90 | +- [ ] Document any intentional behavior changes (bug fixes) |
| 91 | +- [ ] Ensure all 359 existing tests continue to pass |
| 92 | + |
| 93 | +#### 4.2 Enhanced Test Coverage |
| 94 | +- [ ] Add tests for all irregular plurals/singulars |
| 95 | +- [ ] Add performance benchmarks |
| 96 | +- [ ] Test edge cases with new improvements |
| 97 | +- [ ] Add tests for previously incorrect transformations |
| 98 | + |
| 99 | +#### 4.3 Integration Testing |
| 100 | +- [ ] Test with real Amber CLI workflows |
| 101 | +- [ ] Verify generator output remains consistent |
| 102 | +- [ ] Test template generation with new inflector |
| 103 | +- [ ] Validate naming conventions work correctly |
| 104 | + |
| 105 | +### Phase 5: Migration & Cleanup ✅ |
| 106 | + |
| 107 | +#### 5.1 Update Dependencies |
| 108 | +- [ ] Remove `inflector` from `shard.yml` |
| 109 | +- [ ] Update require statements to use vendored version |
| 110 | +- [ ] Update imports in `word_transformer.cr` |
| 111 | +- [ ] Remove external dependency documentation |
| 112 | + |
| 113 | +#### 5.2 Clean Up Custom Overrides |
| 114 | +- [ ] Remove custom overrides that are now fixed in vendored version |
| 115 | +- [ ] Simplify CUSTOM_PLURALS/CUSTOM_SINGULARS hashes |
| 116 | +- [ ] Update comments explaining why custom overrides remain |
| 117 | + |
| 118 | +#### 5.3 Documentation Updates |
| 119 | +- [ ] Update README with vendored library information |
| 120 | +- [ ] Document improvements made over original |
| 121 | +- [ ] Add attribution to original library authors |
| 122 | +- [ ] Document any new irregular words added |
| 123 | + |
| 124 | +--- |
| 125 | + |
| 126 | +## Implementation Checklist |
| 127 | + |
| 128 | +### 🔍 **Phase 1: Research & Analysis** |
| 129 | + |
| 130 | +#### 1.1 Source Code Analysis |
| 131 | +- [ ] `git clone https://github.com/phoffer/inflector.cr` |
| 132 | +- [ ] Document current implementation of `pluralize` method |
| 133 | +- [ ] Document current implementation of `singularize` method |
| 134 | +- [ ] Document current implementation of `classify` method |
| 135 | +- [ ] Document current implementation of `foreign_key` method |
| 136 | +- [ ] Create inventory of all irregular plurals in current library |
| 137 | +- [ ] Identify performance bottlenecks and optimization opportunities |
| 138 | + |
| 139 | +#### 1.2 Issue Research |
| 140 | +- [ ] Research comprehensive English irregular plurals (child/children, mouse/mice, etc.) |
| 141 | +- [ ] Research programming-specific plurals (schema/schemas vs schemata) |
| 142 | +- [ ] Create list of words that Rails ActiveSupport handles correctly |
| 143 | +- [ ] Document any GitHub issues in original `phoffer/inflector.cr` repo |
| 144 | +- [ ] Test original library against comprehensive word lists |
| 145 | + |
| 146 | +### 🏗️ **Phase 2: Setup Vendored Library** |
| 147 | + |
| 148 | +#### 2.1 Directory Structure |
| 149 | +- [ ] Create `src/amber_cli/vendor/inflector/` |
| 150 | +- [ ] Create `src/amber_cli/vendor/inflector/inflector.cr` (main module) |
| 151 | +- [ ] Create `src/amber_cli/vendor/inflector/irregular_words.cr` (word lists) |
| 152 | +- [ ] Create `src/amber_cli/vendor/inflector/README.md` (attribution) |
| 153 | +- [ ] Create `src/amber_cli/vendor/inflector/LICENSE` (copy original license) |
| 154 | + |
| 155 | +#### 2.2 Code Extraction |
| 156 | +- [ ] Copy `pluralize` method and dependencies |
| 157 | +- [ ] Copy `singularize` method and dependencies |
| 158 | +- [ ] Copy `classify` method and dependencies |
| 159 | +- [ ] Copy `foreign_key` method and dependencies |
| 160 | +- [ ] Rename module to `AmberCLI::Vendor::Inflector` |
| 161 | +- [ ] Remove all unused methods and constants |
| 162 | +- [ ] Maintain identical method signatures for drop-in replacement |
| 163 | + |
| 164 | +### ⚡ **Phase 3: Improve Implementation** |
| 165 | + |
| 166 | +#### 3.1 Enhanced Irregular Words |
| 167 | +- [ ] Add comprehensive irregular plurals list (appendix A of this plan) |
| 168 | +- [ ] Add irregular singulars (reverse of plurals) |
| 169 | +- [ ] Add programming-specific words: |
| 170 | + - [ ] "schema" → "schemas" (not "schemata") |
| 171 | + - [ ] "vertex" → "vertices" or "vertexes" |
| 172 | + - [ ] "index" → "indexes" (not "indices" for programming) |
| 173 | + - [ ] "matrix" → "matrices" |
| 174 | + - [ ] "datum" → "data" |
| 175 | +- [ ] Add web development specific words: |
| 176 | + - [ ] "email" → "emails" |
| 177 | + - [ ] "ajax" → "ajax calls" |
| 178 | + - [ ] "api" → "apis" |
| 179 | + |
| 180 | +#### 3.2 Fix Known Issues |
| 181 | +- [ ] Fix "foot" → "feet" (currently returns "foots") |
| 182 | +- [ ] Test and fix other known incorrect transformations |
| 183 | +- [ ] Validate against comprehensive test cases |
| 184 | +- [ ] Compare results with Rails ActiveSupport when possible |
| 185 | + |
| 186 | +#### 3.3 Performance Optimization |
| 187 | +- [ ] Replace custom camel case with Crystal's `String#camelcase` |
| 188 | +- [ ] Replace custom underscore with Crystal's `String#underscore` |
| 189 | +- [ ] Optimize regex patterns for common cases |
| 190 | +- [ ] Add benchmarking to measure improvements |
| 191 | + |
| 192 | +### 🧪 **Phase 4: Testing & Validation** |
| 193 | + |
| 194 | +#### 4.1 Backward Compatibility Testing |
| 195 | +- [ ] Run full existing test suite: `crystal spec` |
| 196 | +- [ ] Ensure all 359 tests pass without modification |
| 197 | +- [ ] Create before/after comparison tests for each method |
| 198 | +- [ ] Document any intentional behavior changes (bug fixes) |
| 199 | + |
| 200 | +#### 4.2 Enhanced Test Coverage |
| 201 | +- [ ] Add test for every word in irregular plurals list |
| 202 | +- [ ] Add test for every word in irregular singulars list |
| 203 | +- [ ] Add performance benchmarks comparing old vs new |
| 204 | +- [ ] Add edge case tests for programming terminology |
| 205 | +- [ ] Add tests for previously failing transformations |
| 206 | + |
| 207 | +#### 4.3 Integration Testing |
| 208 | +- [ ] Test `amber generate model User` (pluralization) |
| 209 | +- [ ] Test `amber generate controller Posts` (singularization) |
| 210 | +- [ ] Test scaffold generation with complex words |
| 211 | +- [ ] Verify template generation still works correctly |
| 212 | +- [ ] Test with custom naming conventions |
| 213 | + |
| 214 | +### 🔄 **Phase 5: Migration & Cleanup** |
| 215 | + |
| 216 | +#### 5.1 Dependency Updates |
| 217 | +- [ ] Remove `inflector:` block from `shard.yml` |
| 218 | +- [ ] Update `require "inflector"` to `require "./vendor/inflector/inflector"` |
| 219 | +- [ ] Update method calls from `Inflector.` to `AmberCLI::Vendor::Inflector.` |
| 220 | +- [ ] Test compilation: `crystal build src/amber_cli.cr` |
| 221 | + |
| 222 | +#### 5.2 Code Cleanup |
| 223 | +- [ ] Remove custom overrides that are now fixed: |
| 224 | + - [ ] Remove "foot" → "feet" from CUSTOM_PLURALS if fixed |
| 225 | + - [ ] Clean up any other custom overrides that are redundant |
| 226 | +- [ ] Update comments explaining remaining custom overrides |
| 227 | +- [ ] Simplify word_transformer.cr if possible |
| 228 | + |
| 229 | +#### 5.3 Documentation |
| 230 | +- [ ] Update README.md with vendored library section |
| 231 | +- [ ] Document improvements over original library |
| 232 | +- [ ] Add attribution: "Based on phoffer/inflector.cr" |
| 233 | +- [ ] Update CHANGELOG with migration details |
| 234 | +- [ ] Add documentation for new irregular words added |
| 235 | + |
| 236 | +--- |
| 237 | + |
| 238 | +## Quality Assurance Checklist |
| 239 | + |
| 240 | +### 📊 **Performance Requirements** |
| 241 | +- [ ] New implementation must be ≥ same speed as original |
| 242 | +- [ ] Built-in Crystal methods should improve performance for camelcase/underscore |
| 243 | +- [ ] Memory usage should be equal or better |
| 244 | +- [ ] Benchmark against 1000+ word transformations |
| 245 | + |
| 246 | +### 🔒 **Compatibility Requirements** |
| 247 | +- [ ] 100% backward compatibility for all existing functionality |
| 248 | +- [ ] All existing tests must pass without modification |
| 249 | +- [ ] Same method signatures and return types |
| 250 | +- [ ] Same error handling behavior |
| 251 | + |
| 252 | +### 📈 **Improvement Requirements** |
| 253 | +- [ ] Must fix "foot" → "feet" issue |
| 254 | +- [ ] Must add at least 50 additional irregular plurals |
| 255 | +- [ ] Must improve accuracy over original library |
| 256 | +- [ ] Must maintain or improve performance |
| 257 | + |
| 258 | +### 🧪 **Testing Requirements** |
| 259 | +- [ ] Minimum 95% test coverage for vendored code |
| 260 | +- [ ] All edge cases from original tests must pass |
| 261 | +- [ ] New irregular words must have explicit tests |
| 262 | +- [ ] Performance benchmarks must be included |
| 263 | + |
| 264 | +--- |
| 265 | + |
| 266 | +## Appendix A: Comprehensive Irregular Plurals |
| 267 | + |
| 268 | +### Core English Irregulars (Must Fix) |
| 269 | +```crystal |
| 270 | +IRREGULAR_PLURALS = { |
| 271 | + # Body parts |
| 272 | + "foot" => "feet", |
| 273 | + "tooth" => "teeth", |
| 274 | + "goose" => "geese", |
| 275 | +
|
| 276 | + # Animals |
| 277 | + "mouse" => "mice", |
| 278 | + "louse" => "lice", |
| 279 | + "ox" => "oxen", |
| 280 | +
|
| 281 | + # People |
| 282 | + "child" => "children", |
| 283 | + "person" => "people", |
| 284 | + "man" => "men", |
| 285 | + "woman" => "women", |
| 286 | +
|
| 287 | + # Latin/Greek origins |
| 288 | + "datum" => "data", |
| 289 | + "genus" => "genera", |
| 290 | + "corpus" => "corpora", |
| 291 | + "opus" => "opera", |
| 292 | +
|
| 293 | + # Special cases |
| 294 | + "sheep" => "sheep", |
| 295 | + "deer" => "deer", |
| 296 | + "fish" => "fish", |
| 297 | + "series" => "series", |
| 298 | + "species" => "species", |
| 299 | +} |
| 300 | +``` |
| 301 | + |
| 302 | +### Programming-Specific Words |
| 303 | +```crystal |
| 304 | +PROGRAMMING_PLURALS = { |
| 305 | + "schema" => "schemas", # Not "schemata" in programming |
| 306 | + "index" => "indexes", # Not "indices" in programming |
| 307 | + "vertex" => "vertices", |
| 308 | + "matrix" => "matrices", |
| 309 | + "regex" => "regexes", |
| 310 | + "ajax" => "ajax", |
| 311 | + "api" => "apis", |
| 312 | +} |
| 313 | +``` |
| 314 | + |
| 315 | +--- |
| 316 | + |
| 317 | +## Success Criteria |
| 318 | + |
| 319 | +### ✅ **Migration Complete When:** |
| 320 | +1. External `inflector` dependency removed from `shard.yml` |
| 321 | +2. All tests pass: `crystal spec` returns 0 failures |
| 322 | +3. CLI compiles without errors: `crystal build src/amber_cli.cr` |
| 323 | +4. Performance equal or better than original |
| 324 | +5. At least 5 previously incorrect words now fixed |
| 325 | +6. Comprehensive test coverage for all new irregular words |
| 326 | + |
| 327 | +### 🎯 **Quality Metrics:** |
| 328 | +- **Test Coverage**: >95% for vendored inflector code |
| 329 | +- **Performance**: ≥100% of original speed |
| 330 | +- **Accuracy**: ≥99% correct on standard English test cases |
| 331 | +- **Maintainability**: Well-documented, clear code structure |
| 332 | +- **Compatibility**: 100% backward compatible |
| 333 | + |
| 334 | +--- |
| 335 | + |
| 336 | +## Timeline Estimate |
| 337 | + |
| 338 | +- **Phase 1 (Research)**: 4-6 hours |
| 339 | +- **Phase 2 (Setup)**: 2-3 hours |
| 340 | +- **Phase 3 (Improve)**: 6-8 hours |
| 341 | +- **Phase 4 (Testing)**: 4-6 hours |
| 342 | +- **Phase 5 (Migration)**: 2-3 hours |
| 343 | + |
| 344 | +**Total**: ~18-26 hours of focused development time |
| 345 | + |
| 346 | +--- |
| 347 | + |
| 348 | +## Risk Mitigation |
| 349 | + |
| 350 | +### 🚨 **Potential Risks & Solutions:** |
| 351 | + |
| 352 | +1. **Breaking Changes** |
| 353 | + - *Risk*: Vendored version behaves differently |
| 354 | + - *Solution*: Comprehensive comparison testing before migration |
| 355 | + |
| 356 | +2. **Performance Regression** |
| 357 | + - *Risk*: New implementation slower than original |
| 358 | + - *Solution*: Benchmark at each step, optimize hot paths |
| 359 | + |
| 360 | +3. **Missing Edge Cases** |
| 361 | + - *Risk*: Original library handles cases we missed |
| 362 | + - *Solution*: Extract complete test suite from original library |
| 363 | + |
| 364 | +4. **Maintenance Burden** |
| 365 | + - *Risk*: Now responsible for maintaining inflector code |
| 366 | + - *Solution*: Well-documented, simple implementation with comprehensive tests |
| 367 | + |
| 368 | +--- |
| 369 | + |
| 370 | +This plan ensures a safe, systematic migration that improves functionality while maintaining complete backward compatibility. |
0 commit comments