From b2fec18098b6a99613012d185801fed72e424997 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 1 Jan 2019 18:11:04 +0300 Subject: move more macros to hir --- crates/ra_hir/src/db.rs | 7 +++ crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/macros.rs | 146 +++++++++++++++++++++++++++++++------------- 3 files changed, 113 insertions(+), 42 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 5a8ca3b47..242d0549d 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -8,6 +8,7 @@ use crate::{ SourceFileItems, SourceItemId, query_definitions, FnScopes, + macros::{MacroInvocationLoc, MacroInvocationId, MacroInput, MacroDef, MacroExpansion}, module::{ModuleId, ModuleTree, ModuleSource, nameres::{ItemMap, InputModuleItems}}, ty::{InferenceResult, Ty}, @@ -18,7 +19,13 @@ salsa::query_group! { pub trait HirDatabase: SyntaxDatabase + AsRef> + + AsRef> { + fn expand_macro_invocation(invoc: MacroInvocationId) -> Option> { + type ExpandMacroInvocationQuery; + use fn crate::macros::expand_macro_invocation; + } + fn fn_scopes(def_id: DefId) -> Arc { type FnScopesQuery; use fn query_definitions::fn_scopes; diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index ce750299f..1bafb1c4d 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -46,7 +46,7 @@ pub use self::{ path::{Path, PathKind}, name::Name, krate::Crate, - macros::{MacroDef, MacroInput, MacroExpansion, MacroDatabase, ExpandMacroQuery}, + macros::{MacroDef, MacroInput, MacroExpansion, MacroInvocationId, MacroInvocationLoc}, module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, function::{Function, FnScopes}, adt::{Struct, Enum}, diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs index ef6502524..f0b99cc1a 100644 --- a/crates/ra_hir/src/macros.rs +++ b/crates/ra_hir/src/macros.rs @@ -1,17 +1,108 @@ use std::sync::Arc; -use ra_db::{SyntaxDatabase, LocalSyntaxPtr}; +use ra_db::{LocalSyntaxPtr, LocationIntener}; use ra_syntax::{ TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode, ast, }; +use crate::{SourceRootId, module::ModuleId, SourceItemId, HirDatabase}; + +/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) +/// in a specific module. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct MacroInvocationId(u32); +ra_db::impl_numeric_id!(MacroInvocationId); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct MacroInvocationLoc { + source_root_id: SourceRootId, + module_id: ModuleId, + source_item_id: SourceItemId, +} + +impl MacroInvocationId { + pub(crate) fn loc( + self, + db: &impl AsRef>, + ) -> MacroInvocationLoc { + db.as_ref().id2loc(self) + } +} + +impl MacroInvocationLoc { + #[allow(unused)] + pub(crate) fn id( + &self, + db: &impl AsRef>, + ) -> MacroInvocationId { + db.as_ref().loc2id(&self) + } +} + // Hard-coded defs for now :-( #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum MacroDef { CTry, } +impl MacroDef { + pub fn ast_expand(macro_call: ast::MacroCall) -> Option<(TextUnit, MacroExpansion)> { + let (def, input) = MacroDef::from_call(macro_call)?; + let exp = def.expand(input)?; + let off = macro_call.token_tree()?.syntax().range().start(); + Some((off, exp)) + } + + fn from_call(macro_call: ast::MacroCall) -> Option<(MacroDef, MacroInput)> { + let def = { + let path = macro_call.path()?; + if path.qualifier().is_some() { + return None; + } + let name_ref = path.segment()?.name_ref()?; + if name_ref.text() != "ctry" { + return None; + } + MacroDef::CTry + }; + + let input = { + let arg = macro_call.token_tree()?.syntax(); + MacroInput { + text: arg.text().to_string(), + } + }; + Some((def, input)) + } + + fn expand(self, input: MacroInput) -> Option { + let MacroDef::CTry = self; + let text = format!( + r" + fn dummy() {{ + match {} {{ + None => return Ok(None), + Some(it) => it, + }} + }}", + input.text + ); + let file = SourceFileNode::parse(&text); + let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?; + let match_arg = match_expr.expr()?; + let ptr = LocalSyntaxPtr::new(match_arg.syntax()); + let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text)); + let ranges_map = vec![(src_range, match_arg.syntax().range())]; + let res = MacroExpansion { + text, + ranges_map, + ptr, + }; + Some(res) + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroInput { // Should be token trees @@ -25,46 +116,6 @@ pub struct MacroExpansion { ptr: LocalSyntaxPtr, } -salsa::query_group! { - -pub trait MacroDatabase: SyntaxDatabase { - fn expand_macro(def: MacroDef, input: MacroInput) -> Option> { - type ExpandMacroQuery; - } -} - -} - -fn expand_macro( - _db: &impl MacroDatabase, - def: MacroDef, - input: MacroInput, -) -> Option> { - let MacroDef::CTry = def; - let text = format!( - r" - fn dummy() {{ - match {} {{ - None => return Ok(None), - Some(it) => it, - }} - }}", - input.text - ); - let file = SourceFileNode::parse(&text); - let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?; - let match_arg = match_expr.expr()?; - let ptr = LocalSyntaxPtr::new(match_arg.syntax()); - let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text)); - let ranges_map = vec![(src_range, match_arg.syntax().range())]; - let res = MacroExpansion { - text, - ranges_map, - ptr, - }; - Some(Arc::new(res)) -} - impl MacroExpansion { pub fn file(&self) -> SourceFileNode { SourceFileNode::parse(&self.text) @@ -96,3 +147,16 @@ impl MacroExpansion { None } } + +pub(crate) fn expand_macro_invocation( + db: &impl HirDatabase, + invoc: MacroInvocationId, +) -> Option> { + let loc = invoc.loc(db); + let syntax = db.file_item(loc.source_item_id); + let syntax = syntax.borrowed(); + let macro_call = ast::MacroCall::cast(syntax).unwrap(); + + let (def, input) = MacroDef::from_call(macro_call)?; + def.expand(input).map(Arc::new) +} -- cgit v1.2.3