Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testament diff rework - unstructured, structured #206

Merged
merged 1 commit into from
Feb 6, 2022

Conversation

haxscramper
Copy link
Collaborator

@haxscramper haxscramper commented Jan 26, 2022

wip, todo:

  • adequate commit message. I could not bear the sight of some testament parts, specifically addResult, so I split it up at least a little, and there were a couple of other entries that I had to reformat because I could not meaningfully work with them any other way, because they were SO badly implemented.
  • squash edits
  • --msgFormat documentation
  • examples of the structured messages for the compiler output, add documentation to nimc.rst
  • Remove temporary attempts for message formatting - I'm sure that toHtml for colored text is not needed
  • Add better documentation for #[tt. inline annotations testament
  • More explanation comments about formatting logic - those are almost always hard to reason about, random string bits placed all over the code don't help to understand anything either
  • make unified diff join adjacent edit lines as well, the -+-+ is less readable compared to --++. Make this configurable, sometimes -+-+ with inline change annotations is more useful than --++ that was joined.
  • more tests for structural comparison - no difference, has difference, more given output with a single expected one, equally weighted options
  • remove debug prints from tests, they fail megatest hack
  • nimsuggest fails because of missing sexp import - it was moved, this needs to be documented
  • add more descriptions for testament spec fields, nobody is going to do this "look in the code" bullshit if there are no comments there even. And the link is constantly broken anyway, and it doesn't even link to the type definition, instead links to the source code of the parse for whatever reason.
  • [?] if annotation is inline, actually show the surrounding code and place arrows around maybe, because it is not clear how location was inferred from the position of the ^. Possibly this is an overkill, but again, at least trying this out is necessary.
  • Examples of test files that use new structured reporting
  • grouped and ungrouped unified diffs

Changes for regular diff:

Convert this:

image

to this

image

and also make testament support structured reports that would allow you to get this

image

Out of this

discard """
nimoutFormat: sexp
cmd: "nim c --msgFormat=sexp --skipUserCfg --hints=on --hint=all:off --hint=User:on --filenames:canonical $file"
nimout: '''
(User :str "User Hint" :location ("tfile.nim" 8 _))
'''
"""

{.hint: "User hint".}

{.hint: "Another hint".} #[tt.Hint
      ^ (User :str "Another hint") ]#

Note how structured diff properly handles both inline and nimout error messages whereas with unstructured diff testament can only report half of the problems.

@haxscramper haxscramper changed the title . Testament diff rework - unstructured, structured Jan 26, 2022
@haxscramper
Copy link
Collaborator Author

bors try

bors bot added a commit that referenced this pull request Jan 26, 2022
@haxscramper haxscramper reopened this Jan 26, 2022
@bors
Copy link
Contributor

bors bot commented Jan 26, 2022

try

Build failed:

@haxscramper
Copy link
Collaborator Author

haxscramper commented Jan 27, 2022

image

Sweep-grouping inline diffs is certainly necessary

that's what was generated before

image

@saem
Copy link
Collaborator

saem commented Feb 2, 2022

I tried to review, little too tired to digest this tonight, will try again tomorrow.

Copy link
Collaborator

@saem saem left a comment

Choose a reason for hiding this comment

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

Reviewed code, will do docs tomorrow 🤞

compiler/front/sexp_reporter.nim Outdated Show resolved Hide resolved
compiler/front/sexp_reporter.nim Outdated Show resolved Hide resolved
compiler/front/sexp_reporter.nim Outdated Show resolved Hide resolved

proc sexp*[E: enum](e: E): SexpNode = newSSymbol($e)

proc sexpItems*[T](s: T): SexpNode =
Copy link
Collaborator

@saem saem Feb 2, 2022

Choose a reason for hiding this comment

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

Can we move this below the other s-exp procs, it flows better and if the T is one of the ones below it'll not be confusing if some declares a new one but this doesn't take it into account up here.

Also, seriously this probably shouldn't compile.

Copy link
Collaborator Author

@haxscramper haxscramper Feb 2, 2022

Choose a reason for hiding this comment

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

Also, seriously this process shouldn't compile.

what 'process' are you talking about and why it shouldn't compile?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Typo, yeah it's strange that it's allowed by the compiler.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

it's strange that it's allowed by the compiler.

again, why?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Because a type T is not guaranteed to have an items, yes?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It won't compile when I instantiate the proc like every other generic, so I guess this is not allowed? I just don't get why this remark is attached to a definition. sexp two lines above can have $ defined as {.error.} and it would've been an instantiation error as well

sexp(writeConf.toMsgFilename(id))


iterator sexpFields[T](obj: T, ignore: seq[string] = @[]): SexpNode =
Copy link
Collaborator

Choose a reason for hiding this comment

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

So weird that this works without constraints, feels like a bug.

I think T should have an a type constraint of object | tuple

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Why does it feel like a bug? Generic iterator, accepts generic type T, works as intended

I think T should have an a type constraint of object | tuple

