From c01e4ce74e96737f99492a185e2d170964f11556 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 11 Sep 2018 16:39:07 +0200 Subject: [PATCH] Emit used rustc invocation in the save-analysis file --- src/Cargo.toml | 1 + src/librustc_save_analysis/dump_visitor.rs | 64 +++++++++++++++++++++- src/librustc_save_analysis/json_dumper.rs | 10 +++- src/librustc_save_analysis/lib.rs | 27 +++++++-- src/librustc_save_analysis/span_utils.rs | 13 +++-- 5 files changed, 101 insertions(+), 14 deletions(-) diff --git a/src/Cargo.toml b/src/Cargo.toml index e8c44ea57c2..b4ef8754b81 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -57,6 +57,7 @@ cargo = { path = "tools/cargo" } # that we're shipping as well (to ensure that the rustfmt in RLS and the # `rustfmt` executable are the same exact version). rustfmt-nightly = { path = "tools/rustfmt" } +rls-data = { git = "https://github.com/Xanewok/rls-data", branch = "compilation-options" } # See comments in `tools/rustc-workspace-hack/README.md` for what's going on # here diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index d719d257f35..b044210c092 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -28,7 +28,8 @@ use rustc::ty::{self, TyCtxt}; use rustc_data_structures::fx::FxHashSet; -use std::path::Path; +use std::path::{Path, PathBuf}; +use std::env; use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID}; use syntax::parse::token; @@ -49,8 +50,10 @@ use span_utils::SpanUtils; use sig; -use rls_data::{CratePreludeData, Def, DefKind, GlobalCrateId, Import, ImportKind, Ref, RefKind, - Relation, RelationKind, SpanData}; +use rls_data::{ + CompilationOptions, CratePreludeData, Def, DefKind, GlobalCrateId, Import, ImportKind, Ref, + RefKind, Relation, RelationKind, SpanData, +}; macro_rules! down_cast_data { ($id:ident, $kind:ident, $sp:expr) => { @@ -169,6 +172,61 @@ pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) { self.dumper.crate_prelude(data); } + pub fn dump_compilation_options(&mut self) { + // Apply possible `remap-path-prefix` remapping to the raw invocation + let invocation = { + let remap_arg_indices = { + let mut indices = FxHashSet(); + for (i, e) in env::args().enumerate() { + if e.starts_with("--remap-path-prefix=") { + indices.insert(i); + } else if e == "--remap-path-prefix" { + indices.insert(i); + indices.insert(i + 1); + } + } + indices + }; + + let args_without_remap_args = env::args() + .enumerate() + .filter(|(i, _)| !remap_arg_indices.contains(i)) + .map(|(_, e)| e); + + let mapping = self.tcx.sess.source_map().path_mapping(); + let remap_arg = |x: &str| -> String { + mapping.map_prefix(PathBuf::from(x)).0.to_str().unwrap().to_owned() + }; + + // Naively attempt to remap every argument + let args = args_without_remap_args + .map(|elem| { + let mut arg = elem.splitn(2, '='); + match (arg.next(), arg.next()) { + // Apart from `--remap...`, in `a=b` args usually only + // `b` is a path (e.g. `--extern some_crate=/path/to..`) + (Some(a), Some(b)) => format!("{}={}", a, remap_arg(b)), + (Some(a), _) => remap_arg(a), + _ => unreachable!(), + } + }).collect::>(); + + args.as_slice().join(" ") + }; + + let opts = &self.tcx.sess.opts; + + let data = CompilationOptions { + invocation, + crate_name: opts.crate_name.clone(), + test: opts.test, + sysroot: opts.maybe_sysroot.clone(), + target_triple: opts.target_triple.to_string(), + }; + + self.dumper.compilation_opts(data); + } + // Return all non-empty prefixes of a path. // For each prefix, we return the span for the last segment in the prefix and // a str representation of the entire prefix. diff --git a/src/librustc_save_analysis/json_dumper.rs b/src/librustc_save_analysis/json_dumper.rs index d2e52f98238..bfd3a01ca42 100644 --- a/src/librustc_save_analysis/json_dumper.rs +++ b/src/librustc_save_analysis/json_dumper.rs @@ -12,9 +12,11 @@ use rustc_serialize::json::as_json; -use rls_data::{self, Analysis, CratePreludeData, Def, DefKind, Import, MacroRef, Ref, RefKind, - Relation, Impl}; use rls_data::config::Config; +use rls_data::{ + self, Analysis, CompilationOptions, CratePreludeData, Def, DefKind, Impl, Import, MacroRef, + Ref, RefKind, Relation, +}; use rls_span::{Column, Row}; #[derive(Debug)] @@ -89,6 +91,10 @@ pub fn crate_prelude(&mut self, data: CratePreludeData) { self.result.prelude = Some(data) } + pub fn compilation_opts(&mut self, data: CompilationOptions) { + self.result.compilation = Some(data); + } + pub fn macro_use(&mut self, data: MacroRef) { if self.config.pub_only || self.config.reachable_only { return; diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index c9bae297031..06496db5274 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -70,10 +70,11 @@ use dump_visitor::DumpVisitor; use span_utils::SpanUtils; -use rls_data::{Def, DefKind, ExternalCrateData, GlobalCrateId, MacroRef, Ref, RefKind, Relation, - RelationKind, SpanData, Impl, ImplKind}; use rls_data::config::Config; - +use rls_data::{ + CrateSource, Def, DefKind, ExternalCrateData, GlobalCrateId, Impl, ImplKind, MacroRef, Ref, + RefKind, Relation, RelationKind, SpanData, +}; pub struct SaveContext<'l, 'tcx: 'l> { tcx: TyCtxt<'l, 'tcx, 'tcx>, @@ -122,16 +123,32 @@ pub fn get_external_crates(&self) -> Vec { continue; } }; + let src = self.tcx.used_crate_source(n); let lo_loc = self.span_utils.sess.source_map().lookup_char_pos(span.lo()); + let map_prefix = |path: &PathBuf| -> PathBuf { + self.tcx.sess.source_map().path_mapping().map_prefix(path.to_owned()).0 + }; + result.push(ExternalCrateData { // FIXME: change file_name field to PathBuf in rls-data // https://github.com/nrc/rls-data/issues/7 - file_name: self.span_utils.make_path_string(&lo_loc.file.name), + file_name: self.span_utils.make_filename_string(&lo_loc.file), num: n.as_u32(), id: GlobalCrateId { name: self.tcx.crate_name(n).to_string(), disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(), }, + source: CrateSource { + dylib: src.dylib.as_ref().map(|(ref path, _)| + map_prefix(path).display().to_string() + ), + rlib: src.rlib.as_ref().map(|(ref path, _)| + map_prefix(path).display().to_string() + ), + rmeta: src.rmeta.as_ref().map(|(ref path, _)| + map_prefix(path).display().to_string() + ), + } }); } @@ -1086,6 +1103,7 @@ fn save<'l, 'tcx>( let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); visitor.dump_crate_info(cratename, krate); + visitor.dump_compilation_options(); visit::walk_crate(&mut visitor, krate); } } @@ -1111,6 +1129,7 @@ fn save<'l, 'tcx>( let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); visitor.dump_crate_info(cratename, krate); + visitor.dump_compilation_options(); visit::walk_crate(&mut visitor, krate); } } diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 2550a312c5d..56728aed769 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -35,14 +35,17 @@ pub fn new(sess: &'a Session) -> SpanUtils<'a> { } } - pub fn make_path_string(&self, path: &FileName) -> String { - match *path { - FileName::Real(ref path) if !path.is_absolute() => + pub fn make_filename_string(&self, file: &SourceFile) -> String { + match &file.name { + FileName::Real(path) if !path.is_absolute() && !file.name_was_remapped => { self.sess.working_dir.0 .join(&path) .display() - .to_string(), - _ => path.to_string(), + .to_string() + }, + // If the file name is already remapped, we assume the user + // configured it the way they wanted to, so use that directly + filename => filename.to_string() } } -- GitLab