insta icon indicating copy to clipboard operation
insta copied to clipboard

Find a different syntax for inline snapshot so that cargo fmt can work

Open tisonkun opened this issue 1 year ago • 8 comments

Currently, @r###"..."### the inline snapshot syntax is invalid during cargo fmt analyze and cannot be formatted.

Perhaps a different syntax (e.g. i=r"") can be used for helping in this case.

tisonkun avatar Jun 08 '24 09:06 tisonkun

Check out https://github.com/mitsuhiko/insta/issues/456, both this:

Would be great for inline snapshots to work with rustfmt, but don't think there's a way — if the inline snapshot is a normal expression without special syntax (such as @), it's not possible to discriminate between (name, value) and (value, snapshot)

...and the broader discussion.

I agree that it would be great to allow rustfmt to work, though lots of other tradeoffs...

max-sixty avatar Jun 08 '24 20:06 max-sixty

Sharing my workaround:

  1. Before cargo fmt, run sg scan --rule <path to yaml> (need to install ast-grep)
# Replace `@` with `-` in macros
id: pre-format
language: Rust
rule:
  pattern: '@'
  precedes:
    kind: raw_string_literal
  inside:
    kind: macro_invocation
    stopBy: end
fix: '-'
  1. Run cargo fmt

  2. Finally, run sg scan --rule <path to yaml>

# Replace `-` with `@` in macros
id: post-format
language: Rust
rule:
  pattern: '-'
  precedes:
    kind: raw_string_literal
  inside:
    kind: macro_invocation
    stopBy: end
fix: '@'

andylokandy avatar Sep 22 '24 18:09 andylokandy

from https://github.com/mitsuhiko/insta/issues/605#issuecomment-2366916072

rustfmt is requiring a syntactical valid expression, but not semantically valid expression. Thus there is room to find such patterns. For example, my using -r###""### utilize the fact that unary minus to a string is valid in syntax but invalid in type. Symbols like *, !, ?(postfix) are also possible.

OK, that's quite interesting.

max-sixty avatar Sep 22 '24 19:09 max-sixty

@andylokandy, on further reflection, I'm not sure there's a syntax which would actually work here?

We need to identify the type of macro in the macro_rules!. Currently we do that with @literal and:

  • If we use something syntactically valid like !"Testing", then the macro has ambiguities
  • If we use something like +"Testing", then cargo fmt no longer works

Am I right in thinking this is the full set of options? Or is there some other way around it?

Here's a WIP branch with me trying things (originally tried +, then tried !...): https://github.com/max-sixty/insta/tree/plus

max-sixty avatar Sep 22 '24 21:09 max-sixty

If we use something syntactically valid like !"Testing", then the macro has ambiguities

Could you provide a example of the ambiguities? I may not fully understand it. (and what if *?)

andylokandy avatar Sep 23 '24 06:09 andylokandy

Try my branch — the rust compiler will complain about ambiguities in the macro...

max-sixty avatar Sep 23 '24 16:09 max-sixty

Got it. It's a limitation of the compiler (lack of backtrack when parsing macro), but there is a nasty way to get through: instead of directly defining the pattern arms, consume the tokens one by one. In detail:

  1. receive input as $($input:tt)*
  2. match one token a time, until the pattern is determined
  3. call sub-macro for each pattern

Here is a demo of this technique.

andylokandy avatar Sep 23 '24 19:09 andylokandy

Ah OK cool!

If you want to make a branch / draft PR with this on, I think that would be quite helpful. Assuming the interface for users is still nice and internal stuff is well-documented, I would be +1 on this.

(...though I'm not the sole decider, to set expectations)

max-sixty avatar Sep 23 '24 19:09 max-sixty