Can be clarified later, but the fact it works without it doesn't really make it a bug IMO

Copy link
Collaborator

@saem saem Feb 2, 2022

Choose a reason for hiding this comment

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

It absolutely is a bug because there is no guarantee you can iterate over T?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What do you mean "can't iterator over T"? The iterator is defined for T therefore I can iterate over it, I don't see any bugs here

Copy link
Collaborator

Choose a reason for hiding this comment

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

T is not guaranteed to have fields for fieldPairs to work, it might be out of scope for this PR, but it's silly that between the stdlib and the compiler that this is allowed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You are talking about need for 'HasFields' concept or something like that here, otherwise it is a perfectly fine generic that would generate a perfectly fine compilation error on instantiation saying that there are no fields in here. I don't understand where the "bug" part comes from here. Just like the sexpItems above - it is instantiation error, just like every other generic proc. I can put object|tuple there, but that would just make code clearer, it won't make it more correct (as in - reject malformed program that would've compiled previously) in any way. If there is no field pairs the code does not compile, pointing to "instantiation of X...". If there are field pairs the code compiles.

compiler/front/sexp_reporter.nim Outdated Show resolved Hide resolved
compiler/front/sexp_reporter.nim Show resolved Hide resolved
@haxscramper
Copy link
Collaborator Author

I will update the PR for review comments after you review the docs. Also, please do read the tests as well - I added some explanations about how diff is intended to function, and it's behavior there.

Copy link
Collaborator

@saem saem left a comment

Choose a reason for hiding this comment

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

Reviewed. There is plenty about the differencing I don't understand. So that'll be fun to dig into later.

Mostly typos and doc adjustments.

doc/nimc.rst Outdated Show resolved Hide resolved
doc/testament.rst Show resolved Hide resolved
doc/testament.rst Show resolved Hide resolved
doc/testament.rst Outdated Show resolved Hide resolved
doc/testament.rst Outdated Show resolved Hide resolved
testament/testament.nim Outdated Show resolved Hide resolved
testament/testament.nim Outdated Show resolved Hide resolved
testament/testament.nim Outdated Show resolved Hide resolved
testament/testament.nim Outdated Show resolved Hide resolved
tests/stdlib/tcolordiff.nim Show resolved Hide resolved
@krux02
Copy link
Contributor

krux02 commented Feb 3, 2022

what and why printing category ""?

@haxscramper
Copy link
Collaborator Author

haxscramper commented Feb 3, 2022

I don't understand the question. The check for tests/**/t**.nim file was removed to allow testament run tlocalfile.nim - is that what you mean?

@krux02
Copy link
Contributor

krux02 commented Feb 3, 2022

I don't understand the question. The check for tests/**/t**.nim file was removed to allow testament run tlocalfile.nim - is that what you mean?

What I mean is the empty quotes in Test "tfile_regular.nim" in category ""

@haxscramper
Copy link
Collaborator Author

Fixed empty quotes, now it prints only test name for empty categories

- rework implementation of the message diff in testament. Now plaintext
  diff is implemented using built-in diff written in nim instead of calling
  into separate `git diff` command that produced noisy, colorless output
  and was completely unconfigurable.
- Add implementation of the structured message diff, structured compiler
  reports for the compiler. These changes had to be made togehter,
  otherwise it would've been a series incomplete PRs that depended on each
  other even for the purposes of testing/documentation.
  - Add s-expression formatter to the compiler output. Selected using
    `--msgFormat=sexp` (for now we have a `text` and `sexp`, in the future
    `json` must be added as well, since that's what people actually expect
    from their tooling - not some obscure data format).
  - Fix 'invalid value' error for cli switch - that bug was discovered when
    adding `msgFormat` option.
  - Add structural S-expression diff algorithm with formatting logic for
    mismatches.
  - Add `nimoutFormat: sexp` field for the testament, to allow it
    understand what kind of data will be generated by the compiler itself.
  - Clean up testament message diff handling a little and add checks for
    structural diffs where appropriate.
- Minor related changes
  - Split `strutils.addf` and reuse the interpolation string for colored
    text - otherwise all futher formatting logic looked a lot uglier than
    necessary (using `strformat.&` would require factoring out macro
    implementation parts)
  - Clean up testament documentation for different spec parts, add
    description of the structural messages.
  - More documentation all over testament implementation
  - Move `sexp` file into `experimental/` directory - it is no longer
    related directly to nimsuggest, @saem has already suggested moving it
    in nim-works#164
  - Testament no longer has a hard assertion on the path of the tested file
    `testament tfile.nim` can also work, and does not force user to create
    needlessly nested directories for purposes of simple file testing.
Copy link
Collaborator

@saem saem left a comment

Choose a reason for hiding this comment

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

Bors r+

Merge me up, Scotty!

@bors
Copy link
Contributor

bors bot commented Feb 6, 2022

Build succeeded:

@bors bors bot merged commit ce43c82 into nim-works:devel Feb 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

3 participants