mirror of
https://github.com/oxalica/nil.git
synced 2025-12-23 09:19:49 +00:00
Split out ModuleKind guessing
This commit is contained in:
parent
3487ed42be
commit
ba70fc01fd
2 changed files with 79 additions and 62 deletions
76
crates/ide/src/def/kind.rs
Normal file
76
crates/ide/src/def/kind.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use smol_str::SmolStr;
|
||||
|
||||
use crate::{DefDatabase, FileId, Module};
|
||||
|
||||
use super::{BindingValue, Expr, NameId};
|
||||
|
||||
/// Guessed kind of a nix file.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ModuleKind {
|
||||
/// Uncatagorized or ambiguous.
|
||||
Unknown,
|
||||
/// Flake definition `flake.nix`.
|
||||
FlakeNix {
|
||||
/// Explicit inputs defined in top-level `inputs`.
|
||||
explicit_inputs: HashMap<SmolStr, NameId>,
|
||||
/// Implicit inputs introduced in the pat-parameter of `outputs`.
|
||||
/// NB. `self` parameter is special and is excluded here.
|
||||
param_inputs: HashMap<SmolStr, NameId>,
|
||||
},
|
||||
}
|
||||
|
||||
impl ModuleKind {
|
||||
pub(crate) fn module_kind_query(db: &dyn DefDatabase, file_id: FileId) -> Arc<ModuleKind> {
|
||||
let module = db.module(file_id);
|
||||
|
||||
// Check if it is the flake definition. This is always accurate.
|
||||
if let Some(flake_info) = db.source_root_flake_info(db.file_source_root(file_id)) {
|
||||
if flake_info.flake_file == file_id {
|
||||
return Arc::new(parse_flake_nix(&module));
|
||||
}
|
||||
}
|
||||
|
||||
Arc::new(ModuleKind::Unknown)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_flake_nix(module: &Module) -> ModuleKind {
|
||||
let mut explicit_inputs = HashMap::new();
|
||||
let mut param_inputs = HashMap::new();
|
||||
if let Expr::Attrset(flake_set) = &module[module.entry_expr()] {
|
||||
for &(name_id, value) in flake_set.statics.iter() {
|
||||
let BindingValue::Expr(value_expr) = value else { continue };
|
||||
match &*module[name_id].text {
|
||||
"inputs" => {
|
||||
let Expr::Attrset(inputs) = &module[value_expr] else { continue };
|
||||
explicit_inputs = inputs
|
||||
.statics
|
||||
.iter()
|
||||
.map(|&(input_name_id, _)| {
|
||||
(module[input_name_id].text.clone(), input_name_id)
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
"outputs" => {
|
||||
let Expr::Lambda(_, Some(pat), _) = &module[value_expr] else { continue };
|
||||
param_inputs = pat
|
||||
.fields
|
||||
.iter()
|
||||
.filter_map(|&(name_id, _)| name_id)
|
||||
.map(|name_id| (module[name_id].text.clone(), name_id))
|
||||
// Exclude `self`.
|
||||
.filter(|(name, _)| name != "self")
|
||||
.collect();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
ModuleKind::FlakeNix {
|
||||
explicit_inputs,
|
||||
param_inputs,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
mod kind;
|
||||
mod liveness;
|
||||
mod lower;
|
||||
mod nameres;
|
||||
|
|
@ -18,6 +19,7 @@ use std::ops;
|
|||
use std::sync::Arc;
|
||||
use syntax::Parse;
|
||||
|
||||
pub use self::kind::ModuleKind;
|
||||
pub use self::liveness::LivenessCheckResult;
|
||||
pub use self::nameres::{
|
||||
ModuleScopes, NameReference, NameResolution, ResolveResult, ScopeData, ScopeId,
|
||||
|
|
@ -38,6 +40,7 @@ pub trait DefDatabase: SourceDatabase {
|
|||
|
||||
fn source_map(&self, file_id: FileId) -> Arc<ModuleSourceMap>;
|
||||
|
||||
#[salsa::invoke(ModuleKind::module_kind_query)]
|
||||
fn module_kind(&self, file_id: FileId) -> Arc<ModuleKind>;
|
||||
|
||||
#[salsa::invoke(Module::module_references_query)]
|
||||
|
|
@ -407,65 +410,3 @@ impl Bindings {
|
|||
.find_map(|&(name_id, value)| (module[name_id].text == name).then_some(value))
|
||||
}
|
||||
}
|
||||
|
||||
/// Guessed kind of a nix file.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ModuleKind {
|
||||
/// Uncatagorized or ambiguous.
|
||||
Unknown,
|
||||
/// Flake definition `flake.nix`.
|
||||
FlakeNix {
|
||||
/// Explicit inputs defined in top-level `inputs`.
|
||||
explicit_inputs: HashMap<SmolStr, NameId>,
|
||||
/// Implicit inputs introduced in the pat-parameter of `outputs`.
|
||||
/// NB. `self` parameter is special and is excluded here.
|
||||
param_inputs: HashMap<SmolStr, NameId>,
|
||||
},
|
||||
}
|
||||
|
||||
fn module_kind(db: &dyn DefDatabase, file_id: FileId) -> Arc<ModuleKind> {
|
||||
let module = db.module(file_id);
|
||||
|
||||
// Check if it is the flake definition. This is always accurate.
|
||||
if let Some(flake_info) = db.source_root_flake_info(db.file_source_root(file_id)) {
|
||||
if flake_info.flake_file == file_id {
|
||||
let mut explicit_inputs = HashMap::new();
|
||||
let mut param_inputs = HashMap::new();
|
||||
if let Expr::Attrset(flake_set) = &module[module.entry_expr()] {
|
||||
for &(name_id, value) in flake_set.statics.iter() {
|
||||
let BindingValue::Expr(value_expr) = value else { continue };
|
||||
match &*module[name_id].text {
|
||||
"inputs" => {
|
||||
let Expr::Attrset(inputs) = &module[value_expr] else { continue };
|
||||
explicit_inputs = inputs
|
||||
.statics
|
||||
.iter()
|
||||
.map(|&(input_name_id, _)| {
|
||||
(module[input_name_id].text.clone(), input_name_id)
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
"outputs" => {
|
||||
let Expr::Lambda(_, Some(pat), _) = &module[value_expr] else { continue };
|
||||
param_inputs = pat
|
||||
.fields
|
||||
.iter()
|
||||
.filter_map(|&(name_id, _)| name_id)
|
||||
.map(|name_id| (module[name_id].text.clone(), name_id))
|
||||
// Exclude `self`.
|
||||
.filter(|(name, _)| name != "self")
|
||||
.collect();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Arc::new(ModuleKind::FlakeNix {
|
||||
explicit_inputs,
|
||||
param_inputs,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Arc::new(ModuleKind::Unknown)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue