Skip to content

Commit

Permalink
Rollup merge of rust-lang#46052 - oli-obk:rendered_diagnostics_in_jso…
Browse files Browse the repository at this point in the history
…n, r=petrochenkov

Include rendered diagnostic in json

r? @petrochenkov
  • Loading branch information
kennytm authored Nov 21, 2017
2 parents 9b090a0 + e7b2702 commit 0af67a4
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/librustc_errors/snippet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl MultilineAnnotation {

pub fn as_end(&self) -> Annotation {
Annotation {
start_col: self.end_col - 1,
start_col: self.end_col.saturating_sub(1),
end_col: self.end_col,
is_primary: self.is_primary,
label: self.label.clone(),
Expand Down
28 changes: 25 additions & 3 deletions src/libsyntax/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
use errors::registry::Registry;
use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, CodeMapper};
use errors::DiagnosticId;
use errors::emitter::Emitter;
use errors::emitter::{Emitter, EmitterWriter};

use std::rc::Rc;
use std::io::{self, Write};
use std::vec;
use std::sync::{Arc, Mutex};

use rustc_serialize::json::{as_json, as_pretty_json};

Expand Down Expand Up @@ -95,7 +96,7 @@ struct Diagnostic {
spans: Vec<DiagnosticSpan>,
/// Associated diagnostic messages.
children: Vec<Diagnostic>,
/// The message as rustc would render it. Currently this is always `None`
/// The message as rustc would render it.
rendered: Option<String>,
}

Expand Down Expand Up @@ -170,6 +171,27 @@ impl Diagnostic {
rendered: None,
}
});

// generate regular command line output and store it in the json

// A threadsafe buffer for writing.
#[derive(Default, Clone)]
struct BufWriter(Arc<Mutex<Vec<u8>>>);

impl Write for BufWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.lock().unwrap().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.0.lock().unwrap().flush()
}
}
let buf = BufWriter::default();
let output = buf.clone();
EmitterWriter::new(Box::new(buf), Some(je.cm.clone()), false).emit(db);
let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
let output = String::from_utf8(output).unwrap();

Diagnostic {
message: db.message(),
code: DiagnosticCode::map_opt_string(db.code.clone(), je),
Expand All @@ -178,7 +200,7 @@ impl Diagnostic {
children: db.children.iter().map(|c| {
Diagnostic::from_sub_diagnostic(c, je)
}).chain(sugg).collect(),
rendered: None,
rendered: Some(output),
}
}

Expand Down
14 changes: 13 additions & 1 deletion src/test/ui/lint/unused_parens_json_suggestion.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,17 @@
"rendered": null
}
],
"rendered": null
"rendered": "warning: unnecessary parentheses around assigned value
--> $DIR/unused_parens_json_suggestion.rs:24:14
|
24 | let _a = (1 / (2 + 3));
| ^^^^^^^^^^^^^ help: remove these parentheses
|
note: lint level defined here
--> $DIR/unused_parens_json_suggestion.rs:19:9
|
19 | #![warn(unused_parens)]
| ^^^^^^^^^^^^^

"
}
138 changes: 123 additions & 15 deletions src/test/ui/lint/use_suggestion_json.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,72 @@
"message": "cannot find type `Iter` in this scope",
"code": {
"code": "E0412",
"explanation": "/nThe type name used is not in scope./n/nErroneous code examples:/n/n```compile_fail,E0412/nimpl Something {} // error: type name `Something` is not in scope/n/n// or:/n/ntrait Foo {/n fn bar(N); // error: type name `N` is not in scope/n}/n/n// or:/n/nfn foo(x: T) {} // type name `T` is not in scope/n```/n/nTo fix this error, please verify you didn't misspell the type name, you did/ndeclare it or imported it into the scope. Examples:/n/n```/nstruct Something;/n/nimpl Something {} // ok!/n/n// or:/n/ntrait Foo {/n type N;/n/n fn bar(_: Self::N); // ok!/n}/n/n// or:/n/nfn foo<T>(x: T) {} // ok!/n```/n/nAnother case that causes this error is when a type is imported into a parent/nmodule. To fix this, you can follow the suggestion and use File directly or/n`use super::File;` which will import the types from the parent namespace. An/nexample that causes this error is below:/n/n```compile_fail,E0412/nuse std::fs::File;/n/nmod foo {/n fn some_function(f: File) {}/n}/n```/n/n```/nuse std::fs::File;/n/nmod foo {/n // either/n use super::File;/n // or/n // use std::fs::File;/n fn foo(f: File) {}/n}/n# fn main() {} // don't insert it for us; that'll break imports/n```/n"
"explanation": "
The type name used is not in scope.

Erroneous code examples:

```compile_fail,E0412
impl Something {} // error: type name `Something` is not in scope

// or:

trait Foo {
fn bar(N); // error: type name `N` is not in scope
}

// or:

fn foo(x: T) {} // type name `T` is not in scope
```

To fix this error, please verify you didn't misspell the type name, you did
declare it or imported it into the scope. Examples:

```
struct Something;

impl Something {} // ok!

// or:

trait Foo {
type N;

fn bar(_: Self::N); // ok!
}

// or:

fn foo<T>(x: T) {} // ok!
```

Another case that causes this error is when a type is imported into a parent
module. To fix this, you can follow the suggestion and use File directly or
`use super::File;` which will import the types from the parent namespace. An
example that causes this error is below:

```compile_fail,E0412
use std::fs::File;

mod foo {
fn some_function(f: File) {}
}
```

```
use std::fs::File;

mod foo {
// either
use super::File;
// or
// use std::fs::File;
fn foo(f: File) {}
}
# fn main() {} // don't insert it for us; that'll break imports
```
"
},
"level": "error",
"spans": [
Expand Down Expand Up @@ -50,7 +115,9 @@
}
],
"label": null,
"suggested_replacement": "use std::collections::binary_heap::Iter;/n/n",
"suggested_replacement": "use std::collections::binary_heap::Iter;

