From b9a548cd13a277d9e7a2b1d2e6eb4472e501230f Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Thu, 16 Nov 2017 14:26:10 -0800 Subject: [PATCH] Squash port of PR #19542 --- src/compiler/core.ts | 14 ++++---- .../unittests/tsserverProjectSystem.ts | 36 +++++++++++++++++++ src/harness/unittests/typingsInstaller.ts | 10 +++--- src/server/editorServices.ts | 13 ++++--- src/services/jsTyping.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 2 +- 6 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index e4b7de205ff..c0eb7e257a6 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -74,13 +74,13 @@ namespace ts { } // The global Map object. This may not be available, so we must test for it. - declare const Map: { new(): Map } | undefined; + declare const Map: { new (): Map } | undefined; // Internet Explorer's Map doesn't support iteration, so don't use it. // tslint:disable-next-line:no-in-operator const MapCtr = typeof Map !== "undefined" && "entries" in Map.prototype ? Map : shimMap(); // Keep the class inside a function so it doesn't get compiled if it's not used. - function shimMap(): { new(): Map } { + function shimMap(): { new (): Map } { class MapIterator { private data: MapLike; @@ -103,7 +103,7 @@ namespace ts { } } - return class implements Map { + return class implements Map { private data = createDictionaryObject(); public size = 0; @@ -166,8 +166,8 @@ namespace ts { } export const enum Comparison { - LessThan = -1, - EqualTo = 0, + LessThan = -1, + EqualTo = 0, GreaterThan = 1 } @@ -2626,7 +2626,7 @@ namespace ts { return findBestPatternMatch(patterns, _ => _, candidate); } - export function patternText({prefix, suffix}: Pattern): string { + export function patternText({ prefix, suffix }: Pattern): string { return `${prefix}*${suffix}`; } @@ -2656,7 +2656,7 @@ namespace ts { return matchedValue; } - function isPatternMatch({prefix, suffix}: Pattern, candidate: string) { + function isPatternMatch({ prefix, suffix }: Pattern, candidate: string) { return candidate.length >= prefix.length + suffix.length && startsWith(candidate, prefix) && endsWith(candidate, suffix); diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index d519c167899..1b2aa481b26 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -1540,6 +1540,42 @@ namespace ts.projectSystem { } }); + it("removes version numbers correctly", () => { + const testData: [string, string][] = [ + ["jquery-max", "jquery-max"], + ["jquery.min", "jquery"], + ["jquery-min.4.2.3", "jquery"], + ["jquery.min.4.2.1", "jquery"], + ["minimum", "minimum"], + ["min", "min"], + ["min.3.2", "min"], + ["jquery", "jquery"] + ]; + for (const t of testData) { + assert.equal(removeMinAndVersionNumbers(t[0]), t[1], t[0]); + } + }); + + it("ignores files excluded by a legacy safe type list", () => { + const file1 = { + path: "/a/b/bliss.js", + content: "let x = 5" + }; + const file2 = { + path: "/a/b/foo.js", + content: "" + }; + const host = createServerHost([file1, file2, customTypesMap]); + const projectService = createProjectService(host); + try { + projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]), typeAcquisition: { enable: true } }); + const proj = projectService.externalProjects[0]; + assert.deepEqual(proj.getFileNames(), [file2.path]); + } finally { + projectService.resetSafeList(); + } + }); + it("open file become a part of configured project if it is referenced from root file", () => { const file1 = { path: "/a/b/f1.ts", diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index ae61c9f528c..dd5cfe904bf 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -521,8 +521,9 @@ namespace ts.projectSystem { // 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, jquery.path, moment.path]); + checkProjectActualFiles(p, [file3dts.path, commander.path, express.path, jquery.path, moment.path]); }); it("Throttle - delayed typings to install", () => { @@ -601,7 +602,7 @@ namespace ts.projectSystem { } host.checkTimeoutQueueLengthAndRun(2); checkNumberOfProjects(projectService, { externalProjects: 1 }); - checkProjectActualFiles(p, [file3.path, commander.path, jquery.path, moment.path, lodash.path]); + checkProjectActualFiles(p, [file3.path, commander.path, express.path, jquery.path, moment.path, lodash.path]); }); it("Throttle - delayed run install requests", () => { @@ -1101,11 +1102,12 @@ namespace ts.projectSystem { const host = createServerHost([app, jquery, chroma]); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [app.path, jquery.path, chroma.path], getDirectoryPath(app.path), safeList, emptyMap, { enable: true }, emptyArray); - assert.deepEqual(logger.finish(), [ + const finish = logger.finish(); + assert.deepEqual(finish, [ 'Inferred typings from file names: ["jquery","chroma-js"]', "Inferred typings from unresolved imports: []", 'Result: {"cachedTypingPaths":[],"newTypingNames":["jquery","chroma-js"],"filesToWatch":["/a/b/bower_components","/a/b/node_modules"]}', - ]); + ], finish.join("\r\n")); assert.deepEqual(result.newTypingNames, ["jquery", "chroma-js"]); }); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index d3815698cef..3c2a3220350 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -431,9 +431,12 @@ namespace ts.server { this.toCanonicalFileName = createGetCanonicalFileName(this.host.useCaseSensitiveFileNames); this.throttledOperations = new ThrottledOperations(this.host, this.logger); - if (opts.typesMapLocation) { + if (this.typesMapLocation) { this.loadTypesMap(); } + else { + this.logger.info("No types map provided; using the default"); + } this.typingsInstaller.attach(this); @@ -1399,7 +1402,7 @@ namespace ts.server { return false; } - private createExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typeAcquisition: TypeAcquisition) { + private createExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typeAcquisition: TypeAcquisition, excludedFiles: NormalizedPath[]) { const compilerOptions = convertCompilerOptions(options); const project = new ExternalProject( projectFileName, @@ -1408,6 +1411,7 @@ namespace ts.server { compilerOptions, /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(projectFileName, compilerOptions, files, externalFilePropertyReader), options.compileOnSave === undefined ? true : options.compileOnSave); + project.excludedFiles = excludedFiles; this.addFilesToNonInferredProjectAndUpdateGraph(project, files, externalFilePropertyReader, typeAcquisition); this.externalProjects.push(project); @@ -2178,7 +2182,7 @@ namespace ts.server { const rule = this.safelist[name]; for (const root of normalizedNames) { if (rule.match.test(root)) { - this.logger.info(`Excluding files based on rule ${name}`); + this.logger.info(`Excluding files based on rule ${name} matching file '${root}'`); // If the file matches, collect its types packages and exclude rules if (rule.types) { @@ -2369,8 +2373,7 @@ namespace ts.server { else { // no config files - remove the item from the collection this.externalProjectToConfiguredProjectMap.delete(proj.projectFileName); - const newProj = this.createExternalProject(proj.projectFileName, rootFiles, proj.options, proj.typeAcquisition); - newProj.excludedFiles = excludedFiles; + this.createExternalProject(proj.projectFileName, rootFiles, proj.options, proj.typeAcquisition, excludedFiles); } if (!suppressRefreshOfInferredProjects) { this.ensureProjectStructuresUptoDate(/*refreshInferredProjects*/ true); diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 572858dd2fd..e31201b951f 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -180,7 +180,7 @@ namespace ts.JsTyping { if (!hasJavaScriptFileExtension(j)) return undefined; const inferredTypingName = removeFileExtension(getBaseFileName(j.toLowerCase())); - const cleanedTypingName = inferredTypingName.replace(/((?:\.|-)min(?=\.|$))|((?:-|\.)\d+)/g, ""); + const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName); return safeList.get(cleanedTypingName); }); if (fromFileNames.length) { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index c1ef8566927..55b6a07bf86 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -7616,7 +7616,7 @@ declare namespace ts.server { private findExternalProjectByProjectName(projectFileName); private convertConfigFileContentToProjectOptions(configFilename, cachedDirectoryStructureHost); private exceededTotalSizeLimitForNonTsFiles(name, options, fileNames, propertyReader); - private createExternalProject(projectFileName, files, options, typeAcquisition); + private createExternalProject(projectFileName, files, options, typeAcquisition, excludedFiles); private sendProjectTelemetry(projectKey, project, projectOptions?); private addFilesToNonInferredProjectAndUpdateGraph(project, files, propertyReader, typeAcquisition); private createConfiguredProject(configFileName);