2019-09-30 08:58:53 +00:00
|
|
|
//! FIXME: write short doc here
|
|
|
|
|
2019-07-04 20:05:17 +00:00
|
|
|
use std::{ops::Index, sync::Arc};
|
2019-03-02 20:59:04 +00:00
|
|
|
|
2019-09-29 18:50:56 +00:00
|
|
|
use mbe::ast_to_token_tree;
|
2019-07-04 20:05:17 +00:00
|
|
|
use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
|
2019-03-02 20:59:04 +00:00
|
|
|
use ra_syntax::{
|
2019-07-04 20:05:17 +00:00
|
|
|
ast::{self, AttrsOwner, NameOwner},
|
2019-07-19 07:43:01 +00:00
|
|
|
AstNode, AstPtr, SmolStr, SourceFile,
|
2019-03-02 20:59:04 +00:00
|
|
|
};
|
2019-07-04 20:05:17 +00:00
|
|
|
use test_utils::tested_by;
|
2019-03-02 20:59:04 +00:00
|
|
|
|
2019-07-04 20:05:17 +00:00
|
|
|
use crate::{
|
2019-09-08 06:53:49 +00:00
|
|
|
db::{AstDatabase, DefDatabase},
|
2019-09-26 17:59:38 +00:00
|
|
|
AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source,
|
2019-07-04 20:05:17 +00:00
|
|
|
};
|
2019-03-02 20:59:04 +00:00
|
|
|
|
2019-03-26 10:53:50 +00:00
|
|
|
/// `RawItems` is a set of top-level items in a file (except for impls).
|
|
|
|
///
|
|
|
|
/// It is the input to name resolution algorithm. `RawItems` are not invalidated
|
|
|
|
/// on most edits.
|
2019-03-13 13:38:02 +00:00
|
|
|
#[derive(Debug, Default, PartialEq, Eq)]
|
|
|
|
pub struct RawItems {
|
2019-03-02 20:59:04 +00:00
|
|
|
modules: Arena<Module, ModuleData>,
|
2019-03-13 13:04:28 +00:00
|
|
|
imports: Arena<ImportId, ImportData>,
|
2019-03-02 20:59:04 +00:00
|
|
|
defs: Arena<Def, DefData>,
|
|
|
|
macros: Arena<Macro, MacroData>,
|
|
|
|
/// items for top-level module
|
|
|
|
items: Vec<RawItem>,
|
|
|
|
}
|
|
|
|
|
2019-09-29 18:50:56 +00:00
|
|
|
type Attrs = Arc<[tt::Subtree]>;
|
|
|
|
|
2019-03-16 14:17:50 +00:00
|
|
|
#[derive(Debug, Default, PartialEq, Eq)]
|
|
|
|
pub struct ImportSourceMap {
|
2019-04-02 14:58:04 +00:00
|
|
|
map: ArenaMap<ImportId, ImportSourcePtr>,
|
|
|
|
}
|
|
|
|
|
2019-04-10 07:12:54 +00:00
|
|
|
type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
|
2019-07-19 07:43:01 +00:00
|
|
|
type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
|
2019-04-02 14:58:04 +00:00
|
|
|
|
|
|
|
impl ImportSourcePtr {
|
|
|
|
fn to_node(self, file: &SourceFile) -> ImportSource {
|
2019-09-25 01:32:01 +00:00
|
|
|
self.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
|
2019-04-02 14:58:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-16 14:17:50 +00:00
|
|
|
impl ImportSourceMap {
|
2019-04-02 14:58:04 +00:00
|
|
|
fn insert(&mut self, import: ImportId, ptr: ImportSourcePtr) {
|
|
|
|
self.map.insert(import, ptr)
|
2019-03-16 14:17:50 +00:00
|
|
|
}
|
|
|
|
|
2019-04-02 14:58:04 +00:00
|
|
|
pub(crate) fn get(&self, source: &ModuleSource, import: ImportId) -> ImportSource {
|
2019-03-16 14:17:50 +00:00
|
|
|
let file = match source {
|
2019-07-19 07:43:01 +00:00
|
|
|
ModuleSource::SourceFile(file) => file.clone(),
|
2019-03-16 14:17:50 +00:00
|
|
|
ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
|
|
|
|
};
|
|
|
|
|
2019-07-19 07:43:01 +00:00
|
|
|
self.map[import].to_node(&file)
|
2019-03-16 14:17:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-02 20:59:04 +00:00
|
|
|
impl RawItems {
|
2019-06-01 18:17:57 +00:00
|
|
|
pub(crate) fn raw_items_query(
|
|
|
|
db: &(impl DefDatabase + AstDatabase),
|
|
|
|
file_id: HirFileId,
|
|
|
|
) -> Arc<RawItems> {
|
2019-03-14 10:14:54 +00:00
|
|
|
db.raw_items_with_source_map(file_id).0
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn raw_items_with_source_map_query(
|
2019-06-01 18:17:57 +00:00
|
|
|
db: &(impl DefDatabase + AstDatabase),
|
2019-03-26 10:09:39 +00:00
|
|
|
file_id: HirFileId,
|
2019-03-14 10:14:54 +00:00
|
|
|
) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
|
2019-03-02 20:59:04 +00:00
|
|
|
let mut collector = RawItemsCollector {
|
|
|
|
raw_items: RawItems::default(),
|
2019-06-03 14:21:08 +00:00
|
|
|
source_ast_id_map: db.ast_id_map(file_id),
|
2019-03-14 10:14:54 +00:00
|
|
|
source_map: ImportSourceMap::default(),
|
2019-09-26 17:59:38 +00:00
|
|
|
file_id,
|
|
|
|
db,
|
2019-03-02 20:59:04 +00:00
|
|
|
};
|
2019-05-13 22:42:59 +00:00
|
|
|
if let Some(node) = db.parse_or_expand(file_id) {
|
2019-09-10 19:12:37 +00:00
|
|
|
if let Some(source_file) = ast::SourceFile::cast(node.clone()) {
|
2019-07-19 07:43:01 +00:00
|
|
|
collector.process_module(None, source_file);
|
2019-09-10 19:12:37 +00:00
|
|
|
} else if let Some(item_list) = ast::MacroItems::cast(node) {
|
|
|
|
collector.process_module(None, item_list);
|
2019-05-13 22:42:59 +00:00
|
|
|
}
|
|
|
|
}
|
2019-03-14 10:14:54 +00:00
|
|
|
(Arc::new(collector.raw_items), Arc::new(collector.source_map))
|
2019-03-13 13:38:02 +00:00
|
|
|
}
|
|
|
|
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) fn items(&self) -> &[RawItem] {
|
2019-03-13 13:38:02 +00:00
|
|
|
&self.items
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Index<Module> for RawItems {
|
|
|
|
type Output = ModuleData;
|
|
|
|
fn index(&self, idx: Module) -> &ModuleData {
|
|
|
|
&self.modules[idx]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 13:04:28 +00:00
|
|
|
impl Index<ImportId> for RawItems {
|
2019-03-02 20:59:04 +00:00
|
|
|
type Output = ImportData;
|
2019-03-13 13:04:28 +00:00
|
|
|
fn index(&self, idx: ImportId) -> &ImportData {
|
2019-03-02 20:59:04 +00:00
|
|
|
&self.imports[idx]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Index<Def> for RawItems {
|
|
|
|
type Output = DefData;
|
|
|
|
fn index(&self, idx: Def) -> &DefData {
|
|
|
|
&self.defs[idx]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Index<Macro> for RawItems {
|
|
|
|
type Output = MacroData;
|
|
|
|
fn index(&self, idx: Macro) -> &MacroData {
|
|
|
|
&self.macros[idx]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-29 18:50:56 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
|
|
pub(super) struct RawItem {
|
|
|
|
pub(super) attrs: Attrs,
|
|
|
|
pub(super) kind: RawItemKind,
|
|
|
|
}
|
|
|
|
|
2019-03-13 13:38:02 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
2019-09-29 18:50:56 +00:00
|
|
|
pub(super) enum RawItemKind {
|
2019-03-02 20:59:04 +00:00
|
|
|
Module(Module),
|
2019-03-13 13:04:28 +00:00
|
|
|
Import(ImportId),
|
2019-03-02 20:59:04 +00:00
|
|
|
Def(Def),
|
|
|
|
Macro(Macro),
|
|
|
|
}
|
|
|
|
|
2019-03-13 13:38:02 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) struct Module(RawId);
|
2019-03-02 20:59:04 +00:00
|
|
|
impl_arena_id!(Module);
|
|
|
|
|
2019-03-13 13:38:02 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) enum ModuleData {
|
2019-08-03 16:44:59 +00:00
|
|
|
Declaration {
|
|
|
|
name: Name,
|
|
|
|
ast_id: FileAstId<ast::Module>,
|
|
|
|
attr_path: Option<SmolStr>,
|
2019-09-06 16:55:58 +00:00
|
|
|
is_macro_use: bool,
|
2019-08-03 16:44:59 +00:00
|
|
|
},
|
|
|
|
Definition {
|
|
|
|
name: Name,
|
|
|
|
ast_id: FileAstId<ast::Module>,
|
|
|
|
items: Vec<RawItem>,
|
|
|
|
attr_path: Option<SmolStr>,
|
2019-09-06 16:55:58 +00:00
|
|
|
is_macro_use: bool,
|
2019-08-03 16:44:59 +00:00
|
|
|
},
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
|
2019-03-16 14:17:50 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub struct ImportId(RawId);
|
|
|
|
impl_arena_id!(ImportId);
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
pub struct ImportData {
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) path: Path,
|
|
|
|
pub(super) alias: Option<Name>,
|
|
|
|
pub(super) is_glob: bool,
|
|
|
|
pub(super) is_prelude: bool,
|
|
|
|
pub(super) is_extern_crate: bool,
|
2019-08-29 17:56:00 +00:00
|
|
|
pub(super) is_macro_use: bool,
|
2019-03-16 14:17:50 +00:00
|
|
|
}
|
2019-03-02 20:59:04 +00:00
|
|
|
|
2019-03-13 13:38:02 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) struct Def(RawId);
|
2019-03-02 20:59:04 +00:00
|
|
|
impl_arena_id!(Def);
|
|
|
|
|
2019-03-13 13:38:02 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) struct DefData {
|
|
|
|
pub(super) name: Name,
|
|
|
|
pub(super) kind: DefKind,
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) enum DefKind {
|
2019-03-26 15:27:22 +00:00
|
|
|
Function(FileAstId<ast::FnDef>),
|
|
|
|
Struct(FileAstId<ast::StructDef>),
|
2019-05-23 17:18:47 +00:00
|
|
|
Union(FileAstId<ast::StructDef>),
|
2019-03-26 15:27:22 +00:00
|
|
|
Enum(FileAstId<ast::EnumDef>),
|
|
|
|
Const(FileAstId<ast::ConstDef>),
|
|
|
|
Static(FileAstId<ast::StaticDef>),
|
|
|
|
Trait(FileAstId<ast::TraitDef>),
|
|
|
|
TypeAlias(FileAstId<ast::TypeAliasDef>),
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
|
2019-03-13 13:38:02 +00:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) struct Macro(RawId);
|
2019-03-02 20:59:04 +00:00
|
|
|
impl_arena_id!(Macro);
|
|
|
|
|
2019-03-13 13:38:02 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) struct MacroData {
|
2019-03-26 15:03:17 +00:00
|
|
|
pub(super) ast_id: FileAstId<ast::MacroCall>,
|
2019-03-26 10:53:50 +00:00
|
|
|
pub(super) path: Path,
|
|
|
|
pub(super) name: Option<Name>,
|
|
|
|
pub(super) export: bool,
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
|
2019-09-26 17:59:38 +00:00
|
|
|
struct RawItemsCollector<DB> {
|
2019-03-02 20:59:04 +00:00
|
|
|
raw_items: RawItems,
|
2019-03-26 16:00:11 +00:00
|
|
|
source_ast_id_map: Arc<AstIdMap>,
|
2019-03-14 10:14:54 +00:00
|
|
|
source_map: ImportSourceMap,
|
2019-09-26 17:59:38 +00:00
|
|
|
file_id: HirFileId,
|
|
|
|
db: DB,
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
|
2019-09-27 02:55:25 +00:00
|
|
|
impl<DB: AstDatabase> RawItemsCollector<&DB> {
|
2019-07-19 07:43:01 +00:00
|
|
|
fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) {
|
2019-03-02 20:59:04 +00:00
|
|
|
for item_or_macro in body.items_with_macros() {
|
|
|
|
match item_or_macro {
|
|
|
|
ast::ItemOrMacro::Macro(m) => self.add_macro(current_module, m),
|
|
|
|
ast::ItemOrMacro::Item(item) => self.add_item(current_module, item),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-19 07:43:01 +00:00
|
|
|
fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) {
|
2019-09-29 18:50:56 +00:00
|
|
|
let attrs = self.parse_attrs(&item);
|
2019-08-19 11:04:51 +00:00
|
|
|
let (kind, name) = match item {
|
|
|
|
ast::ModuleItem::Module(module) => {
|
2019-03-02 20:59:04 +00:00
|
|
|
self.add_module(current_module, module);
|
|
|
|
return;
|
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::UseItem(use_item) => {
|
2019-03-02 20:59:04 +00:00
|
|
|
self.add_use_item(current_module, use_item);
|
|
|
|
return;
|
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::ExternCrateItem(extern_crate) => {
|
2019-03-02 20:59:04 +00:00
|
|
|
self.add_extern_crate_item(current_module, extern_crate);
|
|
|
|
return;
|
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::ImplBlock(_) => {
|
2019-03-02 20:59:04 +00:00
|
|
|
// impls don't participate in name resolution
|
|
|
|
return;
|
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::StructDef(it) => {
|
2019-07-19 07:43:01 +00:00
|
|
|
let id = self.source_ast_id_map.ast_id(&it);
|
2019-05-23 17:18:47 +00:00
|
|
|
let name = it.name();
|
|
|
|
if it.is_union() {
|
|
|
|
(DefKind::Union(id), name)
|
|
|
|
} else {
|
|
|
|
(DefKind::Struct(id), name)
|
|
|
|
}
|
2019-03-26 15:27:22 +00:00
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::EnumDef(it) => {
|
2019-07-19 07:43:01 +00:00
|
|
|
(DefKind::Enum(self.source_ast_id_map.ast_id(&it)), it.name())
|
2019-03-26 15:27:22 +00:00
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::FnDef(it) => {
|
2019-07-19 07:43:01 +00:00
|
|
|
(DefKind::Function(self.source_ast_id_map.ast_id(&it)), it.name())
|
2019-03-26 15:27:22 +00:00
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::TraitDef(it) => {
|
2019-07-19 07:43:01 +00:00
|
|
|
(DefKind::Trait(self.source_ast_id_map.ast_id(&it)), it.name())
|
2019-03-26 15:27:22 +00:00
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::TypeAliasDef(it) => {
|
2019-07-19 07:43:01 +00:00
|
|
|
(DefKind::TypeAlias(self.source_ast_id_map.ast_id(&it)), it.name())
|
2019-03-26 15:27:22 +00:00
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::ConstDef(it) => {
|
2019-07-19 07:43:01 +00:00
|
|
|
(DefKind::Const(self.source_ast_id_map.ast_id(&it)), it.name())
|
2019-03-26 15:27:22 +00:00
|
|
|
}
|
2019-08-19 11:04:51 +00:00
|
|
|
ast::ModuleItem::StaticDef(it) => {
|
2019-07-19 07:43:01 +00:00
|
|
|
(DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name())
|
2019-03-26 15:27:22 +00:00
|
|
|
}
|
2019-03-02 20:59:04 +00:00
|
|
|
};
|
|
|
|
if let Some(name) = name {
|
|
|
|
let name = name.as_name();
|
2019-03-26 15:27:22 +00:00
|
|
|
let def = self.raw_items.defs.alloc(DefData { name, kind });
|
2019-09-29 18:50:56 +00:00
|
|
|
self.push_item(current_module, attrs, RawItemKind::Def(def));
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-19 07:43:01 +00:00
|
|
|
fn add_module(&mut self, current_module: Option<Module>, module: ast::Module) {
|
2019-03-02 20:59:04 +00:00
|
|
|
let name = match module.name() {
|
|
|
|
Some(it) => it.as_name(),
|
|
|
|
None => return,
|
|
|
|
};
|
2019-09-29 18:50:56 +00:00
|
|
|
let attrs = self.parse_attrs(&module);
|
2019-07-06 11:04:56 +00:00
|
|
|
|
2019-07-19 07:43:01 +00:00
|
|
|
let ast_id = self.source_ast_id_map.ast_id(&module);
|
2019-09-06 16:55:58 +00:00
|
|
|
let is_macro_use = module.has_atom_attr("macro_use");
|
2019-03-02 20:59:04 +00:00
|
|
|
if module.has_semi() {
|
2019-08-03 16:44:59 +00:00
|
|
|
let attr_path = extract_mod_path_attribute(&module);
|
2019-09-06 16:55:58 +00:00
|
|
|
let item = self.raw_items.modules.alloc(ModuleData::Declaration {
|
|
|
|
name,
|
|
|
|
ast_id,
|
|
|
|
attr_path,
|
|
|
|
is_macro_use,
|
|
|
|
});
|
2019-09-29 18:50:56 +00:00
|
|
|
self.push_item(current_module, attrs, RawItemKind::Module(item));
|
2019-03-02 20:59:04 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(item_list) = module.item_list() {
|
2019-08-03 16:44:59 +00:00
|
|
|
let attr_path = extract_mod_path_attribute(&module);
|
2019-03-13 13:38:02 +00:00
|
|
|
let item = self.raw_items.modules.alloc(ModuleData::Definition {
|
|
|
|
name,
|
2019-03-26 14:25:14 +00:00
|
|
|
ast_id,
|
2019-03-13 13:38:02 +00:00
|
|
|
items: Vec::new(),
|
2019-08-03 16:44:59 +00:00
|
|
|
attr_path,
|
2019-09-06 16:55:58 +00:00
|
|
|
is_macro_use,
|
2019-03-13 13:38:02 +00:00
|
|
|
});
|
2019-03-02 20:59:04 +00:00
|
|
|
self.process_module(Some(item), item_list);
|
2019-09-29 18:50:56 +00:00
|
|
|
self.push_item(current_module, attrs, RawItemKind::Module(item));
|
2019-03-13 13:38:02 +00:00
|
|
|
return;
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
2019-03-13 13:38:02 +00:00
|
|
|
tested_by!(name_res_works_for_broken_modules);
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
|
2019-07-19 07:43:01 +00:00
|
|
|
fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) {
|
2019-03-13 13:04:28 +00:00
|
|
|
let is_prelude = use_item.has_atom_attr("prelude_import");
|
2019-09-29 18:50:56 +00:00
|
|
|
let attrs = self.parse_attrs(&use_item);
|
2019-03-02 20:59:04 +00:00
|
|
|
|
2019-09-26 17:59:38 +00:00
|
|
|
Path::expand_use_item(
|
|
|
|
Source { ast: use_item, file_id: self.file_id },
|
|
|
|
self.db,
|
|
|
|
|path, use_tree, is_glob, alias| {
|
|
|
|
let import_data = ImportData {
|
|
|
|
path,
|
|
|
|
alias,
|
|
|
|
is_glob,
|
|
|
|
is_prelude,
|
|
|
|
is_extern_crate: false,
|
|
|
|
is_macro_use: false,
|
|
|
|
};
|
2019-09-29 18:50:56 +00:00
|
|
|
self.push_import(
|
|
|
|
current_module,
|
|
|
|
attrs.clone(),
|
|
|
|
import_data,
|
|
|
|
Either::A(AstPtr::new(use_tree)),
|
|
|
|
);
|
2019-09-26 17:59:38 +00:00
|
|
|
},
|
|
|
|
)
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn add_extern_crate_item(
|
|
|
|
&mut self,
|
|
|
|
current_module: Option<Module>,
|
2019-07-19 07:43:01 +00:00
|
|
|
extern_crate: ast::ExternCrateItem,
|
2019-03-02 20:59:04 +00:00
|
|
|
) {
|
|
|
|
if let Some(name_ref) = extern_crate.name_ref() {
|
2019-07-19 07:43:01 +00:00
|
|
|
let path = Path::from_name_ref(&name_ref);
|
|
|
|
let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name());
|
2019-09-29 18:50:56 +00:00
|
|
|
let attrs = self.parse_attrs(&extern_crate);
|
2019-08-29 17:56:00 +00:00
|
|
|
let is_macro_use = extern_crate.has_atom_attr("macro_use");
|
2019-04-02 14:58:04 +00:00
|
|
|
let import_data = ImportData {
|
2019-03-02 20:59:04 +00:00
|
|
|
path,
|
|
|
|
alias,
|
|
|
|
is_glob: false,
|
|
|
|
is_prelude: false,
|
|
|
|
is_extern_crate: true,
|
2019-08-29 17:56:00 +00:00
|
|
|
is_macro_use,
|
2019-04-02 14:58:04 +00:00
|
|
|
};
|
2019-09-29 18:50:56 +00:00
|
|
|
self.push_import(
|
|
|
|
current_module,
|
|
|
|
attrs,
|
|
|
|
import_data,
|
|
|
|
Either::B(AstPtr::new(&extern_crate)),
|
|
|
|
);
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-19 07:43:01 +00:00
|
|
|
fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
|
2019-09-26 17:59:38 +00:00
|
|
|
let path = match m
|
|
|
|
.path()
|
|
|
|
.and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db))
|
|
|
|
{
|
2019-03-26 10:09:39 +00:00
|
|
|
Some(it) => it,
|
2019-03-02 20:59:04 +00:00
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
|
|
|
|
let name = m.name().map(|it| it.as_name());
|
2019-07-19 07:43:01 +00:00
|
|
|
let ast_id = self.source_ast_id_map.ast_id(&m);
|
2019-09-29 21:15:03 +00:00
|
|
|
let export = m.attrs().filter_map(|x| x.simple_name()).any(|name| name == "macro_export");
|
2019-09-12 12:41:16 +00:00
|
|
|
|
2019-03-26 15:03:17 +00:00
|
|
|
let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export });
|
2019-09-29 18:50:56 +00:00
|
|
|
self.push_item(current_module, attrs, RawItemKind::Macro(m));
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
|
2019-04-02 14:58:04 +00:00
|
|
|
fn push_import(
|
|
|
|
&mut self,
|
|
|
|
current_module: Option<Module>,
|
2019-09-29 18:50:56 +00:00
|
|
|
attrs: Attrs,
|
2019-04-02 14:58:04 +00:00
|
|
|
data: ImportData,
|
|
|
|
source: ImportSourcePtr,
|
|
|
|
) {
|
|
|
|
let import = self.raw_items.imports.alloc(data);
|
|
|
|
self.source_map.insert(import, source);
|
2019-09-29 18:50:56 +00:00
|
|
|
self.push_item(current_module, attrs, RawItemKind::Import(import))
|
2019-04-02 14:58:04 +00:00
|
|
|
}
|
|
|
|
|
2019-09-29 18:50:56 +00:00
|
|
|
fn push_item(&mut self, current_module: Option<Module>, attrs: Attrs, kind: RawItemKind) {
|
2019-03-02 20:59:04 +00:00
|
|
|
match current_module {
|
|
|
|
Some(module) => match &mut self.raw_items.modules[module] {
|
|
|
|
ModuleData::Definition { items, .. } => items,
|
|
|
|
ModuleData::Declaration { .. } => unreachable!(),
|
|
|
|
},
|
|
|
|
None => &mut self.raw_items.items,
|
|
|
|
}
|
2019-09-29 18:50:56 +00:00
|
|
|
.push(RawItem { attrs, kind })
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
|
|
|
|
item.attrs()
|
|
|
|
.flat_map(|attr| attr.value())
|
|
|
|
.flat_map(|tt| ast_to_token_tree(&tt))
|
|
|
|
.map(|(tt, _)| tt)
|
|
|
|
.collect()
|
2019-03-02 20:59:04 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-06 11:04:56 +00:00
|
|
|
|
|
|
|
fn extract_mod_path_attribute(module: &ast::Module) -> Option<SmolStr> {
|
|
|
|
module.attrs().into_iter().find_map(|attr| {
|
2019-09-29 21:15:03 +00:00
|
|
|
attr.as_simple_key_value().and_then(|(name, value)| {
|
2019-07-06 11:04:56 +00:00
|
|
|
let is_path = name == "path";
|
|
|
|
if is_path {
|
|
|
|
Some(value)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|