Skip to content

Commit 1326b18

Browse files
authored
fix: autocomplete supports adding extensions (#156)
1 parent 2cffc07 commit 1326b18

File tree

4 files changed

+84
-12
lines changed

4 files changed

+84
-12
lines changed

core/deno_normalize_import_statement.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,19 @@ test("core / deno_normalize_import_statement", () => {
6060
`import { example } from "https://example.com/foo/bar.ts";`
6161
)
6262
).toEqual(`import { example } from "https://example.com/foo/bar.ts";`);
63+
64+
expect(
65+
normalizeImportStatement(__filename, `import { example } from "./deno";`)
66+
).toEqual(`import { example } from "./deno.ts";`);
67+
68+
expect(
69+
normalizeImportStatement(
70+
__filename,
71+
`import { example } from "./testdata/file_walker/a";`
72+
)
73+
).toEqual(`import { example } from "./testdata/file_walker/a.js";`);
74+
75+
expect(
76+
normalizeImportStatement(__filename, `import { example } from "./none";`)
77+
).toEqual(`import { example } from "./none";`);
6378
});

core/deno_normalize_import_statement.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ import * as path from "path";
22

33
import { getDenoDepsDir } from "./deno";
44
import { CacheModule } from "./deno_cache";
5-
import { normalizeFilepath } from "./util";
5+
import { normalizeFilepath, findNonExtensionModule } from "./util";
66
import { Logger } from "./logger";
77

88
/**
99
* Normalize import statement
10-
* @param importStatement eg. `import { path } from "../../../../Library/Caches/deno/deps/https/example.com/da88efaa8b70cda7903ddc29b8d4c6ea3015de65329ea393289f4104ae2da941"`
11-
* @returns string eg. `https://example.com/demo/sub/mod.ts`
10+
* eg. `import { path } from "../../../../Library/Caches/deno/deps/https/example.com/da88efaa8b70cda7903ddc29b8d4c6ea3015de65329ea393289f4104ae2da941"`
11+
* eg. `import { foo } from "./bar"`
12+
* @param importStatement
13+
* eg. `import { path } from "https://example.com/demo/sub/mod.ts"`
14+
* eg. `import { foo } from "./bar.ts"`
15+
* @returns string
1216
*/
1317
export function normalizeImportStatement(
1418
filename: string,
@@ -31,26 +35,28 @@ export function normalizeImportStatement(
3135
? moduleFilepath
3236
: path.resolve(path.dirname(filename), moduleFilepath)
3337
);
34-
const rest = matcher[3];
38+
const rest = matcher[3] || "";
3539

3640
/* istanbul ignore next */
3741
logger?.info(
3842
`normalize import \`${importStatement}\` in file \`${filename}\` with module \`${moduleAbsoluteFilepath}\``
3943
);
4044

41-
/* istanbul ignore else */
4245
if (moduleAbsoluteFilepath.startsWith(getDenoDepsDir())) {
4346
const cache = CacheModule.create(moduleAbsoluteFilepath);
4447
/* istanbul ignore else */
4548
if (cache) {
46-
importStatement = `import ${importModuleNames} from "${
47-
cache.meta.url
48-
}"${
49-
/* istanbul ignore next */
50-
rest ? rest : ""
51-
}`;
49+
importStatement = `import ${importModuleNames} from "${cache.meta.url}"${rest}`;
5250
}
5351
}
52+
// if cache not found. then it should be relative path
53+
// eg. `import { foo } from "./bar"`
54+
else if (moduleName.startsWith(".")) {
55+
importStatement = `import ${importModuleNames} from "${findNonExtensionModule(
56+
filename,
57+
moduleName
58+
)}"${rest}`;
59+
}
5460
}
5561

5662
return importStatement;

core/util.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
normalizeFilepath,
88
isValidDenoDocument,
99
isUntitledDocument,
10+
findNonExtensionModule,
1011
} from "./util";
1112

1213
test("core / util / pathExists", async () => {
@@ -72,3 +73,12 @@ test("core / util / isUntitledDocument", () => {
7273
expect(isUntitledDocument("../bar")).toBe(false);
7374
expect(isUntitledDocument("untitled: ")).toBe(true);
7475
});
76+
77+
test("core / util / findNonExtensionModule", () => {
78+
expect(findNonExtensionModule(__filename, "./deno")).toBe("./deno.ts");
79+
expect(findNonExtensionModule(__filename, "./logger")).toBe("./logger.ts");
80+
expect(findNonExtensionModule(__filename, "./testdata/file_walker/a")).toBe(
81+
"./testdata/file_walker/a.js"
82+
);
83+
expect(findNonExtensionModule(__filename, "./none")).toBe("./none");
84+
});

core/util.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { promises as fs, statSync } from "fs";
22
import crypto from "crypto";
3-
import * as path from "path";
3+
import path from "path";
44

55
export function pathExistsSync(filepath: string): boolean {
66
try {
@@ -80,3 +80,44 @@ export function isUntitledDocument(filename: string): boolean {
8080
// In vscode, tsserver may crash because a temporary document is not saved
8181
return /^untitled:/.test(filename);
8282
}
83+
84+
/**
85+
* find module which has no extension name
86+
* We hope it can find the module correctly in Deno's way
87+
* eg. `import { foo } from "./bar"` should be `import { foo } from "./bar.ts"`
88+
* @param filepath
89+
* @param moduleName
90+
*/
91+
export function findNonExtensionModule(
92+
filepath: string,
93+
moduleName: string
94+
): string {
95+
function resolveModule(modulePath: string): string | void {
96+
if (pathExistsSync(path.resolve(path.dirname(filepath), modulePath))) {
97+
return modulePath;
98+
}
99+
100+
return;
101+
}
102+
103+
const denoSupportedExtensions = [
104+
".ts",
105+
".tsx",
106+
".d.ts",
107+
".js",
108+
".jsx",
109+
".mjs",
110+
];
111+
112+
while (denoSupportedExtensions.length) {
113+
const extension = denoSupportedExtensions.shift();
114+
115+
const modulePath = resolveModule(moduleName + extension);
116+
117+
if (modulePath) {
118+
return modulePath;
119+
}
120+
}
121+
122+
return moduleName;
123+
}

0 commit comments

Comments
 (0)