facebook / jscodeshift

A JavaScript codemod toolkit.
https://jscodeshift.com
MIT License
9.31k stars 480 forks source link

Removing TS import alias from a TS namespace breaks TS namespace #393

Open wmluke opened 4 years ago

wmluke commented 4 years ago

Hello, I'm trying to remove all namespace alias from within a TS namespace.

Unfortunately, the output of the TS namespace body is missing open and closing brackets. I'm wondering if this somehow related to https://github.com/facebook/jscodeshift/issues/327.

Also see AST Explorer

Input

namespace Foo {

    import Bar = Foo.Bar;

    function aa(){

    }

    function bb(){

    }
}

Transform

export default function transformer(file, api) {
    const j = api.jscodeshift.withParser('ts');
    const root = j(file.source);
    root
        .find(j.TSImportEqualsDeclaration)
        .remove();
    return root.toSource();
}

Output

namespace Foo function aa(){

}

function bb(){

}

Expected

namespace Foo {

    function aaaa(){

    }

    function bbbb(){

    }

}

Thanks in advance for your time.

wmluke commented 4 years ago

I managed to workaround this issue with...

export default function transformer(file, api) {
    const j = api.jscodeshift.withParser('ts');
    const root = j(file.source);
    root
        .find(j.TSImportEqualsDeclaration)
        .forEach((p) => {
            if (p.parentPath.node.type !== 'TSModuleBlock') {
                p.prune();
                return;
            }
            // Workaround: Redeclare the TS Namespace and filter out the
            //    TS namespace aliases from the body
            // TODO: figure out how to avoid visiting namespaces that have
            //    already been visited
            // Note: have to walk up *TWO* TSModuleBlock's to get to
            //    the TSModuleDeclaration.  Is this by design?
            const tsModuleBlockPath1 = p.parentPath;
            const tsModuleBlockPath2 = tsModuleBlockPath1.parentPath;
            const tsModuleDeclarationPath = tsModuleBlockPath2.parentPath;
            tsModuleDeclarationPath.replace(j.tsModuleDeclaration.from({
                id: tsModuleDeclarationPath.node.id,
                body: j.tsModuleBlock.from({
                    body: tsModuleBlockPath2.node.body.filter((n) => {
                        return n.type !== 'TSImportEqualsDeclaration';
                    }),
                }),
            }));
        });
    return root.toSource();
}

https://astexplorer.net/#/gist/49746d4e235c42fadf00c052de47af2f/3ec54424310a849beeff687343d37052842e569b