Skip to content

Commit

Permalink
Use resolveModuleNames when making an extension cache, if available. …
Browse files Browse the repository at this point in the history
…Implement loadExtension on LSHost
  • Loading branch information
weswigham committed Aug 9, 2016
1 parent 9b593ec commit 8ee57f3
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 18 deletions.
14 changes: 13 additions & 1 deletion src/compiler/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ namespace ts {

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

export interface Program {
Expand Down Expand Up @@ -113,11 +114,22 @@ namespace ts {
};
return cache;

// Defer to the host's `resolveModuleName` method if it has it, otherwise use it as a ModuleResolutionHost.
function resolveModuleName(name: string, fromLocation: string) {
if (host.resolveModuleNames) {
const results = host.resolveModuleNames([name], fromLocation, /*loadJs*/true);
return results && results[0];
}
else {
return ts.resolveModuleName(name, fromLocation, options, host, /*loadJs*/true).resolvedModule;
}
}

function resolveExtensionNames(): Map<string> {
const basePath = options.configFilePath || combinePaths(host.getCurrentDirectory ? host.getCurrentDirectory() : "", "tsconfig.json");
const extMap: Map<string> = {};
forEach(extensionNames, name => {
const resolved = resolveModuleName(name, basePath, options, host, /*loadJs*/true).resolvedModule;
const resolved = resolveModuleName(name, basePath);
if (resolved) {
extMap[name] = resolved.resolvedFileName;
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"declarationEmitter.ts",
"emitter.ts",
"program.ts",
"extensions.ts",
"extensions.ts",
"commandLineParser.ts",
"tsc.ts",
"diagnosticInformationMap.generated.ts"
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2962,7 +2962,7 @@ namespace ts {
* If resolveModuleNames is implemented then implementation for members from ModuleResolutionHost can be just
* 'throw new Error("NotImplemented")'
*/
resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[];
resolveModuleNames?(moduleNames: string[], containingFile: string, loadJs?: boolean): ResolvedModule[];
/**
* This method is a companion for 'resolveModuleNames' and is used to resolve 'types' references to actual type declaration files
*/
Expand Down
6 changes: 3 additions & 3 deletions src/harness/harnessLanguageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ namespace Harness.LanguageService {
class ShimLanguageServiceHost extends LanguageServiceAdapterHost implements ts.LanguageServiceShimHost, ts.CoreServicesShimHost {
private nativeHost: NativeLanguageServiceHost;

public getModuleResolutionsForFile: (fileName: string) => string;
public getModuleResolutionsForFile: (fileName: string, loadJs?: boolean) => string;
public getTypeReferenceDirectiveResolutionsForFile: (fileName: string) => string;

constructor(preprocessToResolve: boolean, cancellationToken?: ts.HostCancellationToken, options?: ts.CompilerOptions) {
Expand All @@ -232,12 +232,12 @@ namespace Harness.LanguageService {
return scriptInfo && scriptInfo.content;
}
};
this.getModuleResolutionsForFile = (fileName) => {
this.getModuleResolutionsForFile = (fileName, loadJs) => {
const scriptInfo = this.getScriptInfo(fileName);
const preprocessInfo = ts.preProcessFile(scriptInfo.content, /*readImportFiles*/ true);
const imports: ts.Map<string> = {};
for (const module of preprocessInfo.importedFiles) {
const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost);
const resolutionInfo = ts.resolveModuleName(module.fileName, fileName, compilerOptions, moduleResolutionHost, loadJs);
if (resolutionInfo.resolvedModule) {
imports[module.fileName] = resolutionInfo.resolvedModule.resolvedFileName;
}
Expand Down
20 changes: 14 additions & 6 deletions src/server/editorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,9 @@ namespace ts.server {
names: string[],
containingFile: string,
cache: ts.FileMap<Map<T>>,
loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost) => T,
getResult: (s: T) => R): R[] {
loader: (name: string, containingFile: string, options: CompilerOptions, host: ModuleResolutionHost, loadJs?: boolean) => T,
getResult: (s: T) => R,
loadJs: boolean): R[] {

const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName);
const currentResolutionsInFile = cache.get(path);
Expand All @@ -144,7 +145,7 @@ namespace ts.server {
resolution = existingResolution;
}
else {
resolution = loader(name, containingFile, compilerOptions, this.moduleResolutionHost);
resolution = loader(name, containingFile, compilerOptions, this.moduleResolutionHost, loadJs);
resolution.lastCheckTime = Date.now();
newResolutions[name] = resolution;
}
Expand Down Expand Up @@ -177,11 +178,11 @@ namespace ts.server {
}

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

resolveModuleNames(moduleNames: string[], containingFile: string): ResolvedModule[] {
return this.resolveNamesWithLocalCache(moduleNames, containingFile, this.resolvedModuleNames, resolveModuleName, m => m.resolvedModule);
resolveModuleNames(moduleNames: string[], containingFile: string, loadJs?: boolean): ResolvedModule[] {
return this.resolveNamesWithLocalCache(moduleNames, containingFile, this.resolvedModuleNames, resolveModuleName, m => m.resolvedModule, loadJs);
}

getDefaultLibFileName() {
Expand Down Expand Up @@ -1377,6 +1378,13 @@ namespace ts.server {
return false;
}

loadExtension(name: string) {
if (!sys.loadExtension) {
throw new Error("Extension loading not implemented on the active host!");
}
return sys.loadExtension(name);
}

openConfigFile(configFilename: string, clientFileName?: string): { success: boolean, project?: Project, errors?: Diagnostic[] } {
const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(configFilename);
if (!succeeded) {
Expand Down
4 changes: 2 additions & 2 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1163,7 +1163,7 @@ namespace ts {
* if implementation is omitted then language service will use built-in module resolution logic and get answers to
* host specific questions using 'getScriptSnapshot'.
*/
resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[];
resolveModuleNames?(moduleNames: string[], containingFile: string, loadJs?: boolean): ResolvedModule[];
resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string): ResolvedTypeReferenceDirective[];
directoryExists?(directoryName: string): boolean;
getDirectories?(directoryName: string): string[];
Expand Down Expand Up @@ -3147,7 +3147,7 @@ namespace ts {
}

if (host.resolveModuleNames) {
compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile);
compilerHost.resolveModuleNames = (moduleNames, containingFile, loadJs) => host.resolveModuleNames(moduleNames, containingFile, loadJs);
}
if (host.resolveTypeReferenceDirectives) {
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile) => {
Expand Down
8 changes: 4 additions & 4 deletions src/services/shims.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ namespace ts {
getProjectVersion?(): string;
useCaseSensitiveFileNames?(): boolean;

getModuleResolutionsForFile?(fileName: string): string;
getModuleResolutionsForFile?(fileName: string, loadJs?: boolean): string;
getTypeReferenceDirectiveResolutionsForFile?(fileName: string): string;
directoryExists(directoryName: string): boolean;
}
Expand Down Expand Up @@ -303,16 +303,16 @@ namespace ts {
private loggingEnabled = false;
private tracingEnabled = false;

public resolveModuleNames: (moduleName: string[], containingFile: string) => ResolvedModule[];
public resolveModuleNames: (moduleName: string[], containingFile: string, loadJs?: boolean) => ResolvedModule[];
public resolveTypeReferenceDirectives: (typeDirectiveNames: string[], containingFile: string) => ResolvedTypeReferenceDirective[];
public directoryExists: (directoryName: string) => boolean;

constructor(private shimHost: LanguageServiceShimHost) {
// if shimHost is a COM object then property check will become method call with no arguments.
// 'in' does not have this effect.
if ("getModuleResolutionsForFile" in this.shimHost) {
this.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
this.resolveModuleNames = (moduleNames: string[], containingFile: string, loadJs?: boolean) => {
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile, loadJs));
return map(moduleNames, name => {
const result = lookUp(resolutionsInFile, name);
return result ? { resolvedFileName: result } : undefined;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//// [hello.ts]
console.log("Hello, world!");/*EOL*/

//// [hello.js]
console.log("Hello, world!"); /*EOL*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//// [hello.ts]
console.log("Hello, world!");/*EOL*/

//// [hello.js]
console.log("Hello, world!"); /*EOL*/
1 change: 1 addition & 0 deletions tests/cases/extensions/available/dummy/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log("loaded");
7 changes: 7 additions & 0 deletions tests/cases/extensions/available/dummy/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "dummy",
"version": "1.0.0",
"description": "",
"main": "index.js",
"author": ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"inputFiles": [
"hello.ts"
],
"availableExtensions": ["dummy"],
"compilerOptions": {
"extensions": ["dummy"]
}
}

0 comments on commit 8ee57f3

Please sign in to comment.