提交 c2bb7cad 编写于 作者: N Nick Cameron

save-analysis: remove hacky, unnecessary code now that we have spans for every ident

上级 b49da276
......@@ -60,9 +60,7 @@
use syntax::ast::{self, Attribute, NodeId, PatKind};
use syntax::source_map::Spanned;
use syntax::parse::lexer::comments::strip_doc_comment_decoration;
use syntax::parse::token;
use syntax::print::pprust;
use syntax::symbol::keywords;
use syntax::visit::{self, Visitor};
use syntax::print::pprust::{arg_to_string, ty_to_string};
use syntax::source_map::MacroAttribute;
......@@ -162,14 +160,12 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
match item.node {
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
let sub_span = self.span_utils
.sub_span_after_keyword(item.span, keywords::Fn);
filter!(self.span_utils, sub_span, item.span, None);
filter!(self.span_utils, item.ident.span);
Some(Data::DefData(Def {
kind: DefKind::ForeignFunction,
id: id_from_node_id(item.id, self),
span: self.span_from_span(sub_span.unwrap()),
span: self.span_from_span(item.ident.span),
name: item.ident.to_string(),
qualname,
value: make_signature(decl, generics),
......@@ -181,13 +177,11 @@ pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option<Data> {
attributes: lower_attributes(item.attrs.clone(), self),
}))
}
ast::ForeignItemKind::Static(ref ty, m) => {
let keyword = if m { keywords::Mut } else { keywords::Static };
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
filter!(self.span_utils, sub_span, item.span, None);
ast::ForeignItemKind::Static(ref ty, _) => {
filter!(self.span_utils, item.ident.span);
let id = ::id_from_node_id(item.id, self);
let span = self.span_from_span(sub_span.unwrap());
let span = self.span_from_span(item.ident.span);
Some(Data::DefData(Def {
kind: DefKind::ForeignStatic,
......@@ -214,13 +208,11 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
match item.node {
ast::ItemKind::Fn(ref decl, .., ref generics, _) => {
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
let sub_span = self.span_utils
.sub_span_after_keyword(item.span, keywords::Fn);
filter!(self.span_utils, sub_span, item.span, None);
filter!(self.span_utils, item.ident.span);
Some(Data::DefData(Def {
kind: DefKind::Function,
id: id_from_node_id(item.id, self),
span: self.span_from_span(sub_span.unwrap()),
span: self.span_from_span(item.ident.span),
name: item.ident.to_string(),
qualname,
value: make_signature(decl, generics),
......@@ -232,19 +224,13 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
attributes: lower_attributes(item.attrs.clone(), self),
}))
}
ast::ItemKind::Static(ref typ, mt, _) => {
ast::ItemKind::Static(ref typ, ..) => {
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
let keyword = match mt {
ast::Mutability::Mutable => keywords::Mut,
ast::Mutability::Immutable => keywords::Static,
};
let sub_span = self.span_utils.sub_span_after_keyword(item.span, keyword);
filter!(self.span_utils, sub_span, item.span, None);
filter!(self.span_utils, item.ident.span);
let id = id_from_node_id(item.id, self);
let span = self.span_from_span(sub_span.unwrap());
let span = self.span_from_span(item.ident.span);
Some(Data::DefData(Def {
kind: DefKind::Static,
......@@ -263,12 +249,10 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
}
ast::ItemKind::Const(ref typ, _) => {
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
let sub_span = self.span_utils
.sub_span_after_keyword(item.span, keywords::Const);
filter!(self.span_utils, sub_span, item.span, None);
filter!(self.span_utils, item.ident.span);
let id = id_from_node_id(item.id, self);
let span = self.span_from_span(sub_span.unwrap());
let span = self.span_from_span(item.ident.span);
Some(Data::DefData(Def {
kind: DefKind::Const,
......@@ -291,16 +275,14 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
let cm = self.tcx.sess.source_map();
let filename = cm.span_to_filename(m.inner);
let sub_span = self.span_utils
.sub_span_after_keyword(item.span, keywords::Mod);
filter!(self.span_utils, sub_span, item.span, None);
filter!(self.span_utils, item.ident.span);
Some(Data::DefData(Def {
kind: DefKind::Mod,
id: id_from_node_id(item.id, self),
name: item.ident.to_string(),
qualname,
span: self.span_from_span(sub_span.unwrap()),
span: self.span_from_span(item.ident.span),
value: filename.to_string(),
parent: None,
children: m.items
......@@ -316,9 +298,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
ast::ItemKind::Enum(ref def, _) => {
let name = item.ident.to_string();
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
let sub_span = self.span_utils
.sub_span_after_keyword(item.span, keywords::Enum);
filter!(self.span_utils, sub_span, item.span, None);
filter!(self.span_utils, item.ident.span);
let variants_str = def.variants
.iter()
.map(|v| v.node.ident.to_string())
......@@ -328,7 +308,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
Some(Data::DefData(Def {
kind: DefKind::Enum,
id: id_from_node_id(item.id, self),
span: self.span_from_span(sub_span.unwrap()),
span: self.span_from_span(item.ident.span),
name,
qualname,
value,
......@@ -349,11 +329,11 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
if generated_code(path.span) {
return None;
}
let sub_span = self.span_utils.sub_span_for_type_name(path.span);
filter!(self.span_utils, sub_span, typ.span, None);
let sub_span = path.segments.last().unwrap().ident.span;
filter!(self.span_utils, sub_span);
let impl_id = self.next_impl_id();
let span = self.span_from_span(sub_span.unwrap());
let span = self.span_from_span(sub_span);
let type_data = self.lookup_ref_id(typ.id);
type_data.map(|type_data| {
......@@ -402,15 +382,13 @@ pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<
if let Some(ident) = field.ident {
let name = ident.to_string();
let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident);
let sub_span = self.span_utils
.sub_span_before_token(field.span, token::Colon);
filter!(self.span_utils, sub_span, field.span, None);
filter!(self.span_utils, ident.span);
let def_id = self.tcx.hir.local_def_id(field.id);
let typ = self.tcx.type_of(def_id).to_string();
let id = id_from_node_id(field.id, self);
let span = self.span_from_span(sub_span.unwrap());
let span = self.span_from_span(ident.span);
Some(Def {
kind: DefKind::Field,
......@@ -433,7 +411,7 @@ pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<
// FIXME would be nice to take a MethodItem here, but the ast provides both
// trait and impl flavours, so the caller must do the disassembly.
pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> Option<Def> {
pub fn get_method_data(&self, id: ast::NodeId, ident: ast::Ident, span: Span) -> Option<Def> {
// The qualname for a method is the trait name or name of the struct in an impl in
// which the method is declared in, followed by the method's name.
let (qualname, parent_scope, decl_id, docs, attributes) =
......@@ -459,7 +437,7 @@ pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> O
qualname.push_str(&self.tcx.item_path_str(def_id));
self.tcx
.associated_items(def_id)
.find(|item| item.ident.name == name)
.find(|item| item.ident.name == ident.name)
.map(|item| decl_id = Some(item.def_id));
}
qualname.push_str(">");
......@@ -512,16 +490,15 @@ pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> O
},
};
let qualname = format!("{}::{}", qualname, name);
let qualname = format!("{}::{}", qualname, ident.name);
let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
filter!(self.span_utils, sub_span, span, None);
filter!(self.span_utils, ident.span);
Some(Def {
kind: DefKind::Method,
id: id_from_node_id(id, self),
span: self.span_from_span(sub_span.unwrap()),
name: name.to_string(),
span: self.span_from_span(ident.span),
name: ident.name.to_string(),
qualname,
// FIXME you get better data here by using the visitor.
value: String::new(),
......@@ -540,9 +517,9 @@ pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option<Ref> {
if generated_code(span) {
return None;
}
let sub_span = self.span_utils.sub_span_for_type_name(span).or(Some(span));
filter!(self.span_utils, sub_span, span, None);
let span = self.span_from_span(sub_span.unwrap());
let sub_span = trait_ref.path.segments.last().unwrap().ident.span;
filter!(self.span_utils, sub_span);
let span = self.span_from_span(sub_span);
Some(Ref {
kind: RefKind::Type,
span,
......@@ -574,9 +551,8 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
ty::Adt(def, _) if !def.is_enum() => {
let variant = &def.non_enum_variant();
let index = self.tcx.find_field_index(ident, variant).unwrap();
let sub_span = self.span_utils.span_for_last_ident(expr.span);
filter!(self.span_utils, sub_span, expr.span, None);
let span = self.span_from_span(sub_span.unwrap());
filter!(self.span_utils, ident.span);
let span = self.span_from_span(ident.span);
return Some(Data::RefData(Ref {
kind: RefKind::Variable,
span,
......@@ -593,9 +569,9 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
ast::ExprKind::Struct(ref path, ..) => {
match self.tables.expr_ty_adjusted(&hir_node).sty {
ty::Adt(def, _) if !def.is_enum() => {
let sub_span = self.span_utils.span_for_last_ident(path.span);
filter!(self.span_utils, sub_span, path.span, None);
let span = self.span_from_span(sub_span.unwrap());
let sub_span = path.segments.last().unwrap().ident.span;
filter!(self.span_utils, sub_span);
let span = self.span_from_span(sub_span);
Some(Data::RefData(Ref {
kind: RefKind::Type,
span,
......@@ -624,7 +600,7 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
ty::TraitContainer(_) => (None, Some(method_id)),
};
let sub_span = seg.ident.span;
filter!(self.span_utils, Some(sub_span), expr.span, None);
filter!(self.span_utils, sub_span);
let span = self.span_from_span(sub_span);
Some(Data::RefData(Ref {
kind: RefKind::Function,
......@@ -729,7 +705,7 @@ fn fn_type(path: &ast::Path) -> bool {
let def = self.get_path_def(id);
let last_seg = &path.segments[path.segments.len() - 1];
let sub_span = last_seg.ident.span;
filter!(self.span_utils, Some(sub_span), path.span, None);
filter!(self.span_utils, sub_span);
match def {
HirDef::Upvar(id, ..) | HirDef::Local(id) => {
let span = self.span_from_span(sub_span);
......@@ -753,13 +729,11 @@ fn fn_type(path: &ast::Path) -> bool {
HirDef::Trait(def_id) if fn_type(path) => {
// Function type bounds are desugared in the parser, so we have to
// special case them here.
let fn_span = self.span_utils.span_for_first_ident(path.span);
fn_span.map(|span| {
Ref {
kind: RefKind::Type,
span: self.span_from_span(span),
ref_id: id_from_def_id(def_id),
}
let fn_span = path.segments.first().unwrap().ident.span;
Some(Ref {
kind: RefKind::Type,
span: self.span_from_span(fn_span),
ref_id: id_from_def_id(def_id),
})
}
HirDef::Struct(def_id) |
......@@ -844,10 +818,8 @@ pub fn get_field_ref_data(
variant: &ty::VariantDef,
) -> Option<Ref> {
let index = self.tcx.find_field_index(field_ref.ident, variant).unwrap();
// We don't really need a sub-span here, but no harm done
let sub_span = self.span_utils.span_for_last_ident(field_ref.ident.span);
filter!(self.span_utils, sub_span, field_ref.ident.span, None);
let span = self.span_from_span(sub_span.unwrap());
filter!(self.span_utils, field_ref.ident.span);
let span = self.span_from_span(field_ref.ident.span);
Some(Ref {
kind: RefKind::Variable,
span,
......
......@@ -16,7 +16,6 @@
use syntax::parse::lexer::{self, StringReader};
use syntax::parse::token::{self, Token};
use syntax::symbol::keywords;
use syntax_pos::*;
#[derive(Clone)]
......@@ -67,131 +66,6 @@ pub fn retokenise_span(&self, span: Span) -> StringReader<'a> {
lexer::StringReader::retokenize(&self.sess.parse_sess, span)
}
// Re-parses a path and returns the span for the last identifier in the path
pub fn span_for_last_ident(&self, span: Span) -> Option<Span> {
let mut result = None;
let mut toks = self.retokenise_span(span);
let mut bracket_count = 0;
loop {
let ts = toks.real_token();
if ts.tok == token::Eof {
return result;
}
if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
result = Some(ts.sp);
}
bracket_count += match ts.tok {
token::Lt => 1,
token::Gt => -1,
token::BinOp(token::Shr) => -2,
_ => 0,
}
}
}
// Return the span for the first identifier in the path.
pub fn span_for_first_ident(&self, span: Span) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut bracket_count = 0;
loop {
let ts = toks.real_token();
if ts.tok == token::Eof {
return None;
}
if bracket_count == 0 && (ts.tok.is_ident() || ts.tok.is_keyword(keywords::SelfValue)) {
return Some(ts.sp);
}
bracket_count += match ts.tok {
token::Lt => 1,
token::Gt => -1,
token::BinOp(token::Shr) => -2,
_ => 0,
}
}
}
// Return the span for the last ident before a `<` and outside any
// angle brackets, or the last span.
pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut prev = toks.real_token();
let mut result = None;
// We keep track of the following two counts - the depth of nesting of
// angle brackets, and the depth of nesting of square brackets. For the
// angle bracket count, we only count tokens which occur outside of any
// square brackets (i.e. bracket_count == 0). The intuition here is
// that we want to count angle brackets in the type, but not any which
// could be in expression context (because these could mean 'less than',
// etc.).
let mut angle_count = 0;
let mut bracket_count = 0;
loop {
let next = toks.real_token();
if (next.tok == token::Lt || next.tok == token::Colon) && angle_count == 0
&& bracket_count == 0 && prev.tok.is_ident()
{
result = Some(prev.sp);
}
if bracket_count == 0 {
angle_count += match prev.tok {
token::Lt => 1,
token::Gt => -1,
token::BinOp(token::Shl) => 2,
token::BinOp(token::Shr) => -2,
_ => 0,
};
}
bracket_count += match prev.tok {
token::OpenDelim(token::Bracket) => 1,
token::CloseDelim(token::Bracket) => -1,
_ => 0,
};
if next.tok == token::Eof {
break;
}
prev = next;
}
#[cfg(debug_assertions)] {
if angle_count != 0 || bracket_count != 0 {
let loc = self.sess.source_map().lookup_char_pos(span.lo());
span_bug!(
span,
"Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
self.snippet(span),
loc.file.name,
loc.line
);
}
}
if result.is_none() && prev.tok.is_ident() {
return Some(prev.sp);
}
result
}
pub fn sub_span_before_token(&self, span: Span, tok: Token) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut prev = toks.real_token();
loop {
if prev.tok == token::Eof {
return None;
}
let next = toks.real_token();
if next.tok == tok {
return Some(prev.sp);
}
prev = next;
}
}
pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option<Span> {
let mut toks = self.retokenise_span(span);
loop {
......@@ -205,28 +79,6 @@ pub fn sub_span_of_token(&self, span: Span, tok: Token) -> Option<Span> {
}
}
pub fn sub_span_after_keyword(&self, span: Span, keyword: keywords::Keyword) -> Option<Span> {
self.sub_span_after(span, |t| t.is_keyword(keyword))
}
fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span> {
let mut toks = self.retokenise_span(span);
loop {
let ts = toks.real_token();
if ts.tok == token::Eof {
return None;
}
if f(ts.tok) {
let ts = toks.real_token();
if ts.tok == token::Eof {
return None;
} else {
return Some(ts.sp);
}
}
}
}
// // Return the name for a macro definition (identifier after first `!`)
// pub fn span_for_macro_def_name(&self, span: Span) -> Option<Span> {
// let mut toks = self.retokenise_span(span);
......@@ -271,42 +123,28 @@ fn sub_span_after<F: Fn(Token) -> bool>(&self, span: Span, f: F) -> Option<Span>
///
/// Used to filter out spans of minimal value,
/// such as references to macro internal variables.
pub fn filter_generated(&self, sub_span: Option<Span>, parent: Span) -> bool {
if !generated_code(parent) {
// Edge case - this occurs on generated code with incorrect expansion info.
return sub_span.is_none()
pub fn filter_generated(&self, span: Span) -> bool {
if span.is_dummy() {
return true;
}
if !generated_code(span) {
return false;
}
// If sub_span is none, filter out generated code.
let sub_span = match sub_span {
Some(ss) => ss,
None => return true,
};
//If the span comes from a fake source_file, filter it.
if !self.sess
!self.sess
.source_map()
.lookup_char_pos(parent.lo())
.lookup_char_pos(span.lo())
.file
.is_real_file()
{
return true;
}
// Otherwise, a generated span is deemed invalid if it is not a sub-span of the root
// callsite. This filters out macro internal variables and most malformed spans.
!parent.source_callsite().contains(sub_span)
}
}
macro_rules! filter {
($util: expr, $span: expr, $parent: expr, None) => {
if $util.filter_generated($span, $parent) {
($util: expr, $parent: expr) => {
if $util.filter_generated($parent) {
return None;
}
};
($util: expr, $span: ident, $parent: expr) => {
if $util.filter_generated($span, $parent) {
return;
}
};
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册