allow filtering analysis by reachability

This commit is contained in:
Andy Russell 2017-11-14 17:17:09 -05:00
parent d08a164960
commit 409297f529
No known key found for this signature in database
GPG Key ID: BE2221033EDBC374
2 changed files with 119 additions and 44 deletions

View File

@ -42,7 +42,7 @@ use syntax::codemap::Spanned;
use syntax_pos::*;
use {escape, generated_code, lower_attributes, PathCollector, SaveContext};
use json_dumper::{DumpOutput, JsonDumper};
use json_dumper::{Access, DumpOutput, JsonDumper};
use span_utils::SpanUtils;
use sig;
@ -341,7 +341,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
let span = self.span_from_span(sub_span.expect("No span found for variable"));
self.dumper.dump_def(
false,
&Access {
public: false,
reachable: false,
},
Def {
kind: DefKind::Local,
id,
@ -387,8 +390,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
method_data.value = sig_str;
method_data.sig = sig::method_signature(id, name, generics, sig, &self.save_ctxt);
self.dumper
.dump_def(vis == ast::Visibility::Public, method_data);
self.dumper.dump_def(
&Access {
public: vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(id),
},
method_data);
}
// walk arg and return types
@ -409,8 +416,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) {
let field_data = self.save_ctxt.get_field_data(field, parent_id);
if let Some(field_data) = field_data {
self.dumper
.dump_def(field.vis == ast::Visibility::Public, field_data);
self.dumper.dump_def(
&Access {
public: field.vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(field.id),
},
field_data,
);
}
}
@ -432,7 +444,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
let span = self.span_from_span(param_ss);
self.dumper.dump_def(
false,
&Access {
public: false,
reachable: false,
},
Def {
kind: DefKind::Type,
id,
@ -467,8 +482,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
|v| v.process_formals(&decl.inputs, &fn_data.qualname),
);
self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
self.dumper
.dump_def(item.vis == ast::Visibility::Public, fn_data);
self.dumper.dump_def(
&Access {
public: item.vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(item.id),
},
fn_data,
);
}
for arg in &decl.inputs {
@ -491,8 +511,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
self.nest_tables(item.id, |v| {
if let Some(var_data) = v.save_ctxt.get_item_data(item) {
down_cast_data!(var_data, DefData, item.span);
v.dumper
.dump_def(item.vis == ast::Visibility::Public, var_data);
v.dumper.dump_def(
&Access {
public: item.vis == ast::Visibility::Public,
reachable: v.save_ctxt.analysis.access_levels.is_reachable(item.id),
},
var_data,
);
}
v.visit_ty(&typ);
v.visit_expr(expr);
@ -516,14 +541,16 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
if !self.span.filter_generated(sub_span, span) {
let sig = sig::assoc_const_signature(id, name, typ, expr, &self.save_ctxt);
let id = ::id_from_node_id(id, &self.save_ctxt);
let span = self.span_from_span(sub_span.expect("No span found for variable"));
self.dumper.dump_def(
vis == ast::Visibility::Public,
&Access {
public: vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(id),
},
Def {
kind: DefKind::Const,
id,
id: ::id_from_node_id(id, &self.save_ctxt),
span,
name: name.to_string(),
qualname,
@ -596,7 +623,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
if !self.span.filter_generated(sub_span, item.span) {
let span = self.span_from_span(sub_span.expect("No span found for struct"));
self.dumper.dump_def(
item.vis == ast::Visibility::Public,
&Access {
public: item.vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(item.id),
},
Def {
kind,
id: ::id_from_node_id(item.id, &self.save_ctxt),
@ -635,6 +665,11 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
};
down_cast_data!(enum_data, DefData, item.span);
let access = Access {
public: item.vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(item.id),
};
for variant in &enum_definition.variants {
let name = variant.node.name.name.to_string();
let mut qualname = enum_data.qualname.clone();
@ -660,7 +695,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
self.dumper.dump_def(
item.vis == ast::Visibility::Public,
&access,
Def {
kind: DefKind::StructVariant,
id,
@ -700,7 +735,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
let parent = Some(::id_from_node_id(item.id, &self.save_ctxt));
self.dumper.dump_def(
item.vis == ast::Visibility::Public,
&access,
Def {
kind: DefKind::TupleVariant,
id,
@ -730,8 +765,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
}
}
self.process_generic_params(ty_params, item.span, &enum_data.qualname, item.id);
self.dumper
.dump_def(item.vis == ast::Visibility::Public, enum_data);
self.dumper.dump_def(&access, enum_data);
}
fn process_impl(
@ -783,7 +817,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
.map(|i| ::id_from_node_id(i.id, &self.save_ctxt))
.collect();
self.dumper.dump_def(
item.vis == ast::Visibility::Public,
&Access {
public: item.vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(item.id),
},
Def {
kind: DefKind::Trait,
id,
@ -846,8 +883,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
fn process_mod(&mut self, item: &ast::Item) {
if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
down_cast_data!(mod_data, DefData, item.span);
self.dumper
.dump_def(item.vis == ast::Visibility::Public, mod_data);
self.dumper.dump_def(
&Access {
public: item.vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(item.id),
},
mod_data,
);
}
}
@ -1038,7 +1080,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
let span = self.span_from_span(sub_span.expect("No span found for variable"));
self.dumper.dump_def(
false,
&Access {
public: false,
reachable: false,
},
Def {
kind: DefKind::Local,
id,
@ -1138,7 +1183,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
let id = ::id_from_node_id(trait_item.id, &self.save_ctxt);
self.dumper.dump_def(
true,
&Access {
public: true,
reachable: true,
},
Def {
kind: DefKind::Type,
id,
@ -1225,7 +1273,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
let span = self.span_from_span(span);
self.dumper.dump_def(
true,
&Access {
public: true,
reachable: true,
},
Def {
kind: DefKind::Mod,
id: data_id,
@ -1249,6 +1300,11 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
self.process_macro_use(item.span);
match item.node {
Use(ref use_item) => {
let access = Access {
public: item.vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(item.id),
};
match use_item.node {
ast::ViewPathSimple(ident, ref path) => {
let sub_span = self.span.span_for_last_ident(path.span);
@ -1273,7 +1329,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
let span =
self.span_from_span(sub_span.expect("No span found for use"));
self.dumper.import(
item.vis == ast::Visibility::Public,
&access,
Import {
kind: ImportKind::Use,
ref_id: mod_id.map(|id| ::id_from_def_id(id)),
@ -1302,7 +1358,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
let span =
self.span_from_span(sub_span.expect("No span found for use glob"));
self.dumper.import(
item.vis == ast::Visibility::Public,
&access,
Import {
kind: ImportKind::GlobUse,
ref_id: None,
@ -1334,7 +1390,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
let span =
self.span_from_span(alias_span.expect("No span found for extern crate"));
self.dumper.import(
false,
&Access {
public: false,
reachable: false,
},
Import {
kind: ImportKind::ExternCrate,
ref_id: None,
@ -1373,7 +1432,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
let id = ::id_from_node_id(item.id, &self.save_ctxt);
self.dumper.dump_def(
item.vis == ast::Visibility::Public,
&Access {
public: item.vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(item.id),
},
Def {
kind: DefKind::Type,
id,
@ -1596,7 +1658,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
let span = self.span_from_span(sp);
self.dumper.dump_def(
false,
&Access {
public: false,
reachable: false,
},
Def {
kind: DefKind::Local,
id,
@ -1662,6 +1727,11 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
}
fn visit_foreign_item(&mut self, item: &'l ast::ForeignItem) {
let access = Access {
public: item.vis == ast::Visibility::Public,
reachable: self.save_ctxt.analysis.access_levels.is_reachable(item.id),
};
match item.node {
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
@ -1672,8 +1742,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
|v| v.process_formals(&decl.inputs, &fn_data.qualname),
);
self.process_generic_params(generics, item.span, &fn_data.qualname, item.id);
self.dumper
.dump_def(item.vis == ast::Visibility::Public, fn_data);
self.dumper.dump_def(&access, fn_data);
}
for arg in &decl.inputs {
@ -1687,8 +1756,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
ast::ForeignItemKind::Static(ref ty, _) => {
if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
down_cast_data!(var_data, DefData, item.span);
self.dumper
.dump_def(item.vis == ast::Visibility::Public, var_data);
self.dumper.dump_def(&access, var_data);
}
self.visit_ty(ty);
@ -1696,8 +1764,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
ast::ForeignItemKind::Ty => {
if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
down_cast_data!(var_data, DefData, item.span);
self.dumper
.dump_def(item.vis == ast::Visibility::Public, var_data);
self.dumper.dump_def(&access, var_data);
}
}
}

View File

@ -17,6 +17,12 @@ use rls_data::{self, Analysis, CratePreludeData, Def, DefKind, Import, MacroRef,
use rls_data::config::Config;
use rls_span::{Column, Row};
#[derive(Debug)]
pub struct Access {
pub reachable: bool,
pub public: bool,
}
pub struct JsonDumper<O: DumpOutput> {
result: Analysis,
config: Config,
@ -84,33 +90,35 @@ impl<'b, O: DumpOutput + 'b> JsonDumper<O> {
}
pub fn macro_use(&mut self, data: MacroRef) {
if self.config.pub_only {
if self.config.pub_only || self.config.reachable_only {
return;
}
self.result.macro_refs.push(data);
}
pub fn import(&mut self, public: bool, import: Import) {
if !public && self.config.pub_only {
pub fn import(&mut self, access: &Access, import: Import) {
if !access.public && self.config.pub_only
|| !access.reachable && self.config.reachable_only {
return;
}
self.result.imports.push(import);
}
pub fn dump_ref(&mut self, data: Ref) {
if self.config.pub_only {
if self.config.pub_only || self.config.reachable_only {
return;
}
self.result.refs.push(data);
}
pub fn dump_def(&mut self, public: bool, mut data: Def) {
if !public && self.config.pub_only {
pub fn dump_def(&mut self, access: &Access, mut data: Def) {
if !access.public && self.config.pub_only
|| !access.reachable && self.config.reachable_only {
return;
}
if data.kind == DefKind::Mod && data.span.file_name.to_str().unwrap() != data.value {
// If the module is an out-of-line defintion, then we'll make the
// definition the first character in the module's file and turn the
// If the module is an out-of-line definition, then we'll make the
// definition the first character in the module's file and turn
// the declaration into a reference to it.
let rf = Ref {
kind: RefKind::Mod,