Как удалить объемный IIFE из @ babel / template? - PullRequest
0 голосов
/ 14 января 2020

Я пытаюсь преобразовать некоторые коды Ember в React. Вот что я хочу преобразовать.

С

export default Ember.Component.extend(({
    didInsertElement() { }
});

К

export default class MyComponent extends React.Component {
    componentDidMount() { }
}

Я пишу Babel Плагин, и попробуйте заменить вызов Ember.Component.extend на узел AST, который создается методом template. Вот фрагмент кода.

babel-plugin

const { default: template } = require("@babel/template");

const code = `class TestComponent extends React.Component { 
   componentDidMount() { }
 }`;
let classDeclarationNode = template.ast(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            CallExpression(path) {
                if (!path.getSource().startsWith("Ember.Component.extend")) {
                    return;
                }
                path.replaceWith(classDeclarationNode);
            }
        }
    };
};

Выход

export default (function () {
  class TestComponent extends React.Component {
    componentDidMount() {}
  }
})();

Вместо ожидаемого В коде, который я написал выше, я получаю оператор ClassDeclaration, окруженный IIFE. Есть ли способ удалить IIFE?

Я боролся с проблемой один день, но не могу решить ее.


Кстати, я также попробовал метод parseExpression, но все еще не могу получить то, что хочу.

babel-plugin

const { parseExpression } = require('@babel/parser');

const code = `class TestComponent extends React.Component { 
    componentDidMount() { }
}`;
let expression = parseExpression(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            CallExpression(path) {
                if (!path.getSource().startsWith("Ember.Component.extend")) {
                    return;
                }
                path.replaceWith(expression);
            }
        }
    };
};

Вывод

export default (class TestComponent extends React.Component {
  componentDidMount() {}
});

Это довольно близко к правильному коду, за исключением дополнительной пары (). Есть ли способ генерировать чистый class declaration?

1 Ответ

1 голос
/ 14 января 2020

Спасибо за помощь loganfsmyth в Slack, проблема была окончательно решена. Я должен заменить узел всего export default, а не только CallExpression. Вот код.

babel-plugin

const { default: template } = require("@babel/template");

const code = `export default class TestComponent extends React.Component { 
   componentDidMount() { }
 }`;
let rootNode = template.ast(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            ExportDefaultDeclaration(path) {
                let isMatchedNode = (path.node.declaration &&
                    t.matchesPattern(path.node.declaration.callee, "Ember.Component.extend"));
                if (!isMatchedNode) {
                    return;
                }
                path.replaceWith(rootNode);
            }
        }
    };
};

Выход

export default class TestComponent extends React.Component {
  componentDidMount() {}
}

...