From b911ee542b2f4d1cd62a655f24197856cd9b9097 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 28 Dec 2018 18:21:30 +0300 Subject: move macro to a separate module --- crates/ra_analysis/src/macros.rs | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 crates/ra_analysis/src/macros.rs (limited to 'crates/ra_analysis/src/macros.rs') diff --git a/crates/ra_analysis/src/macros.rs b/crates/ra_analysis/src/macros.rs new file mode 100644 index 000000000..c0dd49dc8 --- /dev/null +++ b/crates/ra_analysis/src/macros.rs @@ -0,0 +1,64 @@ +/// Begining of macro expansion. +/// +/// This code should be moved out of ra_analysis into hir (?) ideally. +use ra_syntax::{ast, AstNode, SourceFileNode, TextRange}; + +use crate::{db::RootDatabase, FileId}; + +pub(crate) fn expand( + _db: &RootDatabase, + _file_id: FileId, + macro_call: ast::MacroCall, +) -> Option { + 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; + } + + let arg = macro_call.token_tree()?; + let text = format!( + r" + fn dummy() {{ + match {} {{ + None => return Ok(None), + Some(it) => it, + }} + }}", + arg.syntax().text() + ); + let file = SourceFileNode::parse(&text); + let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?; + let match_arg = match_expr.expr()?; + let ranges_map = vec![(arg.syntax().range(), match_arg.syntax().range())]; + let res = MacroExpansion { + source_file: file, + ranges_map, + }; + Some(res) +} + +pub(crate) struct MacroExpansion { + pub(crate) source_file: SourceFileNode, + pub(crate) ranges_map: Vec<(TextRange, TextRange)>, +} + +impl MacroExpansion { + pub(crate) fn source_file(&self) -> &SourceFileNode { + &self.source_file + } + pub(crate) fn map_range_back(&self, tgt_range: TextRange) -> Option { + for (s_range, t_range) in self.ranges_map.iter() { + if tgt_range.is_subrange(&t_range) { + let tgt_at_zero_range = tgt_range - tgt_range.start(); + let tgt_range_offset = tgt_range.start() - t_range.start(); + let src_range = tgt_at_zero_range + tgt_range_offset + s_range.start(); + return Some(src_range); + } + } + None + } +} -- cgit v1.2.3