use crate::{CompoundExpressionChild, ExpressionNode};
use super::{
super::context::CodegenContext,
generate_simple_expression,
helpers::{prefix_identifiers_with_context, strip_ctx_for_slot_params},
};
use vize_carton::String;
#[allow(dead_code)]
pub fn generate_simple_expression_with_prefix(ctx: &CodegenContext, content: &str) -> String {
prefix_identifiers_with_context(content, ctx)
}
pub fn is_simple_member_expression(s: &str) -> bool {
crate::steps::is_event_handler_reference_expression(s)
}
#[allow(dead_code)]
pub fn is_inline_handler(exp: &ExpressionNode<'_>) -> bool {
match exp {
ExpressionNode::Simple(simple) => {
if simple.is_static {
return false;
}
let content = simple.loc.source.as_str();
if crate::steps::expression::is_function_expression(content) {
return false;
}
if crate::steps::is_simple_identifier(content) || is_simple_member_expression(content) {
return false;
}
true
}
ExpressionNode::Compound(_) => true,
}
}
pub fn generate_event_handler(
ctx: &mut CodegenContext,
exp: &ExpressionNode<'_>,
for_caching: bool,
) {
match exp {
ExpressionNode::Simple(simple) => {
if simple.is_static {
ctx.push("\"");
ctx.push(&simple.content);
ctx.push("\"");
return;
}
let processed: String = if simple.is_ref_transformed {
simple.content.clone()
} else {
let content = &simple.content;
let ts_stripped: String = if ctx.options.is_ts && content.contains(" as ") {
crate::steps::strip_typescript_from_expression(content)
} else {
content.clone()
};
if ctx.options.prefix_identifiers {
prefix_identifiers_with_context(&ts_stripped, ctx)
} else {
ts_stripped
}
};
let processed = if ctx.has_slot_params() && processed.contains("_ctx.") {
strip_ctx_for_slot_params(ctx, &processed)
} else {
processed
};
if crate::steps::expression::is_function_expression(&processed) {
ctx.push(&processed);
return;
}
if crate::steps::is_simple_identifier(&processed)
|| is_simple_member_expression(&processed)
{
if for_caching {
ctx.push("(...args) => (");
ctx.push(&processed);
ctx.push(" && ");
ctx.push(&processed);
ctx.push("(...args))");
} else {
ctx.push(&processed);
}
return;
}
if processed.contains(';') {
ctx.push("$event => {");
ctx.push(&processed);
ctx.push("}");
} else {
ctx.push("$event => (");
ctx.push(&processed);
ctx.push(")");
}
}
ExpressionNode::Compound(comp) => {
for child in comp.children.iter() {
match child {
CompoundExpressionChild::Simple(exp) => {
generate_simple_expression(ctx, exp);
}
CompoundExpressionChild::String(s) => {
ctx.push(s);
}
CompoundExpressionChild::Symbol(helper) => {
ctx.push(ctx.helper(*helper));
}
_ => {}
}
}
}
}
}
#[cfg(test)]
#[allow(clippy::disallowed_macros)]
mod tests {
use super::generate_simple_expression_with_prefix;
use crate::codegen::context::CodegenContext;
use crate::codegen::expression::{generate_event_handler, generate_simple_expression};
use crate::options::{BindingMetadata, BindingType, CodegenOptions};
use crate::{ExpressionNode, SimpleExpressionNode, SourceLocation};
use vize_carton::{Bump, FxHashMap};
#[test]
fn test_shorthand_property_expansion() {
let mut bindings = FxHashMap::default();
bindings.insert("foo".into(), BindingType::SetupConst);
let metadata = BindingMetadata {
bindings,
props_aliases: FxHashMap::default(),
is_script_setup: true,
};
let options = CodegenOptions {
inline: false,
binding_metadata: Some(metadata),
..Default::default()
};
let ctx = CodegenContext::new(options);
let result = generate_simple_expression_with_prefix(&ctx, "{ foo }");
insta::assert_snapshot!(result.as_str());
}
#[test]
fn test_assignment_setup_let_adds_value() {
let mut bindings = FxHashMap::default();
bindings.insert("count".into(), BindingType::SetupLet);
let metadata = BindingMetadata {
bindings,
props_aliases: FxHashMap::default(),
is_script_setup: true,
};
let options = CodegenOptions {
inline: false,
binding_metadata: Some(metadata),
..Default::default()
};
let ctx = CodegenContext::new(options);
let result = generate_simple_expression_with_prefix(&ctx, "count = count + 1");
insta::assert_snapshot!(result.as_str());
}
#[test]
fn test_assignment_setup_ref_adds_value() {
let mut bindings = FxHashMap::default();
bindings.insert("quoteId".into(), BindingType::SetupRef);
let metadata = BindingMetadata {
bindings,
props_aliases: FxHashMap::default(),
is_script_setup: true,
};
let options = CodegenOptions {
inline: false,
binding_metadata: Some(metadata),
..Default::default()
};
let ctx = CodegenContext::new(options);
let result = generate_simple_expression_with_prefix(&ctx, "quoteId = null");
insta::assert_snapshot!(result.as_str());
}
#[test]
fn test_assignment_setup_ref_inline_adds_value() {
let mut bindings = FxHashMap::default();
bindings.insert("quoteId".into(), BindingType::SetupRef);
bindings.insert("renoteTargetNote".into(), BindingType::SetupRef);
let metadata = BindingMetadata {
bindings,
props_aliases: FxHashMap::default(),
is_script_setup: true,
};
let options = CodegenOptions {
inline: true,
binding_metadata: Some(metadata),
..Default::default()
};
let ctx = CodegenContext::new(options);
let result = generate_simple_expression_with_prefix(
&ctx,
"quoteId = null; renoteTargetNote = null;",
);
insta::assert_snapshot!(result.as_str());
}
#[test]
fn test_static_string_escaping() {
let mut ctx = CodegenContext::new(CodegenOptions::default());
let exp = SimpleExpressionNode::new("Line 1\nLine 2", true, SourceLocation::STUB);
generate_simple_expression(&mut ctx, &exp);
let output = ctx.into_code();
insta::assert_snapshot!(output.as_str());
}
#[test]
fn test_generate_event_handler_keeps_ref_transformed_arrow() {
let mut bindings = FxHashMap::default();
bindings.insert("selectedFolders".into(), BindingType::SetupRef);
bindings.insert("folder".into(), BindingType::SetupRef);
let metadata = BindingMetadata {
bindings,
props_aliases: FxHashMap::default(),
is_script_setup: true,
};
let options = CodegenOptions {
inline: true,
binding_metadata: Some(metadata),
prefix_identifiers: true,
is_ts: true,
..Default::default()
};
let allocator = Bump::new();
let mut ctx = CodegenContext::new(options);
let exp = ExpressionNode::Simple(vize_carton::Box::new_in(
SimpleExpressionNode {
content: "$event => (selectedFolders.value = selectedFolders.value.filter((f) => f.id !== folder.value.id))".into(),
is_static: false,
const_type: crate::ConstantType::NotConstant,
loc: SourceLocation::STUB,
js_ast: None,
hoisted: None,
identifiers: None,
is_handler_key: true,
is_ref_transformed: true,
},
&allocator,
));
generate_event_handler(&mut ctx, &exp, true);
let output = ctx.into_code();
assert_eq!(
output.as_str(),
"$event => (selectedFolders.value = selectedFolders.value.filter((f) => f.id !== folder.value.id))"
);
}
}