Merge commit 'aa9bc86125' into sync-from-ra

This commit is contained in:
Laurențiu Nicola 2023-06-05 12:04:23 +03:00
parent 1570299af4
commit c48062fe2a
598 changed files with 57696 additions and 17615 deletions

View file

@ -4,7 +4,6 @@ use hir_def::{
attr::{AttrsWithOwner, Documentation},
item_scope::ItemInNs,
path::ModPath,
per_ns::PerNs,
resolver::HasResolver,
AttrDefId, GenericParamId, ModuleDefId,
};
@ -41,7 +40,7 @@ macro_rules! impl_has_attrs {
impl HasAttrs for $def {
fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
let def = AttrDefId::$def_id(self.into());
db.attrs(def)
db.attrs_with_owner(def)
}
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
let def = AttrDefId::$def_id(self.into());
@ -121,6 +120,7 @@ impl HasAttrs for AssocItem {
}
}
/// Resolves the item `link` points to in the scope of `def`.
fn resolve_doc_path(
db: &dyn HirDatabase,
def: AttrDefId,
@ -155,14 +155,14 @@ fn resolve_doc_path(
.syntax_node()
.descendants()
.find_map(ast::Path::cast)?;
if ast_path.to_string() != link {
if ast_path.syntax().text() != link {
return None;
}
ModPath::from_src(db.upcast(), ast_path, &Hygiene::new_unhygienic())?
};
let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath);
let resolved = if resolved == PerNs::none() {
let resolved = if resolved.is_none() {
resolver.resolve_module_path_in_trait_assoc_items(db.upcast(), &modpath)?
} else {
resolved

View file

@ -6,8 +6,8 @@
pub use hir_def::db::*;
pub use hir_expand::db::{
AstIdMapQuery, ExpandDatabase, ExpandDatabaseStorage, ExpandProcMacroQuery, HygieneFrameQuery,
InternMacroCallQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandErrorQuery,
MacroExpandQuery, ParseMacroExpansionQuery,
InternMacroCallQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery,
ParseMacroExpansionErrorQuery, ParseMacroExpansionQuery,
};
pub use hir_ty::db::*;

View file

@ -10,7 +10,7 @@ use cfg::{CfgExpr, CfgOptions};
use either::Either;
use hir_def::path::ModPath;
use hir_expand::{name::Name, HirFileId, InFile};
use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};
use syntax::{ast, AstPtr, SyntaxError, SyntaxNodePtr, TextRange};
use crate::{AssocItem, Field, Local, MacroKind, Type};
@ -38,19 +38,25 @@ diagnostics![
IncorrectCase,
InvalidDeriveTarget,
IncoherentImpl,
MacroDefError,
MacroError,
MacroExpansionParseError,
MalformedDerive,
MismatchedArgCount,
MissingFields,
MissingMatchArms,
MissingUnsafe,
MovedOutOfRef,
NeedMut,
NoSuchField,
PrivateAssocItem,
PrivateField,
ReplaceFilterMapNextWithFindMap,
TypedHole,
TypeMismatch,
UndeclaredLabel,
UnimplementedBuiltinMacro,
UnreachableLabel,
UnresolvedExternCrate,
UnresolvedField,
UnresolvedImport,
@ -61,6 +67,19 @@ diagnostics![
UnusedMut,
];
#[derive(Debug)]
pub struct BreakOutsideOfLoop {
pub expr: InFile<AstPtr<ast::Expr>>,
pub is_break: bool,
pub bad_value_break: bool,
}
#[derive(Debug)]
pub struct TypedHole {
pub expr: InFile<AstPtr<ast::Expr>>,
pub expected: Type,
}
#[derive(Debug)]
pub struct UnresolvedModule {
pub decl: InFile<AstPtr<ast::Module>>,
@ -84,6 +103,17 @@ pub struct UnresolvedMacroCall {
pub path: ModPath,
pub is_bang: bool,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct UnreachableLabel {
pub node: InFile<AstPtr<ast::Lifetime>>,
pub name: Name,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct UndeclaredLabel {
pub node: InFile<AstPtr<ast::Lifetime>>,
pub name: Name,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct InactiveCode {
@ -111,6 +141,20 @@ pub struct MacroError {
pub message: String,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct MacroExpansionParseError {
pub node: InFile<SyntaxNodePtr>,
pub precise_location: Option<TextRange>,
pub errors: Box<[SyntaxError]>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct MacroDefError {
pub node: InFile<AstPtr<ast::Macro>>,
pub message: String,
pub name: Option<TextRange>,
}
#[derive(Debug)]
pub struct UnimplementedBuiltinMacro {
pub node: InFile<SyntaxNodePtr>,
@ -166,13 +210,6 @@ pub struct PrivateField {
pub field: Field,
}
#[derive(Debug)]
pub struct BreakOutsideOfLoop {
pub expr: InFile<AstPtr<ast::Expr>>,
pub is_break: bool,
pub bad_value_break: bool,
}
#[derive(Debug)]
pub struct MissingUnsafe {
pub expr: InFile<AstPtr<ast::Expr>>,
@ -223,3 +260,9 @@ pub struct NeedMut {
pub struct UnusedMut {
pub local: Local,
}
#[derive(Debug)]
pub struct MovedOutOfRef {
pub ty: Type,
pub span: InFile<SyntaxNodePtr>,
}

View file

@ -1,6 +1,6 @@
//! HirDisplay implementations for various hir types.
use hir_def::{
adt::VariantData,
data::adt::VariantData,
generics::{
TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
},
@ -8,6 +8,7 @@ use hir_def::{
type_ref::{TypeBound, TypeRef},
AdtId, GenericDefId,
};
use hir_expand::name;
use hir_ty::{
display::{
write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
@ -50,7 +51,7 @@ impl HirDisplay for Function {
// FIXME: String escape?
write!(f, "extern \"{}\" ", &**abi)?;
}
write!(f, "fn {}", data.name)?;
write!(f, "fn {}", data.name.display(f.db.upcast()))?;
write_generic_params(GenericDefId::FunctionId(self.id), f)?;
@ -62,7 +63,7 @@ impl HirDisplay for Function {
{
f.write_char('&')?;
if let Some(lifetime) = lifetime {
write!(f, "{} ", lifetime.name)?;
write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
}
if let hir_def::type_ref::Mutability::Mut = mut_ {
f.write_str("mut ")?;
@ -76,22 +77,22 @@ impl HirDisplay for Function {
};
let mut first = true;
for (name, type_ref) in &data.params {
// FIXME: Use resolved `param.ty` once we no longer discard lifetimes
for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)) {
let local = param.as_local(db).map(|it| it.name(db));
if !first {
f.write_str(", ")?;
} else {
first = false;
if data.has_self_param() {
if local == Some(name!(self)) {
write_self_param(type_ref, f)?;
continue;
}
}
match name {
Some(name) => write!(f, "{name}: ")?,
match local {
Some(name) => write!(f, "{}: ", name.display(f.db.upcast()))?,
None => f.write_str("_: ")?,
}
// FIXME: Use resolved `param.ty` or raw `type_ref`?
// The former will ignore lifetime arguments currently.
type_ref.hir_fmt(f)?;
}
@ -150,7 +151,7 @@ impl HirDisplay for Struct {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("struct ")?;
write!(f, "{}", self.name(f.db))?;
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
let def_id = GenericDefId::AdtId(AdtId::StructId(self.id));
write_generic_params(def_id, f)?;
write_where_clause(def_id, f)?;
@ -162,7 +163,7 @@ impl HirDisplay for Enum {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("enum ")?;
write!(f, "{}", self.name(f.db))?;
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
let def_id = GenericDefId::AdtId(AdtId::EnumId(self.id));
write_generic_params(def_id, f)?;
write_where_clause(def_id, f)?;
@ -174,7 +175,7 @@ impl HirDisplay for Union {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
f.write_str("union ")?;
write!(f, "{}", self.name(f.db))?;
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
let def_id = GenericDefId::AdtId(AdtId::UnionId(self.id));
write_generic_params(def_id, f)?;
write_where_clause(def_id, f)?;
@ -185,14 +186,14 @@ impl HirDisplay for Union {
impl HirDisplay for Field {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.parent.module(f.db).id, self.visibility(f.db), f)?;
write!(f, "{}: ", self.name(f.db))?;
write!(f, "{}: ", self.name(f.db).display(f.db.upcast()))?;
self.ty(f.db).hir_fmt(f)
}
}
impl HirDisplay for Variant {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write!(f, "{}", self.name(f.db))?;
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
let data = self.variant_data(f.db);
match &*data {
VariantData::Unit => {}
@ -221,7 +222,7 @@ impl HirDisplay for Variant {
f.write_str(", ")?;
}
// Enum variant fields must be pub.
write!(f, "{}: ", field.name)?;
write!(f, "{}: ", field.name.display(f.db.upcast()))?;
field.type_ref.hir_fmt(f)?;
}
f.write_str(" }")?;
@ -258,7 +259,7 @@ impl HirDisplay for TypeOrConstParam {
impl HirDisplay for TypeParam {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write!(f, "{}", self.name(f.db))?;
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
if f.omit_verbose_types() {
return Ok(());
}
@ -285,13 +286,13 @@ impl HirDisplay for TypeParam {
impl HirDisplay for LifetimeParam {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write!(f, "{}", self.name(f.db))
write!(f, "{}", self.name(f.db).display(f.db.upcast()))
}
}
impl HirDisplay for ConstParam {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write!(f, "const {}: ", self.name(f.db))?;
write!(f, "const {}: ", self.name(f.db).display(f.db.upcast()))?;
self.ty(f.db).hir_fmt(f)
}
}
@ -324,7 +325,7 @@ fn write_generic_params(
};
for (_, lifetime) in params.lifetimes.iter() {
delim(f)?;
write!(f, "{}", lifetime.name)?;
write!(f, "{}", lifetime.name.display(f.db.upcast()))?;
}
for (_, ty) in params.type_or_consts.iter() {
if let Some(name) = &ty.name() {
@ -334,7 +335,7 @@ fn write_generic_params(
continue;
}
delim(f)?;
write!(f, "{name}")?;
write!(f, "{}", name.display(f.db.upcast()))?;
if let Some(default) = &ty.default {
f.write_str(" = ")?;
default.hir_fmt(f)?;
@ -342,7 +343,7 @@ fn write_generic_params(
}
TypeOrConstParamData::ConstParamData(c) => {
delim(f)?;
write!(f, "const {name}: ")?;
write!(f, "const {}: ", name.display(f.db.upcast()))?;
c.ty.hir_fmt(f)?;
}
}
@ -379,7 +380,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(),
WherePredicateTypeTarget::TypeRef(ty) => ty.hir_fmt(f),
WherePredicateTypeTarget::TypeOrConstParam(id) => {
match &params.type_or_consts[*id].name() {
Some(name) => write!(f, "{name}"),
Some(name) => write!(f, "{}", name.display(f.db.upcast())),
None => f.write_str("{unnamed}"),
}
}
@ -411,10 +412,15 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(),
WherePredicate::Lifetime { target, bound } => {
if matches!(prev_pred, Some(WherePredicate::Lifetime { target: target_, .. }) if target_ == target)
{
write!(f, " + {}", bound.name)?;
write!(f, " + {}", bound.name.display(f.db.upcast()))?;
} else {
new_predicate(f)?;
write!(f, "{}: {}", target.name, bound.name)?;
write!(
f,
"{}: {}",
target.name.display(f.db.upcast()),
bound.name.display(f.db.upcast())
)?;
}
}
WherePredicate::ForLifetime { lifetimes, target, bound } => {
@ -431,7 +437,7 @@ fn write_where_clause(def: GenericDefId, f: &mut HirFormatter<'_>) -> Result<(),
if idx != 0 {
f.write_str(", ")?;
}
write!(f, "{lifetime}")?;
write!(f, "{}", lifetime.display(f.db.upcast()))?;
}
f.write_str("> ")?;
write_target(target, f)?;
@ -461,7 +467,7 @@ impl HirDisplay for Const {
let data = db.const_data(self.id);
f.write_str("const ")?;
match &data.name {
Some(name) => write!(f, "{name}: ")?,
Some(name) => write!(f, "{}: ", name.display(f.db.upcast()))?,
None => f.write_str("_: ")?,
}
data.type_ref.hir_fmt(f)?;
@ -477,7 +483,7 @@ impl HirDisplay for Static {
if data.mutable {
f.write_str("mut ")?;
}
write!(f, "{}: ", &data.name)?;
write!(f, "{}: ", data.name.display(f.db.upcast()))?;
data.type_ref.hir_fmt(f)?;
Ok(())
}
@ -493,7 +499,7 @@ impl HirDisplay for Trait {
if data.is_auto {
f.write_str("auto ")?;
}
write!(f, "trait {}", data.name)?;
write!(f, "trait {}", data.name.display(f.db.upcast()))?;
let def_id = GenericDefId::TraitId(self.id);
write_generic_params(def_id, f)?;
write_where_clause(def_id, f)?;
@ -505,7 +511,7 @@ impl HirDisplay for TraitAlias {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
let data = f.db.trait_alias_data(self.id);
write!(f, "trait {}", data.name)?;
write!(f, "trait {}", data.name.display(f.db.upcast()))?;
let def_id = GenericDefId::TraitAliasId(self.id);
write_generic_params(def_id, f)?;
f.write_str(" = ")?;
@ -521,7 +527,7 @@ impl HirDisplay for TypeAlias {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
let data = f.db.type_alias_data(self.id);
write!(f, "type {}", data.name)?;
write!(f, "type {}", data.name.display(f.db.upcast()))?;
let def_id = GenericDefId::TypeAliasId(self.id);
write_generic_params(def_id, f)?;
write_where_clause(def_id, f)?;
@ -541,8 +547,8 @@ impl HirDisplay for Module {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
// FIXME: Module doesn't have visibility saved in data.
match self.name(f.db) {
Some(name) => write!(f, "mod {name}"),
None if self.is_crate_root(f.db) => match self.krate(f.db).display_name(f.db) {
Some(name) => write!(f, "mod {}", name.display(f.db.upcast())),
None if self.is_crate_root() => match self.krate(f.db).display_name(f.db) {
Some(name) => write!(f, "extern crate {name}"),
None => f.write_str("extern crate {unknown}"),
},
@ -558,6 +564,6 @@ impl HirDisplay for Macro {
hir_def::MacroId::MacroRulesId(_) => f.write_str("macro_rules!"),
hir_def::MacroId::ProcMacroId(_) => f.write_str("proc_macro"),
}?;
write!(f, " {}", self.name(f.db))
write!(f, " {}", self.name(f.db).display(f.db.upcast()))
}
}

View file

@ -4,7 +4,7 @@
//! are splitting the hir.
use hir_def::{
expr::{BindingId, LabelId},
hir::{BindingId, LabelId},
AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, GenericDefId, GenericParamId,
ModuleDefId, VariantId,
};

File diff suppressed because it is too large Load diff

View file

@ -7,9 +7,10 @@ use std::{cell::RefCell, fmt, iter, mem, ops};
use base_db::{FileId, FileRange};
use either::Either;
use hir_def::{
body,
expr::Expr,
hir::Expr,
lower::LowerCtx,
macro_id_to_def_id,
nameres::MacroSubNs,
resolver::{self, HasResolver, Resolver, TypeNs},
type_ref::Mutability,
AsMacroCall, DefWithBodyId, FieldId, FunctionId, MacroId, TraitId, VariantId,
@ -140,7 +141,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.parse(file_id)
}
pub fn parse_or_expand(&self, file_id: HirFileId) -> Option<SyntaxNode> {
pub fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode {
self.imp.parse_or_expand(file_id)
}
@ -350,6 +351,13 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.type_of_pat(pat)
}
/// It also includes the changes that binding mode makes in the type. For example in
/// `let ref x @ Some(_) = None` the result of `type_of_pat` is `Option<T>` but the result
/// of this function is `&mut Option<T>`
pub fn type_of_binding_in_pat(&self, pat: &ast::IdentPat) -> Option<Type> {
self.imp.type_of_binding_in_pat(pat)
}
pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
self.imp.type_of_self(param)
}
@ -518,23 +526,23 @@ impl<'db> SemanticsImpl<'db> {
tree
}
fn parse_or_expand(&self, file_id: HirFileId) -> Option<SyntaxNode> {
let node = self.db.parse_or_expand(file_id)?;
fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode {
let node = self.db.parse_or_expand(file_id);
self.cache(node.clone(), file_id);
Some(node)
node
}
fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
let sa = self.analyze_no_infer(macro_call.syntax())?;
let file_id = sa.expand(self.db, InFile::new(sa.file_id, macro_call))?;
let node = self.parse_or_expand(file_id)?;
let node = self.parse_or_expand(file_id);
Some(node)
}
fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> {
let src = self.wrap_node_infile(item.clone());
let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src))?;
self.parse_or_expand(macro_call_id.as_file())
Some(self.parse_or_expand(macro_call_id.as_file()))
}
fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option<SyntaxNode> {
@ -543,7 +551,7 @@ impl<'db> SemanticsImpl<'db> {
let call_id = self.with_ctx(|ctx| {
ctx.attr_to_derive_macro_call(src.with_value(&adt), src).map(|(_, it, _)| it)
})?;
self.parse_or_expand(call_id.as_file())
Some(self.parse_or_expand(call_id.as_file()))
}
fn resolve_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<Option<Macro>>> {
@ -566,7 +574,7 @@ impl<'db> SemanticsImpl<'db> {
.into_iter()
.flat_map(|call| {
let file_id = call?.as_file();
let node = self.db.parse_or_expand(file_id)?;
let node = self.db.parse_or_expand(file_id);
self.cache(node.clone(), file_id);
Some(node)
})
@ -609,7 +617,7 @@ impl<'db> SemanticsImpl<'db> {
let krate = resolver.krate();
let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
resolver
.resolve_path_as_macro(self.db.upcast(), &path)
.resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
.map(|it| macro_id_to_def_id(self.db.upcast(), it))
})?;
hir_expand::db::expand_speculative(
@ -990,7 +998,7 @@ impl<'db> SemanticsImpl<'db> {
}
fn diagnostics_display_range(&self, src: InFile<SyntaxNodePtr>) -> FileRange {
let root = self.parse_or_expand(src.file_id).unwrap();
let root = self.parse_or_expand(src.file_id);
let node = src.map(|it| it.to_node(&root));
node.as_ref().original_file_range(self.db.upcast())
}
@ -1065,7 +1073,7 @@ impl<'db> SemanticsImpl<'db> {
fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
let analyze = self.analyze(ty.syntax())?;
let ctx = body::LowerCtx::new(self.db.upcast(), analyze.file_id);
let ctx = LowerCtx::with_file_id(self.db.upcast(), analyze.file_id);
let ty = hir_ty::TyLoweringContext::new(self.db, &analyze.resolver)
.lower_ty(&crate::TypeRef::from_ast(&ctx, ty.clone()));
Some(Type::new_with_resolver(self.db, &analyze.resolver, ty))
@ -1074,12 +1082,9 @@ impl<'db> SemanticsImpl<'db> {
fn resolve_trait(&self, path: &ast::Path) -> Option<Trait> {
let analyze = self.analyze(path.syntax())?;
let hygiene = hir_expand::hygiene::Hygiene::new(self.db.upcast(), analyze.file_id);
let ctx = body::LowerCtx::with_hygiene(self.db.upcast(), &hygiene);
let ctx = LowerCtx::with_hygiene(self.db.upcast(), &hygiene);
let hir_path = Path::from_src(path.clone(), &ctx)?;
match analyze
.resolver
.resolve_path_in_type_ns_fully(self.db.upcast(), hir_path.mod_path())?
{
match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? {
TypeNs::TraitId(id) => Some(Trait { id }),
_ => None,
}
@ -1141,6 +1146,10 @@ impl<'db> SemanticsImpl<'db> {
.map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
}
fn type_of_binding_in_pat(&self, pat: &ast::IdentPat) -> Option<Type> {
self.analyze(pat.syntax())?.type_of_binding_in_pat(self.db, pat)
}
fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
self.analyze(param.syntax())?.type_of_self(self.db, param)
}
@ -1647,6 +1656,7 @@ impl<'a> SemanticsScope<'a> {
VisibleTraits(resolver.traits_in_scope(self.db.upcast()))
}
/// Calls the passed closure `f` on all names in scope.
pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
let scope = self.resolver.names_in_scope(self.db.upcast());
for (name, entries) in scope {
@ -1674,7 +1684,7 @@ impl<'a> SemanticsScope<'a> {
/// Resolve a path as-if it was written at the given scope. This is
/// necessary a heuristic, as it doesn't take hygiene into account.
pub fn speculative_resolve(&self, path: &ast::Path) -> Option<PathResolution> {
let ctx = body::LowerCtx::new(self.db.upcast(), self.file_id);
let ctx = LowerCtx::with_file_id(self.db.upcast(), self.file_id);
let path = Path::from_src(path.clone(), &ctx)?;
resolve_hir_path(self.db, &self.resolver, &path)
}

View file

@ -14,7 +14,7 @@
//! expression, an item definition.
//!
//! Knowing only the syntax gives us relatively little info. For example,
//! looking at the syntax of the function we can realise that it is a part of an
//! looking at the syntax of the function we can realize that it is a part of an
//! `impl` block, but we won't be able to tell what trait function the current
//! function overrides, and whether it does that correctly. For that, we need to
//! go from [`ast::Fn`] to [`crate::Function`], and that's exactly what this
@ -88,9 +88,11 @@
use base_db::FileId;
use hir_def::{
child_by_source::ChildBySource,
dyn_map::DynMap,
expr::{BindingId, LabelId},
keys::{self, Key},
dyn_map::{
keys::{self, Key},
DynMap,
},
hir::{BindingId, LabelId},
AdtId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId,
GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId, StructId,
TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId,

View file

@ -5,21 +5,19 @@
//!
//! So, this modules should not be used during hir construction, it exists
//! purely for "IDE needs".
use std::{
iter::{self, once},
sync::Arc,
};
use std::iter::{self, once};
use either::Either;
use hir_def::{
body::{
self,
scope::{ExprScopes, ScopeId},
Body, BodySourceMap,
},
expr::{ExprId, Pat, PatId},
hir::{BindingId, ExprId, Pat, PatId},
lang_item::LangItem,
lower::LowerCtx,
macro_id_to_def_id,
nameres::MacroSubNs,
path::{ModPath, Path, PathKind},
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
type_ref::Mutability,
@ -39,7 +37,8 @@ use hir_ty::{
record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions,
UnsafeExpr,
},
method_resolution::{self, lang_items_for_bin_op},
lang_items::lang_items_for_bin_op,
method_resolution::{self},
Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind, TyLoweringContext,
};
use itertools::Itertools;
@ -48,6 +47,7 @@ use syntax::{
ast::{self, AstNode},
SyntaxKind, SyntaxNode, TextRange, TextSize,
};
use triomphe::Arc;
use crate::{
db::HirDatabase, semantics::PathResolution, Adt, AssocItem, BindingMode, BuiltinAttr,
@ -134,13 +134,22 @@ impl SourceAnalyzer {
self.body_source_map()?.node_pat(src)
}
fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingId> {
let pat_id = self.pat_id(&pat.clone().into())?;
if let Pat::Bind { id, .. } = self.body()?.pats[pat_id] {
Some(id)
} else {
None
}
}
fn expand_expr(
&self,
db: &dyn HirDatabase,
expr: InFile<ast::MacroCall>,
) -> Option<InFile<ast::Expr>> {
let macro_file = self.body_source_map()?.node_macro_file(expr.as_ref())?;
let expanded = db.parse_or_expand(macro_file)?;
let expanded = db.parse_or_expand(macro_file);
let res = if let Some(stmts) = ast::MacroStmts::cast(expanded.clone()) {
match stmts.expr()? {
ast::Expr::MacroExpr(mac) => {
@ -199,6 +208,18 @@ impl SourceAnalyzer {
Some((mk_ty(ty), coerced.map(mk_ty)))
}
pub(crate) fn type_of_binding_in_pat(
&self,
db: &dyn HirDatabase,
pat: &ast::IdentPat,
) -> Option<Type> {
let binding_id = self.binding_id_of_pat(pat)?;
let infer = self.infer.as_ref()?;
let ty = infer[binding_id].clone();
let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
Some(mk_ty(ty))
}
pub(crate) fn type_of_self(
&self,
db: &dyn HirDatabase,
@ -215,9 +236,9 @@ impl SourceAnalyzer {
_db: &dyn HirDatabase,
pat: &ast::IdentPat,
) -> Option<BindingMode> {
let pat_id = self.pat_id(&pat.clone().into())?;
let binding_id = self.binding_id_of_pat(pat)?;
let infer = self.infer.as_ref()?;
infer.pat_binding_modes.get(&pat_id).map(|bm| match bm {
infer.binding_modes.get(binding_id).map(|bm| match bm {
hir_ty::BindingMode::Move => BindingMode::Move,
hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut),
hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => {
@ -420,7 +441,10 @@ impl SourceAnalyzer {
None
} else {
// Shorthand syntax, resolve to the local
let path = ModPath::from_segments(PathKind::Plain, once(local_name.clone()));
let path = Path::from_known_path_with_no_generic(ModPath::from_segments(
PathKind::Plain,
once(local_name.clone()),
));
match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) {
Some(ValueNs::LocalBinding(binding_id)) => {
Some(Local { binding_id, parent: self.resolver.body_owner()? })
@ -459,9 +483,11 @@ impl SourceAnalyzer {
db: &dyn HirDatabase,
macro_call: InFile<&ast::MacroCall>,
) -> Option<Macro> {
let ctx = body::LowerCtx::new(db.upcast(), macro_call.file_id);
let ctx = LowerCtx::with_file_id(db.upcast(), macro_call.file_id);
let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?;
self.resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(|it| it.into())
self.resolver
.resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
.map(|it| it.into())
}
pub(crate) fn resolve_bind_pat_to_const(
@ -571,7 +597,7 @@ impl SourceAnalyzer {
// This must be a normal source file rather than macro file.
let hygiene = Hygiene::new(db.upcast(), self.file_id);
let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene);
let ctx = LowerCtx::with_hygiene(db.upcast(), &hygiene);
let hir_path = Path::from_src(path.clone(), &ctx)?;
// Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
@ -655,7 +681,7 @@ impl SourceAnalyzer {
}
}
}
return match resolve_hir_path_as_macro(db, &self.resolver, &hir_path) {
return match resolve_hir_path_as_attr_macro(db, &self.resolver, &hir_path) {
Some(m) => Some(PathResolution::Def(ModuleDef::Macro(m))),
// this labels any path that starts with a tool module as the tool itself, this is technically wrong
// but there is no benefit in differentiating these two cases for the time being
@ -733,7 +759,7 @@ impl SourceAnalyzer {
let krate = self.resolver.krate();
let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
self.resolver
.resolve_path_as_macro(db.upcast(), &path)
.resolve_path_as_macro(db.upcast(), &path, Some(MacroSubNs::Bang))
.map(|it| macro_id_to_def_id(db.upcast(), it))
})?;
Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64)
@ -801,15 +827,11 @@ impl SourceAnalyzer {
func: FunctionId,
substs: Substitution,
) -> FunctionId {
let krate = self.resolver.krate();
let owner = match self.resolver.body_owner() {
Some(it) => it,
None => return func,
};
let env = owner.as_generic_def_id().map_or_else(
|| Arc::new(hir_ty::TraitEnvironment::empty(krate)),
|d| db.trait_environment(d),
);
let env = db.trait_environment_for_body(owner);
method_resolution::lookup_impl_method(db, env, func, substs).0
}
@ -819,15 +841,11 @@ impl SourceAnalyzer {
const_id: ConstId,
subs: Substitution,
) -> ConstId {
let krate = self.resolver.krate();
let owner = match self.resolver.body_owner() {
Some(it) => it,
None => return const_id,
};
let env = owner.as_generic_def_id().map_or_else(
|| Arc::new(hir_ty::TraitEnvironment::empty(krate)),
|d| db.trait_environment(d),
);
let env = db.trait_environment_for_body(owner);
method_resolution::lookup_impl_const(db, env, const_id, subs).0
}
@ -941,12 +959,14 @@ pub(crate) fn resolve_hir_path(
}
#[inline]
pub(crate) fn resolve_hir_path_as_macro(
pub(crate) fn resolve_hir_path_as_attr_macro(
db: &dyn HirDatabase,
resolver: &Resolver,
path: &Path,
) -> Option<Macro> {
resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(Into::into)
resolver
.resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Attr))
.map(Into::into)
}
fn resolve_hir_path_(
@ -962,8 +982,7 @@ fn resolve_hir_path_(
res.map(|ty_ns| (ty_ns, path.segments().first()))
}
None => {
let (ty, remaining_idx) =
resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?;
let (ty, remaining_idx) = resolver.resolve_path_in_type_ns(db.upcast(), path)?;
match remaining_idx {
Some(remaining_idx) => {
if remaining_idx + 1 == path.segments().len() {
@ -1019,7 +1038,7 @@ fn resolve_hir_path_(
let body_owner = resolver.body_owner();
let values = || {
resolver.resolve_path_in_value_ns_fully(db.upcast(), path.mod_path()).and_then(|val| {
resolver.resolve_path_in_value_ns_fully(db.upcast(), path).and_then(|val| {
let res = match val {
ValueNs::LocalBinding(binding_id) => {
let var = Local { parent: body_owner?, binding_id };
@ -1039,14 +1058,14 @@ fn resolve_hir_path_(
let items = || {
resolver
.resolve_module_path_in_items(db.upcast(), path.mod_path())
.resolve_module_path_in_items(db.upcast(), path.mod_path()?)
.take_types()
.map(|it| PathResolution::Def(it.into()))
};
let macros = || {
resolver
.resolve_path_as_macro(db.upcast(), path.mod_path())
.resolve_path_as_macro(db.upcast(), path.mod_path()?, None)
.map(|def| PathResolution::Def(ModuleDef::Macro(def.into())))
};
@ -1074,7 +1093,7 @@ fn resolve_hir_path_qualifier(
path: &Path,
) -> Option<PathResolution> {
resolver
.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path())
.resolve_path_in_type_ns_fully(db.upcast(), &path)
.map(|ty| match ty {
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),
@ -1089,7 +1108,7 @@ fn resolve_hir_path_qualifier(
})
.or_else(|| {
resolver
.resolve_module_path_in_items(db.upcast(), path.mod_path())
.resolve_module_path_in_items(db.upcast(), path.mod_path()?)
.take_types()
.map(|it| PathResolution::Def(it.into()))
})

View file

@ -2,23 +2,25 @@
use base_db::FileRange;
use hir_def::{
item_tree::ItemTreeNode, src::HasSource, AdtId, AssocItemId, AssocItemLoc, DefWithBodyId,
HasModule, ImplId, ItemContainerId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId,
src::HasSource, AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId,
ModuleDefId, ModuleId, TraitId,
};
use hir_expand::{HirFileId, InFile};
use hir_ty::db::HirDatabase;
use syntax::{ast::HasName, AstNode, SmolStr, SyntaxNode, SyntaxNodePtr};
use crate::{Module, Semantics};
use crate::{Module, ModuleDef, Semantics};
/// The actual data that is stored in the index. It should be as compact as
/// possible.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FileSymbol {
// even though name can be derived from the def, we store it for efficiency
pub name: SmolStr,
pub def: ModuleDef,
pub loc: DeclarationLocation,
pub kind: FileSymbolKind,
pub container_name: Option<SmolStr>,
pub is_alias: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -32,18 +34,26 @@ pub struct DeclarationLocation {
}
impl DeclarationLocation {
pub fn syntax<DB: HirDatabase>(&self, sema: &Semantics<'_, DB>) -> Option<SyntaxNode> {
let root = sema.parse_or_expand(self.hir_file_id)?;
Some(self.ptr.to_node(&root))
pub fn syntax<DB: HirDatabase>(&self, sema: &Semantics<'_, DB>) -> SyntaxNode {
let root = sema.parse_or_expand(self.hir_file_id);
self.ptr.to_node(&root)
}
pub fn original_range(&self, db: &dyn HirDatabase) -> Option<FileRange> {
let node = resolve_node(db, self.hir_file_id, &self.ptr)?;
Some(node.as_ref().original_file_range(db.upcast()))
pub fn original_range(&self, db: &dyn HirDatabase) -> FileRange {
if let Some(file_id) = self.hir_file_id.file_id() {
// fast path to prevent parsing
return FileRange { file_id, range: self.ptr.text_range() };
}
let node = resolve_node(db, self.hir_file_id, &self.ptr);
node.as_ref().original_file_range(db.upcast())
}
pub fn original_name_range(&self, db: &dyn HirDatabase) -> Option<FileRange> {
let node = resolve_node(db, self.hir_file_id, &self.name_ptr)?;
if let Some(file_id) = self.hir_file_id.file_id() {
// fast path to prevent parsing
return Some(FileRange { file_id, range: self.name_ptr.text_range() });
}
let node = resolve_node(db, self.hir_file_id, &self.name_ptr);
node.as_ref().original_file_range_opt(db.upcast())
}
}
@ -52,38 +62,10 @@ fn resolve_node(
db: &dyn HirDatabase,
file_id: HirFileId,
ptr: &SyntaxNodePtr,
) -> Option<InFile<SyntaxNode>> {
let root = db.parse_or_expand(file_id)?;
) -> InFile<SyntaxNode> {
let root = db.parse_or_expand(file_id);
let node = ptr.to_node(&root);
Some(InFile::new(file_id, node))
}
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum FileSymbolKind {
Const,
Enum,
Function,
Macro,
Module,
Static,
Struct,
Trait,
TraitAlias,
TypeAlias,
Union,
}
impl FileSymbolKind {
pub fn is_type(self: FileSymbolKind) -> bool {
matches!(
self,
FileSymbolKind::Struct
| FileSymbolKind::Enum
| FileSymbolKind::Trait
| FileSymbolKind::TypeAlias
| FileSymbolKind::Union
)
}
InFile::new(file_id, node)
}
/// Represents an outstanding module that the symbol collector must collect symbols from.
@ -102,21 +84,33 @@ pub struct SymbolCollector<'a> {
/// Given a [`ModuleId`] and a [`HirDatabase`], use the DefMap for the module's crate to collect
/// all symbols that should be indexed for the given module.
impl<'a> SymbolCollector<'a> {
pub fn collect(db: &dyn HirDatabase, module: Module) -> Vec<FileSymbol> {
let mut symbol_collector = SymbolCollector {
pub fn new(db: &'a dyn HirDatabase) -> Self {
SymbolCollector {
db,
symbols: Default::default(),
work: Default::default(),
current_container_name: None,
// The initial work is the root module we're collecting, additional work will
// be populated as we traverse the module's definitions.
work: vec![SymbolCollectorWork { module_id: module.into(), parent: None }],
};
while let Some(work) = symbol_collector.work.pop() {
symbol_collector.do_work(work);
}
}
symbol_collector.symbols
pub fn collect(&mut self, module: Module) {
// The initial work is the root module we're collecting, additional work will
// be populated as we traverse the module's definitions.
self.work.push(SymbolCollectorWork { module_id: module.into(), parent: None });
while let Some(work) = self.work.pop() {
self.do_work(work);
}
}
pub fn finish(self) -> Vec<FileSymbol> {
self.symbols
}
pub fn collect_module(db: &dyn HirDatabase, module: Module) -> Vec<FileSymbol> {
let mut symbol_collector = SymbolCollector::new(db);
symbol_collector.collect(module);
symbol_collector.finish()
}
fn do_work(&mut self, work: SymbolCollectorWork) {
@ -134,36 +128,34 @@ impl<'a> SymbolCollector<'a> {
match module_def_id {
ModuleDefId::ModuleId(id) => self.push_module(id),
ModuleDefId::FunctionId(id) => {
self.push_decl_assoc(id, FileSymbolKind::Function);
self.push_decl(id);
self.collect_from_body(id);
}
ModuleDefId::AdtId(AdtId::StructId(id)) => {
self.push_decl(id, FileSymbolKind::Struct)
}
ModuleDefId::AdtId(AdtId::EnumId(id)) => self.push_decl(id, FileSymbolKind::Enum),
ModuleDefId::AdtId(AdtId::UnionId(id)) => self.push_decl(id, FileSymbolKind::Union),
ModuleDefId::AdtId(AdtId::StructId(id)) => self.push_decl(id),
ModuleDefId::AdtId(AdtId::EnumId(id)) => self.push_decl(id),
ModuleDefId::AdtId(AdtId::UnionId(id)) => self.push_decl(id),
ModuleDefId::ConstId(id) => {
self.push_decl_assoc(id, FileSymbolKind::Const);
self.push_decl(id);
self.collect_from_body(id);
}
ModuleDefId::StaticId(id) => {
self.push_decl_assoc(id, FileSymbolKind::Static);
self.push_decl(id);
self.collect_from_body(id);
}
ModuleDefId::TraitId(id) => {
self.push_decl(id, FileSymbolKind::Trait);
self.push_decl(id);
self.collect_from_trait(id);
}
ModuleDefId::TraitAliasId(id) => {
self.push_decl(id, FileSymbolKind::TraitAlias);
self.push_decl(id);
}
ModuleDefId::TypeAliasId(id) => {
self.push_decl_assoc(id, FileSymbolKind::TypeAlias);
self.push_decl(id);
}
ModuleDefId::MacroId(id) => match id {
MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::Macro2Id(id) => self.push_decl(id),
MacroId::MacroRulesId(id) => self.push_decl(id),
MacroId::ProcMacroId(id) => self.push_decl(id),
},
// Don't index these.
ModuleDefId::BuiltinType(_) => {}
@ -183,9 +175,9 @@ impl<'a> SymbolCollector<'a> {
for &id in id {
if id.module(self.db.upcast()) == module_id {
match id {
MacroId::Macro2Id(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::MacroRulesId(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::ProcMacroId(id) => self.push_decl(id, FileSymbolKind::Macro),
MacroId::Macro2Id(id) => self.push_decl(id),
MacroId::MacroRulesId(id) => self.push_decl(id),
MacroId::ProcMacroId(id) => self.push_decl(id),
}
}
}
@ -233,124 +225,94 @@ impl<'a> SymbolCollector<'a> {
}
}
fn current_container_name(&self) -> Option<SmolStr> {
self.current_container_name.clone()
}
fn def_with_body_id_name(&self, body_id: DefWithBodyId) -> Option<SmolStr> {
match body_id {
DefWithBodyId::FunctionId(id) => Some(
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
),
DefWithBodyId::StaticId(id) => Some(
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
),
DefWithBodyId::ConstId(id) => Some(
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
),
DefWithBodyId::VariantId(id) => Some({
let db = self.db.upcast();
id.parent.lookup(db).source(db).value.name()?.text().into()
}),
DefWithBodyId::FunctionId(id) => Some(self.db.function_data(id).name.to_smol_str()),
DefWithBodyId::StaticId(id) => Some(self.db.static_data(id).name.to_smol_str()),
DefWithBodyId::ConstId(id) => Some(self.db.const_data(id).name.as_ref()?.to_smol_str()),
DefWithBodyId::VariantId(id) => {
Some(self.db.enum_data(id.parent).variants[id.local_id].name.to_smol_str())
}
}
}
fn push_assoc_item(&mut self, assoc_item_id: AssocItemId) {
match assoc_item_id {
AssocItemId::FunctionId(id) => self.push_decl_assoc(id, FileSymbolKind::Function),
AssocItemId::ConstId(id) => self.push_decl_assoc(id, FileSymbolKind::Const),
AssocItemId::TypeAliasId(id) => self.push_decl_assoc(id, FileSymbolKind::TypeAlias),
AssocItemId::FunctionId(id) => self.push_decl(id),
AssocItemId::ConstId(id) => self.push_decl(id),
AssocItemId::TypeAliasId(id) => self.push_decl(id),
}
}
fn push_decl_assoc<L, T>(&mut self, id: L, kind: FileSymbolKind)
fn push_decl<L>(&mut self, id: L)
where
L: Lookup<Data = AssocItemLoc<T>>,
T: ItemTreeNode,
<T as ItemTreeNode>::Source: HasName,
{
fn container_name(db: &dyn HirDatabase, container: ItemContainerId) -> Option<SmolStr> {
match container {
ItemContainerId::ModuleId(module_id) => {
let module = Module::from(module_id);
module.name(db).and_then(|name| name.as_text())
}
ItemContainerId::TraitId(trait_id) => {
let trait_data = db.trait_data(trait_id);
trait_data.name.as_text()
}
ItemContainerId::ImplId(_) | ItemContainerId::ExternBlockId(_) => None,
}
}
self.push_file_symbol(|s| {
let loc = id.lookup(s.db.upcast());
let source = loc.source(s.db.upcast());
let name_node = source.value.name()?;
let container_name =
container_name(s.db, loc.container).or_else(|| s.current_container_name());
Some(FileSymbol {
name: name_node.text().into(),
kind,
container_name,
loc: DeclarationLocation {
hir_file_id: source.file_id,
ptr: SyntaxNodePtr::new(source.value.syntax()),
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
},
})
})
}
fn push_decl<L>(&mut self, id: L, kind: FileSymbolKind)
where
L: Lookup,
L: Lookup + Into<ModuleDefId>,
<L as Lookup>::Data: HasSource,
<<L as Lookup>::Data as HasSource>::Value: HasName,
{
self.push_file_symbol(|s| {
let loc = id.lookup(s.db.upcast());
let source = loc.source(s.db.upcast());
let name_node = source.value.name()?;
let loc = id.lookup(self.db.upcast());
let source = loc.source(self.db.upcast());
let Some(name_node) = source.value.name() else { return };
let def = ModuleDef::from(id.into());
let dec_loc = DeclarationLocation {
hir_file_id: source.file_id,
ptr: SyntaxNodePtr::new(source.value.syntax()),
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
};
Some(FileSymbol {
name: name_node.text().into(),
kind,
container_name: s.current_container_name(),
loc: DeclarationLocation {
hir_file_id: source.file_id,
ptr: SyntaxNodePtr::new(source.value.syntax()),
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
},
})
})
if let Some(attrs) = def.attrs(self.db) {
for alias in attrs.doc_aliases() {
self.symbols.push(FileSymbol {
name: alias,
def,
loc: dec_loc.clone(),
container_name: self.current_container_name.clone(),
is_alias: true,
});
}
}
self.symbols.push(FileSymbol {
name: name_node.text().into(),
def,
container_name: self.current_container_name.clone(),
loc: dec_loc,
is_alias: false,
});
}
fn push_module(&mut self, module_id: ModuleId) {
self.push_file_symbol(|s| {
let def_map = module_id.def_map(s.db.upcast());
let module_data = &def_map[module_id.local_id];
let declaration = module_data.origin.declaration()?;
let module = declaration.to_node(s.db.upcast());
let name_node = module.name()?;
let def_map = module_id.def_map(self.db.upcast());
let module_data = &def_map[module_id.local_id];
let Some(declaration) = module_data.origin.declaration() else { return };
let module = declaration.to_node(self.db.upcast());
let Some(name_node) = module.name() else { return };
let dec_loc = DeclarationLocation {
hir_file_id: declaration.file_id,
ptr: SyntaxNodePtr::new(module.syntax()),
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
};
Some(FileSymbol {
name: name_node.text().into(),
kind: FileSymbolKind::Module,
container_name: s.current_container_name(),
loc: DeclarationLocation {
hir_file_id: declaration.file_id,
ptr: SyntaxNodePtr::new(module.syntax()),
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
},
})
})
}
let def = ModuleDef::Module(module_id.into());
fn push_file_symbol(&mut self, f: impl FnOnce(&Self) -> Option<FileSymbol>) {
if let Some(file_symbol) = f(self) {
self.symbols.push(file_symbol);
if let Some(attrs) = def.attrs(self.db) {
for alias in attrs.doc_aliases() {
self.symbols.push(FileSymbol {
name: alias,
def,
loc: dec_loc.clone(),
container_name: self.current_container_name.clone(),
is_alias: true,
});
}
}
self.symbols.push(FileSymbol {
name: name_node.text().into(),
def: ModuleDef::Module(module_id.into()),
container_name: self.current_container_name.clone(),
loc: dec_loc,
is_alias: false,
});
}
}