mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 14:21:44 +00:00
Merge #2130
2130: improve compile time a bit r=matklad a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
d929f9c49b
24 changed files with 178 additions and 157 deletions
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{name::AsName, type_ref::TypeRef};
|
use hir_def::type_ref::TypeRef;
|
||||||
|
use hir_expand::name::AsName;
|
||||||
use ra_arena::{impl_arena_id, Arena, RawId};
|
use ra_arena::{impl_arena_id, Arena, RawId};
|
||||||
use ra_syntax::ast::{self, NameOwner, StructKind, TypeAscriptionOwner};
|
use ra_syntax::ast::{self, NameOwner, StructKind, TypeAscriptionOwner};
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,13 @@ pub(crate) mod docs;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
name::{
|
|
||||||
self, AsName, BOOL, CHAR, F32, F64, I128, I16, I32, I64, I8, ISIZE, SELF_TYPE, STR, U128,
|
|
||||||
U16, U32, U64, U8, USIZE,
|
|
||||||
},
|
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
CrateModuleId, ModuleId,
|
CrateModuleId, ModuleId,
|
||||||
};
|
};
|
||||||
|
use hir_expand::name::{
|
||||||
|
self, AsName, BOOL, CHAR, F32, F64, I128, I16, I32, I64, I8, ISIZE, SELF_TYPE, STR, U128, U16,
|
||||||
|
U32, U64, U8, USIZE,
|
||||||
|
};
|
||||||
use ra_db::{CrateId, Edition};
|
use ra_db::{CrateId, Edition};
|
||||||
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
|
use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::{path::GenericArgs, type_ref::TypeRef};
|
||||||
|
use hir_expand::{
|
||||||
|
hygiene::Hygiene,
|
||||||
name::{self, AsName, Name},
|
name::{self, AsName, Name},
|
||||||
path::GenericArgs,
|
|
||||||
type_ref::TypeRef,
|
|
||||||
};
|
};
|
||||||
use ra_arena::Arena;
|
use ra_arena::Arena;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
|
@ -597,7 +597,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
|
fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
|
||||||
Path::from_src(Source { ast: path, file_id: self.current_file_id }, self.db)
|
let hygiene = Hygiene::new(self.db, self.current_file_id);
|
||||||
|
Path::from_src(path, &hygiene)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use hir_def::name::AsName;
|
use hir_expand::name::AsName;
|
||||||
use ra_syntax::ast::{self, AstNode, NameOwner};
|
use ra_syntax::ast::{self, AstNode, NameOwner};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
name::{self, AsName},
|
|
||||||
path::Path,
|
path::Path,
|
||||||
type_ref::{TypeBound, TypeRef},
|
type_ref::{TypeBound, TypeRef},
|
||||||
};
|
};
|
||||||
|
use hir_expand::name::{self, AsName};
|
||||||
use ra_syntax::ast::{self, DefaultTypeParamOwner, NameOwner, TypeBoundsOwner, TypeParamsOwner};
|
use ra_syntax::ast::{self, DefaultTypeParamOwner, NameOwner, TypeBoundsOwner, TypeParamsOwner};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -4,6 +4,7 @@ use rustc_hash::FxHashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{attr::Attr, type_ref::TypeRef};
|
use hir_def::{attr::Attr, type_ref::TypeRef};
|
||||||
|
use hir_expand::hygiene::Hygiene;
|
||||||
use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
|
use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
|
||||||
use ra_cfg::CfgOptions;
|
use ra_cfg::CfgOptions;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
|
@ -227,10 +228,11 @@ impl ModuleImplBlocks {
|
||||||
owner: &dyn ast::ModuleItemOwner,
|
owner: &dyn ast::ModuleItemOwner,
|
||||||
file_id: HirFileId,
|
file_id: HirFileId,
|
||||||
) {
|
) {
|
||||||
|
let hygiene = Hygiene::new(db, file_id);
|
||||||
for item in owner.items_with_macros() {
|
for item in owner.items_with_macros() {
|
||||||
match item {
|
match item {
|
||||||
ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => {
|
ast::ItemOrMacro::Item(ast::ModuleItem::ImplBlock(impl_block_ast)) => {
|
||||||
let attrs = Attr::from_attrs_owner(file_id, &impl_block_ast, db);
|
let attrs = Attr::from_attrs_owner(&impl_block_ast, &hygiene);
|
||||||
if attrs.map_or(false, |attrs| {
|
if attrs.map_or(false, |attrs| {
|
||||||
attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
|
attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
|
||||||
}) {
|
}) {
|
||||||
|
@ -247,7 +249,7 @@ impl ModuleImplBlocks {
|
||||||
}
|
}
|
||||||
ast::ItemOrMacro::Item(_) => (),
|
ast::ItemOrMacro::Item(_) => (),
|
||||||
ast::ItemOrMacro::Macro(macro_call) => {
|
ast::ItemOrMacro::Macro(macro_call) => {
|
||||||
let attrs = Attr::from_attrs_owner(file_id, ¯o_call, db);
|
let attrs = Attr::from_attrs_owner(¯o_call, &hygiene);
|
||||||
if attrs.map_or(false, |attrs| {
|
if attrs.map_or(false, |attrs| {
|
||||||
attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
|
attrs.iter().any(|attr| attr.is_cfg_enabled(cfg_options) == Some(false))
|
||||||
}) {
|
}) {
|
||||||
|
@ -256,9 +258,8 @@ impl ModuleImplBlocks {
|
||||||
|
|
||||||
//FIXME: we should really cut down on the boilerplate required to process a macro
|
//FIXME: we should really cut down on the boilerplate required to process a macro
|
||||||
let ast_id = AstId::new(file_id, db.ast_id_map(file_id).ast_id(¯o_call));
|
let ast_id = AstId::new(file_id, db.ast_id_map(file_id).ast_id(¯o_call));
|
||||||
if let Some(path) = macro_call
|
if let Some(path) =
|
||||||
.path()
|
macro_call.path().and_then(|path| Path::from_src(path, &hygiene))
|
||||||
.and_then(|path| Path::from_src(Source { ast: path, file_id }, db))
|
|
||||||
{
|
{
|
||||||
if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path)
|
if let Some(def) = self.module.resolver(db).resolve_path_as_macro(db, &path)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,6 +60,13 @@ use crate::{ids::MacroFileKind, resolve::Resolver};
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
adt::VariantDef,
|
adt::VariantDef,
|
||||||
|
code_model::{
|
||||||
|
docs::{DocDef, Docs, Documentation},
|
||||||
|
src::{HasBodySource, HasSource, Source},
|
||||||
|
Adt, AssocItem, BuiltinType, Const, ConstData, Container, Crate, CrateDependency,
|
||||||
|
DefWithBody, Enum, EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module,
|
||||||
|
ModuleDef, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
|
||||||
|
},
|
||||||
expr::ExprScopes,
|
expr::ExprScopes,
|
||||||
from_source::FromSource,
|
from_source::FromSource,
|
||||||
generics::{GenericDef, GenericParam, GenericParams, HasGenericParams},
|
generics::{GenericDef, GenericParam, GenericParams, HasGenericParams},
|
||||||
|
@ -73,17 +80,8 @@ pub use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use self::code_model::{
|
|
||||||
docs::{DocDef, Docs, Documentation},
|
|
||||||
src::{HasBodySource, HasSource, Source},
|
|
||||||
Adt, AssocItem, BuiltinType, Const, ConstData, Container, Crate, CrateDependency, DefWithBody,
|
|
||||||
Enum, EnumVariant, FieldSource, FnData, Function, HasBody, MacroDef, Module, ModuleDef,
|
|
||||||
ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub use hir_def::{
|
pub use hir_def::{
|
||||||
either::Either,
|
|
||||||
name::Name,
|
|
||||||
path::{Path, PathKind},
|
path::{Path, PathKind},
|
||||||
type_ref::Mutability,
|
type_ref::Mutability,
|
||||||
};
|
};
|
||||||
|
pub use hir_expand::{either::Either, name::Name};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! FIXME: write short doc here
|
//! FIXME: write short doc here
|
||||||
|
|
||||||
use hir_def::{attr::Attr, name, nameres::raw};
|
use hir_def::{attr::Attr, nameres::raw};
|
||||||
|
use hir_expand::name;
|
||||||
use ra_cfg::CfgOptions;
|
use ra_cfg::CfgOptions;
|
||||||
use ra_db::FileId;
|
use ra_db::FileId;
|
||||||
use ra_syntax::{ast, SmolStr};
|
use ra_syntax::{ast, SmolStr};
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
name::{self, Name},
|
|
||||||
path::{Path, PathKind},
|
path::{Path, PathKind},
|
||||||
CrateModuleId,
|
CrateModuleId,
|
||||||
};
|
};
|
||||||
|
use hir_expand::name::{self, Name};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
//! purely for "IDE needs".
|
//! purely for "IDE needs".
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{name::AsName, path::known};
|
use hir_def::path::known;
|
||||||
|
use hir_expand::name::AsName;
|
||||||
use ra_db::FileId;
|
use ra_db::FileId;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::name::AsName;
|
use hir_expand::name::AsName;
|
||||||
|
|
||||||
use ra_syntax::ast::{self, NameOwner};
|
use ra_syntax::ast::{self, NameOwner};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use std::iter::successors;
|
use std::iter::successors;
|
||||||
|
|
||||||
use hir_def::name;
|
use hir_expand::name;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
|
||||||
use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
|
use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk};
|
||||||
|
|
|
@ -22,10 +22,10 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
name,
|
|
||||||
path::known,
|
path::known,
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
};
|
};
|
||||||
|
use hir_expand::name;
|
||||||
use ra_arena::map::ArenaMap;
|
use ra_arena::map::ArenaMap;
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use test_utils::tested_by;
|
use test_utils::tested_by;
|
||||||
|
|
|
@ -3,10 +3,8 @@
|
||||||
use std::iter::{repeat, repeat_with};
|
use std::iter::{repeat, repeat_with};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::path::{GenericArg, GenericArgs};
|
||||||
name,
|
use hir_expand::name;
|
||||||
path::{GenericArg, GenericArgs},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
|
use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -9,7 +9,8 @@ use chalk_ir::{
|
||||||
};
|
};
|
||||||
use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
|
use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum};
|
||||||
|
|
||||||
use hir_def::name;
|
use hir_expand::name;
|
||||||
|
|
||||||
use ra_db::salsa::{InternId, InternKey};
|
use ra_db::salsa::{InternId, InternKey};
|
||||||
|
|
||||||
use super::{Canonical, ChalkContext, Impl, Obligation};
|
use super::{Canonical, ChalkContext, Impl, Obligation};
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_def::{
|
use hir_def::type_ref::TypeRef;
|
||||||
name::{AsName, Name},
|
use hir_expand::name::{AsName, Name};
|
||||||
type_ref::TypeRef,
|
|
||||||
};
|
|
||||||
use ra_syntax::ast::NameOwner;
|
use ra_syntax::ast::NameOwner;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_expand::db::AstDatabase;
|
use hir_expand::hygiene::Hygiene;
|
||||||
use mbe::ast_to_token_tree;
|
use mbe::ast_to_token_tree;
|
||||||
use ra_cfg::CfgOptions;
|
use ra_cfg::CfgOptions;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
|
@ -11,7 +11,7 @@ use ra_syntax::{
|
||||||
};
|
};
|
||||||
use tt::Subtree;
|
use tt::Subtree;
|
||||||
|
|
||||||
use crate::{path::Path, HirFileId, Source};
|
use crate::path::Path;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Attr {
|
pub struct Attr {
|
||||||
|
@ -26,11 +26,8 @@ pub enum AttrInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attr {
|
impl Attr {
|
||||||
pub(crate) fn from_src(
|
pub(crate) fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option<Attr> {
|
||||||
Source { file_id, ast }: Source<ast::Attr>,
|
let path = Path::from_src(ast.path()?, hygiene)?;
|
||||||
db: &impl AstDatabase,
|
|
||||||
) -> Option<Attr> {
|
|
||||||
let path = Path::from_src(Source { file_id, ast: ast.path()? }, db)?;
|
|
||||||
let input = match ast.input() {
|
let input = match ast.input() {
|
||||||
None => None,
|
None => None,
|
||||||
Some(ast::AttrInput::Literal(lit)) => {
|
Some(ast::AttrInput::Literal(lit)) => {
|
||||||
|
@ -46,17 +43,13 @@ impl Attr {
|
||||||
Some(Attr { path, input })
|
Some(Attr { path, input })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_attrs_owner(
|
pub fn from_attrs_owner(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Option<Arc<[Attr]>> {
|
||||||
file_id: HirFileId,
|
|
||||||
owner: &dyn AttrsOwner,
|
|
||||||
db: &impl AstDatabase,
|
|
||||||
) -> Option<Arc<[Attr]>> {
|
|
||||||
let mut attrs = owner.attrs().peekable();
|
let mut attrs = owner.attrs().peekable();
|
||||||
if attrs.peek().is_none() {
|
if attrs.peek().is_none() {
|
||||||
// Avoid heap allocation
|
// Avoid heap allocation
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(attrs.flat_map(|ast| Attr::from_src(Source { file_id, ast }, db)).collect())
|
Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_simple_atom(&self, name: &str) -> bool {
|
pub fn is_simple_atom(&self, name: &str) -> bool {
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
//! actually true.
|
//! actually true.
|
||||||
|
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod either;
|
|
||||||
pub mod attr;
|
pub mod attr;
|
||||||
pub mod name;
|
|
||||||
pub mod path;
|
pub mod path;
|
||||||
pub mod type_ref;
|
pub mod type_ref;
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,20 @@
|
||||||
|
|
||||||
use std::{ops::Index, sync::Arc};
|
use std::{ops::Index, sync::Arc};
|
||||||
|
|
||||||
use hir_expand::{ast_id_map::AstIdMap, db::AstDatabase};
|
use hir_expand::{
|
||||||
|
ast_id_map::AstIdMap,
|
||||||
|
db::AstDatabase,
|
||||||
|
either::Either,
|
||||||
|
hygiene::Hygiene,
|
||||||
|
name::{AsName, Name},
|
||||||
|
};
|
||||||
use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
|
use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, AttrsOwner, NameOwner},
|
ast::{self, AttrsOwner, NameOwner},
|
||||||
AstNode, AstPtr, SourceFile,
|
AstNode, AstPtr, SourceFile,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{attr::Attr, db::DefDatabase2, path::Path, FileAstId, HirFileId, ModuleSource, Source};
|
||||||
attr::Attr,
|
|
||||||
db::DefDatabase2,
|
|
||||||
either::Either,
|
|
||||||
name::{AsName, Name},
|
|
||||||
path::Path,
|
|
||||||
FileAstId, HirFileId, ModuleSource, Source,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// `RawItems` is a set of top-level items in a file (except for impls).
|
/// `RawItems` is a set of top-level items in a file (except for impls).
|
||||||
///
|
///
|
||||||
|
@ -40,10 +39,8 @@ pub struct ImportSourceMap {
|
||||||
type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
|
type ImportSourcePtr = Either<AstPtr<ast::UseTree>, AstPtr<ast::ExternCrateItem>>;
|
||||||
type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
|
type ImportSource = Either<ast::UseTree, ast::ExternCrateItem>;
|
||||||
|
|
||||||
impl ImportSourcePtr {
|
fn to_node(ptr: ImportSourcePtr, file: &SourceFile) -> ImportSource {
|
||||||
fn to_node(self, file: &SourceFile) -> ImportSource {
|
ptr.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
|
||||||
self.map(|ptr| ptr.to_node(file.syntax()), |ptr| ptr.to_node(file.syntax()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportSourceMap {
|
impl ImportSourceMap {
|
||||||
|
@ -57,7 +54,7 @@ impl ImportSourceMap {
|
||||||
ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
|
ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.map[import].to_node(&file)
|
to_node(self.map[import], &file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +75,7 @@ impl RawItems {
|
||||||
source_ast_id_map: db.ast_id_map(file_id),
|
source_ast_id_map: db.ast_id_map(file_id),
|
||||||
source_map: ImportSourceMap::default(),
|
source_map: ImportSourceMap::default(),
|
||||||
file_id,
|
file_id,
|
||||||
db,
|
hygiene: Hygiene::new(db, file_id),
|
||||||
};
|
};
|
||||||
if let Some(node) = db.parse_or_expand(file_id) {
|
if let Some(node) = db.parse_or_expand(file_id) {
|
||||||
if let Some(source_file) = ast::SourceFile::cast(node.clone()) {
|
if let Some(source_file) = ast::SourceFile::cast(node.clone()) {
|
||||||
|
@ -204,15 +201,15 @@ pub struct MacroData {
|
||||||
pub export: bool,
|
pub export: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RawItemsCollector<DB> {
|
struct RawItemsCollector {
|
||||||
raw_items: RawItems,
|
raw_items: RawItems,
|
||||||
source_ast_id_map: Arc<AstIdMap>,
|
source_ast_id_map: Arc<AstIdMap>,
|
||||||
source_map: ImportSourceMap,
|
source_map: ImportSourceMap,
|
||||||
file_id: HirFileId,
|
file_id: HirFileId,
|
||||||
db: DB,
|
hygiene: Hygiene,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DB: AstDatabase> RawItemsCollector<&DB> {
|
impl RawItemsCollector {
|
||||||
fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) {
|
fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) {
|
||||||
for item_or_macro in body.items_with_macros() {
|
for item_or_macro in body.items_with_macros() {
|
||||||
match item_or_macro {
|
match item_or_macro {
|
||||||
|
@ -309,9 +306,10 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
|
||||||
let is_prelude = use_item.has_atom_attr("prelude_import");
|
let is_prelude = use_item.has_atom_attr("prelude_import");
|
||||||
let attrs = self.parse_attrs(&use_item);
|
let attrs = self.parse_attrs(&use_item);
|
||||||
|
|
||||||
|
let mut buf = Vec::new();
|
||||||
Path::expand_use_item(
|
Path::expand_use_item(
|
||||||
Source { ast: use_item, file_id: self.file_id },
|
Source { ast: use_item, file_id: self.file_id },
|
||||||
self.db,
|
&self.hygiene,
|
||||||
|path, use_tree, is_glob, alias| {
|
|path, use_tree, is_glob, alias| {
|
||||||
let import_data = ImportData {
|
let import_data = ImportData {
|
||||||
path,
|
path,
|
||||||
|
@ -321,14 +319,12 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
|
||||||
is_extern_crate: false,
|
is_extern_crate: false,
|
||||||
is_macro_use: false,
|
is_macro_use: false,
|
||||||
};
|
};
|
||||||
self.push_import(
|
buf.push((import_data, Either::A(AstPtr::new(use_tree))));
|
||||||
current_module,
|
|
||||||
attrs.clone(),
|
|
||||||
import_data,
|
|
||||||
Either::A(AstPtr::new(use_tree)),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
|
for (import_data, ptr) in buf {
|
||||||
|
self.push_import(current_module, attrs.clone(), import_data, ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_extern_crate_item(
|
fn add_extern_crate_item(
|
||||||
|
@ -361,10 +357,7 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
|
||||||
|
|
||||||
fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
|
fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
|
||||||
let attrs = self.parse_attrs(&m);
|
let attrs = self.parse_attrs(&m);
|
||||||
let path = match m
|
let path = match m.path().and_then(|path| Path::from_src(path, &self.hygiene)) {
|
||||||
.path()
|
|
||||||
.and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db))
|
|
||||||
{
|
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
@ -402,6 +395,6 @@ impl<DB: AstDatabase> RawItemsCollector<&DB> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
|
fn parse_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
|
||||||
Attr::from_attrs_owner(self.file_id, item, self.db)
|
Attr::from_attrs_owner(item, &self.hygiene)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
use std::{iter, sync::Arc};
|
use std::{iter, sync::Arc};
|
||||||
|
|
||||||
use hir_expand::db::AstDatabase;
|
use hir_expand::{
|
||||||
|
either::Either,
|
||||||
|
hygiene::Hygiene,
|
||||||
|
name::{self, AsName, Name},
|
||||||
|
};
|
||||||
use ra_db::CrateId;
|
use ra_db::CrateId;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{self, NameOwner, TypeAscriptionOwner},
|
ast::{self, NameOwner, TypeAscriptionOwner},
|
||||||
AstNode,
|
AstNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{type_ref::TypeRef, Source};
|
||||||
name::{self, AsName, Name},
|
|
||||||
type_ref::TypeRef,
|
|
||||||
Source,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Path {
|
pub struct Path {
|
||||||
|
@ -68,11 +68,11 @@ impl Path {
|
||||||
/// Calls `cb` with all paths, represented by this use item.
|
/// Calls `cb` with all paths, represented by this use item.
|
||||||
pub fn expand_use_item(
|
pub fn expand_use_item(
|
||||||
item_src: Source<ast::UseItem>,
|
item_src: Source<ast::UseItem>,
|
||||||
db: &impl AstDatabase,
|
hygiene: &Hygiene,
|
||||||
mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
|
mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
|
||||||
) {
|
) {
|
||||||
if let Some(tree) = item_src.ast.use_tree() {
|
if let Some(tree) = item_src.ast.use_tree() {
|
||||||
expand_use_tree(None, tree, &|| item_src.file_id.macro_crate(db), &mut cb);
|
expand_use_tree(None, tree, hygiene, &mut cb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,17 +89,12 @@ impl Path {
|
||||||
/// Converts an `ast::Path` to `Path`. Works with use trees.
|
/// Converts an `ast::Path` to `Path`. Works with use trees.
|
||||||
/// DEPRECATED: It does not handle `$crate` from macro call.
|
/// DEPRECATED: It does not handle `$crate` from macro call.
|
||||||
pub fn from_ast(path: ast::Path) -> Option<Path> {
|
pub fn from_ast(path: ast::Path) -> Option<Path> {
|
||||||
Path::parse(path, &|| None)
|
Path::from_src(path, &Hygiene::new_unhygienic())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an `ast::Path` to `Path`. Works with use trees.
|
/// Converts an `ast::Path` to `Path`. Works with use trees.
|
||||||
/// It correctly handles `$crate` based path from macro call.
|
/// It correctly handles `$crate` based path from macro call.
|
||||||
pub fn from_src(source: Source<ast::Path>, db: &impl AstDatabase) -> Option<Path> {
|
pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
|
||||||
let file_id = source.file_id;
|
|
||||||
Path::parse(source.ast, &|| file_id.macro_crate(db))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse(mut path: ast::Path, macro_crate: &impl Fn() -> Option<CrateId>) -> Option<Path> {
|
|
||||||
let mut kind = PathKind::Plain;
|
let mut kind = PathKind::Plain;
|
||||||
let mut segments = Vec::new();
|
let mut segments = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
|
@ -110,14 +105,10 @@ impl Path {
|
||||||
}
|
}
|
||||||
|
|
||||||
match segment.kind()? {
|
match segment.kind()? {
|
||||||
ast::PathSegmentKind::Name(name) => {
|
ast::PathSegmentKind::Name(name_ref) => {
|
||||||
if name.text() == "$crate" {
|
// FIXME: this should just return name
|
||||||
if let Some(macro_crate) = macro_crate() {
|
match hygiene.name_ref_to_name(name_ref) {
|
||||||
kind = PathKind::DollarCrate(macro_crate);
|
Either::A(name) => {
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let args = segment
|
let args = segment
|
||||||
.type_arg_list()
|
.type_arg_list()
|
||||||
.and_then(GenericArgs::from_ast)
|
.and_then(GenericArgs::from_ast)
|
||||||
|
@ -128,9 +119,15 @@ impl Path {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(Arc::new);
|
.map(Arc::new);
|
||||||
let segment = PathSegment { name: name.as_name(), args_and_bindings: args };
|
let segment = PathSegment { name, args_and_bindings: args };
|
||||||
segments.push(segment);
|
segments.push(segment);
|
||||||
}
|
}
|
||||||
|
Either::B(crate_id) => {
|
||||||
|
kind = PathKind::DollarCrate(crate_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ast::PathSegmentKind::Type { type_ref, trait_ref } => {
|
ast::PathSegmentKind::Type { type_ref, trait_ref } => {
|
||||||
assert!(path.qualifier().is_none()); // this can only occur at the first segment
|
assert!(path.qualifier().is_none()); // this can only occur at the first segment
|
||||||
|
|
||||||
|
@ -143,7 +140,7 @@ impl Path {
|
||||||
}
|
}
|
||||||
// <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
|
// <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
|
||||||
Some(trait_ref) => {
|
Some(trait_ref) => {
|
||||||
let path = Path::parse(trait_ref.path()?, macro_crate)?;
|
let path = Path::from_src(trait_ref.path()?, hygiene)?;
|
||||||
kind = path.kind;
|
kind = path.kind;
|
||||||
let mut prefix_segments = path.segments;
|
let mut prefix_segments = path.segments;
|
||||||
prefix_segments.reverse();
|
prefix_segments.reverse();
|
||||||
|
@ -294,8 +291,8 @@ impl From<Name> for Path {
|
||||||
fn expand_use_tree(
|
fn expand_use_tree(
|
||||||
prefix: Option<Path>,
|
prefix: Option<Path>,
|
||||||
tree: ast::UseTree,
|
tree: ast::UseTree,
|
||||||
macro_crate: &impl Fn() -> Option<CrateId>,
|
hygiene: &Hygiene,
|
||||||
cb: &mut impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
|
cb: &mut dyn FnMut(Path, &ast::UseTree, bool, Option<Name>),
|
||||||
) {
|
) {
|
||||||
if let Some(use_tree_list) = tree.use_tree_list() {
|
if let Some(use_tree_list) = tree.use_tree_list() {
|
||||||
let prefix = match tree.path() {
|
let prefix = match tree.path() {
|
||||||
|
@ -303,13 +300,13 @@ fn expand_use_tree(
|
||||||
None => prefix,
|
None => prefix,
|
||||||
// E.g. `use something::{inner}` (prefix is `None`, path is `something`)
|
// E.g. `use something::{inner}` (prefix is `None`, path is `something`)
|
||||||
// or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
|
// or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
|
||||||
Some(path) => match convert_path(prefix, path, macro_crate) {
|
Some(path) => match convert_path(prefix, path, hygiene) {
|
||||||
Some(it) => Some(it),
|
Some(it) => Some(it),
|
||||||
None => return, // FIXME: report errors somewhere
|
None => return, // FIXME: report errors somewhere
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
for child_tree in use_tree_list.use_trees() {
|
for child_tree in use_tree_list.use_trees() {
|
||||||
expand_use_tree(prefix.clone(), child_tree, macro_crate, cb);
|
expand_use_tree(prefix.clone(), child_tree, hygiene, cb);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
|
let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name());
|
||||||
|
@ -326,7 +323,7 @@ fn expand_use_tree(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(path) = convert_path(prefix, ast_path, macro_crate) {
|
if let Some(path) = convert_path(prefix, ast_path, hygiene) {
|
||||||
let is_glob = tree.has_star();
|
let is_glob = tree.has_star();
|
||||||
cb(path, &tree, is_glob, alias)
|
cb(path, &tree, is_glob, alias)
|
||||||
}
|
}
|
||||||
|
@ -336,38 +333,37 @@ fn expand_use_tree(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_path(
|
fn convert_path(prefix: Option<Path>, path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
|
||||||
prefix: Option<Path>,
|
|
||||||
path: ast::Path,
|
|
||||||
macro_crate: &impl Fn() -> Option<CrateId>,
|
|
||||||
) -> Option<Path> {
|
|
||||||
let prefix = if let Some(qual) = path.qualifier() {
|
let prefix = if let Some(qual) = path.qualifier() {
|
||||||
Some(convert_path(prefix, qual, macro_crate)?)
|
Some(convert_path(prefix, qual, hygiene)?)
|
||||||
} else {
|
} else {
|
||||||
prefix
|
prefix
|
||||||
};
|
};
|
||||||
|
|
||||||
let segment = path.segment()?;
|
let segment = path.segment()?;
|
||||||
let res = match segment.kind()? {
|
let res = match segment.kind()? {
|
||||||
ast::PathSegmentKind::Name(name) => {
|
ast::PathSegmentKind::Name(name_ref) => {
|
||||||
if name.text() == "$crate" {
|
match hygiene.name_ref_to_name(name_ref) {
|
||||||
if let Some(krate) = macro_crate() {
|
Either::A(name) => {
|
||||||
return Some(Path::from_simple_segments(
|
|
||||||
PathKind::DollarCrate(krate),
|
|
||||||
iter::empty(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no type args in use
|
// no type args in use
|
||||||
let mut res = prefix
|
let mut res = prefix.unwrap_or_else(|| Path {
|
||||||
.unwrap_or_else(|| Path { kind: PathKind::Plain, segments: Vec::with_capacity(1) });
|
kind: PathKind::Plain,
|
||||||
|
segments: Vec::with_capacity(1),
|
||||||
|
});
|
||||||
res.segments.push(PathSegment {
|
res.segments.push(PathSegment {
|
||||||
name: name.as_name(),
|
name,
|
||||||
args_and_bindings: None, // no type args in use
|
args_and_bindings: None, // no type args in use
|
||||||
});
|
});
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
Either::B(crate_id) => {
|
||||||
|
return Some(Path::from_simple_segments(
|
||||||
|
PathKind::DollarCrate(crate_id),
|
||||||
|
iter::empty(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ast::PathSegmentKind::CrateKw => {
|
ast::PathSegmentKind::CrateKw => {
|
||||||
if prefix.is_some() {
|
if prefix.is_some() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -395,8 +391,9 @@ fn convert_path(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod known {
|
pub mod known {
|
||||||
|
use hir_expand::name;
|
||||||
|
|
||||||
use super::{Path, PathKind};
|
use super::{Path, PathKind};
|
||||||
use crate::name;
|
|
||||||
|
|
||||||
pub fn std_iter_into_iterator() -> Path {
|
pub fn std_iter_into_iterator() -> Path {
|
||||||
Path::from_simple_segments(
|
Path::from_simple_segments(
|
||||||
|
|
46
crates/ra_hir_expand/src/hygiene.rs
Normal file
46
crates/ra_hir_expand/src/hygiene.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
//! This modules handles hygiene information.
|
||||||
|
//!
|
||||||
|
//! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at
|
||||||
|
//! this moment, this is horribly incomplete and handles only `$crate`.
|
||||||
|
use ra_db::CrateId;
|
||||||
|
use ra_syntax::ast;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
db::AstDatabase,
|
||||||
|
either::Either,
|
||||||
|
name::{AsName, Name},
|
||||||
|
HirFileId, HirFileIdRepr,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Hygiene {
|
||||||
|
// This is what `$crate` expands to
|
||||||
|
def_crate: Option<CrateId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hygiene {
|
||||||
|
pub fn new(db: &impl AstDatabase, file_id: HirFileId) -> Hygiene {
|
||||||
|
let def_crate = match file_id.0 {
|
||||||
|
HirFileIdRepr::FileId(_) => None,
|
||||||
|
HirFileIdRepr::MacroFile(macro_file) => {
|
||||||
|
let loc = db.lookup_intern_macro(macro_file.macro_call_id);
|
||||||
|
Some(loc.def.krate)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Hygiene { def_crate }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_unhygienic() -> Hygiene {
|
||||||
|
Hygiene { def_crate: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: this should just return name
|
||||||
|
pub fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either<Name, CrateId> {
|
||||||
|
if let Some(def_crate) = self.def_crate {
|
||||||
|
if name_ref.text() == "$crate" {
|
||||||
|
return Either::B(def_crate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Either::A(name_ref.as_name())
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod ast_id_map;
|
pub mod ast_id_map;
|
||||||
|
pub mod either;
|
||||||
|
pub mod name;
|
||||||
|
pub mod hygiene;
|
||||||
|
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
|
@ -59,17 +62,6 @@ impl HirFileId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the crate which the macro lives in, if it is a macro file.
|
|
||||||
pub fn macro_crate(self, db: &dyn db::AstDatabase) -> Option<CrateId> {
|
|
||||||
match self.0 {
|
|
||||||
HirFileIdRepr::FileId(_) => None,
|
|
||||||
HirFileIdRepr::MacroFile(macro_file) => {
|
|
||||||
let loc = db.lookup_intern_macro(macro_file.macro_call_id);
|
|
||||||
Some(loc.def.krate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue