Treat BlockExpr as a potential module origin

This commit is contained in:
Jonas Schievink 2021-01-20 20:05:48 +01:00
parent 7d5ed18c42
commit 82146737ac
8 changed files with 44 additions and 7 deletions

View file

@ -158,11 +158,11 @@ impl FunctionBuilder {
it.text_range().end() it.text_range().end()
} }
GeneratedFunctionTarget::InEmptyItemList(it) => { GeneratedFunctionTarget::InEmptyItemList(it) => {
let indent = IndentLevel::from_node(it.syntax()); let indent = IndentLevel::from_node(&it);
leading_ws = format!("\n{}", indent + 1); leading_ws = format!("\n{}", indent + 1);
fn_def = fn_def.indent(indent + 1); fn_def = fn_def.indent(indent + 1);
trailing_ws = format!("\n{}", indent); trailing_ws = format!("\n{}", indent);
it.syntax().text_range().start() + TextSize::of('{') it.text_range().start() + TextSize::of('{')
} }
}; };
@ -179,14 +179,14 @@ impl FunctionBuilder {
enum GeneratedFunctionTarget { enum GeneratedFunctionTarget {
BehindItem(SyntaxNode), BehindItem(SyntaxNode),
InEmptyItemList(ast::ItemList), InEmptyItemList(SyntaxNode),
} }
impl GeneratedFunctionTarget { impl GeneratedFunctionTarget {
fn syntax(&self) -> &SyntaxNode { fn syntax(&self) -> &SyntaxNode {
match self { match self {
GeneratedFunctionTarget::BehindItem(it) => it, GeneratedFunctionTarget::BehindItem(it) => it,
GeneratedFunctionTarget::InEmptyItemList(it) => it.syntax(), GeneratedFunctionTarget::InEmptyItemList(it) => it,
} }
} }
} }
@ -323,7 +323,16 @@ fn next_space_for_fn_in_module(
if let Some(last_item) = it.item_list().and_then(|it| it.items().last()) { if let Some(last_item) = it.item_list().and_then(|it| it.items().last()) {
GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) GeneratedFunctionTarget::BehindItem(last_item.syntax().clone())
} else { } else {
GeneratedFunctionTarget::InEmptyItemList(it.item_list()?) GeneratedFunctionTarget::InEmptyItemList(it.item_list()?.syntax().clone())
}
}
hir::ModuleSource::BlockExpr(it) => {
if let Some(last_item) =
it.statements().take_while(|stmt| matches!(stmt, ast::Stmt::Item(_))).last()
{
GeneratedFunctionTarget::BehindItem(last_item.syntax().clone())
} else {
GeneratedFunctionTarget::InEmptyItemList(it.syntax().clone())
} }
} }
}; };

View file

@ -207,6 +207,7 @@ impl Attrs {
mod_data.definition_source(db).as_ref().map(|src| match src { mod_data.definition_source(db).as_ref().map(|src| match src {
ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, ModuleSource::SourceFile(file) => file as &dyn AttrsOwner,
ModuleSource::Module(module) => module as &dyn AttrsOwner, ModuleSource::Module(module) => module as &dyn AttrsOwner,
ModuleSource::BlockExpr(block) => block as &dyn AttrsOwner,
}), }),
), ),
} }

View file

