mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 04:23:25 +00:00
Don't store call-site text offsets in hygiene info
This commit is contained in:
parent
b37b709459
commit
976a3226fe
19 changed files with 145 additions and 93 deletions
|
@ -27,3 +27,5 @@ debug = 0 # Set this to 1 or 2 to get more useful backtraces in debugger.
|
||||||
# chalk-recursive = { path = "../chalk/chalk-recursive" }
|
# chalk-recursive = { path = "../chalk/chalk-recursive" }
|
||||||
|
|
||||||
# ungrammar = { path = "../ungrammar" }
|
# ungrammar = { path = "../ungrammar" }
|
||||||
|
|
||||||
|
# salsa = { path = "../salsa" }
|
||||||
|
|
|
@ -112,7 +112,7 @@ fn resolve_doc_path(
|
||||||
AttrDefId::MacroDefId(_) => return None,
|
AttrDefId::MacroDefId(_) => return None,
|
||||||
};
|
};
|
||||||
let path = ast::Path::parse(link).ok()?;
|
let path = ast::Path::parse(link).ok()?;
|
||||||
let modpath = ModPath::from_src(path, &Hygiene::new_unhygienic()).unwrap();
|
let modpath = ModPath::from_src(db.upcast(), path, &Hygiene::new_unhygienic()).unwrap();
|
||||||
let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath);
|
let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath);
|
||||||
if resolved == PerNs::none() {
|
if resolved == PerNs::none() {
|
||||||
if let Some(trait_id) = resolver.resolve_module_path_in_trait_items(db.upcast(), &modpath) {
|
if let Some(trait_id) = resolver.resolve_module_path_in_trait_items(db.upcast(), &modpath) {
|
||||||
|
|
|
@ -1666,7 +1666,7 @@ impl Impl {
|
||||||
.value
|
.value
|
||||||
.attrs()
|
.attrs()
|
||||||
.filter_map(|it| {
|
.filter_map(|it| {
|
||||||
let path = ModPath::from_src(it.path()?, &hygenic)?;
|
let path = ModPath::from_src(db.upcast(), it.path()?, &hygenic)?;
|
||||||
if path.as_ident()?.to_string() == "derive" {
|
if path.as_ident()?.to_string() == "derive" {
|
||||||
Some(it)
|
Some(it)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -855,7 +855,7 @@ impl<'a> SemanticsScope<'a> {
|
||||||
/// necessary a heuristic, as it doesn't take hygiene into account.
|
/// necessary a heuristic, as it doesn't take hygiene into account.
|
||||||
pub fn speculative_resolve(&self, path: &ast::Path) -> Option<PathResolution> {
|
pub fn speculative_resolve(&self, path: &ast::Path) -> Option<PathResolution> {
|
||||||
let ctx = body::LowerCtx::new(self.db.upcast(), self.file_id);
|
let ctx = body::LowerCtx::new(self.db.upcast(), self.file_id);
|
||||||
let path = Path::from_src(path.clone(), &ctx)?;
|
let path = Path::from_src(self.db.upcast(), path.clone(), &ctx)?;
|
||||||
resolve_hir_path(self.db, &self.resolver, &path)
|
resolve_hir_path(self.db, &self.resolver, &path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,7 +204,8 @@ impl SourceAnalyzer {
|
||||||
macro_call: InFile<&ast::MacroCall>,
|
macro_call: InFile<&ast::MacroCall>,
|
||||||
) -> Option<MacroDef> {
|
) -> Option<MacroDef> {
|
||||||
let ctx = body::LowerCtx::new(db.upcast(), macro_call.file_id);
|
let ctx = body::LowerCtx::new(db.upcast(), macro_call.file_id);
|
||||||
let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?;
|
let path =
|
||||||
|
macro_call.value.path().and_then(|ast| Path::from_src(db.upcast(), 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()).map(|it| it.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,8 +284,8 @@ impl SourceAnalyzer {
|
||||||
|
|
||||||
// This must be a normal source file rather than macro file.
|
// This must be a normal source file rather than macro file.
|
||||||
let hygiene = Hygiene::new(db.upcast(), self.file_id);
|
let hygiene = Hygiene::new(db.upcast(), self.file_id);
|
||||||
let ctx = body::LowerCtx::with_hygiene(&hygiene);
|
let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene);
|
||||||
let hir_path = Path::from_src(path.clone(), &ctx)?;
|
let hir_path = Path::from_src(db.upcast(), path.clone(), &ctx)?;
|
||||||
|
|
||||||
// Case where path is a qualifier of another path, e.g. foo::bar::Baz where we
|
// Case where path is a qualifier of another path, e.g. foo::bar::Baz where we
|
||||||
// trying to resolve foo::bar.
|
// trying to resolve foo::bar.
|
||||||
|
|
|
@ -95,13 +95,17 @@ impl ops::Deref for AttrsWithOwner {
|
||||||
impl RawAttrs {
|
impl RawAttrs {
|
||||||
pub(crate) const EMPTY: Self = Self { entries: None };
|
pub(crate) const EMPTY: Self = Self { entries: None };
|
||||||
|
|
||||||
pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self {
|
pub(crate) fn new(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
owner: &dyn ast::AttrsOwner,
|
||||||
|
hygiene: &Hygiene,
|
||||||
|
) -> Self {
|
||||||
let entries = collect_attrs(owner)
|
let entries = collect_attrs(owner)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.flat_map(|(i, attr)| {
|
.flat_map(|(i, attr)| {
|
||||||
let index = AttrId(i as u32);
|
let index = AttrId(i as u32);
|
||||||
match attr {
|
match attr {
|
||||||
Either::Left(attr) => Attr::from_src(attr, hygiene, index),
|
Either::Left(attr) => Attr::from_src(db, attr, hygiene, index),
|
||||||
Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
|
Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
|
||||||
id: index,
|
id: index,
|
||||||
input: Some(AttrInput::Literal(SmolStr::new(doc))),
|
input: Some(AttrInput::Literal(SmolStr::new(doc))),
|
||||||
|
@ -116,7 +120,7 @@ impl RawAttrs {
|
||||||
|
|
||||||
fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn ast::AttrsOwner>) -> Self {
|
fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn ast::AttrsOwner>) -> Self {
|
||||||
let hygiene = Hygiene::new(db.upcast(), owner.file_id);
|
let hygiene = Hygiene::new(db.upcast(), owner.file_id);
|
||||||
Self::new(owner.value, &hygiene)
|
Self::new(db, owner.value, &hygiene)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn merge(&self, other: Self) -> Self {
|
pub(crate) fn merge(&self, other: Self) -> Self {
|
||||||
|
@ -170,7 +174,7 @@ impl RawAttrs {
|
||||||
let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?;
|
let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?;
|
||||||
// FIXME hygiene
|
// FIXME hygiene
|
||||||
let hygiene = Hygiene::new_unhygienic();
|
let hygiene = Hygiene::new_unhygienic();
|
||||||
Attr::from_src(attr, &hygiene, index)
|
Attr::from_src(db, attr, &hygiene, index)
|
||||||
});
|
});
|
||||||
|
|
||||||
let cfg_options = &crate_graph[krate].cfg_options;
|
let cfg_options = &crate_graph[krate].cfg_options;
|
||||||
|
@ -627,8 +631,13 @@ pub enum AttrInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attr {
|
impl Attr {
|
||||||
fn from_src(ast: ast::Attr, hygiene: &Hygiene, id: AttrId) -> Option<Attr> {
|
fn from_src(
|
||||||
let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?);
|
db: &dyn DefDatabase,
|
||||||
|
ast: ast::Attr,
|
||||||
|
hygiene: &Hygiene,
|
||||||
|
id: AttrId,
|
||||||
|
) -> Option<Attr> {
|
||||||
|
let path = Interned::new(ModPath::from_src(db, ast.path()?, hygiene)?);
|
||||||
let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
|
let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
|
||||||
let value = match lit.kind() {
|
let value = match lit.kind() {
|
||||||
ast::LiteralKind::String(string) => string.value()?.into(),
|
ast::LiteralKind::String(string) => string.value()?.into(),
|
||||||
|
|
|
@ -72,7 +72,7 @@ impl CfgExpander {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
|
pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
|
||||||
RawAttrs::new(owner, &self.hygiene).filter(db, self.krate)
|
RawAttrs::new(db, owner, &self.hygiene).filter(db, self.krate)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> bool {
|
pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> bool {
|
||||||
|
@ -192,9 +192,9 @@ impl Expander {
|
||||||
self.current_file_id
|
self.current_file_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
|
fn parse_path(&mut self, db: &dyn DefDatabase, path: ast::Path) -> Option<Path> {
|
||||||
let ctx = LowerCtx::with_hygiene(&self.cfg_expander.hygiene);
|
let ctx = LowerCtx::with_hygiene(db, &self.cfg_expander.hygiene);
|
||||||
Path::from_src(path, &ctx)
|
Path::from_src(db, path, &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> {
|
fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> {
|
||||||
|
|
|
@ -40,23 +40,25 @@ use crate::{
|
||||||
|
|
||||||
use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource};
|
use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource};
|
||||||
|
|
||||||
pub struct LowerCtx {
|
pub struct LowerCtx<'a> {
|
||||||
|
db: &'a dyn DefDatabase,
|
||||||
hygiene: Hygiene,
|
hygiene: Hygiene,
|
||||||
file_id: Option<HirFileId>,
|
file_id: Option<HirFileId>,
|
||||||
source_ast_id_map: Option<Arc<AstIdMap>>,
|
source_ast_id_map: Option<Arc<AstIdMap>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LowerCtx {
|
impl<'a> LowerCtx<'a> {
|
||||||
pub fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self {
|
pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
|
||||||
LowerCtx {
|
LowerCtx {
|
||||||
|
db,
|
||||||
hygiene: Hygiene::new(db.upcast(), file_id),
|
hygiene: Hygiene::new(db.upcast(), file_id),
|
||||||
file_id: Some(file_id),
|
file_id: Some(file_id),
|
||||||
source_ast_id_map: Some(db.ast_id_map(file_id)),
|
source_ast_id_map: Some(db.ast_id_map(file_id)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_hygiene(hygiene: &Hygiene) -> Self {
|
pub fn with_hygiene(db: &'a dyn DefDatabase, hygiene: &Hygiene) -> Self {
|
||||||
LowerCtx { hygiene: hygiene.clone(), file_id: None, source_ast_id_map: None }
|
LowerCtx { db, hygiene: hygiene.clone(), file_id: None, source_ast_id_map: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn hygiene(&self) -> &Hygiene {
|
pub(crate) fn hygiene(&self) -> &Hygiene {
|
||||||
|
@ -68,7 +70,7 @@ impl LowerCtx {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
|
pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
|
||||||
Path::from_src(ast, self)
|
Path::from_src(self.db, ast, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> Option<FileAstId<N>> {
|
pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> Option<FileAstId<N>> {
|
||||||
|
@ -145,7 +147,7 @@ impl ExprCollector<'_> {
|
||||||
(self.body, self.source_map)
|
(self.body, self.source_map)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ctx(&self) -> LowerCtx {
|
fn ctx(&self) -> LowerCtx<'_> {
|
||||||
LowerCtx::new(self.db, self.expander.current_file_id)
|
LowerCtx::new(self.db, self.expander.current_file_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +378,7 @@ impl ExprCollector<'_> {
|
||||||
ast::Expr::PathExpr(e) => {
|
ast::Expr::PathExpr(e) => {
|
||||||
let path = e
|
let path = e
|
||||||
.path()
|
.path()
|
||||||
.and_then(|path| self.expander.parse_path(path))
|
.and_then(|path| self.expander.parse_path(self.db, path))
|
||||||
.map(Expr::Path)
|
.map(Expr::Path)
|
||||||
.unwrap_or(Expr::Missing);
|
.unwrap_or(Expr::Missing);
|
||||||
self.alloc_expr(path, syntax_ptr)
|
self.alloc_expr(path, syntax_ptr)
|
||||||
|
@ -408,7 +410,8 @@ impl ExprCollector<'_> {
|
||||||
self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
|
self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
|
||||||
}
|
}
|
||||||
ast::Expr::RecordExpr(e) => {
|
ast::Expr::RecordExpr(e) => {
|
||||||
let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
|
let path =
|
||||||
|
e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
|
||||||
let record_lit = if let Some(nfl) = e.record_expr_field_list() {
|
let record_lit = if let Some(nfl) = e.record_expr_field_list() {
|
||||||
let fields = nfl
|
let fields = nfl
|
||||||
.fields()
|
.fields()
|
||||||
|
@ -791,7 +794,8 @@ impl ExprCollector<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::Pat::TupleStructPat(p) => {
|
ast::Pat::TupleStructPat(p) => {
|
||||||
let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
|
let path =
|
||||||
|
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
|
||||||
let (args, ellipsis) = self.collect_tuple_pat(p.fields());
|
let (args, ellipsis) = self.collect_tuple_pat(p.fields());
|
||||||
Pat::TupleStruct { path, args, ellipsis }
|
Pat::TupleStruct { path, args, ellipsis }
|
||||||
}
|
}
|
||||||
|
@ -801,7 +805,8 @@ impl ExprCollector<'_> {
|
||||||
Pat::Ref { pat, mutability }
|
Pat::Ref { pat, mutability }
|
||||||
}
|
}
|
||||||
ast::Pat::PathPat(p) => {
|
ast::Pat::PathPat(p) => {
|
||||||
let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
|
let path =
|
||||||
|
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
|
||||||
path.map(Pat::Path).unwrap_or(Pat::Missing)
|
path.map(Pat::Path).unwrap_or(Pat::Missing)
|
||||||
}
|
}
|
||||||
ast::Pat::OrPat(p) => {
|
ast::Pat::OrPat(p) => {
|
||||||
|
@ -815,7 +820,8 @@ impl ExprCollector<'_> {
|
||||||
}
|
}
|
||||||
ast::Pat::WildcardPat(_) => Pat::Wild,
|
ast::Pat::WildcardPat(_) => Pat::Wild,
|
||||||
ast::Pat::RecordPat(p) => {
|
ast::Pat::RecordPat(p) => {
|
||||||
let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
|
let path =
|
||||||
|
p.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);
|
||||||
let args: Vec<_> = p
|
let args: Vec<_> = p
|
||||||
.record_pat_field_list()
|
.record_pat_field_list()
|
||||||
.expect("every struct should have a field list")
|
.expect("every struct should have a field list")
|
||||||
|
|
|
@ -386,7 +386,7 @@ mod tests {
|
||||||
let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path));
|
let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path));
|
||||||
let ast_path =
|
let ast_path =
|
||||||
parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
|
parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
|
||||||
let mod_path = ModPath::from_src(ast_path, &Hygiene::new_unhygienic()).unwrap();
|
let mod_path = ModPath::from_src(&db, ast_path, &Hygiene::new_unhygienic()).unwrap();
|
||||||
|
|
||||||
let def_map = module.def_map(&db);
|
let def_map = module.def_map(&db);
|
||||||
let resolved = def_map
|
let resolved = def_map
|
||||||
|
|
|
@ -88,7 +88,7 @@ impl ItemTree {
|
||||||
let mut item_tree = match_ast! {
|
let mut item_tree = match_ast! {
|
||||||
match syntax {
|
match syntax {
|
||||||
ast::SourceFile(file) => {
|
ast::SourceFile(file) => {
|
||||||
top_attrs = Some(RawAttrs::new(&file, &hygiene));
|
top_attrs = Some(RawAttrs::new(db, &file, &hygiene));
|
||||||
ctx.lower_module_items(&file)
|
ctx.lower_module_items(&file)
|
||||||
},
|
},
|
||||||
ast::MacroItems(items) => {
|
ast::MacroItems(items) => {
|
||||||
|
|
|
@ -31,18 +31,20 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct Ctx {
|
pub(super) struct Ctx<'a> {
|
||||||
|
db: &'a dyn DefDatabase,
|
||||||
tree: ItemTree,
|
tree: ItemTree,
|
||||||
hygiene: Hygiene,
|
hygiene: Hygiene,
|
||||||
file: HirFileId,
|
file: HirFileId,
|
||||||
source_ast_id_map: Arc<AstIdMap>,
|
source_ast_id_map: Arc<AstIdMap>,
|
||||||
body_ctx: crate::body::LowerCtx,
|
body_ctx: crate::body::LowerCtx<'a>,
|
||||||
forced_visibility: Option<RawVisibilityId>,
|
forced_visibility: Option<RawVisibilityId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ctx {
|
impl<'a> Ctx<'a> {
|
||||||
pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self {
|
pub(super) fn new(db: &'a dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
db,
|
||||||
tree: ItemTree::default(),
|
tree: ItemTree::default(),
|
||||||
hygiene,
|
hygiene,
|
||||||
file,
|
file,
|
||||||
|
@ -126,7 +128,7 @@ impl Ctx {
|
||||||
| ast::Item::MacroDef(_) => {}
|
| ast::Item::MacroDef(_) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
let attrs = RawAttrs::new(item, &self.hygiene);
|
let attrs = RawAttrs::new(self.db, item, &self.hygiene);
|
||||||
let items = match item {
|
let items = match item {
|
||||||
ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into),
|
ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into),
|
||||||
ast::Item::Union(ast) => self.lower_union(ast).map(Into::into),
|
ast::Item::Union(ast) => self.lower_union(ast).map(Into::into),
|
||||||
|
@ -256,7 +258,7 @@ impl Ctx {
|
||||||
for field in fields.fields() {
|
for field in fields.fields() {
|
||||||
if let Some(data) = self.lower_record_field(&field) {
|
if let Some(data) = self.lower_record_field(&field) {
|
||||||
let idx = self.data().fields.alloc(data);
|
let idx = self.data().fields.alloc(data);
|
||||||
self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
|
self.add_attrs(idx.into(), RawAttrs::new(self.db, &field, &self.hygiene));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let end = self.next_field_idx();
|
let end = self.next_field_idx();
|
||||||
|
@ -276,7 +278,7 @@ impl Ctx {
|
||||||
for (i, field) in fields.fields().enumerate() {
|
for (i, field) in fields.fields().enumerate() {
|
||||||
let data = self.lower_tuple_field(i, &field);
|
let data = self.lower_tuple_field(i, &field);
|
||||||
let idx = self.data().fields.alloc(data);
|
let idx = self.data().fields.alloc(data);
|
||||||
self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
|
self.add_attrs(idx.into(), RawAttrs::new(self.db, &field, &self.hygiene));
|
||||||
}
|
}
|
||||||
let end = self.next_field_idx();
|
let end = self.next_field_idx();
|
||||||
IdRange::new(start..end)
|
IdRange::new(start..end)
|
||||||
|
@ -321,7 +323,7 @@ impl Ctx {
|
||||||
for variant in variants.variants() {
|
for variant in variants.variants() {
|
||||||
if let Some(data) = self.lower_variant(&variant) {
|
if let Some(data) = self.lower_variant(&variant) {
|
||||||
let idx = self.data().variants.alloc(data);
|
let idx = self.data().variants.alloc(data);
|
||||||
self.add_attrs(idx.into(), RawAttrs::new(&variant, &self.hygiene));
|
self.add_attrs(idx.into(), RawAttrs::new(self.db, &variant, &self.hygiene));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let end = self.next_variant_idx();
|
let end = self.next_variant_idx();
|
||||||
|
@ -364,7 +366,7 @@ impl Ctx {
|
||||||
};
|
};
|
||||||
let ty = Interned::new(self_type);
|
let ty = Interned::new(self_type);
|
||||||
let idx = self.data().params.alloc(Param::Normal(ty));
|
let idx = self.data().params.alloc(Param::Normal(ty));
|
||||||
self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene));
|
self.add_attrs(idx.into(), RawAttrs::new(self.db, &self_param, &self.hygiene));
|
||||||
has_self_param = true;
|
has_self_param = true;
|
||||||
}
|
}
|
||||||
for param in param_list.params() {
|
for param in param_list.params() {
|
||||||
|
@ -376,7 +378,7 @@ impl Ctx {
|
||||||
self.data().params.alloc(Param::Normal(ty))
|
self.data().params.alloc(Param::Normal(ty))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.add_attrs(idx.into(), RawAttrs::new(¶m, &self.hygiene));
|
self.add_attrs(idx.into(), RawAttrs::new(self.db, ¶m, &self.hygiene));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let end_param = self.next_param_idx();
|
let end_param = self.next_param_idx();
|
||||||
|
@ -522,10 +524,11 @@ impl Ctx {
|
||||||
let is_unsafe = trait_def.unsafe_token().is_some();
|
let is_unsafe = trait_def.unsafe_token().is_some();
|
||||||
let bounds = self.lower_type_bounds(trait_def);
|
let bounds = self.lower_type_bounds(trait_def);
|
||||||
let items = trait_def.assoc_item_list().map(|list| {
|
let items = trait_def.assoc_item_list().map(|list| {
|
||||||
|
let db = self.db;
|
||||||
self.with_inherited_visibility(visibility, |this| {
|
self.with_inherited_visibility(visibility, |this| {
|
||||||
list.assoc_items()
|
list.assoc_items()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
let attrs = RawAttrs::new(&item, &this.hygiene);
|
let attrs = RawAttrs::new(db, &item, &this.hygiene);
|
||||||
this.collect_inner_items(item.syntax());
|
this.collect_inner_items(item.syntax());
|
||||||
this.lower_assoc_item(&item).map(|item| {
|
this.lower_assoc_item(&item).map(|item| {
|
||||||
this.add_attrs(ModItem::from(item).into(), attrs);
|
this.add_attrs(ModItem::from(item).into(), attrs);
|
||||||
|
@ -567,7 +570,7 @@ impl Ctx {
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
self.collect_inner_items(item.syntax());
|
self.collect_inner_items(item.syntax());
|
||||||
let assoc = self.lower_assoc_item(&item)?;
|
let assoc = self.lower_assoc_item(&item)?;
|
||||||
let attrs = RawAttrs::new(&item, &self.hygiene);
|
let attrs = RawAttrs::new(self.db, &item, &self.hygiene);
|
||||||
self.add_attrs(ModItem::from(assoc).into(), attrs);
|
self.add_attrs(ModItem::from(assoc).into(), attrs);
|
||||||
Some(assoc)
|
Some(assoc)
|
||||||
})
|
})
|
||||||
|
@ -585,6 +588,7 @@ impl Ctx {
|
||||||
let mut imports = Vec::new();
|
let mut imports = Vec::new();
|
||||||
let tree = self.tree.data_mut();
|
let tree = self.tree.data_mut();
|
||||||
ModPath::expand_use_item(
|
ModPath::expand_use_item(
|
||||||
|
self.db,
|
||||||
InFile::new(self.file, use_item.clone()),
|
InFile::new(self.file, use_item.clone()),
|
||||||
&self.hygiene,
|
&self.hygiene,
|
||||||
|path, _use_tree, is_glob, alias| {
|
|path, _use_tree, is_glob, alias| {
|
||||||
|
@ -618,7 +622,7 @@ impl Ctx {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
|
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
|
||||||
let path = Interned::new(ModPath::from_src(m.path()?, &self.hygiene)?);
|
let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?);
|
||||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||||
let res = MacroCall { path, ast_id };
|
let res = MacroCall { path, ast_id };
|
||||||
Some(id(self.data().macro_calls.alloc(res)))
|
Some(id(self.data().macro_calls.alloc(res)))
|
||||||
|
@ -647,7 +651,7 @@ impl Ctx {
|
||||||
list.extern_items()
|
list.extern_items()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
self.collect_inner_items(item.syntax());
|
self.collect_inner_items(item.syntax());
|
||||||
let attrs = RawAttrs::new(&item, &self.hygiene);
|
let attrs = RawAttrs::new(self.db, &item, &self.hygiene);
|
||||||
let id: ModItem = match item {
|
let id: ModItem = match item {
|
||||||
ast::ExternItem::Fn(ast) => {
|
ast::ExternItem::Fn(ast) => {
|
||||||
let func_id = self.lower_function(&ast)?;
|
let func_id = self.lower_function(&ast)?;
|
||||||
|
@ -755,7 +759,7 @@ impl Ctx {
|
||||||
fn lower_visibility(&mut self, item: &impl ast::VisibilityOwner) -> RawVisibilityId {
|
fn lower_visibility(&mut self, item: &impl ast::VisibilityOwner) -> RawVisibilityId {
|
||||||
let vis = match self.forced_visibility {
|
let vis = match self.forced_visibility {
|
||||||
Some(vis) => return vis,
|
Some(vis) => return vis,
|
||||||
None => RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene),
|
None => RawVisibility::from_ast_with_hygiene(self.db, item.visibility(), &self.hygiene),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.data().vis.alloc(vis)
|
self.data().vis.alloc(vis)
|
||||||
|
|
|
@ -654,7 +654,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
|
||||||
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
|
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
|
||||||
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
|
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
|
||||||
let h = Hygiene::new(db.upcast(), self.file_id);
|
let h = Hygiene::new(db.upcast(), self.file_id);
|
||||||
let path = self.value.path().and_then(|path| path::ModPath::from_src(path, &h));
|
let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h));
|
||||||
|
|
||||||
let path = match error_sink
|
let path = match error_sink
|
||||||
.option(path, || mbe::ExpandError::Other("malformed macro invocation".into()))
|
.option(path, || mbe::ExpandError::Other("malformed macro invocation".into()))
|
||||||
|
@ -712,7 +712,7 @@ fn macro_call_as_call_id(
|
||||||
krate,
|
krate,
|
||||||
macro_call,
|
macro_call,
|
||||||
def,
|
def,
|
||||||
&|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
|
&|path: ast::Path| resolver(path::ModPath::from_src(db, path, &hygiene)?),
|
||||||
error_sink,
|
error_sink,
|
||||||
)
|
)
|
||||||
.map(MacroCallId::from)
|
.map(MacroCallId::from)
|
||||||
|
|
|
@ -599,6 +599,7 @@ mod diagnostics {
|
||||||
let mut cur = 0;
|
let mut cur = 0;
|
||||||
let mut tree = None;
|
let mut tree = None;
|
||||||
ModPath::expand_use_item(
|
ModPath::expand_use_item(
|
||||||
|
db,
|
||||||
InFile::new(ast.file_id, use_item),
|
InFile::new(ast.file_id, use_item),
|
||||||
&hygiene,
|
&hygiene,
|
||||||
|_mod_path, use_tree, _is_glob, _alias| {
|
|_mod_path, use_tree, _is_glob, _alias| {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{body::LowerCtx, intern::Interned, type_ref::LifetimeRef};
|
use crate::{body::LowerCtx, db::DefDatabase, intern::Interned, type_ref::LifetimeRef};
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
hygiene::Hygiene,
|
hygiene::Hygiene,
|
||||||
|
@ -47,9 +47,9 @@ pub enum ImportAlias {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModPath {
|
impl ModPath {
|
||||||
pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
|
pub fn from_src(db: &dyn DefDatabase, path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
|
||||||
let ctx = LowerCtx::with_hygiene(hygiene);
|
let ctx = LowerCtx::with_hygiene(db, hygiene);
|
||||||
lower::lower_path(path, &ctx).map(|it| (*it.mod_path).clone())
|
lower::lower_path(db, path, &ctx).map(|it| (*it.mod_path).clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath {
|
pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath {
|
||||||
|
@ -64,12 +64,13 @@ impl ModPath {
|
||||||
|
|
||||||
/// Calls `cb` with all paths, represented by this use item.
|
/// Calls `cb` with all paths, represented by this use item.
|
||||||
pub(crate) fn expand_use_item(
|
pub(crate) fn expand_use_item(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
item_src: InFile<ast::Use>,
|
item_src: InFile<ast::Use>,
|
||||||
hygiene: &Hygiene,
|
hygiene: &Hygiene,
|
||||||
mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<ImportAlias>),
|
mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option<ImportAlias>),
|
||||||
) {
|
) {
|
||||||
if let Some(tree) = item_src.value.use_tree() {
|
if let Some(tree) = item_src.value.use_tree() {
|
||||||
lower::lower_use_tree(None, tree, hygiene, &mut cb);
|
lower::lower_use_tree(db, None, tree, hygiene, &mut cb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,8 +169,8 @@ pub enum GenericArg {
|
||||||
impl Path {
|
impl Path {
|
||||||
/// 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(path: ast::Path, ctx: &LowerCtx) -> Option<Path> {
|
pub fn from_src(db: &dyn DefDatabase, path: ast::Path, ctx: &LowerCtx) -> Option<Path> {
|
||||||
lower::lower_path(path, ctx)
|
lower::lower_path(db, path, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a known mod path to `Path`.
|
/// Converts a known mod path to `Path`.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
mod lower_use;
|
mod lower_use;
|
||||||
|
|
||||||
use crate::intern::Interned;
|
use crate::{db::DefDatabase, intern::Interned};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
|
@ -20,7 +20,11 @@ pub(super) use lower_use::lower_use_tree;
|
||||||
|
|
||||||
/// 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(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option<Path> {
|
pub(super) fn lower_path(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
mut path: ast::Path,
|
||||||
|
ctx: &LowerCtx,
|
||||||
|
) -> Option<Path> {
|
||||||
let mut kind = PathKind::Plain;
|
let mut kind = PathKind::Plain;
|
||||||
let mut type_anchor = None;
|
let mut type_anchor = None;
|
||||||
let mut segments = Vec::new();
|
let mut segments = Vec::new();
|
||||||
|
@ -36,7 +40,7 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option<Path> {
|
||||||
match segment.kind()? {
|
match segment.kind()? {
|
||||||
ast::PathSegmentKind::Name(name_ref) => {
|
ast::PathSegmentKind::Name(name_ref) => {
|
||||||
// FIXME: this should just return name
|
// FIXME: this should just return name
|
||||||
match hygiene.name_ref_to_name(name_ref) {
|
match hygiene.name_ref_to_name(db.upcast(), name_ref) {
|
||||||
Either::Left(name) => {
|
Either::Left(name) => {
|
||||||
let args = segment
|
let args = segment
|
||||||
.generic_arg_list()
|
.generic_arg_list()
|
||||||
|
@ -71,7 +75,7 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option<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::from_src(trait_ref.path()?, ctx)?;
|
let path = Path::from_src(db, trait_ref.path()?, ctx)?;
|
||||||
let mod_path = (*path.mod_path).clone();
|
let mod_path = (*path.mod_path).clone();
|
||||||
let num_segments = path.mod_path.segments.len();
|
let num_segments = path.mod_path.segments.len();
|
||||||
kind = mod_path.kind;
|
kind = mod_path.kind;
|
||||||
|
@ -133,7 +137,7 @@ pub(super) fn lower_path(mut path: ast::Path, ctx: &LowerCtx) -> Option<Path> {
|
||||||
// We follow what it did anyway :)
|
// We follow what it did anyway :)
|
||||||
if segments.len() == 1 && kind == PathKind::Plain {
|
if segments.len() == 1 && kind == PathKind::Plain {
|
||||||
if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
|
if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
|
||||||
if let Some(crate_id) = hygiene.local_inner_macros(path) {
|
if let Some(crate_id) = hygiene.local_inner_macros(db.upcast(), path) {
|
||||||
kind = PathKind::DollarCrate(crate_id);
|
kind = PathKind::DollarCrate(crate_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,13 @@ use either::Either;
|
||||||
use hir_expand::{hygiene::Hygiene, name::AsName};
|
use hir_expand::{hygiene::Hygiene, name::AsName};
|
||||||
use syntax::ast::{self, NameOwner};
|
use syntax::ast::{self, NameOwner};
|
||||||
|
|
||||||
use crate::path::{ImportAlias, ModPath, PathKind};
|
use crate::{
|
||||||
|
db::DefDatabase,
|
||||||
|
path::{ImportAlias, ModPath, PathKind},
|
||||||
|
};
|
||||||
|
|
||||||
pub(crate) fn lower_use_tree(
|
pub(crate) fn lower_use_tree(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
prefix: Option<ModPath>,
|
prefix: Option<ModPath>,
|
||||||
tree: ast::UseTree,
|
tree: ast::UseTree,
|
||||||
hygiene: &Hygiene,
|
hygiene: &Hygiene,
|
||||||
|
@ -21,13 +25,13 @@ pub(crate) fn lower_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, hygiene) {
|
Some(path) => match convert_path(db, 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() {
|
||||||
lower_use_tree(prefix.clone(), child_tree, hygiene, cb);
|
lower_use_tree(db, prefix.clone(), child_tree, hygiene, cb);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let alias = tree.rename().map(|a| {
|
let alias = tree.rename().map(|a| {
|
||||||
|
@ -47,7 +51,7 @@ pub(crate) fn lower_use_tree(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(path) = convert_path(prefix, ast_path, hygiene) {
|
if let Some(path) = convert_path(db, prefix, ast_path, hygiene) {
|
||||||
cb(path, &tree, is_glob, alias)
|
cb(path, &tree, is_glob, alias)
|
||||||
}
|
}
|
||||||
// FIXME: report errors somewhere
|
// FIXME: report errors somewhere
|
||||||
|
@ -61,9 +65,14 @@ pub(crate) fn lower_use_tree(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_path(prefix: Option<ModPath>, path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
|
fn convert_path(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
|
prefix: Option<ModPath>,
|
||||||
|
path: ast::Path,
|
||||||
|
hygiene: &Hygiene,
|
||||||
|
) -> Option<ModPath> {
|
||||||
let prefix = if let Some(qual) = path.qualifier() {
|
let prefix = if let Some(qual) = path.qualifier() {
|
||||||
Some(convert_path(prefix, qual, hygiene)?)
|
Some(convert_path(db, prefix, qual, hygiene)?)
|
||||||
} else {
|
} else {
|
||||||
prefix
|
prefix
|
||||||
};
|
};
|
||||||
|
@ -71,7 +80,7 @@ fn convert_path(prefix: Option<ModPath>, path: ast::Path, hygiene: &Hygiene) ->
|
||||||
let segment = path.segment()?;
|
let segment = path.segment()?;
|
||||||
let res = match segment.kind()? {
|
let res = match segment.kind()? {
|
||||||
ast::PathSegmentKind::Name(name_ref) => {
|
ast::PathSegmentKind::Name(name_ref) => {
|
||||||
match hygiene.name_ref_to_name(name_ref) {
|
match hygiene.name_ref_to_name(db.upcast(), name_ref) {
|
||||||
Either::Left(name) => {
|
Either::Left(name) => {
|
||||||
// no type args in use
|
// no type args in use
|
||||||
let mut res = prefix.unwrap_or_else(|| {
|
let mut res = prefix.unwrap_or_else(|| {
|
||||||
|
|
|
@ -33,17 +33,19 @@ impl RawVisibility {
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
node: InFile<Option<ast::Visibility>>,
|
node: InFile<Option<ast::Visibility>>,
|
||||||
) -> RawVisibility {
|
) -> RawVisibility {
|
||||||
Self::from_ast_with_hygiene(node.value, &Hygiene::new(db.upcast(), node.file_id))
|
Self::from_ast_with_hygiene(db, node.value, &Hygiene::new(db.upcast(), node.file_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_ast_with_hygiene(
|
pub(crate) fn from_ast_with_hygiene(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
node: Option<ast::Visibility>,
|
node: Option<ast::Visibility>,
|
||||||
hygiene: &Hygiene,
|
hygiene: &Hygiene,
|
||||||
) -> RawVisibility {
|
) -> RawVisibility {
|
||||||
Self::from_ast_with_hygiene_and_default(node, RawVisibility::private(), hygiene)
|
Self::from_ast_with_hygiene_and_default(db, node, RawVisibility::private(), hygiene)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_ast_with_hygiene_and_default(
|
pub(crate) fn from_ast_with_hygiene_and_default(
|
||||||
|
db: &dyn DefDatabase,
|
||||||
node: Option<ast::Visibility>,
|
node: Option<ast::Visibility>,
|
||||||
default: RawVisibility,
|
default: RawVisibility,
|
||||||
hygiene: &Hygiene,
|
hygiene: &Hygiene,
|
||||||
|
@ -54,7 +56,7 @@ impl RawVisibility {
|
||||||
};
|
};
|
||||||
match node.kind() {
|
match node.kind() {
|
||||||
ast::VisibilityKind::In(path) => {
|
ast::VisibilityKind::In(path) => {
|
||||||
let path = ModPath::from_src(path, hygiene);
|
let path = ModPath::from_src(db, path, hygiene);
|
||||||
let path = match path {
|
let path = match path {
|
||||||
None => return RawVisibility::private(),
|
None => return RawVisibility::private(),
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
|
|
|
@ -32,10 +32,14 @@ impl Hygiene {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this should just return name
|
// FIXME: this should just return name
|
||||||
pub fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either<Name, CrateId> {
|
pub fn name_ref_to_name(
|
||||||
|
&self,
|
||||||
|
db: &dyn AstDatabase,
|
||||||
|
name_ref: ast::NameRef,
|
||||||
|
) -> Either<Name, CrateId> {
|
||||||
if let Some(frames) = &self.frames {
|
if let Some(frames) = &self.frames {
|
||||||
if name_ref.text() == "$crate" {
|
if name_ref.text() == "$crate" {
|
||||||
if let Some(krate) = frames.root_crate(name_ref.syntax()) {
|
if let Some(krate) = frames.root_crate(db, name_ref.syntax()) {
|
||||||
return Either::Right(krate);
|
return Either::Right(krate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,15 +48,19 @@ impl Hygiene {
|
||||||
Either::Left(name_ref.as_name())
|
Either::Left(name_ref.as_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn local_inner_macros(&self, path: ast::Path) -> Option<CrateId> {
|
pub fn local_inner_macros(&self, db: &dyn AstDatabase, path: ast::Path) -> Option<CrateId> {
|
||||||
let mut token = path.syntax().first_token()?.text_range();
|
let mut token = path.syntax().first_token()?.text_range();
|
||||||
let frames = self.frames.as_ref()?;
|
let frames = self.frames.as_ref()?;
|
||||||
let mut current = frames.0.clone();
|
let mut current = frames.0.clone();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (mapped, origin) = current.expansion.as_ref()?.map_ident_up(token)?;
|
let (mapped, origin) = current.expansion.as_ref()?.map_ident_up(db, token)?;
|
||||||
if origin == Origin::Def {
|
if origin == Origin::Def {
|
||||||
return if current.local_inner { frames.root_crate(path.syntax()) } else { None };
|
return if current.local_inner {
|
||||||
|
frames.root_crate(db, path.syntax())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
}
|
}
|
||||||
current = current.call_site.as_ref()?.clone();
|
current = current.call_site.as_ref()?.clone();
|
||||||
token = mapped.value;
|
token = mapped.value;
|
||||||
|
@ -82,13 +90,13 @@ impl HygieneFrames {
|
||||||
HygieneFrames(Arc::new(HygieneFrame::new(db, file_id)))
|
HygieneFrames(Arc::new(HygieneFrame::new(db, file_id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root_crate(&self, node: &SyntaxNode) -> Option<CrateId> {
|
fn root_crate(&self, db: &dyn AstDatabase, node: &SyntaxNode) -> Option<CrateId> {
|
||||||
let mut token = node.first_token()?.text_range();
|
let mut token = node.first_token()?.text_range();
|
||||||
let mut result = self.0.krate;
|
let mut result = self.0.krate;
|
||||||
let mut current = self.0.clone();
|
let mut current = self.0.clone();
|
||||||
|
|
||||||
while let Some((mapped, origin)) =
|
while let Some((mapped, origin)) =
|
||||||
current.expansion.as_ref().and_then(|it| it.map_ident_up(token))
|
current.expansion.as_ref().and_then(|it| it.map_ident_up(db, token))
|
||||||
{
|
{
|
||||||
result = current.krate;
|
result = current.krate;
|
||||||
|
|
||||||
|
@ -112,7 +120,7 @@ impl HygieneFrames {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
struct HygieneInfo {
|
struct HygieneInfo {
|
||||||
arg_start: InFile<TextSize>,
|
file: MacroFile,
|
||||||
/// The `macro_rules!` arguments.
|
/// The `macro_rules!` arguments.
|
||||||
def_start: Option<InFile<TextSize>>,
|
def_start: Option<InFile<TextSize>>,
|
||||||
|
|
||||||
|
@ -122,12 +130,24 @@ struct HygieneInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HygieneInfo {
|
impl HygieneInfo {
|
||||||
fn map_ident_up(&self, token: TextRange) -> Option<(InFile<TextRange>, Origin)> {
|
fn map_ident_up(
|
||||||
|
&self,
|
||||||
|
db: &dyn AstDatabase,
|
||||||
|
token: TextRange,
|
||||||
|
) -> Option<(InFile<TextRange>, Origin)> {
|
||||||
let token_id = self.exp_map.token_by_range(token)?;
|
let token_id = self.exp_map.token_by_range(token)?;
|
||||||
|
|
||||||
let (token_id, origin) = self.macro_def.map_id_up(token_id);
|
let (token_id, origin) = self.macro_def.map_id_up(token_id);
|
||||||
let (token_map, tt) = match origin {
|
let (token_map, tt) = match origin {
|
||||||
mbe::Origin::Call => (&self.macro_arg.1, self.arg_start),
|
mbe::Origin::Call => {
|
||||||
|
let call_id = match self.file.macro_call_id {
|
||||||
|
MacroCallId::LazyMacro(lazy) => lazy,
|
||||||
|
MacroCallId::EagerMacro(_) => unreachable!(),
|
||||||
|
};
|
||||||
|
let loc: MacroCallLoc = db.lookup_intern_macro(call_id);
|
||||||
|
let arg_start = loc.kind.arg(db)?.text_range().start();
|
||||||
|
(&self.macro_arg.1, InFile::new(loc.kind.file_id(), arg_start))
|
||||||
|
}
|
||||||
mbe::Origin::Def => match (&*self.macro_def, self.def_start) {
|
mbe::Origin::Def => match (&*self.macro_def, self.def_start) {
|
||||||
(TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt))
|
(TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt))
|
||||||
| (TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt)) => {
|
| (TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt)) => {
|
||||||
|
@ -147,8 +167,6 @@ fn make_hygiene_info(
|
||||||
macro_file: MacroFile,
|
macro_file: MacroFile,
|
||||||
loc: &MacroCallLoc,
|
loc: &MacroCallLoc,
|
||||||
) -> Option<HygieneInfo> {
|
) -> Option<HygieneInfo> {
|
||||||
let arg_tt = loc.kind.arg(db)?;
|
|
||||||
|
|
||||||
let def_offset = loc.def.ast_id().left().and_then(|id| {
|
let def_offset = loc.def.ast_id().left().and_then(|id| {
|
||||||
let def_tt = match id.to_node(db) {
|
let def_tt = match id.to_node(db) {
|
||||||
ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(),
|
ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(),
|
||||||
|
@ -161,13 +179,7 @@ fn make_hygiene_info(
|
||||||
let (_, exp_map) = db.parse_macro_expansion(macro_file).value?;
|
let (_, exp_map) = db.parse_macro_expansion(macro_file).value?;
|
||||||
let macro_arg = db.macro_arg(macro_file.macro_call_id)?;
|
let macro_arg = db.macro_arg(macro_file.macro_call_id)?;
|
||||||
|
|
||||||
Some(HygieneInfo {
|
Some(HygieneInfo { file: macro_file, def_start: def_offset, macro_arg, macro_def, exp_map })
|
||||||
arg_start: InFile::new(loc.kind.file_id(), arg_tt.text_range().start()),
|
|
||||||
def_start: def_offset,
|
|
||||||
macro_arg,
|
|
||||||
macro_def,
|
|
||||||
exp_map,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HygieneFrame {
|
impl HygieneFrame {
|
||||||
|
@ -178,7 +190,8 @@ impl HygieneFrame {
|
||||||
MacroCallId::EagerMacro(_id) => (None, None, false),
|
MacroCallId::EagerMacro(_id) => (None, None, false),
|
||||||
MacroCallId::LazyMacro(id) => {
|
MacroCallId::LazyMacro(id) => {
|
||||||
let loc = db.lookup_intern_macro(id);
|
let loc = db.lookup_intern_macro(id);
|
||||||
let info = make_hygiene_info(db, macro_file, &loc);
|
let info = make_hygiene_info(db, macro_file, &loc)
|
||||||
|
.map(|info| (loc.kind.file_id(), info));
|
||||||
match loc.def.kind {
|
match loc.def.kind {
|
||||||
MacroDefKind::Declarative(_) => {
|
MacroDefKind::Declarative(_) => {
|
||||||
(info, Some(loc.def.krate), loc.def.local_inner)
|
(info, Some(loc.def.krate), loc.def.local_inner)
|
||||||
|
@ -192,7 +205,7 @@ impl HygieneFrame {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let info = match info {
|
let (calling_file, info) = match info {
|
||||||
None => {
|
None => {
|
||||||
return HygieneFrame {
|
return HygieneFrame {
|
||||||
expansion: None,
|
expansion: None,
|
||||||
|
@ -206,7 +219,7 @@ impl HygieneFrame {
|
||||||
};
|
};
|
||||||
|
|
||||||
let def_site = info.def_start.map(|it| db.hygiene_frame(it.file_id));
|
let def_site = info.def_start.map(|it| db.hygiene_frame(it.file_id));
|
||||||
let call_site = Some(db.hygiene_frame(info.arg_start.file_id));
|
let call_site = Some(db.hygiene_frame(calling_file));
|
||||||
|
|
||||||
HygieneFrame { expansion: Some(info), local_inner, krate, call_site, def_site }
|
HygieneFrame { expansion: Some(info), local_inner, krate, call_site, def_site }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1000,9 +1000,9 @@ impl HirDisplay for TypeRef {
|
||||||
}
|
}
|
||||||
TypeRef::Macro(macro_call) => {
|
TypeRef::Macro(macro_call) => {
|
||||||
let macro_call = macro_call.to_node(f.db.upcast());
|
let macro_call = macro_call.to_node(f.db.upcast());
|
||||||
let ctx = body::LowerCtx::with_hygiene(&Hygiene::new_unhygienic());
|
let ctx = body::LowerCtx::with_hygiene(f.db.upcast(), &Hygiene::new_unhygienic());
|
||||||
match macro_call.path() {
|
match macro_call.path() {
|
||||||
Some(path) => match Path::from_src(path, &ctx) {
|
Some(path) => match Path::from_src(f.db.upcast(), path, &ctx) {
|
||||||
Some(path) => path.hir_fmt(f)?,
|
Some(path) => path.hir_fmt(f)?,
|
||||||
None => write!(f, "{{macro}}")?,
|
None => write!(f, "{{macro}}")?,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue