elm / compiler

Compiler for Elm, a functional language for reliable webapps.
https://elm-lang.org/
BSD 3-Clause "New" or "Revised" License
7.48k stars 659 forks source link

`--report json` prints invalid JSON on "NO TABS" error #2259

Open lydell opened 2 years ago

lydell commented 2 years ago

Quick Summary: --report json prints invalid JSON on "NO TABS" error

SSCCE

# Start a fresh project.
❯ elm init

# Create an Elm file with a single tab character in it.
# (Tab characters are not allowed in Elm source code.)
❯ printf '\t' > Main.elm

# Type check with JSON output, and try to parse that with Node.js.
❯ elm make --output /dev/null Main.elm --report json 2>&1 | node -p 'JSON.parse(fs.readFileSync(process.stdin.fd, "utf8"))'
undefined:1
{"type":"compile-errors","errors":[{"path":"Main.elm","name":"???","problems":[{"title":"NO TABS","region":{"start":{"line":1,"column":1},"end":{"line":1,"column":1}},"message":["I ran into a tab, but tabs are not allowed in Elm files.\n\n1|   \n   ",{"bold":false,"underline":false,"color":"RED","string":"^"},"\nReplace the tab with spaces."]}]}]}
                                                                                                                                                                                                                                                  ^

SyntaxError: Unexpected token    in JSON at position 242
    at JSON.parse (<anonymous>)
    at [eval]:1:6
    at Script.runInThisContext (node:vm:129:12)
    at Object.runInThisContext (node:vm:305:38)
    at node:internal/process/execution:76:19
    at [eval]-wrapper:6:22
    at evalScript (node:internal/process/execution:75:60)
    at node:internal/main/eval_string:27:3

# Workaround: Replace all tab characters with \t.
❯ elm make --output /dev/null Main.elm --report json 2>&1 | node -p 'JSON.parse(fs.readFileSync(process.stdin.fd, "utf8").replace(/\t/g, "\\\\t"))'
{
  type: 'compile-errors',
  errors: [ { path: 'Main.elm', name: '???', problems: [Array] } ]
}

Additional Details

The JSON spec (see the sidebar to the right) defines a JSON string as:

string
    '"' characters '"'

characters
    ""
    character characters

character
    '0020' . '10FFFF' - '"' - '\'
    '\' escape

As you can see, a “character” can be anything from U+0020 (regular space) to U+10FFFF, except double quote and backslash (because of escapes). (How to read that syntax.) A tab character is U+0009, which is outside of that range.

Here’s a StackOverflow answer discussing tabs in JSON

Luckily, consumers of --report json can replace literal tab characters with \t and the parse.

github-actions[bot] commented 2 years ago

Thanks for reporting this! To set expectations:

Finally, please be patient with the core team. They are trying their best with limited resources.