0

I'm working on a SWC Rust WASM plugin to transform JavaScript.

Overall SWC and its API are well designed. However currently I struggle to convert a TaggedTemplateExpression to a CallExpression like in this example:

console.log`Hello, ${name}!`;

to:

console.log("Hello, ", name, "!");

In Babel, this transformation would be relatively straightforward. Here's an example of how it might look:

const babel = require("@babel/core");

function transform({ types: t }) {
  return {
    visitor: {
      TaggedTemplateExpression(path) {
        const { tag, quasi } = path.node;

        if (
          t.isMemberExpression(tag) &&
          t.isIdentifier(tag.object, { name: "console" }) &&
          t.isIdentifier(tag.property, { name: "log" })
        ) {
          let args = [];

          quasi.quasis.forEach((element, index) => {
            args.push(t.stringLiteral(element.value.raw));
            if (index < quasi.expressions.length) {
              args.push(quasi.expressions[index]);
            }
          });

          path.replaceWith(
            t.callExpression(
              t.memberExpression(
                t.identifier("console"),
                t.identifier("log")
              ),
              args
            )
          );
        }
      },
    },
  };
}

I found the Changing AST Type section of the SWC CheatSheet but still I don't know how to convert it properly:

use swc_core::ecma::{
    ast::*,
    visit::{VisitMut, VisitMutWith},
};

struct TemplateToCallTransform;

impl VisitMut for TemplateToCallTransform {
    fn visit_mut_tagged_tpl(&mut self, n: &mut TaggedTpl) {=
        // How do I replace the current node with the new CallExpr?
    }
}

1 Answer 1

1

SWC author here (again).

You need to handle it from fn visit_mut_expr(&mut self, e: &mut Expr).

TaggedTpl and CallExpr both belongs to expression in ECMAScript, so you can handle it from there.


use swc_core::ecma::{
    ast::*,
    visit::{VisitMut, VisitMutWith},
};

struct TemplateToCallTransform;

impl VisitMut for TemplateToCallTransform {
    fn visit_mut_expr(&mut self, e: &mut Expr) {
        // You may skip this, depending on the requirements.
        e.visit_mut_children_with(self);

        match e {
            Expr::TaggedTpl(n) => {
                *e = Expr::Call(CallExpr {
                    // ...fields
                });
            }

            _ => {}
        }
    }
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.