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 {
|
||||
imports,
|
||||
extern_crates,
|
||||
extern_blocks,
|
||||
functions,
|
||||
params,
|
||||
structs,
|
||||
@ -154,6 +155,7 @@ fn shrink_to_fit(&mut self) {
|
||||
|
||||
imports.shrink_to_fit();
|
||||
extern_crates.shrink_to_fit();
|
||||
extern_blocks.shrink_to_fit();
|
||||
functions.shrink_to_fit();
|
||||
params.shrink_to_fit();
|
||||
structs.shrink_to_fit();
|
||||
@ -239,6 +241,7 @@ fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId {
|
||||
struct ItemTreeData {
|
||||
imports: Arena<Import>,
|
||||
extern_crates: Arena<ExternCrate>,
|
||||
extern_blocks: Arena<ExternBlock>,
|
||||
functions: Arena<Function>,
|
||||
params: Arena<Param>,
|
||||
structs: Arena<Struct>,
|
||||
@ -432,6 +435,7 @@ fn index(&self, index: Idx<$typ>) -> &Self::Output {
|
||||
mod_items! {
|
||||
Import in imports -> ast::Use,
|
||||
ExternCrate in extern_crates -> ast::ExternCrate,
|
||||
ExternBlock in extern_blocks -> ast::ExternBlock,
|
||||
Function in functions -> ast::Fn,
|
||||
Struct in structs -> ast::Struct,
|
||||
Union in unions -> ast::Union,
|
||||
@ -507,6 +511,13 @@ pub struct 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)]
|
||||
pub struct Function {
|
||||
pub name: Name,
|
||||
@ -691,6 +702,7 @@ pub fn as_assoc_item(&self) -> Option<AssocItem> {
|
||||
match self {
|
||||
ModItem::Import(_)
|
||||
| ModItem::ExternCrate(_)
|
||||
| ModItem::ExternBlock(_)
|
||||
| ModItem::Struct(_)
|
||||
| ModItem::Union(_)
|
||||
| ModItem::Enum(_)
|
||||
@ -715,6 +727,7 @@ pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
|
||||
match self {
|
||||
ModItem::Import(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::Struct(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::MacroRules(ast) => self.lower_macro_rules(ast).map(Into::into),
|
||||
ast::Item::MacroDef(ast) => self.lower_macro_def(ast).map(Into::into),
|
||||
ast::Item::ExternBlock(ast) => {
|
||||
Some(ModItems(self.lower_extern_block(ast).into_iter().collect::<SmallVec<_>>()))
|
||||
}
|
||||
ast::Item::ExternBlock(ast) => Some(self.lower_extern_block(ast).into()),
|
||||
};
|
||||
|
||||
if !attrs.is_empty() {
|
||||
@ -397,19 +395,7 @@ fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>>
|
||||
ret_type
|
||||
};
|
||||
|
||||
let abi = func.abi().map(|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 abi = func.abi().map(lower_abi);
|
||||
|
||||
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)))
|
||||
}
|
||||
|
||||
fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
|
||||
block.extern_item_list().map_or(Vec::new(), |list| {
|
||||
fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> FileItemTreeId<ExternBlock> {
|
||||
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()
|
||||
.filter_map(|item| {
|
||||
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;
|
||||
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);
|
||||
Some(id)
|
||||
})
|
||||
.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.
|
||||
@ -879,3 +874,17 @@ fn is_intrinsic_fn_unsafe(name: &Name) -> bool {
|
||||
]
|
||||
.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,
|
||||
})
|
||||
}
|
||||
ModItem::ExternBlock(block) => self.collect(&self.item_tree[block].children),
|
||||
ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac]),
|
||||
ModItem::MacroRules(id) => self.collect_macro_rules(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]
|
||||
fn resolves_derive_helper() {
|
||||
cov_mark::check!(resolved_derive_helper);
|
||||
|
Loading…
Reference in New Issue
Block a user