#![forbid(unsafe_code)]
use std::error::Error as StdError;
use std::fmt;
pub use draxl_ast as ast;
pub use draxl_ast::LowerLanguage;
pub use draxl_merge as merge;
pub use draxl_parser as parser;
pub use draxl_patch as patch;
pub use draxl_printer as printer;
pub use draxl_rust as rust;
pub use draxl_rust as lower_rust;
pub use draxl_validate as validate;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
Parse(parser::ParseError),
Validation(Vec<validate::ValidationError>),
RustImport(rust::ImportError),
}
impl Error {
pub fn validation_errors(&self) -> Option<&[validate::ValidationError]> {
match self {
Self::Validation(errors) => Some(errors),
Self::Parse(_) | Self::RustImport(_) => None,
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Parse(error) => error.fmt(f),
Self::Validation(errors) => {
f.write_str("validation failed:")?;
for error in errors {
f.write_str("\n- ")?;
f.write_str(&error.message)?;
}
Ok(())
}
Self::RustImport(error) => error.fmt(f),
}
}
}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
Self::Parse(error) => Some(error),
Self::RustImport(error) => Some(error),
Self::Validation(_) => None,
}
}
}
impl From<parser::ParseError> for Error {
fn from(error: parser::ParseError) -> Self {
Self::Parse(error)
}
}
impl From<rust::ImportError> for Error {
fn from(error: rust::ImportError) -> Self {
Self::RustImport(error)
}
}
pub fn parse_file(source: &str) -> std::result::Result<ast::File, parser::ParseError> {
parser::parse_file(source)
}
pub fn parse_file_for_language(
language: LowerLanguage,
source: &str,
) -> std::result::Result<ast::File, parser::ParseError> {
parser::parse_file_for_language(language, source)
}
pub fn validate_file(file: &ast::File) -> std::result::Result<(), Vec<validate::ValidationError>> {
validate::validate_file(file)
}
pub fn parse_and_validate(source: &str) -> Result<ast::File> {
let file = parse_file(source)?;
validate_file(&file).map_err(Error::Validation)?;
Ok(file)
}
pub fn parse_and_validate_for_language(language: LowerLanguage, source: &str) -> Result<ast::File> {
let file = parse_file_for_language(language, source)?;
validate_file(&file).map_err(Error::Validation)?;
Ok(file)
}
pub fn format_file(file: &ast::File) -> String {
printer::print_file(file)
}
pub fn format_file_for_language(language: LowerLanguage, file: &ast::File) -> String {
printer::print_file_for_language(language, file)
}
pub fn format_source(source: &str) -> Result<String> {
let file = parse_and_validate(source)?;
Ok(format_file(&file))
}
pub fn format_source_for_language(language: LowerLanguage, source: &str) -> Result<String> {
let file = parse_and_validate_for_language(language, source)?;
Ok(format_file_for_language(language, &file))
}
pub fn dump_json_file(file: &ast::File) -> String {
printer::canonicalize_file(file).to_json_pretty()
}
pub fn dump_json_source(source: &str) -> Result<String> {
let file = parse_and_validate(source)?;
Ok(dump_json_file(&file))
}
pub fn lower_rust_file(file: &ast::File) -> String {
lower_file_for_language(LowerLanguage::Rust, file)
}
pub fn lower_file_for_language(language: LowerLanguage, file: &ast::File) -> String {
match language {
LowerLanguage::Rust => lower_rust::lower_file(file),
}
}
pub fn lower_rust_source(source: &str) -> Result<String> {
lower_source_for_language(LowerLanguage::Rust, source)
}
pub fn lower_source_for_language(language: LowerLanguage, source: &str) -> Result<String> {
let file = parse_and_validate_for_language(language, source)?;
Ok(lower_file_for_language(language, &file))
}
pub fn import_rust_source(source: &str) -> Result<String> {
let imported = rust::import_source(source)?;
let printed = format_file_for_language(LowerLanguage::Rust, &imported);
let file = parse_and_validate_for_language(LowerLanguage::Rust, &printed)?;
Ok(format_file_for_language(LowerLanguage::Rust, &file))
}
pub fn apply_patch(
file: &mut ast::File,
op: patch::PatchOp,
) -> std::result::Result<(), patch::PatchError> {
apply_patch_for_language(LowerLanguage::Rust, file, op)
}
pub fn apply_patch_for_language(
language: LowerLanguage,
file: &mut ast::File,
op: patch::PatchOp,
) -> std::result::Result<(), patch::PatchError> {
patch::apply_op_for_language(language, file, op)
}
pub fn apply_patches(
file: &mut ast::File,
ops: impl IntoIterator<Item = patch::PatchOp>,
) -> std::result::Result<(), patch::PatchError> {
apply_patches_for_language(LowerLanguage::Rust, file, ops)
}
pub fn apply_patches_for_language(
language: LowerLanguage,
file: &mut ast::File,
ops: impl IntoIterator<Item = patch::PatchOp>,
) -> std::result::Result<(), patch::PatchError> {
patch::apply_ops_for_language(language, file, ops)
}
pub fn parse_patch_ops(
source: &str,
) -> std::result::Result<Vec<patch::SurfacePatchOp>, patch::PatchTextError> {
patch::parse_patch_ops(source)
}
pub fn resolve_patch_ops(
file: &ast::File,
source: &str,
) -> std::result::Result<Vec<patch::PatchOp>, patch::PatchTextError> {
resolve_patch_ops_for_language(LowerLanguage::Rust, file, source)
}
pub fn resolve_patch_ops_for_language(
language: LowerLanguage,
file: &ast::File,
source: &str,
) -> std::result::Result<Vec<patch::PatchOp>, patch::PatchTextError> {
patch::resolve_patch_ops_for_language(language, file, source)
}
pub fn apply_patch_text(
file: &mut ast::File,
source: &str,
) -> std::result::Result<(), patch::PatchTextError> {
apply_patch_text_for_language(LowerLanguage::Rust, file, source)
}
pub fn apply_patch_text_for_language(
language: LowerLanguage,
file: &mut ast::File,
source: &str,
) -> std::result::Result<(), patch::PatchTextError> {
patch::apply_patch_text_for_language(language, file, source)
}
pub fn check_hard_conflicts(
base: &ast::File,
left: &[patch::PatchOp],
right: &[patch::PatchOp],
) -> merge::HardConflictReport {
check_hard_conflicts_for_language(LowerLanguage::Rust, base, left, right)
}
pub fn check_hard_conflicts_for_language(
language: LowerLanguage,
base: &ast::File,
left: &[patch::PatchOp],
right: &[patch::PatchOp],
) -> merge::HardConflictReport {
merge::check_hard_conflicts_for_language(language, base, left, right)
}
pub fn check_hard_conflicts_json(
base: &ast::File,
left: &[patch::PatchOp],
right: &[patch::PatchOp],
) -> String {
check_hard_conflicts_json_for_language(LowerLanguage::Rust, base, left, right)
}
pub fn check_hard_conflicts_json_for_language(
language: LowerLanguage,
base: &ast::File,
left: &[patch::PatchOp],
right: &[patch::PatchOp],
) -> String {
check_hard_conflicts_for_language(language, base, left, right).to_json_pretty()
}
pub fn check_conflicts(
base: &ast::File,
left: &[patch::PatchOp],
right: &[patch::PatchOp],
) -> merge::ConflictReport {
check_conflicts_for_language(LowerLanguage::Rust, base, left, right)
}
pub fn check_conflicts_for_language(
language: LowerLanguage,
base: &ast::File,
left: &[patch::PatchOp],
right: &[patch::PatchOp],
) -> merge::ConflictReport {
merge::check_conflicts_for_language(language, base, left, right)
}
pub fn check_conflicts_json(
base: &ast::File,
left: &[patch::PatchOp],
right: &[patch::PatchOp],
) -> String {
check_conflicts_json_for_language(LowerLanguage::Rust, base, left, right)
}
pub fn check_conflicts_json_for_language(
language: LowerLanguage,
base: &ast::File,
left: &[patch::PatchOp],
right: &[patch::PatchOp],
) -> String {
check_conflicts_for_language(language, base, left, right).to_json_pretty()
}