use std::path::PathBuf;
use parser::{
expressions::ExpressionId, source_map::MapFileStore, ASTNode, ParseSettings, SourceId,
ToStringSettings,
};
use crate::error_handling::{self, TempDiagnostic};
#[cfg_attr(target_family = "wasm", derive(serde::Serialize))]
pub struct Output {
pub output_path: String,
pub content: String,
pub mappings: String,
}
#[cfg_attr(target_family = "wasm", derive(serde::Serialize))]
pub struct BuildOutput {
pub outputs: Vec<Output>,
pub temp_warnings_and_infos: Vec<TempDiagnostic>,
}
pub fn build(
content: String,
input_path: String,
output_path: String,
) -> (MapFileStore, Result<BuildOutput, Vec<TempDiagnostic>>) {
let mut fs = MapFileStore::default();
let source_id = SourceId::new(&mut fs, PathBuf::from(input_path), content.clone());
let module_result = parser::Module::from_string(
content,
ParseSettings::default(),
source_id,
None,
Default::default(),
);
let mut output = match module_result {
Ok(t) => t,
Err(parse_err) => {
let diag = TempDiagnostic {
label: parse_err.reason,
position: parse_err.position,
kind: error_handling::ErrorWarningInfo::Error,
};
return (fs, Err(vec![diag]));
}
};
let mut visitors_mut = parser::VisitorsMut {
expression_visitors_mut: vec![Box::new(InvertTernaryBranches)],
..Default::default()
};
let mut temp_errors = Vec::new();
output.0.visit_mut(
&mut visitors_mut,
&mut temp_errors,
&mut output.1.function_extractor,
&parser::VisitSettings::default(),
);
let (content, source_map) = output.0.to_string_with_source_map(
&parser::ToStringSettingsAndData(ToStringSettings::minified(), output.1.function_extractor),
&fs,
);
let output = Output { output_path, content, mappings: source_map.mappings };
(fs, Ok(BuildOutput { outputs: vec![output], temp_warnings_and_infos: temp_errors }))
}
struct InvertTernaryBranches;
impl parser::VisitorMut<parser::Expression, Vec<TempDiagnostic>> for InvertTernaryBranches {
fn visit_mut(
&mut self,
item: &mut parser::Expression,
data: &mut Vec<TempDiagnostic>,
_functions: &mut parser::extractor::ExtractedFunctions,
_chain: &parser::Chain,
) {
if let parser::Expression::TernaryExpression {
condition,
truthy_result,
falsy_result,
..
} = item
{
if let parser::Expression::UnaryOperation {
operator: parser::operators::UnaryOperator::LogicalNot,
operand,
position,
..
} = condition.as_mut()
{
let position = position.union(&falsy_result.get_position());
data.push(TempDiagnostic {
label: String::from("Ternary swapped"),
position,
kind: error_handling::ErrorWarningInfo::Info,
});
let temp_swap =
parser::Expression::Null(parser::Span::NULL_SPAN, ExpressionId::NULL);
*condition = Box::new(std::mem::replace(operand, temp_swap));
std::mem::swap(truthy_result, falsy_result);
}
}
}
}