mirror of
https://github.com/oxalica/nil.git
synced 2024-10-27 20:44:38 +03:00
Impl incremental analysis framework
This commit is contained in:
parent
42c2333b8b
commit
fdca59f98a
331
Cargo.lock
generated
331
Cargo.lock
generated
@ -2,6 +2,337 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cbitset"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29b6ad25ae296159fb0da12b970b2fe179b234584d7cd294c891e2bbb284466b"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "countme"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dissimilar"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c97b9233581d84b8e1e689cdd3a47b6f69770084fc246e86a7f78b0d9c1d4a5"
|
||||
|
||||
[[package]]
|
||||
name = "expect-test"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dced95c9dcd4e3241f95841aad395f9c8d7933a3b0b524bdeb2440885c72a271"
|
||||
dependencies = [
|
||||
"dissimilar",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "la-arena"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d43db9f547ba2787bdeac81ef97ccc80784f385b3b39b4d50344270629a2bee3"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nil"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"expect-test",
|
||||
"la-arena",
|
||||
"rnix",
|
||||
"salsa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rnix"
|
||||
version = "0.11.0-dev"
|
||||
source = "git+https://github.com/nix-community/rnix-parser.git#f759fce8ac005ed14d13219579e62c06bdfba678"
|
||||
dependencies = [
|
||||
"cbitset",
|
||||
"rowan",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rowan"
|
||||
version = "0.15.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf980f4bf24d4ea266da37ce8f0e6bfd6eaf06120dcfba53c3e2ad6bdfe5f32b"
|
||||
dependencies = [
|
||||
"countme",
|
||||
"hashbrown",
|
||||
"memoffset",
|
||||
"rustc-hash",
|
||||
"text-size",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "salsa"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b84d9f96071f3f3be0dc818eae3327625d8ebc95b58da37d6850724f31d3403"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"indexmap",
|
||||
"lock_api",
|
||||
"log",
|
||||
"oorandom",
|
||||
"parking_lot",
|
||||
"rustc-hash",
|
||||
"salsa-macros",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "salsa-macros"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd3904a4ba0a9d0211816177fd34b04c7095443f8cdacd11175064fe541c8fe2"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "text-size"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
@ -4,3 +4,9 @@ version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
la-arena = "0.2.1"
|
||||
rnix = { git = "https://github.com/nix-community/rnix-parser.git" }
|
||||
salsa = "0.16.1"
|
||||
|
||||
[dev-dependencies]
|
||||
expect-test = "1.3.0"
|
||||
|
111
src/def/lower.rs
Normal file
111
src/def/lower.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use super::{Expr, ExprId, Literal, Module, ModuleSourceMap, Path, PathAnchor};
|
||||
use crate::source::{FileId, InFile};
|
||||
use rnix::types::{self as ast, ParsedType, TokenWrapper, TypedNode, Wrapper};
|
||||
use rnix::value::Anchor;
|
||||
use rnix::{NixValue, SyntaxNode};
|
||||
|
||||
pub(super) fn lower(root: InFile<ast::Root>) -> (Module, ModuleSourceMap) {
|
||||
let mut ctx = LowerCtx {
|
||||
file_id: root.file_id,
|
||||
module: Module::default(),
|
||||
paths: HashSet::default(),
|
||||
};
|
||||
ctx.lower_node_opt(Some(root.value.node().clone()));
|
||||
(ctx.module, ModuleSourceMap::default())
|
||||
}
|
||||
|
||||
struct LowerCtx {
|
||||
file_id: FileId,
|
||||
module: Module,
|
||||
paths: HashSet<Path>,
|
||||
}
|
||||
|
||||
impl LowerCtx {
|
||||
fn alloc_expr(&mut self, expr: Expr) -> ExprId {
|
||||
self.module.exprs.alloc(expr)
|
||||
}
|
||||
|
||||
fn alloc_missing(&mut self) -> ExprId {
|
||||
self.alloc_expr(Expr::Missing)
|
||||
}
|
||||
|
||||
fn lower_node_opt(&mut self, node: Option<SyntaxNode>) -> ExprId {
|
||||
if let Some(node) = node {
|
||||
if let Ok(expr) = ParsedType::try_from(node) {
|
||||
return self.lower_expr(expr);
|
||||
}
|
||||
}
|
||||
self.alloc_missing()
|
||||
}
|
||||
|
||||
fn lower_path(&mut self, anchor: Anchor, segments: &str) -> ExprId {
|
||||
let anchor = match anchor {
|
||||
Anchor::Relative => PathAnchor::Relative(self.file_id),
|
||||
Anchor::Absolute => todo!(),
|
||||
Anchor::Home => todo!(),
|
||||
Anchor::Store => todo!(),
|
||||
};
|
||||
let path = Path {
|
||||
anchor,
|
||||
raw_segments: segments.into(),
|
||||
};
|
||||
self.paths.insert(path.clone());
|
||||
self.alloc_expr(Expr::Literal(Literal::Path(path)))
|
||||
}
|
||||
|
||||
fn lower_expr(&mut self, expr: ParsedType) -> ExprId {
|
||||
match expr {
|
||||
ParsedType::Root(e) => self.lower_node_opt(e.inner()),
|
||||
ParsedType::Paren(e) => self.lower_node_opt(e.inner()),
|
||||
ParsedType::Ident(e) => {
|
||||
let ident = e.to_inner_string();
|
||||
self.alloc_expr(Expr::Ident(ident.into()))
|
||||
}
|
||||
ParsedType::Value(e) => match e.to_value() {
|
||||
Ok(v) => {
|
||||
let lit = match v {
|
||||
NixValue::Integer(x) => Literal::Int(x),
|
||||
NixValue::Float(_) => todo!(),
|
||||
NixValue::String(s) => Literal::String(s.into()),
|
||||
NixValue::Path(anchor, path) => return self.lower_path(anchor, &path),
|
||||
};
|
||||
self.alloc_expr(Expr::Literal(lit))
|
||||
}
|
||||
Err(_) => self.alloc_missing(),
|
||||
},
|
||||
ParsedType::Apply(e) => {
|
||||
let lam = self.lower_node_opt(e.lambda());
|
||||
let arg = self.lower_node_opt(e.value());
|
||||
self.alloc_expr(Expr::Apply(lam, arg))
|
||||
}
|
||||
ParsedType::Assert(_) => todo!(),
|
||||
ParsedType::IfElse(_) => todo!(),
|
||||
ParsedType::Select(_) => todo!(),
|
||||
ParsedType::Inherit(_) => todo!(),
|
||||
ParsedType::InheritFrom(_) => todo!(),
|
||||
ParsedType::Lambda(_) => todo!(),
|
||||
ParsedType::LegacyLet(_) => todo!(),
|
||||
ParsedType::LetIn(_) => todo!(),
|
||||
ParsedType::List(_) => todo!(),
|
||||
ParsedType::BinOp(_) => todo!(),
|
||||
ParsedType::OrDefault(_) => todo!(),
|
||||
ParsedType::AttrSet(_) => todo!(),
|
||||
ParsedType::KeyValue(_) => todo!(),
|
||||
ParsedType::Str(_) => todo!(),
|
||||
ParsedType::StrInterpol(_) => todo!(),
|
||||
ParsedType::UnaryOp(_) => todo!(),
|
||||
ParsedType::With(_) => todo!(),
|
||||
ParsedType::PathWithInterpol(_) => todo!(),
|
||||
|
||||
// Invalid nodes in expression location.
|
||||
ParsedType::Pattern(_)
|
||||
| ParsedType::PatBind(_)
|
||||
| ParsedType::PatEntry(_)
|
||||
| ParsedType::Key(_)
|
||||
| ParsedType::Dynamic(_)
|
||||
| ParsedType::Error(_) => self.alloc_missing(),
|
||||
}
|
||||
}
|
||||
}
|
89
src/def/mod.rs
Normal file
89
src/def/mod.rs
Normal file
@ -0,0 +1,89 @@
|
||||
mod lower;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::source::{FileId, SourceDatabase};
|
||||
use la_arena::{Arena, Idx};
|
||||
use std::ops;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[salsa::query_group(DefDatabaseStorage)]
|
||||
pub trait DefDatabase: SourceDatabase {
|
||||
#[salsa::invoke(Module::module_with_source_map_query)]
|
||||
fn module_with_source_map(&self, file_id: FileId) -> (Arc<Module>, Arc<ModuleSourceMap>);
|
||||
|
||||
#[salsa::invoke(Module::module_query)]
|
||||
fn module(&self, file_id: FileId) -> Arc<Module>;
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Module {
|
||||
exprs: Arena<Expr>,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
fn module_with_source_map_query(
|
||||
db: &dyn DefDatabase,
|
||||
file_id: FileId,
|
||||
) -> (Arc<Module>, Arc<ModuleSourceMap>) {
|
||||
let root = db.parse(file_id);
|
||||
let (module, source_map) = lower::lower(root);
|
||||
(Arc::new(module), Arc::new(source_map))
|
||||
}
|
||||
|
||||
fn module_query(db: &dyn DefDatabase, file_id: FileId) -> Arc<Module> {
|
||||
db.module_with_source_map(file_id).0
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<ExprId> for Module {
|
||||
type Output = Expr;
|
||||
fn index(&self, index: ExprId) -> &Self::Output {
|
||||
&self.exprs[index]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ModuleSourceMap {}
|
||||
|
||||
pub type ExprId = Idx<Expr>;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Expr {
|
||||
Missing,
|
||||
Ident(Box<str>),
|
||||
Literal(Literal),
|
||||
Apply(ExprId, ExprId),
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Literal {
|
||||
Int(i64),
|
||||
String(Box<str>),
|
||||
Path(Path),
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Path {
|
||||
pub anchor: PathAnchor,
|
||||
// Normalized path separated by `/`, with no `.` or `..` segments.
|
||||
pub raw_segments: Box<str>,
|
||||
}
|
||||
|
||||
impl Path {
|
||||
pub fn segments(&self) -> impl Iterator<Item = &str> + '_ {
|
||||
self.raw_segments.split(' ').filter(|s| !s.is_empty())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum PathAnchor {
|
||||
Relative(FileId),
|
||||
Absolute,
|
||||
Home,
|
||||
Search(Box<str>),
|
||||
}
|
51
src/def/tests.rs
Normal file
51
src/def/tests.rs
Normal file
@ -0,0 +1,51 @@
|
||||
use super::DefDatabase;
|
||||
use crate::tests::FixtureExt;
|
||||
use crate::RootDatabase;
|
||||
use expect_test::expect;
|
||||
|
||||
#[test]
|
||||
fn module_basic() {
|
||||
let (db, root_id) = RootDatabase::from_single_file(
|
||||
r#"
|
||||
foo 123 ./bar.nix
|
||||
"#,
|
||||
);
|
||||
expect![[r#"
|
||||
Module {
|
||||
exprs: Arena {
|
||||
len: 5,
|
||||
data: [
|
||||
Ident(
|
||||
"foo",
|
||||
),
|
||||
Literal(
|
||||
Int(
|
||||
123,
|
||||
),
|
||||
),
|
||||
Apply(
|
||||
Idx::<Expr>(0),
|
||||
Idx::<Expr>(1),
|
||||
),
|
||||
Literal(
|
||||
Path(
|
||||
Path {
|
||||
anchor: Relative(
|
||||
FileId(
|
||||
0,
|
||||
),
|
||||
),
|
||||
raw_segments: "./bar.nix",
|
||||
},
|
||||
),
|
||||
),
|
||||
Apply(
|
||||
Idx::<Expr>(2),
|
||||
Idx::<Expr>(3),
|
||||
),
|
||||
],
|
||||
},
|
||||
}
|
||||
"#]]
|
||||
.assert_debug_eq(&db.module(root_id));
|
||||
}
|
15
src/lib.rs
15
src/lib.rs
@ -0,0 +1,15 @@
|
||||
mod def;
|
||||
mod source;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::{def::DefDatabaseStorage, source::SourceDatabaseStorage};
|
||||
|
||||
#[salsa::database(SourceDatabaseStorage, DefDatabaseStorage)]
|
||||
#[derive(Default)]
|
||||
pub struct RootDatabase {
|
||||
storage: salsa::Storage<Self>,
|
||||
}
|
||||
|
||||
impl salsa::Database for RootDatabase {}
|
35
src/source.rs
Normal file
35
src/source.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use rnix::types as ast;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct FileId(pub u32);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub struct InFile<T> {
|
||||
pub file_id: FileId,
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
impl<T> InFile<T> {
|
||||
pub fn new(file_id: FileId, value: T) -> Self {
|
||||
Self { file_id, value }
|
||||
}
|
||||
}
|
||||
|
||||
#[salsa::query_group(SourceDatabaseStorage)]
|
||||
pub trait SourceDatabase {
|
||||
#[salsa::input]
|
||||
fn file_source_root(&self) -> FileId;
|
||||
|
||||
#[salsa::input]
|
||||
fn file_content(&self, file_id: FileId) -> Arc<[u8]>;
|
||||
|
||||
fn parse(&self, file_id: FileId) -> InFile<ast::Root>;
|
||||
}
|
||||
|
||||
fn parse(db: &dyn SourceDatabase, file_id: FileId) -> InFile<ast::Root> {
|
||||
let content = db.file_content(file_id);
|
||||
let content = std::str::from_utf8(&content).unwrap_or_default();
|
||||
let ast = rnix::parse(content);
|
||||
InFile::new(file_id, ast.root())
|
||||
}
|
14
src/tests.rs
Normal file
14
src/tests.rs
Normal file
@ -0,0 +1,14 @@
|
||||
use crate::source::{FileId, SourceDatabase};
|
||||
use crate::RootDatabase;
|
||||
|
||||
pub trait FixtureExt: Default + SourceDatabase {
|
||||
fn from_single_file(content: &str) -> (Self, FileId) {
|
||||
let mut db = Self::default();
|
||||
let root_id = FileId(0);
|
||||
db.set_file_content(root_id, content.as_bytes().into());
|
||||
db.set_file_source_root(root_id);
|
||||
(db, root_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl FixtureExt for RootDatabase {}
|
Loading…
Reference in New Issue
Block a user