// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use rustc::hir::def_id::{DefId, DefIndex}; use rustc::hir::map::Map; use rustc::ty::TyCtxt; use syntax::ast::{CrateNum, NodeId}; use syntax::codemap::{Span, CodeMap}; use super::data; // FIXME: this should be pub(crate), but the current snapshot doesn't allow it yet pub trait Lower { type Target; fn lower(self, tcx: TyCtxt) -> Self::Target; } fn make_def_id(id: NodeId, map: &Map) -> DefId { map.opt_local_def_id(id).unwrap_or(null_def_id()) } pub fn null_def_id() -> DefId { DefId { krate: u32::max_value(), index: DefIndex::from_u32(u32::max_value()) } } #[derive(Clone, Debug, RustcEncodable)] pub struct SpanData { pub file_name: String, pub byte_start: u32, pub byte_end: u32, /// 1-based. pub line_start: usize, pub line_end: usize, /// 1-based, character offset. pub column_start: usize, pub column_end: usize, } impl SpanData { pub fn from_span(span: Span, cm: &CodeMap) -> SpanData { let start = cm.lookup_char_pos(span.lo); let end = cm.lookup_char_pos(span.hi); SpanData { file_name: start.file.name.clone(), byte_start: span.lo.0, byte_end: span.hi.0, line_start: start.line, line_end: end.line, column_start: start.col.0 + 1, column_end: end.col.0 + 1, } } } #[derive(Debug, RustcEncodable)] pub struct CratePreludeData { pub crate_name: String, pub crate_root: String, pub external_crates: Vec, pub span: SpanData, } impl Lower for data::CratePreludeData { type Target = CratePreludeData; fn lower(self, tcx: TyCtxt) -> CratePreludeData { CratePreludeData { crate_name: self.crate_name, crate_root: self.crate_root, external_crates: self.external_crates, span: SpanData::from_span(self.span, tcx.sess.codemap()), } } } /// Data for enum declarations. #[derive(Clone, Debug, RustcEncodable)] pub struct EnumData { pub id: DefId, pub value: String, pub name: String, pub qualname: String, pub span: SpanData, pub scope: DefId, } impl Lower for data::EnumData { type Target = EnumData; fn lower(self, tcx: TyCtxt) -> EnumData { EnumData { id: make_def_id(self.id, &tcx.map), name: self.name, value: self.value, qualname: self.qualname, span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), } } } /// Data for extern crates. #[derive(Debug, RustcEncodable)] pub struct ExternCrateData { pub id: DefId, pub name: String, pub crate_num: CrateNum, pub location: String, pub span: SpanData, pub scope: DefId, } impl Lower for data::ExternCrateData { type Target = ExternCrateData; fn lower(self, tcx: TyCtxt) -> ExternCrateData { ExternCrateData { id: make_def_id(self.id, &tcx.map), name: self.name, crate_num: self.crate_num, location: self.location, span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), } } } /// Data about a function call. #[derive(Debug, RustcEncodable)] pub struct FunctionCallData { pub span: SpanData, pub scope: DefId, pub ref_id: DefId, } impl Lower for data::FunctionCallData { type Target = FunctionCallData; fn lower(self, tcx: TyCtxt) -> FunctionCallData { FunctionCallData { span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), ref_id: self.ref_id, } } } /// Data for all kinds of functions and methods. #[derive(Clone, Debug, RustcEncodable)] pub struct FunctionData { pub id: DefId, pub name: String, pub qualname: String, pub declaration: Option, pub span: SpanData, pub scope: DefId, pub value: String, } impl Lower for data::FunctionData { type Target = FunctionData; fn lower(self, tcx: TyCtxt) -> FunctionData { FunctionData { id: make_def_id(self.id, &tcx.map), name: self.name, qualname: self.qualname, declaration: self.declaration, span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), value: self.value, } } } /// Data about a function call. #[derive(Debug, RustcEncodable)] pub struct FunctionRefData { pub span: SpanData, pub scope: DefId, pub ref_id: DefId, } impl Lower for data::FunctionRefData { type Target = FunctionRefData; fn lower(self, tcx: TyCtxt) -> FunctionRefData { FunctionRefData { span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), ref_id: self.ref_id, } } } #[derive(Debug, RustcEncodable)] pub struct ImplData { pub id: DefId, pub span: SpanData, pub scope: DefId, pub trait_ref: Option, pub self_ref: Option, } impl Lower for data::ImplData { type Target = ImplData; fn lower(self, tcx: TyCtxt) -> ImplData { ImplData { id: make_def_id(self.id, &tcx.map), span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), trait_ref: self.trait_ref, self_ref: self.self_ref, } } } #[derive(Debug, RustcEncodable)] pub struct InheritanceData { pub span: SpanData, pub base_id: DefId, pub deriv_id: DefId } impl Lower for data::InheritanceData { type Target = InheritanceData; fn lower(self, tcx: TyCtxt) -> InheritanceData { InheritanceData { span: SpanData::from_span(self.span, tcx.sess.codemap()), base_id: self.base_id, deriv_id: make_def_id(self.deriv_id, &tcx.map) } } } /// Data about a macro declaration. #[derive(Debug, RustcEncodable)] pub struct MacroData { pub span: SpanData, pub name: String, pub qualname: String, } impl Lower for data::MacroData { type Target = MacroData; fn lower(self, tcx: TyCtxt) -> MacroData { MacroData { span: SpanData::from_span(self.span, tcx.sess.codemap()), name: self.name, qualname: self.qualname, } } } /// Data about a macro use. #[derive(Debug, RustcEncodable)] pub struct MacroUseData { pub span: SpanData, pub name: String, pub qualname: String, // Because macro expansion happens before ref-ids are determined, // we use the callee span to reference the associated macro definition. pub callee_span: SpanData, pub scope: DefId, } impl Lower for data::MacroUseData { type Target = MacroUseData; fn lower(self, tcx: TyCtxt) -> MacroUseData { MacroUseData { span: SpanData::from_span(self.span, tcx.sess.codemap()), name: self.name, qualname: self.qualname, callee_span: SpanData::from_span(self.callee_span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), } } } /// Data about a method call. #[derive(Debug, RustcEncodable)] pub struct MethodCallData { pub span: SpanData, pub scope: DefId, pub ref_id: Option, pub decl_id: Option, } impl Lower for data::MethodCallData { type Target = MethodCallData; fn lower(self, tcx: TyCtxt) -> MethodCallData { MethodCallData { span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), ref_id: self.ref_id, decl_id: self.decl_id, } } } /// Data for method declarations (methods with a body are treated as functions). #[derive(Clone, Debug, RustcEncodable)] pub struct MethodData { pub id: DefId, pub name: String, pub qualname: String, pub span: SpanData, pub scope: DefId, pub value: String, } impl Lower for data::MethodData { type Target = MethodData; fn lower(self, tcx: TyCtxt) -> MethodData { MethodData { span: SpanData::from_span(self.span, tcx.sess.codemap()), name: self.name, scope: make_def_id(self.scope, &tcx.map), id: make_def_id(self.id, &tcx.map), qualname: self.qualname, value: self.value, } } } /// Data for modules. #[derive(Debug, RustcEncodable)] pub struct ModData { pub id: DefId, pub name: String, pub qualname: String, pub span: SpanData, pub scope: DefId, pub filename: String, } impl Lower for data::ModData { type Target = ModData; fn lower(self, tcx: TyCtxt) -> ModData { ModData { id: make_def_id(self.id, &tcx.map), name: self.name, qualname: self.qualname, span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), filename: self.filename, } } } /// Data for a reference to a module. #[derive(Debug, RustcEncodable)] pub struct ModRefData { pub span: SpanData, pub scope: DefId, pub ref_id: Option, pub qualname: String } impl Lower for data::ModRefData { type Target = ModRefData; fn lower(self, tcx: TyCtxt) -> ModRefData { ModRefData { span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), ref_id: self.ref_id, qualname: self.qualname, } } } #[derive(Debug, RustcEncodable)] pub struct StructData { pub span: SpanData, pub name: String, pub id: DefId, pub ctor_id: DefId, pub qualname: String, pub scope: DefId, pub value: String } impl Lower for data::StructData { type Target = StructData; fn lower(self, tcx: TyCtxt) -> StructData { StructData { span: SpanData::from_span(self.span, tcx.sess.codemap()), name: self.name, id: make_def_id(self.id, &tcx.map), ctor_id: make_def_id(self.ctor_id, &tcx.map), qualname: self.qualname, scope: make_def_id(self.scope, &tcx.map), value: self.value } } } #[derive(Debug, RustcEncodable)] pub struct StructVariantData { pub span: SpanData, pub name: String, pub id: DefId, pub qualname: String, pub type_value: String, pub value: String, pub scope: DefId } impl Lower for data::StructVariantData { type Target = StructVariantData; fn lower(self, tcx: TyCtxt) -> StructVariantData { StructVariantData { span: SpanData::from_span(self.span, tcx.sess.codemap()), name: self.name, id: make_def_id(self.id, &tcx.map), qualname: self.qualname, type_value: self.type_value, value: self.value, scope: make_def_id(self.scope, &tcx.map), } } } #[derive(Debug, RustcEncodable)] pub struct TraitData { pub span: SpanData, pub name: String, pub id: DefId, pub qualname: String, pub scope: DefId, pub value: String } impl Lower for data::TraitData { type Target = TraitData; fn lower(self, tcx: TyCtxt) -> TraitData { TraitData { span: SpanData::from_span(self.span, tcx.sess.codemap()), name: self.name, id: make_def_id(self.id, &tcx.map), qualname: self.qualname, scope: make_def_id(self.scope, &tcx.map), value: self.value, } } } #[derive(Debug, RustcEncodable)] pub struct TupleVariantData { pub span: SpanData, pub id: DefId, pub name: String, pub qualname: String, pub type_value: String, pub value: String, pub scope: DefId, } impl Lower for data::TupleVariantData { type Target = TupleVariantData; fn lower(self, tcx: TyCtxt) -> TupleVariantData { TupleVariantData { span: SpanData::from_span(self.span, tcx.sess.codemap()), id: make_def_id(self.id, &tcx.map), name: self.name, qualname: self.qualname, type_value: self.type_value, value: self.value, scope: make_def_id(self.scope, &tcx.map), } } } /// Data for a typedef. #[derive(Debug, RustcEncodable)] pub struct TypeDefData { pub id: DefId, pub name: String, pub span: SpanData, pub qualname: String, pub value: String, } impl Lower for data::TypeDefData { type Target = TypeDefData; fn lower(self, tcx: TyCtxt) -> TypeDefData { TypeDefData { id: make_def_id(self.id, &tcx.map), name: self.name, span: SpanData::from_span(self.span, tcx.sess.codemap()), qualname: self.qualname, value: self.value, } } } /// Data for a reference to a type or trait. #[derive(Clone, Debug, RustcEncodable)] pub struct TypeRefData { pub span: SpanData, pub scope: DefId, pub ref_id: Option, pub qualname: String, } impl Lower for data::TypeRefData { type Target = TypeRefData; fn lower(self, tcx: TyCtxt) -> TypeRefData { TypeRefData { span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), ref_id: self.ref_id, qualname: self.qualname, } } } #[derive(Debug, RustcEncodable)] pub struct UseData { pub id: DefId, pub span: SpanData, pub name: String, pub mod_id: Option, pub scope: DefId } impl Lower for data::UseData { type Target = UseData; fn lower(self, tcx: TyCtxt) -> UseData { UseData { id: make_def_id(self.id, &tcx.map), span: SpanData::from_span(self.span, tcx.sess.codemap()), name: self.name, mod_id: self.mod_id, scope: make_def_id(self.scope, &tcx.map), } } } #[derive(Debug, RustcEncodable)] pub struct UseGlobData { pub id: DefId, pub span: SpanData, pub names: Vec, pub scope: DefId } impl Lower for data::UseGlobData { type Target = UseGlobData; fn lower(self, tcx: TyCtxt) -> UseGlobData { UseGlobData { id: make_def_id(self.id, &tcx.map), span: SpanData::from_span(self.span, tcx.sess.codemap()), names: self.names, scope: make_def_id(self.scope, &tcx.map), } } } /// Data for local and global variables (consts and statics). #[derive(Debug, RustcEncodable)] pub struct VariableData { pub id: DefId, pub name: String, pub qualname: String, pub span: SpanData, pub scope: DefId, pub value: String, pub type_value: String, } impl Lower for data::VariableData { type Target = VariableData; fn lower(self, tcx: TyCtxt) -> VariableData { VariableData { id: make_def_id(self.id, &tcx.map), name: self.name, qualname: self.qualname, span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), value: self.value, type_value: self.type_value, } } } /// Data for the use of some item (e.g., the use of a local variable, which /// will refer to that variables declaration (by ref_id)). #[derive(Debug, RustcEncodable)] pub struct VariableRefData { pub name: String, pub span: SpanData, pub scope: DefId, pub ref_id: DefId, } impl Lower for data::VariableRefData { type Target = VariableRefData; fn lower(self, tcx: TyCtxt) -> VariableRefData { VariableRefData { name: self.name, span: SpanData::from_span(self.span, tcx.sess.codemap()), scope: make_def_id(self.scope, &tcx.map), ref_id: self.ref_id, } } }