]>
Commit | Line | Data |
---|---|---|
d9579d0f AL |
1 | //! This module contains utilities for outputting metadata for diagnostic errors. |
2 | //! | |
3 | //! Each set of errors is mapped to a metadata file by a name, which is | |
4 | //! currently always a crate name. | |
5 | ||
6 | use std::collections::BTreeMap; | |
ff7c6d11 | 7 | use std::env; |
62682a34 SL |
8 | use std::fs::{remove_file, create_dir_all, File}; |
9 | use std::io::Write; | |
ff7c6d11 | 10 | use std::path::PathBuf; |
d9579d0f | 11 | use std::error::Error; |
62682a34 | 12 | use rustc_serialize::json::as_json; |
d9579d0f | 13 | |
ff7c6d11 | 14 | use syntax_pos::{Span, FileName}; |
9fa01778 XL |
15 | |
16 | use crate::ext::base::ExtCtxt; | |
17 | use crate::diagnostics::plugin::{ErrorMap, ErrorInfo}; | |
d9579d0f | 18 | |
d9579d0f AL |
19 | /// JSON encodable/decodable version of `ErrorInfo`. |
20 | #[derive(PartialEq, RustcDecodable, RustcEncodable)] | |
21 | pub struct ErrorMetadata { | |
22 | pub description: Option<String>, | |
23 | pub use_site: Option<ErrorLocation> | |
24 | } | |
25 | ||
26 | /// Mapping from error codes to metadata that can be (de)serialized. | |
27 | pub type ErrorMetadataMap = BTreeMap<String, ErrorMetadata>; | |
28 | ||
29 | /// JSON encodable error location type with filename and line number. | |
30 | #[derive(PartialEq, RustcDecodable, RustcEncodable)] | |
31 | pub struct ErrorLocation { | |
ff7c6d11 | 32 | pub filename: FileName, |
d9579d0f AL |
33 | pub line: usize |
34 | } | |
35 | ||
36 | impl ErrorLocation { | |
9fa01778 XL |
37 | /// Creates an error location from a span. |
38 | pub fn from_span(ecx: &ExtCtxt<'_>, sp: Span) -> ErrorLocation { | |
b7449926 | 39 | let loc = ecx.source_map().lookup_char_pos_adj(sp.lo()); |
d9579d0f AL |
40 | ErrorLocation { |
41 | filename: loc.filename, | |
42 | line: loc.line | |
43 | } | |
44 | } | |
45 | } | |
46 | ||
9fa01778 | 47 | /// Gets the directory where metadata for a given `prefix` should be stored. |
62682a34 SL |
48 | /// |
49 | /// See `output_metadata`. | |
50 | pub fn get_metadata_dir(prefix: &str) -> PathBuf { | |
ff7c6d11 XL |
51 | env::var_os("RUSTC_ERROR_METADATA_DST") |
52 | .map(PathBuf::from) | |
53 | .expect("env var `RUSTC_ERROR_METADATA_DST` isn't set") | |
54 | .join(prefix) | |
d9579d0f AL |
55 | } |
56 | ||
62682a34 SL |
57 | /// Map `name` to a path in the given directory: <directory>/<name>.json |
58 | fn get_metadata_path(directory: PathBuf, name: &str) -> PathBuf { | |
59 | directory.join(format!("{}.json", name)) | |
d9579d0f AL |
60 | } |
61 | ||
62682a34 SL |
62 | /// Write metadata for the errors in `err_map` to disk, to a file corresponding to `prefix/name`. |
63 | /// | |
64 | /// For our current purposes the prefix is the target architecture and the name is a crate name. | |
65 | /// If an error occurs steps will be taken to ensure that no file is created. | |
9fa01778 | 66 | pub fn output_metadata(ecx: &ExtCtxt<'_>, prefix: &str, name: &str, err_map: &ErrorMap) |
8faf50e0 | 67 | -> Result<(), Box<dyn Error>> |
d9579d0f | 68 | { |
62682a34 SL |
69 | // Create the directory to place the file in. |
70 | let metadata_dir = get_metadata_dir(prefix); | |
54a0048b | 71 | create_dir_all(&metadata_dir)?; |
d9579d0f | 72 | |
62682a34 SL |
73 | // Open the metadata file. |
74 | let metadata_path = get_metadata_path(metadata_dir, name); | |
54a0048b | 75 | let mut metadata_file = File::create(&metadata_path)?; |
d9579d0f AL |
76 | |
77 | // Construct a serializable map. | |
78 | let json_map = err_map.iter().map(|(k, &ErrorInfo { description, use_site })| { | |
79 | let key = k.as_str().to_string(); | |
80 | let value = ErrorMetadata { | |
81 | description: description.map(|n| n.as_str().to_string()), | |
82 | use_site: use_site.map(|sp| ErrorLocation::from_span(ecx, sp)) | |
83 | }; | |
84 | (key, value) | |
85 | }).collect::<ErrorMetadataMap>(); | |
86 | ||
62682a34 SL |
87 | // Write the data to the file, deleting it if the write fails. |
88 | let result = write!(&mut metadata_file, "{}", as_json(&json_map)); | |
89 | if result.is_err() { | |
54a0048b | 90 | remove_file(&metadata_path)?; |
62682a34 | 91 | } |
54a0048b | 92 | Ok(result?) |
d9579d0f | 93 | } |