Skip to content

Commit 74e61e5

Browse files
0xlakshanbrunocroh
andauthored
feat(rmdir-import-alias): handle rmdir import with alias (#166)
Co-authored-by: Bruno Rodrigues <[email protected]>
1 parent 7c1f32e commit 74e61e5

File tree

14 files changed

+169
-3
lines changed

14 files changed

+169
-3
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

recipes/rmdir/codemod.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
schema_version: "1.0"
22
name: "@nodejs/rmdir"
3-
version: 1.0.0
3+
version: 1.1.0
44
description: Handle DEP0147 via transforming `fs.rmdir` to `fs.rm`
55
author: Augustin Mauroy
66
license: MIT

recipes/rmdir/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nodejs/rmdir",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"description": "Handle DEP0147 via transforming `fs.rmdir` to `fs.rm` with the appropriate options.",
55
"type": "module",
66
"scripts": {

recipes/rmdir/src/workflow.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getNodeImportStatements } from "@nodejs/codemod-utils/ast-grep/import-statement";
22
import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call";
3+
import { resolveBindingPath } from "@nodejs/codemod-utils/ast-grep/resolve-binding-path";
34
import type { SgRoot, Edit } from "@codemod.com/jssg-types/main";
45

56
/**
@@ -139,6 +140,75 @@ export default function transform(root: SgRoot): string | null {
139140
hasChanges = true;
140141
}
141142

143+
// Transform named alias import when recursive set to true
144+
// @ts-ignore - ast-grep types are not fully compatible with JSSG types
145+
const importStatements = getNodeImportStatements(root, "fs");
146+
147+
for (const eachNode of importStatements) {
148+
// Get in file reference alias name (import {rmdir as foo} from "node:fs" -> foo)
149+
const referenceNameInFile = resolveBindingPath(eachNode, "$.rmdir");
150+
if (!referenceNameInFile) continue;
151+
// Get in file reference node
152+
const referenceFunctionNode = rootNode.find({
153+
rule: {
154+
any: [
155+
{
156+
pattern: `${referenceNameInFile}($PATH, $OPTIONS, $CALLBACK)`,
157+
},
158+
{
159+
pattern: `${referenceNameInFile}($PATH, $OPTIONS)`,
160+
},
161+
],
162+
},
163+
});
164+
if (!referenceFunctionNode) continue;
165+
const optionsMatch = referenceFunctionNode.getMatch("OPTIONS");
166+
if (!optionsMatch) continue;
167+
const optionsText = optionsMatch.text();
168+
if (!optionsText.includes("recursive") || !optionsText.includes("true")) {
169+
continue;
170+
}
171+
// Proceed with the change since { recursive: true }
172+
const aliasNodes = eachNode.findAll({
173+
rule: {
174+
any: [
175+
{
176+
kind: "import_specifier",
177+
all: [
178+
{
179+
has: {
180+
field: "alias",
181+
pattern: "$ALIAS",
182+
},
183+
},
184+
{
185+
has: {
186+
field: "name",
187+
pattern: "$ORIGINAL",
188+
},
189+
},
190+
],
191+
},
192+
],
193+
},
194+
});
195+
196+
for (const eachAliasNode of aliasNodes) {
197+
// Narrow down to rmdir alias
198+
if (eachAliasNode.text().includes("rmdir")) {
199+
const rmdirNode = eachAliasNode.find({
200+
rule: {
201+
pattern: "rmdir",
202+
kind: "identifier",
203+
},
204+
});
205+
// Change rmdir to rm
206+
edits.push(rmdirNode!.replace("rm"));
207+
hasChanges = true;
208+
}
209+
}
210+
}
211+
142212
// Update imports/requires only if we have destructured calls that need new imports
143213
if (needsRmImport || needsRmSyncImport) {
144214
// @ts-ignore - ast-grep types are not fully compatible with JSSG types
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { rm as foo } from "node:fs";
2+
3+
const pathName = "path/to/directory";
4+
5+
foo(pathName, { recursive: true }, () => {});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { rm as foo } from "node:fs";
2+
3+
const pathName = "path/to/directory";
4+
5+
foo(pathName, { recursive: true });
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { rmdir as foo } from "node:fs"; // should not be transformed
2+
3+
const pathName = "path/to/directory";
4+
5+
foo(pathName, { recursive: false });
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { rmdir as foo } from "node:fs"; // should not be transformed
2+
3+
const pathName = "path/to/directory";
4+
5+
foo(pathName);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {
2+
cp as copy,
3+
rm as foo,
4+
mkdirSync as makeDir,
5+
readdirSync as readDir
6+
} from "node:fs";
7+
8+
import * as fileSystem from "node:fs";
9+
10+
const sourcePath = "path/to/source";
11+
const targetPath = "path/to/target";
12+
const dirPath = "path/to/directory";
13+
14+
copy(sourcePath, targetPath, () => {
15+
console.log("File copied!");
16+
});
17+
18+
foo(dirPath, { recursive: true }, () => {
19+
console.log("Directory removed!");
20+
});
21+
22+
fileSystem.move(targetPath, "path/to/renamed", () => {
23+
console.log("File renamed!");
24+
});
25+
26+
makeDir(dirPath);
27+
28+
const files = readDir(dirPath);

recipes/rmdir/tests/input/file-3.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { rmdir as foo } from "node:fs";
2+
3+
const pathName = "path/to/directory";
4+
5+
foo(pathName, { recursive: true }, () => {});

0 commit comments

Comments
 (0)