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

Output gccrs errors in json format #30

Open
bjorn3 opened this issue Jun 28, 2021 · 7 comments
Open

Output gccrs errors in json format #30

bjorn3 opened this issue Jun 28, 2021 · 7 comments
Labels
enhancement New feature or request

Comments

@bjorn3
Copy link
Contributor

bjorn3 commented Jun 28, 2021

This allows cargo to cache them and allows programs like rust-analyzer to show errors inline. The rustc json error format consists of two parts: The rendered diagnostic as rustc would show it when not using the json error format. This is used by cargo. And the diagnostic in a structured format describing each part of the error message, like which parts of the source are underlined.

$ echo "fn foo() {} # fn bar() {}" | rustc - --error-format json |& jq
{
  "message": "expected one of `!` or `[`, found keyword `fn`",
  "code": null,
  "level": "error",
  "spans": [
    {
      "file_name": "<anon>",
      "byte_start": 14,
      "byte_end": 16,
      "line_start": 1,
      "line_end": 1,
      "column_start": 15,
      "column_end": 17,
      "is_primary": true,
      "text": [
        {
          "text": "fn foo() {} # fn bar() {}",
          "highlight_start": 15,
          "highlight_end": 17
        }
      ],
      "label": "expected one of `!` or `[`",
      "suggested_replacement": null,
      "suggestion_applicability": null,
      "expansion": null
    }
  ],
  "children": [],
  "rendered": "error: expected one of `!` or `[`, found keyword `fn`\n --> <anon>:1:15\n  |\n1 | fn foo() {} # fn bar() {}\n  |               ^^ expected one of `!` or `[`\n\n"
}
{
  "message": "aborting due to previous error",
  "code": null,
  "level": "error",
  "spans": [],
  "children": [],
  "rendered": "error: aborting due to previous error\n\n"
}

You can also pass --json diagnostic-rendered-ansi to use color ansi escape codes for the rendered diagnostic.

@CohenArthur CohenArthur added the enhancement New feature or request label Jun 28, 2021
@CohenArthur
Copy link
Member

I think this is something that should be done on the compiler side of things rather, but I'll see about opening the issues and how we can use it. On the top of your head, do you know where in the codebase cargo uses those JSONs? If not I'll look into it, thanks a lot for the issue!

@bjorn3
Copy link
Contributor Author

bjorn3 commented Jun 28, 2021

It is displayed to the user at https://github.com/rust-lang/cargo/blob/32238b474797da5b6730840219e4a487d73f2f72/src/cargo/core/compiler/mod.rs#L1255-L1288 and written to the disk for replaying during the next compilation at https://github.com/rust-lang/cargo/blob/32238b474797da5b6730840219e4a487d73f2f72/src/cargo/core/compiler/mod.rs#L1203-L1211

@bjorn3
Copy link
Contributor Author

bjorn3 commented Jun 28, 2021

I was thinking that gcc probably has it's own machine readable error format, so it may make sense to translate from this format to rustc's format in cargo-gccrs, just like it translates from rustc's options to gcc's options.

@CohenArthur
Copy link
Member

I was thinking that gcc probably has it's own machine readable error format, so it may make sense to translate from this format to rustc's format in cargo-gccrs, just like it translates from rustc's options to gcc's options.

Ah good point, I didn't think about this. I have no idea about gcc's implementation for this. @philberty @tschwinge @dkm would you know if this is implemented already and where to find it?

@dkm
Copy link
Member

dkm commented Jun 28, 2021

Never really used that, but https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Message-Formatting-Options.html gives a -fdiagnostics-format=json. Maybe you could use that and make cargo and other tools happy?

@CohenArthur
Copy link
Member

> gccrs -fdiagnostics-format=json src/main.rs &| jq .

[
  {
    "kind": "error",
    "column-origin": 1,
    "children": [],
    "locations": [
      {
        "caret": {
          "byte-column": 1,
          "display-column": 1,
          "line": 1,
          "file": "src/main.rs",
          "column": 1
        }
      },
      {
        "caret": {
          "byte-column": 1,
          "display-column": 1,
          "line": 1,
          "file": "src/main.rs",
          "column": 1
        }
      }
    ],
    "message": "expected [()] got [<integer>]"
  }
]

> rustc --error-format=json src/main.rs &| jq .

{
  "message": "mismatched types",
  "code": {
    "code": "E0308",
    "explanation": "Expected type did not match the received type.\n\nErroneous code examples:\n\n```compile_fail,E0308\nfn plus_one(x: i32) -> i32 {\n    x + 1\n}\n\nplus_one(\"Not a number\");\n//       ^^^^^^^^^^^^^^ expected `i32`, found `&str`\n\nif \"Not a bool\" {\n// ^^^^^^^^^^^^ expected `bool`, found `&str`\n}\n\nlet x: f32 = \"Not a float\";\n//     ---   ^^^^^^^^^^^^^ expected `f32`, found `&str`\n//     |\n//     expected due to this\n```\n\nThis error occurs when an expression was used in a place where the compiler\nexpected an expression of a different type. It can occur in several cases, the\nmost common being when calling a function and passing an argument which has a\ndifferent type than the matching type in the function declaration.\n"
  },
  "level": "error",
  "spans": [
    {
      "file_name": "src/main.rs",
      "byte_start": 16,
      "byte_end": 17,
      "line_start": 2,
      "line_end": 2,
      "column_start": 5,
      "column_end": 6,
      "is_primary": true,
      "text": [
        {
          "text": "    1",
          "highlight_start": 5,
          "highlight_end": 6
        }
      ],
      "label": "expected `()`, found integer",
      "suggested_replacement": null,
      "suggestion_applicability": null,
      "expansion": null
    },
    {
      "file_name": "src/main.rs",
      "byte_start": 10,
      "byte_end": 10,
      "line_start": 1,
      "line_end": 1,
      "column_start": 11,
      "column_end": 11,
      "is_primary": false,
      "text": [
        {
          "text": "fn main() {",
          "highlight_start": 11,
          "highlight_end": 11
        }
      ],
      "label": "expected `()` because of default return type",
      "suggested_replacement": null,
      "suggestion_applicability": null,
      "expansion": null
    }
  ],
  "children": [],
  "rendered": "error[E0308]: mismatched types\n --> src/main.rs:2:5\n  |\n1 | fn main() {\n  |           - expected `()` because of default return type\n2 |     1\n  |     ^ expected `()`, found integer\n\n"
}
{
  "message": "aborting due to previous error",
  "code": null,
  "level": "error",
  "spans": [],
  "children": [],
  "rendered": "error: aborting due to previous error\n\n"
}
{
  "message": "For more information about this error, try `rustc --explain E0308`.",
  "code": null,
  "level": "failure-note",
  "spans": [],
  "children": [],
  "rendered": "For more information about this error, try `rustc --explain E0308`.\n"
}

I think the message could definitely be translated. I'll look into how important this is for cargo and get on it if it is high priority. Thanks a lot @dkm I did not know about that gcc option at all!

@CohenArthur
Copy link
Member

This would also probably close #29

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants