aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/macros.rs
blob: 050b97081f214fd5d173ee8e8539128c135214ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use std::sync::Arc;

use ra_db::SyntaxDatabase;
use ra_syntax::{TextRange, TextUnit, SourceFileNode, AstNode, ast};

// Hard-coded defs for now :-(
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum MacroDef {
    CTry,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MacroInput {
    // Should be token trees
    text: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MacroExpansion {
    text: String,
    ranges_map: Vec<(TextRange, TextRange)>,
}

salsa::query_group! {

pub trait MacrosDatabase: SyntaxDatabase {
    fn expand_macro(def: MacroDef, input: MacroInput) -> Option<Arc<MacroExpansion>> {
        type ExpandMacroQuery;
    }
}

}

fn expand_macro(
    _db: &impl MacrosDatabase,
    def: MacroDef,
    input: MacroInput,
) -> Option<Arc<MacroExpansion>> {
    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 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 };
    Some(Arc::new(res))
}