aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/src/db.rs18
-rw-r--r--crates/ra_analysis/src/extend_selection.rs4
-rw-r--r--crates/ra_analysis/src/lib.rs1
-rw-r--r--crates/ra_analysis/src/macros.rs32
-rw-r--r--crates/ra_analysis/src/syntax_highlighting.rs2
-rw-r--r--crates/ra_hir/src/db.rs7
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/macros.rs146
8 files changed, 127 insertions, 85 deletions
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index 712f72484..2a71cc2b6 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -1,7 +1,6 @@
1use std::{fmt, sync::Arc}; 1use std::{fmt, sync::Arc};
2use salsa::{self, Database}; 2use salsa::{self, Database};
3use ra_db::{LocationIntener, BaseDatabase}; 3use ra_db::{LocationIntener, BaseDatabase};
4use hir::{self, DefId, DefLoc};
5 4
6use crate::{ 5use crate::{
7 symbol_index, 6 symbol_index,
@@ -15,7 +14,8 @@ pub(crate) struct RootDatabase {
15 14
16#[derive(Default)] 15#[derive(Default)]
17struct IdMaps { 16struct IdMaps {
18 defs: LocationIntener<DefLoc, DefId>, 17 defs: LocationIntener<hir::DefLoc, hir::DefId>,
18 macros: LocationIntener<hir::MacroInvocationLoc, hir::MacroInvocationId>,
19} 19}
20 20
21impl fmt::Debug for IdMaps { 21impl fmt::Debug for IdMaps {
@@ -59,12 +59,18 @@ impl salsa::ParallelDatabase for RootDatabase {
59 59
60impl BaseDatabase for RootDatabase {} 60impl BaseDatabase for RootDatabase {}
61 61
62impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase { 62impl AsRef<LocationIntener<hir::DefLoc, hir::DefId>> for RootDatabase {
63 fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> { 63 fn as_ref(&self) -> &LocationIntener<hir::DefLoc, hir::DefId> {
64 &self.id_maps.defs 64 &self.id_maps.defs
65 } 65 }
66} 66}
67 67
68impl AsRef<LocationIntener<hir::MacroInvocationLoc, hir::MacroInvocationId>> for RootDatabase {
69 fn as_ref(&self) -> &LocationIntener<hir::MacroInvocationLoc, hir::MacroInvocationId> {
70 &self.id_maps.macros
71 }
72}
73
68salsa::database_storage! { 74salsa::database_storage! {
69 pub(crate) struct RootDatabaseStorage for RootDatabase { 75 pub(crate) struct RootDatabaseStorage for RootDatabase {
70 impl ra_db::FilesDatabase { 76 impl ra_db::FilesDatabase {
@@ -85,6 +91,7 @@ salsa::database_storage! {
85 fn library_symbols() for symbol_index::LibrarySymbolsQuery; 91 fn library_symbols() for symbol_index::LibrarySymbolsQuery;
86 } 92 }
87 impl hir::db::HirDatabase { 93 impl hir::db::HirDatabase {
94 fn expand_macro_invocation() for hir::db::ExpandMacroInvocationQuery;
88 fn module_tree() for hir::db::ModuleTreeQuery; 95 fn module_tree() for hir::db::ModuleTreeQuery;
89 fn fn_scopes() for hir::db::FnScopesQuery; 96 fn fn_scopes() for hir::db::FnScopesQuery;
90 fn file_items() for hir::db::SourceFileItemsQuery; 97 fn file_items() for hir::db::SourceFileItemsQuery;
@@ -98,8 +105,5 @@ salsa::database_storage! {
98 fn struct_data() for hir::db::StructDataQuery; 105 fn struct_data() for hir::db::StructDataQuery;
99 fn enum_data() for hir::db::EnumDataQuery; 106 fn enum_data() for hir::db::EnumDataQuery;
100 } 107 }
101 impl hir::MacroDatabase {
102 fn expand_macro() for hir::ExpandMacroQuery;
103 }
104 } 108 }
105} 109}
diff --git a/crates/ra_analysis/src/extend_selection.rs b/crates/ra_analysis/src/extend_selection.rs
index 62133ef29..f1b77f981 100644
--- a/crates/ra_analysis/src/extend_selection.rs
+++ b/crates/ra_analysis/src/extend_selection.rs
@@ -18,12 +18,12 @@ pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRang
18} 18}
19 19
20fn extend_selection_in_macro( 20fn extend_selection_in_macro(
21 db: &RootDatabase, 21 _db: &RootDatabase,
22 source_file: &SourceFileNode, 22 source_file: &SourceFileNode,
23 frange: FileRange, 23 frange: FileRange,
24) -> Option<TextRange> { 24) -> Option<TextRange> {
25 let macro_call = find_macro_call(source_file.syntax(), frange.range)?; 25 let macro_call = find_macro_call(source_file.syntax(), frange.range)?;
26 let (off, exp) = crate::macros::expand(db, frange.file_id, macro_call)?; 26 let (off, exp) = hir::MacroDef::ast_expand(macro_call)?;
27 let dst_range = exp.map_range_forward(frange.range - off)?; 27 let dst_range = exp.map_range_forward(frange.range - off)?;
28 let dst_range = ra_editor::extend_selection(exp.syntax().borrowed(), dst_range)?; 28 let dst_range = ra_editor::extend_selection(exp.syntax().borrowed(), dst_range)?;
29 let src_range = exp.map_range_back(dst_range)? + off; 29 let src_range = exp.map_range_back(dst_range)? + off;
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index e6cfaecc3..08ecb125a 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -19,7 +19,6 @@ mod runnables;
19 19
20mod extend_selection; 20mod extend_selection;
21mod syntax_highlighting; 21mod syntax_highlighting;
22mod macros;
23 22
24use std::{fmt, sync::Arc}; 23use std::{fmt, sync::Arc};
25 24
diff --git a/crates/ra_analysis/src/macros.rs b/crates/ra_analysis/src/macros.rs
deleted file mode 100644
index 21ec36cd6..000000000
--- a/crates/ra_analysis/src/macros.rs
+++ /dev/null
@@ -1,32 +0,0 @@
1/// Begining of macro expansion.
2///
3/// This code should be moved out of ra_analysis into hir (?) ideally.
4use std::sync::Arc;
5
6use ra_syntax::{ast, AstNode, TextUnit};
7use hir::MacroDatabase;
8
9use crate::{db::RootDatabase, FileId};
10
11pub(crate) fn expand(
12 db: &RootDatabase,
13 _file_id: FileId,
14 macro_call: ast::MacroCall,
15) -> Option<(TextUnit, Arc<hir::MacroExpansion>)> {
16 let path = macro_call.path()?;
17 if path.qualifier().is_some() {
18 return None;
19 }
20 let name_ref = path.segment()?.name_ref()?;
21 if name_ref.text() != "ctry" {
22 return None;
23 }
24 let arg = macro_call.token_tree()?.syntax();
25
26 let def = hir::MacroDef::CTry;
27 let input = hir::MacroInput {
28 text: arg.text().to_string(),
29 };
30 let exp = db.expand_macro(def, input)?;
31 Some((arg.range().start(), exp))
32}
diff --git a/crates/ra_analysis/src/syntax_highlighting.rs b/crates/ra_analysis/src/syntax_highlighting.rs
index 35a4630e9..a644b3fe0 100644
--- a/crates/ra_analysis/src/syntax_highlighting.rs
+++ b/crates/ra_analysis/src/syntax_highlighting.rs
@@ -15,7 +15,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Cancelable<Vec<Hi
15 .descendants() 15 .descendants()
16 .filter_map(ast::MacroCall::cast) 16 .filter_map(ast::MacroCall::cast)
17 { 17 {
18 if let Some((off, exp)) = crate::macros::expand(db, file_id, macro_call) { 18 if let Some((off, exp)) = hir::MacroDef::ast_expand(macro_call) {
19 let mapped_ranges = ra_editor::highlight(exp.syntax().borrowed()) 19 let mapped_ranges = ra_editor::highlight(exp.syntax().borrowed())
20 .into_iter() 20 .into_iter()
21 .filter_map(|r| { 21 .filter_map(|r| {
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::{
8 SourceFileItems, SourceItemId, 8 SourceFileItems, SourceItemId,
9 query_definitions, 9 query_definitions,
10 FnScopes, 10 FnScopes,
11 macros::{MacroInvocationLoc, MacroInvocationId, MacroInput, MacroDef, MacroExpansion},
11 module::{ModuleId, ModuleTree, ModuleSource, 12 module::{ModuleId, ModuleTree, ModuleSource,
12 nameres::{ItemMap, InputModuleItems}}, 13 nameres::{ItemMap, InputModuleItems}},
13 ty::{InferenceResult, Ty}, 14 ty::{InferenceResult, Ty},
@@ -18,7 +19,13 @@ salsa::query_group! {
18 19
19pub trait HirDatabase: SyntaxDatabase 20pub trait HirDatabase: SyntaxDatabase
20 + AsRef<LocationIntener<DefLoc, DefId>> 21 + AsRef<LocationIntener<DefLoc, DefId>>
22 + AsRef<LocationIntener<MacroInvocationLoc, MacroInvocationId>>
21{ 23{
24 fn expand_macro_invocation(invoc: MacroInvocationId) -> Option<Arc<MacroExpansion>> {
25 type ExpandMacroInvocationQuery;
26 use fn crate::macros::expand_macro_invocation;
27 }
28
22 fn fn_scopes(def_id: DefId) -> Arc<FnScopes> { 29 fn fn_scopes(def_id: DefId) -> Arc<FnScopes> {
23 type FnScopesQuery; 30 type FnScopesQuery;
24 use fn query_definitions::fn_scopes; 31 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::{
46 path::{Path, PathKind}, 46 path::{Path, PathKind},
47 name::Name, 47 name::Name,
48 krate::Crate, 48 krate::Crate,
49 macros::{MacroDef, MacroInput, MacroExpansion, MacroDatabase, ExpandMacroQuery}, 49 macros::{MacroDef, MacroInput, MacroExpansion, MacroInvocationId, MacroInvocationLoc},
50 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, 50 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution},
51 function::{Function, FnScopes}, 51 function::{Function, FnScopes},
52 adt::{Struct, Enum}, 52 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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::{SyntaxDatabase, LocalSyntaxPtr}; 3use ra_db::{LocalSyntaxPtr, LocationIntener};
4use ra_syntax::{ 4use ra_syntax::{
5 TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode, 5 TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode,
6 ast, 6 ast,
7}; 7};
8 8
9use crate::{SourceRootId, module::ModuleId, SourceItemId, HirDatabase};
10
11/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
12/// in a specific module.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub struct MacroInvocationId(u32);
15ra_db::impl_numeric_id!(MacroInvocationId);
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub struct MacroInvocationLoc {
19 source_root_id: SourceRootId,
20 module_id: ModuleId,
21 source_item_id: SourceItemId,
22}
23
24impl MacroInvocationId {
25 pub(crate) fn loc(
26 self,
27 db: &impl AsRef<LocationIntener<MacroInvocationLoc, MacroInvocationId>>,
28 ) -> MacroInvocationLoc {
29 db.as_ref().id2loc(self)
30 }
31}
32
33impl MacroInvocationLoc {
34 #[allow(unused)]
35 pub(crate) fn id(
36 &self,
37 db: &impl AsRef<LocationIntener<MacroInvocationLoc, MacroInvocationId>>,
38 ) -> MacroInvocationId {
39 db.as_ref().loc2id(&self)
40 }
41}
42
9// Hard-coded defs for now :-( 43// Hard-coded defs for now :-(
10#[derive(Debug, Clone, PartialEq, Eq, Hash)] 44#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub enum MacroDef { 45pub enum MacroDef {
12 CTry, 46 CTry,
13} 47}
14 48
49impl MacroDef {
50 pub fn ast_expand(macro_call: ast::MacroCall) -> Option<(TextUnit, MacroExpansion)> {
51 let (def, input) = MacroDef::from_call(macro_call)?;
52 let exp = def.expand(input)?;
53 let off = macro_call.token_tree()?.syntax().range().start();
54 Some((off, exp))
55 }
56
57 fn from_call(macro_call: ast::MacroCall) -> Option<(MacroDef, MacroInput)> {
58 let def = {
59 let path = macro_call.path()?;
60 if path.qualifier().is_some() {
61 return None;
62 }
63 let name_ref = path.segment()?.name_ref()?;
64 if name_ref.text() != "ctry" {
65 return None;
66 }
67 MacroDef::CTry
68 };
69
70 let input = {
71 let arg = macro_call.token_tree()?.syntax();
72 MacroInput {
73 text: arg.text().to_string(),
74 }
75 };
76 Some((def, input))
77 }
78
79 fn expand(self, input: MacroInput) -> Option<MacroExpansion> {
80 let MacroDef::CTry = self;
81 let text = format!(
82 r"
83 fn dummy() {{
84 match {} {{
85 None => return Ok(None),
86 Some(it) => it,
87 }}
88 }}",
89 input.text
90 );
91 let file = SourceFileNode::parse(&text);
92 let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?;
93 let match_arg = match_expr.expr()?;
94 let ptr = LocalSyntaxPtr::new(match_arg.syntax());
95 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text));
96 let ranges_map = vec![(src_range, match_arg.syntax().range())];
97 let res = MacroExpansion {
98 text,
99 ranges_map,
100 ptr,
101 };
102 Some(res)
103 }
104}
105
15#[derive(Debug, Clone, PartialEq, Eq, Hash)] 106#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub struct MacroInput { 107pub struct MacroInput {
17 // Should be token trees 108 // Should be token trees
@@ -25,46 +116,6 @@ pub struct MacroExpansion {
25 ptr: LocalSyntaxPtr, 116 ptr: LocalSyntaxPtr,
26} 117}
27 118
28salsa::query_group! {
29
30pub trait MacroDatabase: SyntaxDatabase {
31 fn expand_macro(def: MacroDef, input: MacroInput) -> Option<Arc<MacroExpansion>> {
32 type ExpandMacroQuery;
33 }
34}
35
36}
37
38fn expand_macro(
39 _db: &impl MacroDatabase,
40 def: MacroDef,
41 input: MacroInput,
42) -> Option<Arc<MacroExpansion>> {
43 let MacroDef::CTry = def;
44 let text = format!(
45 r"
46 fn dummy() {{
47 match {} {{
48 None => return Ok(None),
49 Some(it) => it,
50 }}
51 }}",
52 input.text
53 );
54 let file = SourceFileNode::parse(&text);
55 let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?;
56 let match_arg = match_expr.expr()?;
57 let ptr = LocalSyntaxPtr::new(match_arg.syntax());
58 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text));
59 let ranges_map = vec![(src_range, match_arg.syntax().range())];
60 let res = MacroExpansion {
61 text,
62 ranges_map,
63 ptr,
64 };
65 Some(Arc::new(res))
66}
67
68impl MacroExpansion { 119impl MacroExpansion {
69 pub fn file(&self) -> SourceFileNode { 120 pub fn file(&self) -> SourceFileNode {
70 SourceFileNode::parse(&self.text) 121 SourceFileNode::parse(&self.text)
@@ -96,3 +147,16 @@ impl MacroExpansion {
96 None 147 None
97 } 148 }
98} 149}
150
151pub(crate) fn expand_macro_invocation(
152 db: &impl HirDatabase,
153 invoc: MacroInvocationId,
154) -> Option<Arc<MacroExpansion>> {
155 let loc = invoc.loc(db);
156 let syntax = db.file_item(loc.source_item_id);
157 let syntax = syntax.borrowed();
158 let macro_call = ast::MacroCall::cast(syntax).unwrap();
159
160 let (def, input) = MacroDef::from_call(macro_call)?;
161 def.expand(input).map(Arc::new)
162}