Don't lower extern block in the ItemTree
This commit is contained in:
parent
eb08a27f1b
commit
d00bc9c2fc
@ -132,6 +132,7 @@ fn shrink_to_fit(&mut self) {
|
|||||||
let ItemTreeData {
|
let ItemTreeData {
|
||||||
imports,
|
imports,
|
||||||
extern_crates,
|
extern_crates,
|
||||||
|
extern_blocks,
|
||||||
functions,
|
functions,
|
||||||
params,
|
params,
|
||||||
structs,
|
structs,
|
||||||
@ -154,6 +155,7 @@ fn shrink_to_fit(&mut self) {
|
|||||||
|
|
||||||
imports.shrink_to_fit();
|
imports.shrink_to_fit();
|
||||||
extern_crates.shrink_to_fit();
|
extern_crates.shrink_to_fit();
|
||||||
|
extern_blocks.shrink_to_fit();
|
||||||
functions.shrink_to_fit();
|
functions.shrink_to_fit();
|
||||||
params.shrink_to_fit();
|
params.shrink_to_fit();
|
||||||
structs.shrink_to_fit();
|
structs.shrink_to_fit();
|
||||||
@ -239,6 +241,7 @@ fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId {
|
|||||||
struct ItemTreeData {
|
struct ItemTreeData {
|
||||||
imports: Arena<Import>,
|
imports: Arena<Import>,
|
||||||
extern_crates: Arena<ExternCrate>,
|
extern_crates: Arena<ExternCrate>,
|
||||||
|
extern_blocks: Arena<ExternBlock>,
|
||||||
functions: Arena<Function>,
|
functions: Arena<Function>,
|
||||||
params: Arena<Param>,
|
params: Arena<Param>,
|
||||||
structs: Arena<Struct>,
|
structs: Arena<Struct>,
|
||||||
@ -432,6 +435,7 @@ fn index(&self, index: Idx<$typ>) -> &Self::Output {
|
|||||||
mod_items! {
|
mod_items! {
|
||||||
Import in imports -> ast::Use,
|
Import in imports -> ast::Use,
|
||||||
ExternCrate in extern_crates -> ast::ExternCrate,
|
ExternCrate in extern_crates -> ast::ExternCrate,
|
||||||
|
ExternBlock in extern_blocks -> ast::ExternBlock,
|
||||||
Function in functions -> ast::Fn,
|
Function in functions -> ast::Fn,
|
||||||
Struct in structs -> ast::Struct,
|
Struct in structs -> ast::Struct,
|
||||||
Union in unions -> ast::Union,
|
Union in unions -> ast::Union,
|
||||||
@ -507,6 +511,13 @@ pub struct ExternCrate {
|
|||||||
pub ast_id: FileAstId<ast::ExternCrate>,
|
pub ast_id: FileAstId<ast::ExternCrate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub struct ExternBlock {
|
||||||
|
pub abi: Option<Interned<str>>,
|
||||||
|
pub ast_id: FileAstId<ast::ExternBlock>,
|
||||||
|
pub children: Box<[ModItem]>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
@ -691,6 +702,7 @@ pub fn as_assoc_item(&self) -> Option<AssocItem> {
|
|||||||
match self {
|
match self {
|
||||||
ModItem::Import(_)
|
ModItem::Import(_)
|
||||||
| ModItem::ExternCrate(_)
|
| ModItem::ExternCrate(_)
|
||||||
|
| ModItem::ExternBlock(_)
|
||||||
| ModItem::Struct(_)
|
| ModItem::Struct(_)
|
||||||
| ModItem::Union(_)
|
| ModItem::Union(_)
|
||||||
| ModItem::Enum(_)
|
| ModItem::Enum(_)
|
||||||
@ -715,6 +727,7 @@ pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
|
|||||||
match self {
|
match self {
|
||||||
ModItem::Import(it) => tree[it.index].ast_id().upcast(),
|
ModItem::Import(it) => tree[it.index].ast_id().upcast(),
|
||||||
ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(),
|
ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(),
|
||||||
|
ModItem::ExternBlock(it) => tree[it.index].ast_id().upcast(),
|
||||||
ModItem::Function(it) => tree[it.index].ast_id().upcast(),
|
ModItem::Function(it) => tree[it.index].ast_id().upcast(),
|
||||||
ModItem::Struct(it) => tree[it.index].ast_id().upcast(),
|
ModItem::Struct(it) => tree[it.index].ast_id().upcast(),
|
||||||
ModItem::Union(it) => tree[it.index].ast_id().upcast(),
|
ModItem::Union(it) => tree[it.index].ast_id().upcast(),
|
||||||
|
@ -147,9 +147,7 @@ fn lower_mod_item(&mut self, item: &ast::Item, inner: bool) -> Option<ModItems>
|
|||||||
ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
|
ast::Item::MacroCall(ast) => self.lower_macro_call(ast).map(Into::into),
|
||||||
ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
|
ast::Item::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
|
||||||
ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into),
|
ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into),
|
||||||
ast::Item::ExternBlock(ast) => {
|
ast::Item::ExternBlock(ast) => Some(self.lower_extern_block(ast).into()),
|
||||||
Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if !attrs.is_empty() {
|
if !attrs.is_empty() {
|
||||||
@ -397,19 +395,7 @@ fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>>
|
|||||||
ret_type
|
ret_type
|
||||||
};
|
};
|
||||||
|
|
||||||
let abi = func.abi().map(|abi| {
|
let abi = func.abi().map(lower_abi);
|
||||||
// FIXME: Abi::abi() -> Option<SyntaxToken>?
|
|
||||||
match abi.syntax().last_token() {
|
|
||||||
Some(tok) if tok.kind() == SyntaxKind::STRING => {
|
|
||||||
// FIXME: Better way to unescape?
|
|
||||||
Interned::new_str(tok.text().trim_matches('"'))
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// `extern` default to be `extern "C"`.
|
|
||||||
Interned::new_str("C")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let ast_id = self.source_ast_id_map.ast_id(func);
|
let ast_id = self.source_ast_id_map.ast_id(func);
|
||||||
|
|
||||||
@ -647,8 +633,10 @@ fn lower_macro_def(&mut self, m: &ast::MacroDef) -> Option<FileItemTreeId<MacroD
|
|||||||
Some(id(self.data().macro_defs.alloc(res)))
|
Some(id(self.data().macro_defs.alloc(res)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
|
fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId<ExternBlock> {
|
||||||
block.extern_item_list().map_or(Vec::new(), |list| {
|
let ast_id = self.source_ast_id_map.ast_id(block);
|
||||||
|
let abi = block.abi().map(lower_abi);
|
||||||
|
let children: Box<[_]> = block.extern_item_list().map_or(Box::new([]), |list| {
|
||||||
list.extern_items()
|
list.extern_items()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
self.collect_inner_items(item.syntax());
|
self.collect_inner_items(item.syntax());
|
||||||
@ -673,13 +661,20 @@ fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
|
|||||||
self.data().type_aliases[foreign_ty.index].is_extern = true;
|
self.data().type_aliases[foreign_ty.index].is_extern = true;
|
||||||
foreign_ty.into()
|
foreign_ty.into()
|
||||||
}
|
}
|
||||||
ast::ExternItem::MacroCall(_) => return None,
|
ast::ExternItem::MacroCall(call) => {
|
||||||
|
// FIXME: we need some way of tracking that the macro call is in an
|
||||||
|
// extern block
|
||||||
|
self.lower_macro_call(&call)?.into()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
self.add_attrs(id.into(), attrs);
|
self.add_attrs(id.into(), attrs);
|
||||||
Some(id)
|
Some(id)
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
})
|
});
|
||||||
|
|
||||||
|
let res = ExternBlock { abi, ast_id, children };
|
||||||
|
id(self.data().extern_blocks.alloc(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lowers generics defined on `node` and collects inner items defined within.
|
/// Lowers generics defined on `node` and collects inner items defined within.
|
||||||
@ -879,3 +874,17 @@ fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
|
|||||||
]
|
]
|
||||||
.contains(&name)
|
.contains(&name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_abi(abi: ast::Abi) -> Interned<str> {
|
||||||
|
// FIXME: Abi::abi() -> Option<SyntaxToken>?
|
||||||
|
match abi.syntax().last_token() {
|
||||||
|
Some(tok) if tok.kind() == SyntaxKind::STRING => {
|
||||||
|
// FIXME: Better way to unescape?
|
||||||
|
Interned::new_str(tok.text().trim_matches('"'))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// `extern` default to be `extern "C"`.
|
||||||
|
Interned::new_str("C")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1243,6 +1243,7 @@ fn collect(&mut self, items: &[ModItem]) {
|
|||||||
status: PartialResolvedImport::Unresolved,
|
status: PartialResolvedImport::Unresolved,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
ModItem::ExternBlock(block) => self.collect(&self.item_tree[block].children),
|
||||||
ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
|
ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
|
||||||
ModItem::MacroRules(id) => self.collect_macro_rules(id),
|
ModItem::MacroRules(id) => self.collect_macro_rules(id),
|
||||||
ModItem::MacroDef(id) => self.collect_macro_def(id),
|
ModItem::MacroDef(id) => self.collect_macro_def(id),
|
||||||
|
@ -735,6 +735,42 @@ fn unresolved_attributes_fall_back_track_per_file_moditems() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unresolved_attrs_extern_block_hang() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
#[unresolved]
|
||||||
|
extern "C" {
|
||||||
|
#[unresolved]
|
||||||
|
fn f();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
crate
|
||||||
|
f: v
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn macros_in_extern_block() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
macro_rules! m {
|
||||||
|
() => { static S: u8; };
|
||||||
|
}
|
||||||
|
|
||||||
|
extern {
|
||||||
|
m!();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
crate
|
||||||
|
S: v
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn resolves_derive_helper() {
|
fn resolves_derive_helper() {
|
||||||
cov_mark::check!(resolved_derive_helper);
|
cov_mark::check!(resolved_derive_helper);
|
||||||
|
Loading…
Reference in New Issue
Block a user