codemodsquad / astx

Super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring
MIT License
104 stars 6 forks source link

TypeError: Received an unexpected value [object Array] #6

Closed taymonbeal closed 3 years ago

taymonbeal commented 3 years ago

Repro instructions:

cat <<EOF >auction_test.ts && npx astx --parser ts \
  -f 'setFakeServerHandler(() => Promise.resolve($response));' \
  -r 'const fakeServerHandler = jasmine.createSpy<FakeServerHandler>("fakeServerHandler"); fakeServerHandler.withArgs(jasmine.objectContaining<FakeRequest>({url: new URL(biddingLogicUrl1)})).and.resolveTo($response);' \
  auction_test.ts
setFakeServerHandler(() =>
  Promise.resolve({
    headers: javaScriptHeaders,
    body: [
      "function generateBid() {",
      "  return { bid: 0.03, render: 'about:blank#1' };",
      "}",
    ].join("\n"),
  })
);
EOF

Full output:

npx: installed 291 in 16.171s
==========================================
auction_test.ts
==========================================
TypeError: Received an unexpected value [object Array]
    at fromAST (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/node_modules/jscodeshift/src/core.js:70:9)
    at core (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/node_modules/jscodeshift/src/core.js:45:5)
    at /home/taymon/.npm/_npx/3832/lib/node_modules/astx/replace.js:196:44
    at MatchArray.map (<anonymous>)
    at generateReplacements (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/replace.js:183:18)
    at replaceMatches (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/replace.js:205:22)
    at MatchArray.replace (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/Astx.js:75:37)
    at transformFn (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/runTransformOnFile.js:133:50)
    at _callee2$ (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/runTransformOnFile.js:156:35)
    at tryCatch (/home/taymon/.npm/_npx/3832/lib/node_modules/astx/node_modules/regenerator-runtime/runtime.js:63:40)
0 files changed
0 files unchanged
1 file errored
jedwards1211 commented 3 years ago

@taymonbeal thanks for the repro instructions!

So I need to apologize in advance that it's going to take awhile to fix this, I'm having growing pains with this project and it's been hard to clear some hurdles.

I've got WIP on a big refactor that allows using Babel toolchain (instead of jscodeshift/recast) to do the transforms, and I won't be able to completely fix this issue until I get that released (recast output is too buggy, and I'm getting tired of it. Babel code generation will be much more reliable).

And before that, I need to release a major branch I've been working on with a bunch of improvements. I partially fixed this issue on that branch, but as I mentioned, the recast output is buggy for TS, and fails to preserve the type parameters in your replacement:

  find
    with parser: babylon
      ✓ bugs_unexpectedObjectArray
    with parser: flow
      ✓ bugs_unexpectedObjectArray (45ms)
    with parser: tsx
      1) bugs_unexpectedObjectArray

  2 passing (89ms)
  1 failing

  1) find
       with parser: tsx
         bugs_unexpectedObjectArray:

      AssertionError: expected 'const fakeServerHandler = jasmine.createSpy("fakeServerHandler");\n\nfakeServerHandler\n  .withArgs(\n    jasmine.objectContaining({\n      url: new URL(biddingLogicUrl1),\n    })\n  )\n  .and.resolveTo({\n    headers: javaScriptHeaders,\n\n    body: [\n      "function generateBid() {",\n      "  return { bid: 0.03, render: \'about:blank#1\' };",\n      "}",\n    ].join("\\n"),\n  });\n' to deeply equal 'const fakeServerHandler = jasmine.createSpy<FakeServerHandler>(\n  "fakeServerHandler"\n);\n\nfakeServerHandler\n  .withArgs(\n    jasmine.objectContaining<FakeRequest>({\n      url: new URL(biddingLogicUrl1),\n    })\n  )\n  .and.resolveTo({\n    headers: javaScriptHeaders,\n\n    body: [\n      "function generateBid() {",\n      "  return { bid: 0.03, render: \'about:blank#1\' };",\n      "}",\n    ].join("\\n"),\n  });\n'
      + expected - actual

      -const fakeServerHandler = jasmine.createSpy("fakeServerHandler");
      +const fakeServerHandler = jasmine.createSpy<FakeServerHandler>(
      +  "fakeServerHandler"
      +);

       fakeServerHandler
         .withArgs(
      -    jasmine.objectContaining({
      +    jasmine.objectContaining<FakeRequest>({
             url: new URL(biddingLogicUrl1),
           })
         )
         .and.resolveTo({

      at Context.<anonymous> (test/findReplace/jscodeshift.test.ts:118:46)
      at processImmediate (internal/timers.js:456:21)

I've kind of given up on recast. I've made PRs to fix issues like this and they've languished. I'll double check if I've made a PR to fix TSTypeParameter output, but no guarantees recast will merge it anytime soon 😕 So please bear with me until I get the Babel toolchain support released.

Some heads up about that:

jedwards1211 commented 3 years ago

@taymonbeal okay I was able to figure out a solution and released a beta for version 2. Can you try installing astx@beta? and use the --babel-generator option?

Unfortunately this may not preserve formatting (esp if you aren't using prettier in your project) but it's the only thing that works for your example at the moment. Without it the <FakeServerHandler> etc disappears.

Also be sure to check the breaking changes for version 2

jedwards1211 commented 3 years ago

Oh actually, looks like it works in the beta even without the --babel-generator option! But definitely give that option a try if you run into trouble.

jedwards1211 commented 3 years ago

@taymonbeal did you ever get a chance to try out my fixes?

jedwards1211 commented 3 years ago

gonna close this since it should be fixed on beta, but let me know if you have any more issues