aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/db.rs
blob: 335c79e76da5f2010afc99a60d415e705179bbf8 (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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use std::{
    hash::Hash,
    sync::Arc,
};
use libsyntax2::{File};
use im;
use {
    FileId,
    imp::{FileResolverImp},
};

#[derive(Clone)]
pub(crate) struct Db {
    file_resolver: FileResolverImp,
    files: im::HashMap<FileId, Arc<String>>,
}

impl Db {
    pub(crate) fn new() -> Db {
        Db {
            file_resolver: FileResolverImp::default(),
            files: im::HashMap::new(),
        }
    }
    pub(crate) fn change_file(&mut self, file_id: FileId, text: Option<String>) {
        match text {
            None => {
                self.files.remove(&file_id);
            }
            Some(text) => {
                self.files.insert(file_id, Arc::new(text));
            }
        }
    }
    pub(crate) fn set_file_resolver(&mut self, file_resolver: FileResolverImp) {
        self.file_resolver = file_resolver
    }
    pub(crate) fn query_ctx(&self) -> QueryCtx {
        QueryCtx { db: self.clone() }
    }
}

pub(crate) struct QueryCtx {
    db: Db
}

impl QueryCtx {
    pub(crate) fn get<Q: Get>(&self, params: &Q::Params) -> Q::Output {
        Q::get(self, params)
    }
}

pub(crate) trait Query {
    const ID: u32;
    type Params: Hash;
    type Output;
}

pub(crate) trait Get: Query {
    fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
}

impl<T: Eval> Get for T {
    fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output {
        Self::eval(ctx, params)
    }
}

pub(crate) trait Eval: Query {
    fn eval(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
}

pub(crate) struct DbFiles {
    db: Db,
}

impl DbFiles {
    pub(crate) fn iter<'a>(&'a self) -> impl Iterator<Item=FileId> + 'a {
        self.db.files.keys().cloned()
    }
    pub(crate) fn file_resolver(&self) -> FileResolverImp {
        self.db.file_resolver.clone()
    }
}

pub(crate) enum Files {}
impl Query for Files {
    const ID: u32 = 1;
    type Params = ();
    type Output = DbFiles;
}
impl Get for Files {
    fn get(ctx: &QueryCtx, _params: &()) -> DbFiles {
        DbFiles { db: ctx.db.clone() }
    }
}

enum FileText {}
impl Query for FileText {
    const ID: u32 = 10;
    type Params = FileId;
    type Output = Arc<String>;
}
impl Get for FileText {
    fn get(ctx: &QueryCtx, file_id: &FileId) -> Arc<String> {
        ctx.db.files[file_id].clone()
    }
}

pub(crate) enum FileSyntax {}
impl Query for FileSyntax {
    const ID: u32 = 20;
    type Params = FileId;
    type Output = File;
}
impl Eval for FileSyntax {
    fn eval(ctx: &QueryCtx, file_id: &FileId) -> File {
        let text = ctx.get::<FileText>(file_id);
        File::parse(&text)
    }
}