TypeScript Transformer:将子节点添加到类声明并修改特定的子节点

时间:2020-05-25 21:29:20

标签: typescript typescript-compiler-api

我想使用自定义打字机转换器对一个特定的类进行以下转换。函数helper.isTargetClass(node)例如可以是转换正确类的实用方法。但是,这种逻辑实际上并不是问题的一部分。

 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)) {}
});

我介绍了这个小助手,以便能够使用访客模式并修改特定的子节点。

我知道我可以像这样在类声明中添加一些内容:

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)将无法解决问题。至少到目前为止我的经历。

因此,主要问题是将子节点插入类声明并修改其他特定的子节点的组合。

任何建议,我将不胜感激。预先感谢。

0 个答案:

没有答案