diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 18109cfa9db..bc4fceac537 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -16,8 +16,8 @@ namespace ts.server { directoryExists: () => false, getDirectories: () => [], createDirectory: noop, - getExecutingFilePath(): string { return void 0; }, - getCurrentDirectory(): string { return void 0; }, + getExecutingFilePath(): string { return ""; }, + getCurrentDirectory(): string { return ""; }, getEnvironmentVariable(): string { return ""; }, readDirectory() { return []; }, exit: noop, diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index c03b243714e..0a56e66abe2 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -28,6 +28,30 @@ namespace ts.projectSystem { }) }; + export const customTypesMap = { + path: "/typesMap.json", + content: `{ + "typesMap": { + "jquery": { + "match": "jquery(-(\\\\.?\\\\d+)+)?(\\\\.intellisense)?(\\\\.min)?\\\\.js$", + "types": ["jquery"] + }, + "quack": { + "match": "/duckquack-(\\\\d+)\\\\.min\\\\.js", + "types": ["duck-types"] + } + }, + "simpleMap": { + "Bacon": "baconjs", + "bliss": "blissfuljs", + "commander": "commander", + "cordova": "cordova", + "react": "react", + "lodash": "lodash" + } + }` + }; + export interface PostExecAction { readonly success: boolean; readonly callback: TI.RequestCompletedAction; @@ -204,7 +228,7 @@ namespace ts.projectSystem { byteLength: Utils.byteLength, hrtime: process.hrtime, logger: nullLogger, - canUseEvents: false + canUseEvents: false, }; return new TestSession({ ...sessionOptions, ...opts }); @@ -230,6 +254,7 @@ namespace ts.projectSystem { useInferredProjectPerProjectRoot: false, typingsInstaller, eventHandler, + typesMapLocation: customTypesMap.path, ...opts }); } diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index e0874d1fe46..69583b60359 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -322,7 +322,7 @@ namespace ts.projectSystem { content: "declare const lodash: { x: number }" }; - const host = createServerHost([lodashJs, file2Jsx, file3dts]); + const host = createServerHost([lodashJs, file2Jsx, file3dts, customTypesMap]); const installer = new (class extends Installer { constructor() { super(host, { typesRegistry: createTypesRegistry("lodash", "react") }); @@ -350,7 +350,6 @@ namespace ts.projectSystem { installer.installAll(/*expectedCount*/ 1); checkNumberOfProjects(projectService, { externalProjects: 1 }); - host.checkTimeoutQueueLength(2); host.runQueuedTimeoutCallbacks(); checkNumberOfProjects(projectService, { externalProjects: 1 }); checkProjectActualFiles(p, [file2Jsx.path, file3dts.path, lodashDts.path, reactDts.path]); @@ -486,7 +485,7 @@ namespace ts.projectSystem { content: "declare const moment: { x: number }" }; - const host = createServerHost([lodashJs, commanderJs, file3dts, packageJson]); + const host = createServerHost([lodashJs, commanderJs, file3dts, packageJson, customTypesMap]); const installer = new (class extends Installer { constructor() { super(host, { typesRegistry: createTypesRegistry("jquery", "commander", "moment", "express") }); @@ -514,15 +513,13 @@ namespace ts.projectSystem { installer.installAll(/*expectedCount*/ 1); checkNumberOfProjects(projectService, { externalProjects: 1 }); - host.checkTimeoutQueueLength(2); host.runQueuedTimeoutCallbacks(); checkNumberOfProjects(projectService, { externalProjects: 1 }); // Commander: Existed as a JS file // JQuery: Specified in 'include' // Moment: Specified in 'include' - // Express: Specified in package.json // lodash: Excluded (not present) - checkProjectActualFiles(p, [file3dts.path, commander.path, express.path, jquery.path, moment.path]); + checkProjectActualFiles(p, [file3dts.path, commander.path, jquery.path, moment.path]); }); it("Throttle - delayed typings to install", () => { @@ -570,7 +567,7 @@ namespace ts.projectSystem { }; const typingFiles = [commander, express, jquery, moment, lodash]; - const host = createServerHost([lodashJs, commanderJs, file3, packageJson]); + const host = createServerHost([lodashJs, commanderJs, file3, packageJson, customTypesMap]); const installer = new (class extends Installer { constructor() { super(host, { throttleLimit: 3, typesRegistry: createTypesRegistry("commander", "express", "jquery", "moment", "lodash") }); @@ -649,7 +646,7 @@ namespace ts.projectSystem { typings: typingsName("gulp") }; - const host = createServerHost([lodashJs, commanderJs, file3]); + const host = createServerHost([lodashJs, commanderJs, file3, customTypesMap]); const installer = new (class extends Installer { constructor() { super(host, { throttleLimit: 1, typesRegistry: createTypesRegistry("commander", "jquery", "lodash", "cordova", "gulp", "grunt") }); @@ -702,7 +699,6 @@ namespace ts.projectSystem { assert.equal(installer.pendingRunRequests.length, 0, "expected no throttled requests"); installer.executePendingCommands(); - host.checkTimeoutQueueLength(3); // for 2 projects and 1 refreshing inferred project host.runQueuedTimeoutCallbacks(); checkProjectActualFiles(p1, [file3.path, commander.path, jquery.path, lodash.path, cordova.path]); checkProjectActualFiles(p2, [file3.path, grunt.path, gulp.path]); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 1f883899f58..c00e1b3cd76 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -109,14 +109,11 @@ namespace ts.server { "smart": IndentStyle.Smart }); -<<<<<<< HEAD -======= export interface TypesMapFile { typesMap: SafeList; simpleMap: { [libName: string]: string }; } ->>>>>>> f2931a1320... Port PR #20048 /** * How to understand this block: * * The 'match' property is a regexp that matches a filename. @@ -353,6 +350,7 @@ namespace ts.server { globalPlugins?: ReadonlyArray; pluginProbeLocations?: ReadonlyArray; allowLocalPluginLoads?: boolean; + typesMapLocation?: string; } export class ProjectService { @@ -415,6 +413,7 @@ namespace ts.server { public readonly globalPlugins: ReadonlyArray; public readonly pluginProbeLocations: ReadonlyArray; public readonly allowLocalPluginLoads: boolean; + public readonly typesMapLocation: string | undefined; /** Tracks projects that we have already sent telemetry for. */ private readonly seenProjects = createMap(); @@ -431,10 +430,12 @@ namespace ts.server { this.globalPlugins = opts.globalPlugins || emptyArray; this.pluginProbeLocations = opts.pluginProbeLocations || emptyArray; this.allowLocalPluginLoads = !!opts.allowLocalPluginLoads; + this.typesMapLocation = (opts.typesMapLocation === undefined) ? combinePaths(this.getExecutingFilePath(), "../typesMap.json") : opts.typesMapLocation; Debug.assert(!!this.host.createHash, "'ServerHost.createHash' is required for ProjectService"); this.toCanonicalFileName = createGetCanonicalFileName(this.host.useCaseSensitiveFileNames); + this.directoryWatchers = new DirectoryWatchers(this); this.throttledOperations = new ThrottledOperations(this.host); if (this.typesMapLocation) { @@ -481,8 +482,16 @@ namespace ts.server { this.eventHandler(event); } -<<<<<<< HEAD -======= + /*@internal*/ + getNormalizedAbsolutePath(fileName: string) { + return getNormalizedAbsolutePath(fileName, this.host.getCurrentDirectory()); + } + + /*@internal*/ + getExecutingFilePath() { + return this.getNormalizedAbsolutePath(this.host.getExecutingFilePath()); + } + private loadTypesMap() { try { const fileContent = this.host.readFile(this.typesMapLocation); @@ -506,7 +515,6 @@ namespace ts.server { } } ->>>>>>> f2931a1320... Port PR #20048 updateTypingsForProject(response: SetTypings | InvalidateCachedTypings): void { const project = this.findProject(response.projectName); if (!project) { @@ -1791,7 +1799,7 @@ namespace ts.server { const excludeRules: string[] = []; const excludedFiles: NormalizedPath[] = []; - const normalizedNames = rootFiles.map(f => normalizeSlashes(f.fileName)); + const normalizedNames = rootFiles.map(f => normalizeSlashes(f.fileName)) as NormalizedPath[]; for (const name of Object.keys(this.safelist)) { const rule = this.safelist[name]; @@ -1895,7 +1903,7 @@ namespace ts.server { proj.typeAcquisition.enable = hasNoTypeScriptSource(proj.rootFiles.map(f => f.fileName)); } - this.applySafeList(proj); + const excludedFiles = this.applySafeList(proj); let tsConfigFiles: NormalizedPath[]; const rootFiles: protocol.ExternalFile[] = []; diff --git a/src/server/project.ts b/src/server/project.ts index b079e985fad..9451e6c2454 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -1190,6 +1190,7 @@ namespace ts.server { * These are created only if a host explicitly calls `openExternalProject`. */ export class ExternalProject extends Project { + excludedFiles: ReadonlyArray = []; private typeAcquisition: TypeAcquisition; constructor(public externalProjectName: string, projectService: ProjectService,