use anyhow::Result;
use std::collections::HashSet;
use std::path::Path;
use super::hir::FeatureConfig;
use super::syn_walker::{analyze_modules_syn, collect_syn_module_paths};
use super::use_parser::ReExportMap;
use crate::model::{CrateExportMap, CrateInfo, ModulePathMap, ModuleTree, WorkspaceCrates};
use std::collections::HashMap;
#[cfg(feature = "hir")]
use {
super::hir::{collect_hir_module_paths, find_crate_in_workspace, load_workspace_hir},
crate::model::normalize_crate_name,
ra_ap_ide as ide,
};
#[allow(clippy::large_enum_variant)]
pub enum AnalysisBackend {
Syn { include_tests: bool },
#[cfg(feature = "hir")]
Hir {
host: ide::AnalysisHost,
vfs: ra_ap_vfs::Vfs,
},
}
impl AnalysisBackend {
#[allow(clippy::missing_errors_doc)]
pub fn new(
manifest_path: &Path,
feature_config: &FeatureConfig,
use_hir: bool,
) -> Result<Self> {
#[cfg(feature = "hir")]
if use_hir {
let (host, vfs) = load_workspace_hir(manifest_path, feature_config)?;
return Ok(Self::Hir { host, vfs });
}
let include_tests = feature_config.include_tests;
let _ = (manifest_path, use_hir);
Ok(Self::Syn { include_tests })
}
#[must_use]
pub fn collect_module_paths(&self, crate_info: &CrateInfo) -> HashSet<String> {
match self {
Self::Syn { include_tests } => {
collect_syn_module_paths(&crate_info.path, &crate_info.name, *include_tests)
}
#[cfg(feature = "hir")]
Self::Hir { host, vfs } => {
let Ok(krate) = find_crate_in_workspace(crate_info, host, vfs) else {
return HashSet::new();
};
let db = host.raw_database();
let name = normalize_crate_name(&crate_info.name);
collect_hir_module_paths(krate.root_module(db), db, &name, &name)
}
}
}
#[allow(clippy::missing_errors_doc)]
pub(crate) fn analyze_modules(
&self,
crate_info: &CrateInfo,
workspace_crates: &WorkspaceCrates,
all_module_paths: &ModulePathMap,
crate_exports: &CrateExportMap,
reexport_map: &ReExportMap,
external_crate_names: &HashMap<String, String>,
) -> Result<ModuleTree> {
match self {
Self::Syn { include_tests } => analyze_modules_syn(
crate_info,
workspace_crates,
all_module_paths,
crate_exports,
reexport_map,
external_crate_names,
*include_tests,
),
#[cfg(feature = "hir")]
Self::Hir { host, vfs } => {
let _ = reexport_map;
super::hir::analyze_modules(
crate_info,
host,
vfs,
workspace_crates,
all_module_paths,
crate_exports,
external_crate_names,
)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_backend_syn_default() {
let backend = AnalysisBackend::new(Path::new("."), &FeatureConfig::default(), false)
.expect("should create backend");
assert!(matches!(backend, AnalysisBackend::Syn { .. }));
}
#[cfg(feature = "hir")]
#[test]
fn test_backend_syn_when_hir_not_requested() {
let backend = AnalysisBackend::new(Path::new("."), &FeatureConfig::default(), false)
.expect("should create backend");
assert!(matches!(backend, AnalysisBackend::Syn { .. }));
}
}