TS compiler API: prevent Export. to appear on nodes where there is not a export modifier

本秂侑毒 提交于 2021-02-10 17:35:33

问题


in js an exported variable is declared like: "Exports.my_var = cool_value ",

when using the Typyscript compiler api i have some varibales that originally have the export modifier like:

export let a = 1;
a = a + 1;

that resolves in

Exports.a = 1;
Exports.a = Exports.a + 1;

but i don't want them to be exported in the js file, i tried removing the export modifiers on the nodes, but they are still compiled with the Exports.

[UPDATE]

some example code

Transformer:

 ast = VisitNode(ast,function() {
                let visitor = (n) => {
                    console.log('VISITING',n.kind);
                    if(n.modifiers) {
                        n.modifiers = undefined;
                        console.log(n.modifiers);
                    }

                    return visitEachChild(n,visitor,ctx);
                }

                return visitor;
            }());

 return ast;

VisitNode and visitEachChild are custom function, but work as the ts. ones.

test.ts:

export let a = 30;
export let z = 10;

z = z + a;
a = a + z;
export let c = 'hello';
c = 'hey there';

output:

exports.a = 30;
exports.z = 10;
exports.z = exports.z + exports.a;
exports.a = exports.a + exports.z;
exports.c = 'hello';
exports.c = 'hey there';

回答1:


It seems one way to do it is to set all the identifiers to have a LocalName emit flag and remove the internal externalModuleIndicator property on the source file.

const transformer = <T extends ts.Node>(context: ts.TransformationContext) =>
    (rootNode: T) => {
        function visit(sourceFile: ts.Node): ts.Node {
            if (!ts.isSourceFile(sourceFile))
                throw new Error("This code only works with a source file.");

            // strip this internal property to get rid of `exports.__esModule = true;`
            delete (sourceFile as any).externalModuleIndicator;

            return ts.visitEachChild(sourceFile, statement => {
                // remove the export modifiers
                if (statement.modifiers) {
                    const newModifiers = statement.modifiers
                        .filter(m => m.kind !== ts.SyntaxKind.ExportKeyword);
                    statement.modifiers = ts.createNodeArray(newModifiers);
                }

                return ts.visitEachChild(statement, visitIdentifiers, context);

                function visitIdentifiers(descendant: ts.Node) {
                    if (ts.isIdentifier(descendant))
                        return ts.setEmitFlags(descendant, ts.EmitFlags.LocalName);
                    return ts.visitEachChild(descendant, visitIdentifiers, context);
                }
            }, context);
        }
        return ts.visitNode(rootNode, visit);
    };

Basically, the compiler collects all the names to export before the transformation phase, then it substitutes all the identifiers that match an exported name to have an exports. prefix. So stripping the export modifier has no effect because the compiler has already decided what names to export.



来源:https://stackoverflow.com/questions/58793176/ts-compiler-api-prevent-export-to-appear-on-nodes-where-there-is-not-a-export

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!