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

Some escapes are unexpectedly modified in character literal patterns #1372

Closed
2 of 3 tasks
vain0x opened this issue Jan 18, 2021 · 3 comments · Fixed by #1375
Closed
2 of 3 tasks

Some escapes are unexpectedly modified in character literal patterns #1372

vain0x opened this issue Jan 18, 2021 · 3 comments · Fixed by #1375

Comments

@vain0x
Copy link
Contributor

vain0x commented Jan 18, 2021

Issue created from fantomas-online

Code

match char 0 with
| '\''
| '\"'
| '\x00'
| '\u0000'
| _ -> ()

Result

match char 0 with
| '''
| '"'
| '�'
| '�'
| _ -> ()

Problem description

In character literal patterns, hex escape sequences, unicode escape sequences and single/double quote escape sequences are modified (unescaped). Expected behavior is that these literals are kept unchanged.

Extra information

  • The formatted result breaks by code.
  • The formatted result gives compiler warnings.
  • I or my company would be willing to help fix this.

Options

Fantomas Master at 01/17/2021 13:01:42 - b36e5a5

Default Fantomas configuration

Did you know that you can ignore files when formatting from fantomas-tool or the FAKE targets by using a .fantomasignore file?

vain0x added a commit to vain0x/fantomas that referenced this issue Jan 19, 2021
vain0x added a commit to vain0x/fantomas that referenced this issue Jan 19, 2021
@nojaf
Copy link
Contributor

nojaf commented Jan 20, 2021

Hello @vain0x, thank you for reporting this issue and showing interest in the project.

The nature of this problem is that the AST does not represent anymore what the user originally typed.

ImplFile
  (ParsedImplFileInput
     ("tmp.fsx", true, QualifiedNameOfFile Tmp$fsx, [], [],
      [SynModuleOrNamespace
         ([Tmp], false, AnonModule,
          [DoExpr
             (NoDebugPointAtDoBinding,
              Match
                (DebugPointAtBinding tmp.fsx (1,0--1,17) IsSynthetic=false,
                 App
                   (NonAtomic, false, Ident char,
                    Const (Int32 0, tmp.fsx (1,11--1,12) IsSynthetic=false),
                    tmp.fsx (1,6--1,12) IsSynthetic=false),
                 [Clause
                    (Or
                       (Or
                          (Or
                             (Or
                                (Const
                                   (Char '\'',
                                    tmp.fsx (2,2--2,6) IsSynthetic=false),
                                 Const
                                   (Char '"',
                                    tmp.fsx (3,2--3,6) IsSynthetic=false),
                                 tmp.fsx (2,2--3,6) IsSynthetic=false),
                              Const
                                (Char '\000',
                                 tmp.fsx (4,2--4,8) IsSynthetic=false),
                              tmp.fsx (2,2--4,8) IsSynthetic=false),
                           Const
                             (Char '\000', tmp.fsx (5,2--5,10) IsSynthetic=false),
                           tmp.fsx (2,2--5,10) IsSynthetic=false),
                        Wild tmp.fsx (6,2--6,3) IsSynthetic=false,
                        tmp.fsx (2,2--6,3) IsSynthetic=false), None,
                     Const (Unit, tmp.fsx (6,7--6,9) IsSynthetic=false),
                     tmp.fsx (2,2--6,3) IsSynthetic=false, Yes)],
                 tmp.fsx (1,0--6,9) IsSynthetic=false),
              tmp.fsx (1,0--6,9) IsSynthetic=false)], PreXmlDocEmpty, [], None,
          tmp.fsx (1,0--7,0) IsSynthetic=false)], (true, true)))

Notice the last two Char '\000',. In the future, I'd like to solve these things in the F# compiler.

For now, we can work around this with trivia. (capturing the original char contents via the F# tokens).

image

We have a helper to detect the char content of the trivia:

TriviaHelpers.``get CharContent`` r ctx.TriviaMainNodes

This helper needs a fix, please move ``get CharContent`` to the end of the file and change it to

    let ``get CharContent`` range (nodes: Map<FsAstType, TriviaNode list>) =
        getNodesForTypes
            [ SynExpr_Const
              SynPat_Const  ]
            nodes
        |> List.tryFind (fun tv -> RangeHelpers.rangeEq tv.Range range)
        |> Option.bind
            (fun tv ->
                match tv.ContentItself with
                | Some (CharContent c) -> Some c
                | _ -> None)

This will solve the problem I believe.
Many thanks for your contribution.

@vain0x
Copy link
Contributor Author

vain0x commented Jan 20, 2021

Thanks for help!

@nojaf
Copy link
Contributor

nojaf commented Jan 20, 2021

Thanks for your first contribution to this project!

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

Successfully merging a pull request may close this issue.

2 participants