]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/diagnostics/metadata.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / libsyntax / diagnostics / metadata.rs
CommitLineData
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
6use std::collections::BTreeMap;
ff7c6d11 7use std::env;
62682a34
SL
8use std::fs::{remove_file, create_dir_all, File};
9use std::io::Write;
ff7c6d11 10use std::path::PathBuf;
d9579d0f 11use std::error::Error;
62682a34 12use rustc_serialize::json::as_json;
d9579d0f 13
ff7c6d11 14use syntax_pos::{Span, FileName};
9fa01778
XL
15
16use crate::ext::base::ExtCtxt;
17use crate::diagnostics::plugin::{ErrorMap, ErrorInfo};
d9579d0f 18
d9579d0f
AL
19/// JSON encodable/decodable version of `ErrorInfo`.
20#[derive(PartialEq, RustcDecodable, RustcEncodable)]
21pub 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.
27pub type ErrorMetadataMap = BTreeMap<String, ErrorMetadata>;
28
29/// JSON encodable error location type with filename and line number.
30#[derive(PartialEq, RustcDecodable, RustcEncodable)]
31pub struct ErrorLocation {
ff7c6d11 32 pub filename: FileName,
d9579d0f
AL
33 pub line: usize
34}
35
36impl 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`.
50pub 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
58fn 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 66pub 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}