use oxc_ast_macros::ast_meta;
use oxc_estree::{ESTree, JsonSafeString, Serializer, StructSerializer};
use crate::ast::*;
use super::Null;
#[ast_meta]
#[estree(
ts_type = "string | null",
raw_deser = "(THIS.start === 0 && THIS.end === 0) ? null : THIS.value + ''"
)]
pub struct BooleanLiteralRaw<'b>(pub &'b BooleanLiteral);
impl ESTree for BooleanLiteralRaw<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
#[expect(clippy::collection_is_never_read)] let raw = if self.0.span.is_unspanned() {
None
} else if self.0.value {
Some(JsonSafeString("true"))
} else {
Some(JsonSafeString("false"))
};
raw.serialize(serializer);
}
}
#[ast_meta]
#[estree(
ts_type = "'null' | null",
raw_deser = "(THIS.start === 0 && THIS.end === 0) ? null : 'null'",
raw_deser_inline
)]
pub struct NullLiteralRaw<'b>(pub &'b NullLiteral);
impl ESTree for NullLiteralRaw<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
#[expect(clippy::collection_is_never_read)] let raw = if self.0.span.is_unspanned() { None } else { Some(JsonSafeString("null")) };
raw.serialize(serializer);
}
}
#[ast_meta]
#[estree(
ts_type = "bigint",
raw_deser = "
const bigint = DESER[Str](POS_OFFSET.value);
BigInt(bigint)
",
raw_deser_inline
)]
pub struct BigIntLiteralValue<'a, 'b>(#[expect(dead_code)] pub &'b BigIntLiteral<'a>);
impl ESTree for BigIntLiteralValue<'_, '_> {
fn serialize<S: Serializer>(&self, mut serializer: S) {
serializer.record_fix_path();
Null(()).serialize(serializer);
}
}
#[ast_meta]
#[estree(ts_type = "string", raw_deser = "bigint", raw_deser_inline)]
pub struct BigIntLiteralBigint<'a, 'b>(pub &'b BigIntLiteral<'a>);
impl ESTree for BigIntLiteralBigint<'_, '_> {
fn serialize<S: Serializer>(&self, serializer: S) {
JsonSafeString(self.0.value.as_str()).serialize(serializer);
}
}
#[ast_meta]
#[estree(
ts_type = "RegExp | null",
raw_deser = "
let value = null;
try {
value = new RegExp(THIS.regex.pattern, THIS.regex.flags);
} catch (e) {}
value
"
)]
pub struct RegExpLiteralValue<'a, 'b>(#[expect(dead_code)] pub &'b RegExpLiteral<'a>);
impl ESTree for RegExpLiteralValue<'_, '_> {
fn serialize<S: Serializer>(&self, mut serializer: S) {
serializer.record_fix_path();
Null(()).serialize(serializer);
}
}
#[ast_meta]
#[estree(
ts_type = "string",
raw_deser = "
const flagBits = DESER[u8](POS);
let flags = '';
// Alphabetical order
if (flagBits & 64) flags += 'd';
if (flagBits & 1) flags += 'g';
if (flagBits & 2) flags += 'i';
if (flagBits & 4) flags += 'm';
if (flagBits & 8) flags += 's';
if (flagBits & 16) flags += 'u';
if (flagBits & 128) flags += 'v';
if (flagBits & 32) flags += 'y';
flags
"
)]
pub struct RegExpFlagsConverter<'b>(pub &'b RegExpFlags);
impl ESTree for RegExpFlagsConverter<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
JsonSafeString(self.0.to_inline_string().as_str()).serialize(serializer);
}
}
#[ast_meta]
#[estree(raw_deser = r#"
const tail = DESER[bool](POS_OFFSET.tail),
start = IS_TS ? DESER[i32](POS_OFFSET.span.start) - 1 : DESER[i32](POS_OFFSET.span.start),
end = IS_TS ? DESER[i32](POS_OFFSET.span.end) + 2 - tail : DESER[i32](POS_OFFSET.span.end),
value = DESER[TemplateElementValue](POS_OFFSET.value);
{ type: 'TemplateElement', value, tail, start, end, ...(RANGE && { range: [start, end] }), ...(PARENT && { parent }) }
"#)]
pub struct TemplateElementConverter<'a, 'b>(pub &'b TemplateElement<'a>);
impl ESTree for TemplateElementConverter<'_, '_> {
fn serialize<S: Serializer>(&self, serializer: S) {
let element = self.0;
let mut state = serializer.serialize_struct();
state.serialize_field("type", &JsonSafeString("TemplateElement"));
state.serialize_field("value", &element.value);
state.serialize_field("tail", &element.tail);
let mut span = element.span;
if state.include_ts_fields() {
span.start -= 1;
span.end += if element.tail { 1 } else { 2 };
}
state.serialize_span(span);
state.end();
}
}