@ -109,6 +109,10 @@ pub enum ModuleOrigin {
Inline { Inline {
definition: AstId<ast::Module>, definition: AstId<ast::Module>,
}, },
/// Pseudo-module introduced by a block scope (contains only inner items).
BlockExpr {
block: AstId<ast::BlockExpr>,
},
} }
impl Default for ModuleOrigin { impl Default for ModuleOrigin {
@ -122,7 +126,7 @@ impl ModuleOrigin {
match self { match self {
ModuleOrigin::File { declaration: module, .. } ModuleOrigin::File { declaration: module, .. }
| ModuleOrigin::Inline { definition: module, .. } => Some(*module), | ModuleOrigin::Inline { definition: module, .. } => Some(*module),
ModuleOrigin::CrateRoot { .. } => None, ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None,
} }
} }
@ -137,7 +141,7 @@ impl ModuleOrigin {
pub fn is_inline(&self) -> bool { pub fn is_inline(&self) -> bool {
match self { match self {
ModuleOrigin::Inline { .. } => true, ModuleOrigin::Inline { .. } | ModuleOrigin::BlockExpr { .. } => true,
ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false, ModuleOrigin::CrateRoot { .. } | ModuleOrigin::File { .. } => false,
} }
} }
@ -155,6 +159,9 @@ impl ModuleOrigin {
definition.file_id, definition.file_id,
ModuleSource::Module(definition.to_node(db.upcast())), ModuleSource::Module(definition.to_node(db.upcast())),
), ),
ModuleOrigin::BlockExpr { block } => {
InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast())))
}
} }
} }
} }
@ -300,6 +307,7 @@ impl ModuleData {
pub enum ModuleSource { pub enum ModuleSource {
SourceFile(ast::SourceFile), SourceFile(ast::SourceFile),
Module(ast::Module), Module(ast::Module),
BlockExpr(ast::BlockExpr),
} }
mod diagnostics { mod diagnostics {

View file

@ -294,6 +294,7 @@ impl ToNav for hir::Module {
ModuleSource::Module(node) => { ModuleSource::Module(node) => {
(node.syntax(), node.name().map(|it| it.syntax().text_range())) (node.syntax(), node.name().map(|it| it.syntax().text_range()))
} }
ModuleSource::BlockExpr(node) => (node.syntax(), None),
}; };
let frange = src.with_value(syntax).original_file_range(db); let frange = src.with_value(syntax).original_file_range(db);
NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, SymbolKind::Module) NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, SymbolKind::Module)

View file

@ -53,6 +53,12 @@ impl ShortLabel for ast::SourceFile {
} }
} }
impl ShortLabel for ast::BlockExpr {
fn short_label(&self) -> Option<String> {
None
}
}
impl ShortLabel for ast::TypeAlias { impl ShortLabel for ast::TypeAlias {
fn short_label(&self) -> Option<String> { fn short_label(&self) -> Option<String> {
short_label_from_node(self, "type ") short_label_from_node(self, "type ")

View file

@ -321,6 +321,7 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> {
match it.definition_source(db).value { match it.definition_source(db).value {
ModuleSource::Module(it) => it.short_label(), ModuleSource::Module(it) => it.short_label(),
ModuleSource::SourceFile(it) => it.short_label(), ModuleSource::SourceFile(it) => it.short_label(),
ModuleSource::BlockExpr(it) => it.short_label(),
}, },
mod_path, mod_path,
), ),

View file

@ -131,6 +131,7 @@ fn runnables_mod(sema: &Semantics<RootDatabase>, acc: &mut Vec<Runnable>, module
match submodule.definition_source(sema.db).value { match submodule.definition_source(sema.db).value {
hir::ModuleSource::Module(_) => runnables_mod(sema, acc, submodule), hir::ModuleSource::Module(_) => runnables_mod(sema, acc, submodule),
hir::ModuleSource::SourceFile(_) => mark::hit!(dont_recurse_in_outline_submodules), hir::ModuleSource::SourceFile(_) => mark::hit!(dont_recurse_in_outline_submodules),
hir::ModuleSource::BlockExpr(_) => {} // inner items aren't runnable
} }
} }
} }

View file

@ -228,6 +228,15 @@ impl Definition {
// so do nothing. // so do nothing.
} }
} }
ModuleSource::BlockExpr(b) => {
if is_first {
let range = Some(b.syntax().text_range());
res.insert(file_id, range);
} else {
// We have already added the enclosing file to the search scope,
// so do nothing.
}
}
ModuleSource::SourceFile(_) => { ModuleSource::SourceFile(_) => {
res.insert(file_id, None); res.insert(file_id, None);
} }
@ -257,6 +266,7 @@ impl Definition {
let mut res = FxHashMap::default(); let mut res = FxHashMap::default();
let range = match module_src.value { let range = match module_src.value {
ModuleSource::Module(m) => Some(m.syntax().text_range()), ModuleSource::Module(m) => Some(m.syntax().text_range()),
ModuleSource::BlockExpr(b) => Some(b.syntax().text_range()),
ModuleSource::SourceFile(_) => None, ModuleSource::SourceFile(_) => None,
}; };
res.insert(file_id, range); res.insert(file_id, range);