benjamn / recast

JavaScript syntax tree transformer, nondestructive pretty-printer, and automatic source map generator
MIT License
4.95k stars 346 forks source link

insertAfter a CommentBlock or CommentLine #1341

Open mbroadst opened 1 year ago

mbroadst commented 1 year ago

Hi, I'm trying to figure out how to insert an import statement after a comment block at the top of a file. The sample input is:

/**
 * This is a code block I want to add an import statement after
 */

// something else 
const thar = 'that';

and I'd like to insert:

import {SomeClass} from 'my-module';

after the first block to produce:

/**
 * This is a code block I want to add an import statement after
 */
import {SomeClass} from 'my-module';

// something else 
const thar = 'that';

I wrote a visitor look for comments and append my import declaration, but it seems like when I run that code it doesn't change the output at all. Here's the transformer I came up with:

export default function transformer(code, { recast, parsers }) {
  const ast = recast.parse(code, { parser: parsers.esprima });
  const b = recast.types.builders;

  recast.visit(ast, {
    visitComment: function (comment) {
      comment.insertAfter(
        b.importDeclaration(
          [b.importSpecifier(b.identifier("SomeClass"))],
          b.literal("my-module")
        )
      );

      this.traverse(comment);
    }
  });

  return recast.print(ast).code;
}

(view in astexplorer)

what's more curious is that if I reduce the input script to just the top comment block, then running this transformer actually removes all the code in the input.