Skip to content

LineRange and StringDiff invariants static checks - #34

Open
ninioArtillero wants to merge 2 commits into
masterfrom
xg/output-checks
Open

LineRange and StringDiff invariants static checks#34
ninioArtillero wants to merge 2 commits into
masterfrom
xg/output-checks

Conversation

@ninioArtillero

Copy link
Copy Markdown
Collaborator

This PR adds LiquidHaskell static checks to the DiffOutput module based on:

  • StringDiff refinement for the Diff values of this module by its implicit invariants, namely: they are always non-empty and have coherent Both values.
  • LineRange has been refined to make to make lrNumbers an ordered pair where its lrContents must fit.

The smart constructor mkLineRange was introduced to factor out the correctness check of most LineRanges.

Finally, parsePrettyDiffs are checked to reduce their input.

Comment thread src/Data/Algorithm/DiffOutput.hs Outdated
let diff = Deletion (mkLineRange leftLine lsF) (rightLine-1)
in diff : toLineRange (leftLine + length lsF) rightLine rs
-- Skip empty 'Second' and 'First' entries.
-- NOTE: Both these cases are unreachable.

@facundominguez facundominguez Jul 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, they are unreachable if the caller respects the invariants of StringDiff, right?

Invalid input could cause these equations to be reached, and diffToLineRanges is exported, so it may be used in unchecked ways.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, some wishful thinking here: got carried away expecting inputs to always come from the output of Diff.getGroupedDiff... but downstream users might have other ideas.

I have merged the case back so that everything is handled homogeneously.

Comment thread src/Data/Algorithm/DiffOutput.hs Outdated
in toLineRange (leftLine+lins) (rightLine+lins) rs
-- A 'Change' is introduced when an addition is followed by a deletion, or vice versa.
toLineRange leftLine rightLine (Second lsS:First lsF:rs)=
toLineRange leftLine rightLine (Second lsS@(_:_) : First lsF@(_:_) : rs) =

@facundominguez facundominguez Jul 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the need to pattern match on the lists lsS and lsF?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember that without the pattern match verification would fail, but now I just removed all the pattern matches, along with the unreachable empty value case below, and verification passes. Seems like an artifact from a previous specification approach, or maybe it became unnecessary after some recent upstream change 🤔 .

_ -> (fstLine,rs)
in ((read fstLine,read sndLine),rs3)
b = max a (read sndLine)
in ((a, b), rs3)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is changing behavior of parseRange.

Before parseRange "3,2abc" == ((3, 2), "abc").

After parseRange "3,2abc" == ((3, 3), "abc").

Comment on lines +174 to +176
in case contents of
(_:_) -> (Just $ Deletion (mkLineRange (fst r1) contents) (fst r2), rs2)
_ -> (Nothing, rs2)

@facundominguez facundominguez Jul 22, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is changing behavior of parseDel.

Before parseDel (a, b) "1,2" [] == (Just (Deletion (LineRange (a, a - 1) []) 1), []).

After parseDel (a, b) "1,2" [] == (Nothing, "").

The other parsing functions are modified in a similar way.

@facundominguez

Copy link
Copy Markdown
Contributor

It is looking to me like the changes of behavior need more of a justification, and they would be easier to spot if they were put in separate commits.

The refactoring of mkLineRange also deserves a separate commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants