feat(music): type-safe factories and canonical round-trip ToString/Parse#113
Merged
Conversation
…canonical ToString
…ccidental via Notation
…tring, structural equality
…e ToString/Parse/TryParse + structural equality; migrate call sites
… and chart-style progressions
…tive complexity and remove always-true check (SonarQube S3776/S2583)
… netstandard2.0 compatibility
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Summary
Gives
Semantics.Musiccompiler-enforced construction and round-trippable text. Implements thedocs/superpowers/plans/2026-07-02-music-type-safe-factories.mdplan (20 tasks, TDD, one commit each).NoteLetter/Accidentalvalue-backed enums (underlying value = natural pitch class / semitone offset) and typed factories:PitchClass.Create(NoteLetter, Accidental),Pitch.Create(NoteLetter, Accidental, octave).ToString()+Parse/TryParseon every in-scope type (PitchClass,Pitch,Interval,Duration,TimeSignature,Velocity,Tempo,Scale,Key,Chord,ChordEvent,Note,Rest,Form,Progression,Section,Arrangement), with a testedParse(x.ToString()) == xround-trip.ParsethrowsFormatException;TryParse(string?, out T?)never throws.Pitch.FromName/Mode.FromName→Parse/TryParse;Form.FromPattern→Parse/TryParse.Notationscanner dedupes the note-letter/accidental parsing acrossPitch,Chord, and roman-numeral parsing.Breaking changes
Progression.Parse(string)format changed. The bar-delimited lead-sheet parser ("C | Am | F | G") is replaced by the chart-style format ("4/4 Dm7 / G7 / | Cmaj7 / / /"): a leading time signature is now required, and beat slashes carry duration. All in-repo call sites migrated. (Decision made during implementation; the plan had not accounted for the pre-existing analysis-layer parser.)Form,Progression, andArrangement(Sectiongets it transitively) soParse(x.ToString()) == xholds — these records previously compared their list members by reference.Suggest tagging the merge commit
[major](or[minor]if the changedProgression.Parsefrom the recent analysis layer is considered not-yet-stable API).Test plan
net8.0–net10.0+netstandard2.0/netstandard2.1), 0 warnings.🤖 Generated with Claude Code