From b911ee542b2f4d1cd62a655f24197856cd9b9097 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 28 Dec 2018 18:21:30 +0300 Subject: [PATCH] move macro to a separate module --- crates/ra_analysis/src/lib.rs | 1 + crates/ra_analysis/src/macros.rs | 64 +++++++++++++++++++ crates/ra_analysis/src/syntax_highlighting.rs | 62 +----------------- 3 files changed, 67 insertions(+), 60 deletions(-) create mode 100644 crates/ra_analysis/src/macros.rs diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 98abe85233f..67b1c148241 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -18,6 +18,7 @@ macro_rules! ctry { mod extend_selection; mod syntax_highlighting; +mod macros; use std::{fmt, sync::Arc}; diff --git a/crates/ra_analysis/src/macros.rs b/crates/ra_analysis/src/macros.rs new file mode 100644 index 00000000000..c0dd49dc873 --- /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 + } +} diff --git a/crates/ra_analysis/src/syntax_highlighting.rs b/crates/ra_analysis/src/syntax_highlighting.rs index 98551df8f45..38219da71db 100644 --- a/crates/ra_analysis/src/syntax_highlighting.rs +++ b/crates/ra_analysis/src/syntax_highlighting.rs @@ -1,4 +1,4 @@ -use ra_syntax::{ast, AstNode, SourceFileNode, TextRange}; +use ra_syntax::{ast, AstNode,}; use ra_editor::HighlightedRange; use ra_db::SyntaxDatabase; @@ -15,7 +15,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Cancelable Cancelable 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) -} - -struct MacroExpansion { - source_file: SourceFileNode, - ranges_map: Vec<(TextRange, TextRange)>, -} - -impl MacroExpansion { - fn source_file(&self) -> &SourceFileNode { - &self.source_file - } - 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 - } -} - #[cfg(test)] mod tests { use crate::mock_analysis::single_file;