2318: Fix panic when use `Expand Macro` on `assert_eq` r=matklad a=edwin0cheng

The cause of this [bug](https://github.com/rust-analyzer/rust-analyzer/pull/2291#issuecomment-555651542) is, when calling `SourceAnalyzer::expand` when an `ast::MacroCall` which is outside of `SourceAnalyzer::node`. 

Note that if we use a node in `SourceAnalyzer::new` with a `MacroFile` file id, the resolver inside `SourceAnalyzer` still will not work properly. Another PR will need to fix it.

Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
bors[bot] 2019-11-20 13:36:19 +00:00 committed by GitHub
commit 4ef9cab41a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 9 deletions

View File

@ -405,9 +405,16 @@ impl SourceAnalyzer {
implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait)
}
pub fn expand(&self, db: &impl HirDatabase, macro_call: &ast::MacroCall) -> Option<Expansion> {
let def = self.resolve_macro_call(db, macro_call)?.id;
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(macro_call));
pub fn expand(
&self,
db: &impl HirDatabase,
macro_call: Source<&ast::MacroCall>,
) -> Option<Expansion> {
let def = self.resolve_macro_call(db, macro_call.value)?.id;
let ast_id = AstId::new(
macro_call.file_id,
db.ast_id_map(macro_call.file_id).ast_id(macro_call.value),
);
let macro_call_loc = MacroCallLoc { def, ast_id };
Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) })
}

View File

@ -55,7 +55,7 @@ pub(crate) fn descend_into_macros(
}
let source_analyzer =
hir::SourceAnalyzer::new(db, token.with_value(token.value.parent()).as_ref(), None);
let exp = source_analyzer.expand(db, &macro_call)?;
let exp = source_analyzer.expand(db, token.with_value(&macro_call))?;
exp.map_token_down(db, token.as_ref())
})
.last()

View File

@ -23,7 +23,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?;
let source = hir::Source::new(position.file_id.into(), mac.syntax());
let expanded = expand_macro_recur(db, source, &mac)?;
let expanded = expand_macro_recur(db, source, source.with_value(&mac))?;
// FIXME:
// macro expansion may lose all white space information
@ -35,10 +35,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
fn expand_macro_recur(
db: &RootDatabase,
source: hir::Source<&SyntaxNode>,
macro_call: &ast::MacroCall,
macro_call: hir::Source<&ast::MacroCall>,
) -> Option<SyntaxNode> {
let analyzer = hir::SourceAnalyzer::new(db, source, None);
let expansion = analyzer.expand(db, &macro_call)?;
let expansion = analyzer.expand(db, macro_call)?;
let macro_file_id = expansion.file_id();
let expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?;
@ -46,8 +46,8 @@ fn expand_macro_recur(
let mut replaces = FxHashMap::default();
for child in children.into_iter() {
let source = hir::Source::new(macro_file_id, source.value);
let new_node = expand_macro_recur(db, source, &child)?;
let node = hir::Source::new(macro_file_id, &child);
let new_node = expand_macro_recur(db, source, node)?;
replaces.insert(child.syntax().clone().into(), new_node.into());
}