TypeScript Transformer: добавление дочернего узла к объявлению класса и изменение спецификаций c дочерних узлов - PullRequest
0 голосов
/ 26 мая 2020

Я хотел бы выполнить следующие преобразования для одного конкретного класса c с помощью специального преобразователя машинописного текста. Функция helper.isTargetClass(node) может, например, быть служебным методом для преобразования правильного класса. Но этот logi c на самом деле не является частью вопроса.

 if (ts.isClassDeclaration(node) && helper.isTargetClass(node) {
            /**
             * 1)
             * I would like to add a child to the class declaration.
             * Specifically I would like to add a static property.
             * E.g. public static instances = [];
             */

            /**
             * 2)
             * I would like to add a constructor if there is none defined
             */

            /**
             * 3)
             * I would like to insert the following line in the constructor block.
             * this.instances.push(this);
             */

            /**
             * 4)
             * I would like to to something for each method declaration.
             * Specifically on ts.isMethodDeclaration(node)
             * The use case does not matter.
             * But e.g. changing...
             *
             * public greet(): string {
             *   return "Hello";
             * }
             *
             * ... to public greet = jasmine.createSpy();
             */

            /**
             * 5)
             * I would like to do something on property declaration.
             * Specifically on ts.isPropertyDeclaration(node)
             * The use case does not matter.
             * But e.g. changing public myNumber = 7; to public myNumber = "7";
             */
        }

Я написал небольшую вспомогательную функцию для обхода дочерних узлов узла объявления класса.

export function doForEachChild(node: ts.Node, context: ts.TransformationContext, callback: (node: ts.Node) => ts.VisitResult<ts.Node>): ts.VisitResult<ts.Node> {
    const visitor: ts.Visitor = (node: ts.Node): ts.VisitResult<ts.Node> => {
        return callback(node);
    };

    return ts.visitEachChild(node, visitor, context);
}

Это могло можно использовать следующим образом:

return doForEachChild(node, context, (childNode) => {
   if (ts.isConstructorDeclaration(node)) {}
   if (ts.isMethodDeclaration(node)) {}
   if (ts.isPropertyDeclaration(node)) {}
});

Я представил этот маленький помощник, чтобы иметь возможность использовать шаблон посетителя и изменять указанные c дочерние узлы.

Я знаю, что, возможно, смогу добавьте что-нибудь в объявление класса, например:

const extendedMembers = ts.createNodeArray([createInstancesProperty(symbol.name), ...node.members]);
return ts.createClassDeclaration(node.decorators, node.modifiers, node.name, node.typeParameters, node.heritageClauses, extendedMembers);

Но я не знаю, как скомбинировать представленный материал.

Поэтому я хотел спросить, есть ли у кого-нибудь идеи или опыт работы с этим ? Есть ли хороший подход для достижения всех желаемых задач? Можно ли использовать шаблон посетителя, если я хочу вставить дочерний узел? Имеет ли смысл мой маленький помощник или есть лучший способ подойти к этому?

Эта проблема (https://github.com/madou/typescript-transformer-handbook/issues/12) решает в основном тот же вопрос. Может быть, это поможет, если мой вопрос все еще неясен.

В этом вопросе кто-то предлагает следующее:

В общем, вы в основном хотите делать это методом исключения, пока не дойдете до узел, который вы на самом деле хотите изменить, поэтому у меня может быть что-то в выражении if, которое я хочу изменить

В моем случае я действительно не хочу что-то менять; Я хотел бы кое-что вставить. Итак, да; верно, что узел, который будет изменен, будет объявлением класса. Я уже включил фрагмент кода, как это можно сделать. Но я не знаю, как я могу изменить другие вещи / выполнить другие задачи. Это немного сложно объяснить; но так или иначе; простое изменение узла (без шаблона посетителя и возвращение VisitorResult) не поможет. По крайней мере, то, что я испытал до сих пор.

Итак, основная проблема заключается в сочетании вставки дочернего узла в объявление класса и изменения других определенных c дочерних узлов.

Буду признателен за любые предложения. Заранее спасибо.

...