Skip to content

Commit 8ee57f3

Browse files
committed
Use resolveModuleNames when making an extension cache, if available. Implement loadExtension on LSHost
1 parent 9b593ec commit 8ee57f3

File tree

12 files changed

+65
-18
lines changed

12 files changed

+65
-18
lines changed

src/compiler/extensions.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ namespace ts {
3030

3131
export interface ExtensionHost extends ModuleResolutionHost {
3232
loadExtension?(name: string): any;
33+
resolveModuleNames?(moduleNames: string[], containingFile: string, loadJs?: boolean): ResolvedModule[];
3334
}
3435

3536
export interface Program {
@@ -113,11 +114,22 @@ namespace ts {
113114
};
114115
return cache;
115116

117+
// Defer to the host's `resolveModuleName` method if it has it, otherwise use it as a ModuleResolutionHost.
118+
function resolveModuleName(name: string, fromLocation: string) {
119+
if (host.resolveModuleNames) {
120+
const results = host.resolveModuleNames([name], fromLocation, /*loadJs*/true);
121+
return results && results[0];
122+
}
123+
else {
124+
return ts.resolveModuleName(name, fromLocation, options, host, /*loadJs*/true).resolvedModule;
125+
}
126+
}
127+
116128
function resolveExtensionNames(): Map<string> {
117129
const basePath = options.configFilePath || combinePaths(host.getCurrentDirectory ? host.getCurrentDirectory() : "", "tsconfig.json");
118130
const extMap: Map<string> = {};
119131
forEach(extensionNames, name => {
120-
const resolved = resolveModuleName(name, basePath, options, host, /*loadJs*/true).resolvedModule;
132+
const resolved = resolveModuleName(name, basePath);
121133
if (resolved) {
122134
extMap[name] = resolved.resolvedFileName;
123135
}

src/compiler/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"declarationEmitter.ts",
2525
"emitter.ts",
2626
"program.ts",
27-
"extensions.ts",
27+
"extensions.ts",
2828
"commandLineParser.ts",
2929
"tsc.ts",
3030
"diagnosticInformationMap.generated.ts"

src/compiler/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2962,7 +2962,7 @@ namespace ts {
29622962
* If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just
29632963
* 'throw new Error("NotImplemented")'
29642964
*/
2965-
resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[];
2965+
resolveModuleNames?(moduleNames: string[], containingFile: string, loadJs?: boolean): ResolvedModule[];
29662966
/**
29672967
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
29682968
*/

src/harness/harnessLanguageService.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ namespace Harness.LanguageService {
216216
class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceShimHost, ts.CoreServicesShimHost {
217217
private nativeHost: NativeLanguageServiceHost;
218218

219-
public getModuleResolutionsForFile: (fileName: string) => string;
219+
public getModuleResolutionsForFile: (fileName: string, loadJs?: boolean) => string;
220220
public getTypeReferenceDirectiveResolutionsForFile: (fileName: string) => string;
221221

222222
constructor(preprocessToResolve: boolean, cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
@@ -232,12 +232,12 @@ namespace Harness.LanguageService {
232232
return scriptInfo && scriptInfo.content;
233233
}
234234
};
235-
this.getModuleResolutionsForFile = (fileName) => {
235+
this.getModuleResolutionsForFile = (fileName, loadJs) => {
236236
const scriptInfo = this.getScriptInfo(fileName);
237237
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
238238
const imports: ts.Map<string> = {};
239239
for (const module of preprocessInfo.importedFiles) {
240-
const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost);
240+
const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost, loadJs);
241241
if (resolutionInfo.resolvedModule) {
242242
imports[module.fileName] = resolutionInfo.resolvedModule.resolvedFileName;
243243
}

src/server/editorServices.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,9 @@ namespace ts.server {
124124
names: string[],
125125
containingFile: string,
126126
cache: ts.FileMap<Map<T>>,
127-
loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost) => T,
128-
getResult: (s: T) => R): R[] {
127+
loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost, loadJs?: boolean) => T,
128+
getResult: (s: T) => R,
129+
loadJs: boolean): R[] {
129130

130131
const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName);
131132
const currentResolutionsInFile = cache.get(path);
@@ -144,7 +145,7 @@ namespace ts.server {
144145
resolution = existingResolution;
145146
}
146147
else {
147-
resolution = loader(name, containingFile, compilerOptions, this.moduleResolutionHost);
148+
resolution = loader(name, containingFile, compilerOptions, this.moduleResolutionHost, loadJs);
148149
resolution.lastCheckTime = Date.now();
149150
newResolutions[name] = resolution;
150151
}
@@ -177,11 +178,11 @@ namespace ts.server {
177178
}
178179

179180
resolveTypeReferenceDirectives(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[] {
180-
return this.resolveNamesWithLocalCache(typeDirectiveNames, containingFile, this.resolvedTypeReferenceDirectives, resolveTypeReferenceDirective, m => m.resolvedTypeReferenceDirective);
181+
return this.resolveNamesWithLocalCache(typeDirectiveNames, containingFile, this.resolvedTypeReferenceDirectives, resolveTypeReferenceDirective, m => m.resolvedTypeReferenceDirective, /*loadJs*/false);
181182
}
182183

183-
resolveModuleNames(moduleNames: string[], containingFile: string): ResolvedModule[] {
184-
return this.resolveNamesWithLocalCache(moduleNames, containingFile, this.resolvedModuleNames, resolveModuleName, m => m.resolvedModule);
184+
resolveModuleNames(moduleNames: string[], containingFile: string, loadJs?: boolean): ResolvedModule[] {
185+
return this.resolveNamesWithLocalCache(moduleNames, containingFile, this.resolvedModuleNames, resolveModuleName, m => m.resolvedModule, loadJs);
185186
}
186187

187188
getDefaultLibFileName() {
@@ -1377,6 +1378,13 @@ namespace ts.server {
13771378
return false;
13781379
}
13791380

1381+
loadExtension(name: string) {
1382+
if (!sys.loadExtension) {
1383+
throw new Error("Extension loading not implemented on the active host!");
1384+
}
1385+
return sys.loadExtension(name);
1386+
}
1387+
13801388
openConfigFile(configFilename: string, clientFileName?: string): { success: boolean, project?: Project, errors?: Diagnostic[] } {
13811389
const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(configFilename);
13821390
if (!succeeded) {

src/services/services.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ namespace ts {
11631163
* if implementation is omitted then language service will use built-in module resolution logic and get answers to
11641164
* host specific questions using 'getScriptSnapshot'.
11651165
*/
1166-
resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[];
1166+
resolveModuleNames?(moduleNames: string[], containingFile: string, loadJs?: boolean): ResolvedModule[];
11671167
resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
11681168
directoryExists?(directoryName: string): boolean;
11691169
getDirectories?(directoryName: string): string[];
@@ -3147,7 +3147,7 @@ namespace ts {
31473147
}
31483148

31493149
if (host.resolveModuleNames) {
3150-
compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile);
3150+
compilerHost.resolveModuleNames = (moduleNames, containingFile, loadJs) => host.resolveModuleNames(moduleNames, containingFile, loadJs);
31513151
}
31523152
if (host.resolveTypeReferenceDirectives) {
31533153
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile) => {

src/services/shims.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ namespace ts {
6767
getProjectVersion?(): string;
6868
useCaseSensitiveFileNames?(): boolean;
6969

70-
getModuleResolutionsForFile?(fileName: string): string;
70+
getModuleResolutionsForFile?(fileName: string, loadJs?: boolean): string;
7171
getTypeReferenceDirectiveResolutionsForFile?(fileName: string): string;
7272
directoryExists(directoryName: string): boolean;
7373
}
@@ -303,16 +303,16 @@ namespace ts {
303303
private loggingEnabled = false;
304304
private tracingEnabled = false;
305305

306-
public resolveModuleNames: (moduleName: string[], containingFile: string) => ResolvedModule[];
306+
public resolveModuleNames: (moduleName: string[], containingFile: string, loadJs?: boolean) => ResolvedModule[];
307307
public resolveTypeReferenceDirectives: (typeDirectiveNames: string[], containingFile: string) => ResolvedTypeReferenceDirective[];
308308
public directoryExists: (directoryName: string) => boolean;
309309

310310
constructor(private shimHost: LanguageServiceShimHost) {
311311
// if shimHost is a COM object then property check will become method call with no arguments.
312312
// 'in' does not have this effect.
313313
if ("getModuleResolutionsForFile" in this.shimHost) {
314-
this.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
315-
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
314+
this.resolveModuleNames = (moduleNames: string[], containingFile: string, loadJs?: boolean) => {
315+
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile, loadJs));
316316
return map(moduleNames, name => {
317317
const result = lookUp(resolutionsInFile, name);
318318
return result ? { resolvedFileName: result } : undefined;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//// [hello.ts]
2+
console.log("Hello, world!");/*EOL*/
3+
4+
//// [hello.js]
5+
console.log("Hello, world!"); /*EOL*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//// [hello.ts]
2+
console.log("Hello, world!");/*EOL*/
3+
4+
//// [hello.js]
5+
console.log("Hello, world!"); /*EOL*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log("loaded");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "dummy",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"author": ""
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"inputFiles": [
3+
"hello.ts"
4+
],
5+
"availableExtensions": ["dummy"],
6+
"compilerOptions": {
7+
"extensions": ["dummy"]
8+
}
9+
}

0 commit comments

Comments
 (0)