use std::path::Path;
use hash::HashSet;
use parser::PathCollector;
use syn::visit::Visit;
mod cache;
mod error;
mod hash;
pub mod i18n;
mod manifest;
mod options;
mod parser;
mod rewriter;
mod runner;
mod walker;
pub use cache::find_project_root;
pub use error::{Error, Result};
pub use manifest::load_project_crates;
pub use options::Options;
pub use parser::{FileScope, ModuleContext, QualifiedPath, collect_file_scope};
pub use rewriter::{
RewriteResult, rewrite_modules_with_offsets, rewrite_source, rewrite_source_with_offsets,
};
pub use runner::{
ProcessSummary, find_top_level_insert_pos, find_top_level_insert_pos_with_offsets, finish_run,
format_file, process_file_with_crates, run,
};
pub use walker::scan_rs_files;
pub fn fix_source(source: &str, options: &Options) -> Result<Option<RewriteResult>> {
let syntax = syn::parse_file(source)?;
if syntax
.attrs
.iter()
.any(|a| a.path().is_ident("no_implicit_prelude"))
{
return Ok(None);
}
let mut known_crates = HashSet::default();
for &builtin in manifest::BUILTIN_CRATES {
known_crates.insert(builtin.to_string());
}
for extra in &options.extra_crates {
known_crates.insert(extra.clone());
}
Ok(fix_syntax_with_crates(
&syntax,
source,
options,
&known_crates,
))
}
pub fn fix_syntax_with_crates(
syntax: &syn::File,
source: &str,
options: &Options,
known_crates: &HashSet<String>,
) -> Option<RewriteResult> {
let scope = collect_file_scope(syntax);
let line_offsets = rewriter::compute_line_offsets(source);
let insert_pos = find_top_level_insert_pos_with_offsets(syntax, source, &line_offsets);
let has_existing_use = !scope.existing_use_paths.is_empty();
let root_module = ModuleContext {
insert_pos,
indent: String::new(),
has_existing_use,
scope,
paths: Vec::new(),
};
let mut collector =
PathCollector::new(options, known_crates, root_module, source, &line_offsets);
collector.visit_file(syntax);
let modules = collector.finish();
let has_paths = modules.iter().any(|m| !m.paths.is_empty());
if !has_paths {
return None;
}
rewriter::rewrite_modules_with_offsets(source, &line_offsets, &modules, options)
}
#[inline]
pub fn fix_str(source: &str, options: &Options) -> Result<Option<String>> {
Ok(fix_source(source, options)?.map(|r| r.content))
}
pub fn fix_file(path: &Path, options: &Options) -> Result<Option<RewriteResult>> {
let project_root = find_project_root(path);
let known_crates = manifest::load_project_crates(&project_root, &options.extra_crates);
process_file_with_crates(path, options, &known_crates)
}
#[inline]
pub fn fix_project(options: &Options) -> Result<ProcessSummary> {
run(options)
}
pub fn process_file(path: &Path, options: &Options) -> Result<Option<String>> {
let res = fix_file(path, options)?;
Ok(res.map(|r| r.content))
}