-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Emit used rustc invocation in the save-analysis file #54356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c01e4ce
cddd00a
d45f877
1e593be
24123dd
3ceae8d
58a8621
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,6 +97,19 @@ pub fn find_crate_name(sess: Option<&Session>, | |
"rust_out".to_string() | ||
} | ||
|
||
pub fn filename_for_metadata(sess: &Session, | ||
crate_name: &str, | ||
outputs: &OutputFilenames) -> PathBuf { | ||
let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed the formatting while moving to mimick |
||
|
||
let out_filename = outputs.single_output_file.clone() | ||
.unwrap_or(outputs.out_directory.join(&format!("lib{}.rmeta", libname))); | ||
|
||
check_file_is_writeable(&out_filename, sess); | ||
|
||
out_filename | ||
} | ||
|
||
pub fn filename_for_input(sess: &Session, | ||
crate_type: config::CrateType, | ||
crate_name: &str, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,10 +25,12 @@ | |
|
||
use rustc::hir::def::Def as HirDef; | ||
use rustc::hir::def_id::DefId; | ||
use rustc::session::config::Input; | ||
use rustc::ty::{self, TyCtxt}; | ||
use rustc_data_structures::fx::FxHashSet; | ||
|
||
use std::path::Path; | ||
use std::env; | ||
|
||
use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID}; | ||
use syntax::parse::token; | ||
|
@@ -49,8 +51,8 @@ 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 +171,54 @@ 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, input: &Input, crate_name: &str) { | ||
// Apply possible `remap-path-prefix` remapping to the input source file | ||
// (and don't include remapping args anymore) | ||
let (program, arguments) = { | ||
let remap_arg_indices = { | ||
let mut indices = FxHashSet(); | ||
// Args are guaranteed to be valid UTF-8 (checked early) | ||
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 mut args = env::args() | ||
.enumerate() | ||
.filter(|(i, _)| !remap_arg_indices.contains(i)) | ||
.map(|(_, arg)| { | ||
match input { | ||
Input::File(ref path) if path == Path::new(&arg) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I decided to propagate I was also thinking about trying to remap every argument and see if it matches the already remapped |
||
let mapped = &self.tcx.sess.local_crate_source_file; | ||
mapped | ||
.as_ref() | ||
.unwrap() | ||
.to_string_lossy() | ||
.into() | ||
}, | ||
_ => arg, | ||
} | ||
}); | ||
|
||
(args.next().unwrap(), args.collect()) | ||
}; | ||
|
||
let data = CompilationOptions { | ||
directory: self.tcx.sess.working_dir.0.clone(), | ||
program, | ||
arguments, | ||
output: self.save_ctxt.compilation_output(crate_name), | ||
}; | ||
|
||
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. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ extern crate rustc; | |
#[macro_use] | ||
extern crate log; | ||
extern crate rustc_data_structures; | ||
extern crate rustc_codegen_utils; | ||
extern crate rustc_serialize; | ||
extern crate rustc_target; | ||
extern crate rustc_typeck; | ||
|
@@ -45,9 +46,10 @@ use rustc::hir::def::Def as HirDef; | |
use rustc::hir::Node; | ||
use rustc::hir::def_id::{DefId, LOCAL_CRATE}; | ||
use rustc::middle::cstore::ExternCrate; | ||
use rustc::session::config::CrateType; | ||
use rustc::session::config::{CrateType, Input, OutputType}; | ||
use rustc::ty::{self, TyCtxt}; | ||
use rustc_typeck::hir_ty_to_ty; | ||
use rustc_codegen_utils::link::{filename_for_metadata, out_filename}; | ||
|
||
use std::cell::Cell; | ||
use std::default::Default; | ||
|
@@ -110,6 +112,24 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { | |
} | ||
} | ||
|
||
// Returns path to the compilation output (e.g. libfoo-12345678.rmeta) | ||
pub fn compilation_output(&self, crate_name: &str) -> PathBuf { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought you said you were removing the output stuff? (Which seems like a good idea to me). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this doesn't use the file-based approach to figure out dependencies (crate disambiguators are used instead) but if we decide to somehow use save-analysis to lower this info further into low level file-based dep graph (potentially for Cargo build system integration? or maybe we shouldn't use save-analysis for that?) then we need some kind of related file input/output. I removed Edit: |
||
let sess = &self.tcx.sess; | ||
// Save-analysis is emitted per whole session, not per each crate type | ||
let crate_type = sess.crate_types.borrow()[0]; | ||
let outputs = &*self.tcx.output_filenames(LOCAL_CRATE); | ||
|
||
if outputs.outputs.contains_key(&OutputType::Metadata) { | ||
filename_for_metadata(sess, crate_name, outputs) | ||
} else if outputs.outputs.should_codegen() { | ||
out_filename(sess, crate_type, outputs, crate_name) | ||
} else { | ||
// Otherwise it's only a DepInfo, in which case we return early and | ||
// not even reach the analysis stage. | ||
unreachable!() | ||
} | ||
} | ||
|
||
// List external crates used by the current crate. | ||
pub fn get_external_crates(&self) -> Vec<ExternalCrateData> { | ||
let mut result = Vec::with_capacity(self.tcx.crates().len()); | ||
|
@@ -126,7 +146,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { | |
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(), | ||
|
@@ -1015,6 +1035,7 @@ pub trait SaveHandler { | |
save_ctxt: SaveContext<'l, 'tcx>, | ||
krate: &ast::Crate, | ||
cratename: &str, | ||
input: &'l Input, | ||
); | ||
} | ||
|
||
|
@@ -1080,12 +1101,14 @@ impl<'a> SaveHandler for DumpHandler<'a> { | |
save_ctxt: SaveContext<'l, 'tcx>, | ||
krate: &ast::Crate, | ||
cratename: &str, | ||
input: &'l Input, | ||
) { | ||
let output = &mut self.output_file(&save_ctxt); | ||
let mut dumper = JsonDumper::new(output, save_ctxt.config.clone()); | ||
let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); | ||
|
||
visitor.dump_crate_info(cratename, krate); | ||
visitor.dump_compilation_options(input, cratename); | ||
visit::walk_crate(&mut visitor, krate); | ||
} | ||
} | ||
|
@@ -1101,6 +1124,7 @@ impl<'b> SaveHandler for CallbackHandler<'b> { | |
save_ctxt: SaveContext<'l, 'tcx>, | ||
krate: &ast::Crate, | ||
cratename: &str, | ||
input: &'l Input, | ||
) { | ||
// We're using the JsonDumper here because it has the format of the | ||
// save-analysis results that we will pass to the callback. IOW, we are | ||
|
@@ -1111,6 +1135,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(input, cratename); | ||
visit::walk_crate(&mut visitor, krate); | ||
} | ||
} | ||
|
@@ -1120,6 +1145,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( | |
krate: &ast::Crate, | ||
analysis: &'l ty::CrateAnalysis, | ||
cratename: &str, | ||
input: &'l Input, | ||
config: Option<Config>, | ||
mut handler: H, | ||
) { | ||
|
@@ -1137,7 +1163,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( | |
impl_counter: Cell::new(0), | ||
}; | ||
|
||
handler.save(save_ctxt, krate, cratename) | ||
handler.save(save_ctxt, krate, cratename, input) | ||
}) | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,14 +35,24 @@ impl<'a> SpanUtils<'a> { | |
} | ||
} | ||
|
||
pub fn make_path_string(&self, path: &FileName) -> String { | ||
match *path { | ||
FileName::Real(ref path) if !path.is_absolute() => | ||
self.sess.working_dir.0 | ||
.join(&path) | ||
.display() | ||
.to_string(), | ||
_ => path.to_string(), | ||
pub fn make_filename_string(&self, file: &SourceFile) -> String { | ||
match &file.name { | ||
FileName::Real(path) if !file.name_was_remapped => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In practice every file that's going through |
||
if path.is_absolute() { | ||
self.sess.source_map().path_mapping() | ||
.map_prefix(path.clone()).0 | ||
.display() | ||
.to_string() | ||
} else { | ||
self.sess.working_dir.0 | ||
.join(&path) | ||
.display() | ||
.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() | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved it so I can only depend on
librustc_codegen_utils
in the save analysis crate (see here)