about summary refs log tree commit diff
diff options
context:
space:
mode:
authorIgor Matuszewski <Xanewok@gmail.com>2018-09-11 16:39:07 +0200
committerIgor Matuszewski <Xanewok@gmail.com>2018-09-28 01:53:59 +0200
commitc01e4ce74e96737f99492a185e2d170964f11556 (patch)
tree3ef1abc8b427b9d0219d332a63c70caf0acb8ac7
parent8876906867b2db3c7177d69dd020c40d89177f86 (diff)
downloadrust-c01e4ce74e96737f99492a185e2d170964f11556.tar.gz
rust-c01e4ce74e96737f99492a185e2d170964f11556.zip
Emit used rustc invocation in the save-analysis file
-rw-r--r--src/Cargo.toml1
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs64
-rw-r--r--src/librustc_save_analysis/json_dumper.rs10
-rw-r--r--src/librustc_save_analysis/lib.rs27
-rw-r--r--src/librustc_save_analysis/span_utils.rs13
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::hir::def_id::DefId;
 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 json_dumper::{Access, DumpOutput, JsonDumper};
 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 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
         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::<Vec<_>>();
+
+            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 std::io::Write;
 
 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 @@ impl<'b, O: DumpOutput + 'b> JsonDumper<O> {
         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 json_dumper::JsonDumper;
 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 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     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 @@ impl<'a> SaveHandler for DumpHandler<'a> {
         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 @@ impl<'b> SaveHandler for CallbackHandler<'b> {
         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 @@ impl<'a> 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()
         }
     }