dsherret / dsherret/ts-morph

transform doesn't handle recursively transformed nodes (fix suggested)

Open
#1,471 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
6.2k
Forks
238
Avg merge
2m
Merged PRs (30d)
1

Description

So, I had this hair-brained idea to use ts-morph to wrap await around sub-expressions.

E.g. `fetch('http://example.com').json().data.x` -> `(await (await fetch('http://example.com')).json()).data.x`

**Describe the bug**

Version: 20.0.0

I get the following error attempting this

```
filePath: '/__temp___.ts',
oldText: "export default fetch('http://example.com').json().data.x",
newText: "export default (await fetch('http://example.com'))fetch('http://example.com')(await (await fetch('http://example.com')).json()).data.x"
```

**To Reproduce**

```ts
import { Project, ScriptTarget, ModuleKind, ts } from "ts-morph";

const project = new Project({
compilerOptions: {
allowJs: true,
target: ScriptTarget.ES2022,
module: ModuleKind.ES2022,
},
useInMemoryFileSystem: true,
});

const expr = `fetch('http://example.com').json().data.x`;

console.log(
project
.createSourceFile("__temp___.ts", `export default ${expr}`)
.getDefaultExportSymbol()
.getValueDeclaration()
.getChildAtIndex(2) // (BTW is there a cleaner way to make a file -> get an expression? I'm all ears.)
.transform(({ currentNode, factory, visitChildren }) => {
if (ts.isCallExpression(currentNode)) {
return factory.createParenthesizedExpression(factory.createAwaitExpression(visitChildren()));
}
return visitChildren();
})
.getFullText(),
);
```

**Expected behavior**

```
% node example.js
(await (await fetch('http://example.com')).json()).data.x
```

... as was produced after applying the following fix ... 😉

```diff
diff --git a/node_modules/ts-morph/dist/ts-morph.js b/node_modules/ts-morph/dist/ts-morph.js
index df176bd..918503f 100644
--- a/node_modules/ts-morph/dist/ts-morph.js
+++ b/node_modules/ts-morph/dist/ts-morph.js
@@ -3746,7 +3746,7 @@ class Node {
const start = oldNode.getStart(compilerSourceFile, true);
const end = oldNode.end;
let lastTransformation;
- while ((lastTransformation = transformations[transformations.length - 1]) && lastTransformation.start > start)
+ while ((lastTransformation = transformations[transformations.length - 1]) && lastTransformation.start >= start)
transformations.pop();
const wrappedNode = compilerFactory.getExistingNodeFromCompilerNode(oldNode);
transformations.push({
```

**See also**
Issue #852 / PR #853

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.