use emmylua_code_analysis::{
EmmyLuaAnalysis, WorkspaceFolder, build_workspace_folders, collect_workspace_files,
file_path_to_uri, load_configs, uri_to_file_path,
};
use fern::Dispatch;
use log::LevelFilter;
use std::path::{Path, PathBuf};
fn root_from_configs(config_paths: &[PathBuf], fallback: &Path) -> PathBuf {
if config_paths.len() != 1 {
fallback.to_path_buf()
} else {
let config_path = &config_paths[0];
match config_path.canonicalize() {
Ok(path) => normalize_local_path(path.parent().unwrap().to_path_buf()),
Err(err) => {
log::error!(
"Failed to canonicalize config path: \"{:?}\": {}",
config_path,
err
);
fallback.to_path_buf()
}
}
}
}
pub fn setup_logger(verbose: bool) {
let logger = Dispatch::new()
.format(move |out, message, record| {
let (color, reset) = match record.level() {
log::Level::Error => ("\x1b[31m", "\x1b[0m"), log::Level::Warn => ("\x1b[33m", "\x1b[0m"), log::Level::Info | log::Level::Debug | log::Level::Trace => ("", ""),
};
out.finish(format_args!(
"{}{}: {}{}",
color,
record.level(),
if verbose {
format!("({}) {}", record.target(), message)
} else {
message.to_string()
},
reset
))
})
.level(if verbose {
LevelFilter::Info
} else {
LevelFilter::Warn
})
.chain(std::io::stderr());
if let Err(e) = logger.apply() {
eprintln!("Failed to apply logger: {:?}", e);
}
}
pub async fn load_workspace(
main_path: PathBuf,
cmd_workspace_folders: Vec<PathBuf>,
config_paths: Option<Vec<PathBuf>>,
ignore: Option<Vec<String>>,
) -> Option<EmmyLuaAnalysis> {
let main_path = normalize_local_path(main_path);
let cmd_workspace_folders = cmd_workspace_folders
.into_iter()
.map(normalize_local_path)
.collect::<Vec<_>>();
let (config_files, config_root): (Vec<PathBuf>, PathBuf) =
if let Some(config_paths) = config_paths {
(
config_paths.clone(),
root_from_configs(&config_paths, &main_path),
)
} else {
(
vec![
main_path.join(".luarc.json"),
main_path.join(".emmyrc.json"),
]
.into_iter()
.filter(|path| path.exists())
.collect(),
main_path.clone(),
)
};
let mut emmyrc = load_configs(config_files, None);
log::info!(
"Pre processing configurations using root: \"{}\"",
config_root.display()
);
emmyrc.pre_process_emmyrc(&config_root);
let workspace_folders = cmd_workspace_folders
.iter()
.map(|path| WorkspaceFolder::new(path.clone(), false))
.collect::<Vec<WorkspaceFolder>>();
let mut analysis = EmmyLuaAnalysis::new();
analysis.update_config(emmyrc.clone().into());
analysis.init_std_lib(None);
let workspace_folders = build_workspace_folders(&workspace_folders, &emmyrc);
for workspace in &workspace_folders {
if workspace.is_library {
analysis.add_library_workspace(workspace);
} else {
analysis.add_main_workspace(workspace.root.clone());
}
}
let file_infos = collect_workspace_files(&workspace_folders, &analysis.emmyrc, None, ignore);
let files = file_infos
.into_iter()
.map(|file| file.into_tuple())
.collect();
analysis.update_files_by_path(files);
Some(analysis)
}
pub(crate) fn normalize_local_path(path: PathBuf) -> PathBuf {
let path = path.canonicalize().unwrap_or(path);
file_path_to_uri(&path)
.and_then(|uri| uri_to_file_path(&uri))
.unwrap_or(path)
}