",
"expansion": null
},
{
Expand All @@ -70,7 +137,9 @@
}
],
"label": null,
"suggested_replacement": "use std::collections::btree_map::Iter;/n/n",
"suggested_replacement": "use std::collections::btree_map::Iter;

",
"expansion": null
},
{
Expand All @@ -90,7 +159,9 @@
}
],
"label": null,
"suggested_replacement": "use std::collections::btree_set::Iter;/n/n",
"suggested_replacement": "use std::collections::btree_set::Iter;

",
"expansion": null
},
{
Expand All @@ -110,7 +181,9 @@
}
],
"label": null,
"suggested_replacement": "use std::collections::hash_map::Iter;/n/n",
"suggested_replacement": "use std::collections::hash_map::Iter;

",
"expansion": null
},
{
Expand All @@ -130,7 +203,9 @@
}
],
"label": null,
"suggested_replacement": "use std::collections::hash_set::Iter;/n/n",
"suggested_replacement": "use std::collections::hash_set::Iter;

",
"expansion": null
},
{
Expand All @@ -150,7 +225,9 @@
}
],
"label": null,
"suggested_replacement": "use std::collections::linked_list::Iter;/n/n",
"suggested_replacement": "use std::collections::linked_list::Iter;

",
"expansion": null
},
{
Expand All @@ -170,7 +247,9 @@
}
],
"label": null,
"suggested_replacement": "use std::collections::vec_deque::Iter;/n/n",
"suggested_replacement": "use std::collections::vec_deque::Iter;

",
"expansion": null
},
{
Expand All @@ -190,7 +269,9 @@
}
],
"label": null,
"suggested_replacement": "use std::option::Iter;/n/n",
"suggested_replacement": "use std::option::Iter;

",
"expansion": null
},
{
Expand All @@ -210,7 +291,9 @@
}
],
"label": null,
"suggested_replacement": "use std::path::Iter;/n/n",
"suggested_replacement": "use std::path::Iter;

",
"expansion": null
},
{
Expand All @@ -230,7 +313,9 @@
}
],
"label": null,
"suggested_replacement": "use std::result::Iter;/n/n",
"suggested_replacement": "use std::result::Iter;

",
"expansion": null
},
{
Expand All @@ -250,7 +335,9 @@
}
],
"label": null,
"suggested_replacement": "use std::slice::Iter;/n/n",
"suggested_replacement": "use std::slice::Iter;

",
"expansion": null
},
{
Expand All @@ -270,21 +357,42 @@
}
],
"label": null,
"suggested_replacement": "use std::sync::mpsc::Iter;/n/n",
"suggested_replacement": "use std::sync::mpsc::Iter;

",
"expansion": null
}
],
"children": [],
"rendered": null
}
],
"rendered": null
"rendered": "error[E0412]: cannot find type `Iter` in this scope
--> $DIR/use_suggestion_json.rs:20:12
|
20 | let x: Iter;
| ^^^^ not found in this scope
help: possible candidates are found in other modules, you can import them into scope
|
19 | use std::collections::binary_heap::Iter;
|
19 | use std::collections::btree_map::Iter;
|
19 | use std::collections::btree_set::Iter;
|
19 | use std::collections::hash_map::Iter;
|
and 8 other candidates

"
}
{
"message": "aborting due to previous error",
"code": null,
"level": "error",
"spans": [],
"children": [],
"rendered": null
"rendered": "error: aborting due to previous error

"
}
18 changes: 14 additions & 4 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2424,15 +2424,25 @@ actual:\n\
fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String {
let parent_dir = self.testpaths.file.parent().unwrap();
let cflags = self.props.compile_flags.join(" ");
let parent_dir_str = if cflags.contains("--error-format json")
|| cflags.contains("--error-format pretty-json") {
let json = cflags.contains("--error-format json") ||
cflags.contains("--error-format pretty-json");
let parent_dir_str = if json {
parent_dir.display().to_string().replace("\\", "\\\\")
} else {
parent_dir.display().to_string()
};

let mut normalized = output.replace(&parent_dir_str, "$DIR")
.replace("\\\\", "\\") // denormalize for paths on windows
let mut normalized = output.replace(&parent_dir_str, "$DIR");

if json {
// escaped newlines in json strings should be readable
// in the stderr files. There's no point int being correct,
// since only humans process the stderr files.
// Thus we just turn escaped newlines back into newlines.
normalized = normalized.replace("\\n", "\n");
}

normalized = normalized.replace("\\\\", "\\") // denormalize for paths on windows
.replace("\\", "/") // normalize for paths on windows
.replace("\r\n", "\n") // normalize for linebreaks on windows
.replace("\t", "\\t"); // makes tabs visible
Expand Down

0 comments on commit 0af67a4

Please sign in to comment.