Skip to content

Commit 9d96652

Browse files
committed
walk and morph functions to preserve import statement along with tests
1 parent 11f9cd6 commit 9d96652

File tree

11 files changed

+172
-0
lines changed

11 files changed

+172
-0
lines changed

src/app/parser/typescript/morph.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,40 @@ describe("morph::user-defined-types", async () => {
137137
}
138138
});
139139

140+
const importDeclarationsTests: TestCase[] = [
141+
{
142+
name: "Preserve Imports",
143+
directory: "./test-data/morph-tests/imports/",
144+
}
145+
];
146+
147+
describe("morph::import-declarations", async () => {
148+
for (const testCase of importDeclarationsTests) {
149+
before(function () {
150+
setupTest(testCase);
151+
});
152+
153+
it(testCase.name, async () => {
154+
morph.preserveImportDeclarations(
155+
testCase.staleSourceFile!,
156+
testCase.freshSourceFile!,
157+
);
158+
159+
const gotStr = await prettier.format(
160+
testCase.freshSourceFile?.getFullText()!,
161+
{
162+
parser: "typescript",
163+
},
164+
);
165+
166+
assert.equal(testCase.mergedFileContents, gotStr);
167+
168+
// uncomment to update merged golden file
169+
// fs.writeFileSync(path.resolve(testCase.directory, "merged.ts"), gotStr);
170+
});
171+
}
172+
});
173+
140174
function setupTest(testCase: TestCase) {
141175
testCase.directory = path.resolve(__dirname, testCase.directory);
142176
const staleProject = new ts.Project();

src/app/parser/typescript/morph.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,29 @@ export function preserveSavedClasses(
6565
preserveNode(staleSourceClasses, freshSourceClasses, freshTsSourceFile);
6666
}
6767

68+
export function preserveImportDeclarations(
69+
staleTsSourceFile: tsMorph.SourceFile,
70+
freshTsSourceFile: tsMorph.SourceFile,
71+
) {
72+
const staleSourceImports = walk.getAllImportDeclarationsMap(staleTsSourceFile);
73+
const freshSourceImports = walk.getAllImportDeclarationsMap(freshTsSourceFile);
74+
75+
staleSourceImports.forEach((staleNode, staleNodeName) => {
76+
const freshNode = freshSourceImports.get(staleNodeName);
77+
78+
if (freshNode) {
79+
// this import statement already exists in the fresh source file
80+
// replace it with the stale import statement
81+
freshNode.replaceWithText(staleNode.getText());
82+
} else {
83+
// this import statement does not exist in the fresh source file
84+
// add it to the fresh source
85+
freshTsSourceFile.insertStatements(0, staleNode.getText());
86+
}
87+
})
88+
}
89+
90+
6891
/**
6992
* this function preservers nodes that are marked with `@save` annotation in the stale source file
7093
* if a saved node is missing in the fresh source file, it will be copied to it
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function helloWorld() {
2+
return "hello world";
3+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import * as a from "./a";
2+
import * as tsMorph from "ts-morph";
3+
import { exit } from "process";
4+
import { SemVer } from "semver";
5+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as fs from "fs";
2+
import * as path from "path";
3+
import { helloWorld } from "./a";
4+
import {
5+
SourceFile,
6+
SourceFileEmitOptions,
7+
NamespaceImport,
8+
NamedImports,
9+
NamedExports,
10+
ModuleDeclaration,
11+
} from "ts-morph";
12+
import * as process from "process";
13+
import { SemVer } from "semver";
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { helloWorld } from "./a";
2+
import {
3+
SourceFile,
4+
SourceFileEmitOptions,
5+
NamespaceImport,
6+
NamedImports,
7+
NamedExports,
8+
ModuleDeclaration,
9+
} from "ts-morph";
10+
import * as process from "process";
11+
import * as path from "path";
12+
import * as fs from "fs";
13+
14+
export function hello() {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function helloWorld() {
2+
return "hello world";
3+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import * as a from "./a";
2+
import * as tsMorph from "ts-morph";
3+
import { exit } from "process";
4+
import { SemVer } from "semver";
5+
import * as path from "path";
6+
import * as fs from "fs";
7+
8+
export function hello() {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"\"./a\"": "import * as a from \"./a\";",
3+
"\"ts-morph\"": "import * as tsMorph from \"ts-morph\";",
4+
"\"process\"": "import { exit } from \"process\";",
5+
"\"semver\"": "import { SemVer } from \"semver\";",
6+
"\"path\"": "import * as path from \"path\";",
7+
"\"fs\"": "import * as fs from \"fs\";"
8+
}

src/app/parser/typescript/walk.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,36 @@ describe("walk::user-defined-types-tests", async () => {
136136
}
137137
});
138138

139+
const importDeclarationsTests: TestCase[] = [{
140+
name: "getImportDeclarationTests",
141+
testFile: "./test-data/walk-tests/imports/got.ts",
142+
goldenFile: "./test-data/walk-tests/imports/want.json",
143+
}];
144+
145+
describe("walk::import-declarations-tests", async () => {
146+
for (const testCase of importDeclarationsTests) {
147+
before(function () {
148+
setupTestCase(testCase);
149+
});
150+
151+
it(`${testCase.name}`, function () {
152+
const project = new ts.Project();
153+
const tsSourceFile = project.addSourceFileAtPath(testCase.testFile);
154+
155+
const importsMap = tsWalk.getAllImportDeclarationsMap(tsSourceFile);
156+
const gotImports: Record<string, string> = {};
157+
158+
importsMap.forEach((importDeclaration, importName) => {
159+
gotImports[importName] = importDeclaration.getText();
160+
});
161+
162+
assert.deepEqual(testCase.goldenFileContents, gotImports);
163+
164+
// writeFileSync(testCase.goldenFile, JSON.stringify(gotImports, null, 2));
165+
});
166+
}
167+
});
168+
139169
function setupTestCase(testCase: TestCase) {
140170
testCase.testFile = path.resolve(__dirname, testCase.testFile);
141171
testCase.goldenFile = path.resolve(__dirname, testCase.goldenFile);

0 commit comments

Comments
 (0)