Merge pull request #20079 from RyanCavanaugh/port20048

Port #20048 to release-2.6
This commit is contained in:
Ryan Cavanaugh
2017-11-17 09:59:04 -08:00
committed by GitHub
9 changed files with 208 additions and 90 deletions
+18 -7
View File
@@ -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<T>(): Map<T> } | undefined;
declare const Map: { new <T>(): Map<T> } | 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<T>(): Map<T> } {
function shimMap(): { new <T>(): Map<T> } {
class MapIterator<T, U extends (string | T | [string, T])> {
private data: MapLike<T>;
@@ -103,7 +103,7 @@ namespace ts {
}
}
return class<T> implements Map<T> {
return class <T> implements Map<T> {
private data = createDictionaryObject<T>();
public size = 0;
@@ -166,8 +166,8 @@ namespace ts {
}
export const enum Comparison {
LessThan = -1,
EqualTo = 0,
LessThan = -1,
EqualTo = 0,
GreaterThan = 1
}
@@ -2413,6 +2413,17 @@ namespace ts {
return <T>(removeFileExtension(path) + newExtension);
}
/**
* Takes a string like "jquery-min.4.2.3" and returns "jquery"
*/
export function removeMinAndVersionNumbers(fileName: string) {
// Match a "." or "-" followed by a version number or 'min' at the end of the name
const trailingMinOrVersion = /[.-]((min)|(\d+(\.\d+)*))$/;
// The "min" or version may both be present, in either order, so try applying the above twice.
return fileName.replace(trailingMinOrVersion, "").replace(trailingMinOrVersion, "");
}
export interface ObjectAllocator {
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
getTokenConstructor(): new <TKind extends SyntaxKind>(kind: TKind, pos?: number, end?: number) => Token<TKind>;
@@ -2615,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}`;
}
@@ -2645,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);
+38 -2
View File
@@ -1483,7 +1483,7 @@ namespace ts.projectSystem {
it("ignores files excluded by a custom safe type list", () => {
const file1 = {
path: "/a/b/f1.ts",
path: "/a/b/f1.js",
content: "export let x = 5"
};
const office = {
@@ -1504,7 +1504,7 @@ namespace ts.projectSystem {
it("ignores files excluded by the default type list", () => {
const file1 = {
path: "/a/b/f1.ts",
path: "/a/b/f1.js",
content: "export let x = 5"
};
const minFile = {
@@ -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",
+83 -37
View File
@@ -304,35 +304,35 @@ namespace ts.projectSystem {
// 1. react typings are installed for .jsx
// 2. loose files names are matched against safe list for typings if
// this is a JS project (only js, jsx, d.ts files are present)
const file1 = {
const lodashJs = {
path: "/a/b/lodash.js",
content: ""
};
const file2 = {
const file2Jsx = {
path: "/a/b/file2.jsx",
content: ""
};
const file3 = {
const file3dts = {
path: "/a/b/file3.d.ts",
content: ""
};
const react = {
const reactDts = {
path: "/a/data/node_modules/@types/react/index.d.ts",
content: "declare const react: { x: number }"
};
const lodash = {
const lodashDts = {
path: "/a/data/node_modules/@types/lodash/index.d.ts",
content: "declare const lodash: { x: number }"
};
const host = createServerHost([file1, file2, file3, customTypesMap]);
const host = createServerHost([lodashJs, file2Jsx, file3dts, customTypesMap]);
const installer = new (class extends Installer {
constructor() {
super(host, { typesRegistry: createTypesRegistry("lodash", "react") });
}
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings = ["@types/lodash", "@types/react"];
const typingFiles = [lodash, react];
const typingFiles = [lodashDts, reactDts];
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
@@ -342,35 +342,31 @@ namespace ts.projectSystem {
projectService.openExternalProject({
projectFileName,
options: { allowJS: true, moduleResolution: ModuleResolutionKind.NodeJs },
rootFiles: [toExternalFile(file1.path), toExternalFile(file2.path), toExternalFile(file3.path)],
typeAcquisition: {}
rootFiles: [toExternalFile(lodashJs.path), toExternalFile(file2Jsx.path), toExternalFile(file3dts.path)],
typeAcquisition: { }
});
const p = projectService.externalProjects[0];
projectService.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path, file3.path]);
checkProjectActualFiles(p, [file2Jsx.path, file3dts.path]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { externalProjects: 1 });
host.checkTimeoutQueueLengthAndRun(2);
checkNumberOfProjects(projectService, { externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path, file3.path, lodash.path, react.path]);
checkProjectActualFiles(p, [file2Jsx.path, file3dts.path, lodashDts.path, reactDts.path]);
});
it("external project - no type acquisition, with js & ts files", () => {
it("external project - type acquisition with enable: false", () => {
// Tests:
// 1. No typings are included for JS projects when the project contains ts files
const file1 = {
// Exclude
const jqueryJs = {
path: "/a/b/jquery.js",
content: ""
};
const file2 = {
path: "/a/b/file2.ts",
content: ""
};
const host = createServerHost([file1, file2]);
const host = createServerHost([jqueryJs]);
const installer = new (class extends Installer {
constructor() {
super(host, { typesRegistry: createTypesRegistry("jquery") });
@@ -390,18 +386,62 @@ namespace ts.projectSystem {
projectService.openExternalProject({
projectFileName,
options: { allowJS: true, moduleResolution: ModuleResolutionKind.NodeJs },
rootFiles: [toExternalFile(file1.path), toExternalFile(file2.path)],
rootFiles: [toExternalFile(jqueryJs.path)],
typeAcquisition: { enable: false }
});
const p = projectService.externalProjects[0];
projectService.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(p, [jqueryJs.path]);
installer.checkPendingCommands(/*expectedCount*/ 0);
});
it("external project - no type acquisition, with js & ts files", () => {
// Tests:
// 1. No typings are included for JS projects when the project contains ts files
const jqueryJs = {
path: "/a/b/jquery.js",
content: ""
};
const file2Ts = {
path: "/a/b/file2.ts",
content: ""
};
const host = createServerHost([jqueryJs, file2Ts]);
const installer = new (class extends Installer {
constructor() {
super(host, { typesRegistry: createTypesRegistry("jquery") });
}
enqueueInstallTypingsRequest(project: server.Project, typeAcquisition: TypeAcquisition, unresolvedImports: server.SortedReadonlyArray<string>) {
super.enqueueInstallTypingsRequest(project, typeAcquisition, unresolvedImports);
}
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
const installedTypings: string[] = [];
const typingFiles: FileOrFolder[] = [];
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
const projectFileName = "/a/app/test.csproj";
const projectService = createProjectService(host, { typingsInstaller: installer });
projectService.openExternalProject({
projectFileName,
options: { allowJS: true, moduleResolution: ModuleResolutionKind.NodeJs },
rootFiles: [toExternalFile(jqueryJs.path), toExternalFile(file2Ts.path)],
typeAcquisition: {}
});
const p = projectService.externalProjects[0];
projectService.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(p, [file2.path]);
checkProjectActualFiles(p, [jqueryJs.path, file2Ts.path]);
installer.checkPendingCommands(/*expectedCount*/ 0);
checkNumberOfProjects(projectService, { externalProjects: 1 });
checkProjectActualFiles(p, [file2.path]);
checkProjectActualFiles(p, [jqueryJs.path, file2Ts.path]);
});
it("external project - with type acquisition, with only js, d.ts files", () => {
@@ -409,15 +449,15 @@ namespace ts.projectSystem {
// 1. Safelist matching, type acquisition includes/excludes and package.json typings are all acquired
// 2. Types for safelist matches are not included when they also appear in the type acquisition exclude list
// 3. Multiple includes and excludes are respected in type acquisition
const file1 = {
const lodashJs = {
path: "/a/b/lodash.js",
content: ""
};
const file2 = {
const commanderJs = {
path: "/a/b/commander.js",
content: ""
};
const file3 = {
const file3dts = {
path: "/a/b/file3.d.ts",
content: ""
};
@@ -448,7 +488,7 @@ namespace ts.projectSystem {
content: "declare const moment: { x: number }"
};
const host = createServerHost([file1, file2, file3, packageJson, customTypesMap]);
const host = createServerHost([lodashJs, commanderJs, file3dts, packageJson, customTypesMap]);
const installer = new (class extends Installer {
constructor() {
super(host, { typesRegistry: createTypesRegistry("jquery", "commander", "moment", "express") });
@@ -465,20 +505,25 @@ namespace ts.projectSystem {
projectService.openExternalProject({
projectFileName,
options: { allowJS: true, moduleResolution: ModuleResolutionKind.NodeJs },
rootFiles: [toExternalFile(file1.path), toExternalFile(file2.path), toExternalFile(file3.path)],
typeAcquisition: { include: ["jquery", "moment"], exclude: ["lodash"] }
rootFiles: [toExternalFile(lodashJs.path), toExternalFile(commanderJs.path), toExternalFile(file3dts.path)],
typeAcquisition: { enable: true, include: ["jquery", "moment"], exclude: ["lodash"] }
});
const p = projectService.externalProjects[0];
projectService.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path, file3.path]);
checkProjectActualFiles(p, [file3dts.path]);
installer.installAll(/*expectedCount*/ 1);
checkNumberOfProjects(projectService, { externalProjects: 1 });
host.checkTimeoutQueueLengthAndRun(2);
checkNumberOfProjects(projectService, { externalProjects: 1 });
checkProjectActualFiles(p, [file1.path, file2.path, file3.path, commander.path, express.path, jquery.path, moment.path]);
// 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]);
});
it("Throttle - delayed typings to install", () => {
@@ -548,7 +593,7 @@ namespace ts.projectSystem {
const p = projectService.externalProjects[0];
projectService.checkNumberOfProjects({ externalProjects: 1 });
checkProjectActualFiles(p, [lodashJs.path, commanderJs.path, file3.path]);
checkProjectActualFiles(p, [file3.path]);
installer.checkPendingCommands(/*expectedCount*/ 1);
installer.executePendingCommands();
// expected all typings file to exist
@@ -557,7 +602,7 @@ namespace ts.projectSystem {
}
host.checkTimeoutQueueLengthAndRun(2);
checkNumberOfProjects(projectService, { externalProjects: 1 });
checkProjectActualFiles(p, [lodashJs.path, commanderJs.path, file3.path, commander.path, express.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", () => {
@@ -648,7 +693,7 @@ namespace ts.projectSystem {
const p1 = projectService.externalProjects[0];
const p2 = projectService.externalProjects[1];
projectService.checkNumberOfProjects({ externalProjects: 2 });
checkProjectActualFiles(p1, [lodashJs.path, commanderJs.path, file3.path]);
checkProjectActualFiles(p1, [file3.path]);
checkProjectActualFiles(p2, [file3.path]);
installer.executePendingCommands();
@@ -659,7 +704,7 @@ namespace ts.projectSystem {
installer.executePendingCommands();
host.checkTimeoutQueueLengthAndRun(3); // for 2 projects and 1 refreshing inferred project
checkProjectActualFiles(p1, [lodashJs.path, commanderJs.path, file3.path, commander.path, jquery.path, lodash.path, cordova.path]);
checkProjectActualFiles(p1, [file3.path, commander.path, jquery.path, lodash.path, cordova.path]);
checkProjectActualFiles(p2, [file3.path, grunt.path, gulp.path]);
});
@@ -973,7 +1018,7 @@ namespace ts.projectSystem {
}
};
session.executeCommand(changeRequest);
host.checkTimeoutQueueLengthAndRun(2); // This enqueues the updategraph and refresh inferred projects
host.checkTimeoutQueueLengthAndRun(0); // This enqueues the updategraph and refresh inferred projects
const version2 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion();
assert.equal(version1, version2, "set of unresolved imports should not change");
});
@@ -1057,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(<Path>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"]);
});
+2 -2
View File
@@ -137,9 +137,9 @@ namespace ts.TestFSWithWatch {
}
export function checkFileNames(caption: string, actualFileNames: ReadonlyArray<string>, expectedFileNames: string[]) {
assert.equal(actualFileNames.length, expectedFileNames.length, `${caption}: incorrect actual number of files, expected ${expectedFileNames}, got ${actualFileNames}`);
assert.equal(actualFileNames.length, expectedFileNames.length, `${caption}: incorrect actual number of files, expected:\r\n${expectedFileNames.join("\r\n")}\r\ngot: ${actualFileNames.join("\r\n")}`);
for (const f of expectedFileNames) {
assert.isTrue(contains(actualFileNames, f), `${caption}: expected to find ${f} in ${actualFileNames}`);
assert.equal(true, contains(actualFileNames, f), `${caption}: expected to find ${f} in ${actualFileNames}`);
}
}
+51 -16
View File
@@ -110,7 +110,7 @@ namespace ts.server {
export interface TypesMapFile {
typesMap: SafeList;
simpleMap: string[];
simpleMap: { [libName: string]: string };
}
/**
@@ -378,6 +378,7 @@ namespace ts.server {
private readonly hostConfiguration: HostConfiguration;
private safelist: SafeList = defaultTypeSafeList;
private legacySafelist: { [key: string]: string } = {};
private changedFiles: ScriptInfo[];
private pendingProjectUpdates = createMap<Project>();
@@ -430,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);
@@ -522,10 +526,12 @@ namespace ts.server {
}
// raw is now fixed and ready
this.safelist = raw.typesMap;
this.legacySafelist = raw.simpleMap;
}
catch (e) {
this.logger.info(`Error loading types map: ${e}`);
this.safelist = defaultTypeSafeList;
this.legacySafelist = {};
}
}
@@ -1396,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,
@@ -1405,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);
@@ -2159,8 +2166,13 @@ namespace ts.server {
applySafeList(proj: protocol.ExternalProject): NormalizedPath[] {
const { rootFiles, typeAcquisition } = proj;
const types = (typeAcquisition && typeAcquisition.include) || [];
Debug.assert(!!typeAcquisition, "proj.typeAcquisition should be set by now");
// If type acquisition has been explicitly disabled, do not exclude anything from the project
if (typeAcquisition.enable === false) {
return [];
}
const typeAcqInclude = typeAcquisition.include || (typeAcquisition.include = []);
const excludeRules: string[] = [];
const normalizedNames = rootFiles.map(f => normalizeSlashes(f.fileName)) as NormalizedPath[];
@@ -2170,13 +2182,15 @@ 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) {
for (const type of rule.types) {
if (types.indexOf(type) < 0) {
types.push(type);
// Best-effort de-duping here - doesn't need to be unduplicated but
// we don't want the list to become a 400-element array of just 'kendo'
if (typeAcqInclude.indexOf(type) < 0) {
typeAcqInclude.push(type);
}
}
}
@@ -2214,12 +2228,6 @@ namespace ts.server {
}
}
}
// Copy back this field into the project if needed
if (types.length > 0) {
proj.typeAcquisition = proj.typeAcquisition || {};
proj.typeAcquisition.include = types;
}
}
const excludeRegexes = excludeRules.map(e => new RegExp(e, "i"));
@@ -2229,7 +2237,29 @@ namespace ts.server {
excludedFiles.push(normalizedNames[i]);
}
else {
filesToKeep.push(proj.rootFiles[i]);
let exclude = false;
if (typeAcquisition.enable || typeAcquisition.enableAutoDiscovery) {
const baseName = getBaseFileName(normalizedNames[i].toLowerCase());
if (fileExtensionIs(baseName, "js")) {
const inferredTypingName = removeFileExtension(baseName);
const cleanedTypingName = removeMinAndVersionNumbers(inferredTypingName);
if (this.legacySafelist[cleanedTypingName]) {
this.logger.info(`Excluded '${normalizedNames[i]}' because it matched ${cleanedTypingName} from the legacy safelist`);
excludedFiles.push(normalizedNames[i]);
// *exclude* it from the project...
exclude = true;
// ... but *include* it in the list of types to acquire
const typeName = this.legacySafelist[cleanedTypingName];
// Same best-effort dedupe as above
if (typeAcqInclude.indexOf(typeName) < 0) {
typeAcqInclude.push(typeName);
}
}
}
}
if (!exclude) {
filesToKeep.push(proj.rootFiles[i]);
}
}
}
proj.rootFiles = filesToKeep;
@@ -2243,6 +2273,12 @@ namespace ts.server {
const typeAcquisition = convertEnableAutoDiscoveryToEnable(proj.typingOptions);
proj.typeAcquisition = typeAcquisition;
}
proj.typeAcquisition = proj.typeAcquisition || {};
proj.typeAcquisition.include = proj.typeAcquisition.include || [];
proj.typeAcquisition.exclude = proj.typeAcquisition.exclude || [];
if (proj.typeAcquisition.enable === undefined) {
proj.typeAcquisition.enable = hasNoTypeScriptSource(proj.rootFiles.map(f => f.fileName));
}
const excludedFiles = this.applySafeList(proj);
@@ -2337,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);
+9 -20
View File
@@ -52,6 +52,11 @@ namespace ts.server {
return counts.ts === 0 && counts.tsx === 0;
}
/* @internal */
export function hasNoTypeScriptSource(fileNames: string[]): boolean {
return !fileNames.some(fileName => (fileExtensionIs(fileName, Extension.Ts) && !fileExtensionIs(fileName, Extension.Dts)) || fileExtensionIs(fileName, Extension.Tsx));
}
/* @internal */
export interface ProjectFilesWithTSDiagnostics extends protocol.ProjectFiles {
projectErrors: ReadonlyArray<Diagnostic>;
@@ -1436,26 +1441,10 @@ namespace ts.server {
}
setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void {
if (!newTypeAcquisition) {
// set default typings options
newTypeAcquisition = {
enable: allRootFilesAreJsOrDts(this),
include: [],
exclude: []
};
}
else {
if (newTypeAcquisition.enable === undefined) {
// if autoDiscovery was not specified by the caller - set it based on the content of the project
newTypeAcquisition.enable = allRootFilesAreJsOrDts(this);
}
if (!newTypeAcquisition.include) {
newTypeAcquisition.include = [];
}
if (!newTypeAcquisition.exclude) {
newTypeAcquisition.exclude = [];
}
}
Debug.assert(!!newTypeAcquisition, "newTypeAcquisition may not be null/undefined");
Debug.assert(!!newTypeAcquisition.include, "newTypeAcquisition.include may not be null/undefined");
Debug.assert(!!newTypeAcquisition.exclude, "newTypeAcquisition.exclude may not be null/undefined");
Debug.assert(typeof newTypeAcquisition.enable === "boolean", "newTypeAcquisition.enable may not be null/undefined");
this.typeAcquisition = newTypeAcquisition;
}
}
@@ -123,9 +123,6 @@ namespace ts.server.typingsInstaller {
this.log.writeLine(`Finished typings discovery: ${JSON.stringify(discoverTypingsResult)}`);
}
// respond with whatever cached typings we have now
this.sendResponse(this.createSetTypings(req, discoverTypingsResult.cachedTypingPaths));
// start watching files
this.watchFiles(req.projectName, discoverTypingsResult.filesToWatch);
@@ -134,6 +131,7 @@ namespace ts.server.typingsInstaller {
this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames);
}
else {
this.sendResponse(this.createSetTypings(req, discoverTypingsResult.cachedTypingPaths));
if (this.log.isEnabled()) {
this.log.writeLine(`No new typings were requested as a result of typings discovery`);
}
+1 -1
View File
@@ -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) {
+5 -2
View File
@@ -7424,7 +7424,9 @@ declare namespace ts.server {
}
interface TypesMapFile {
typesMap: SafeList;
simpleMap: string[];
simpleMap: {
[libName: string]: string;
};
}
function convertFormatOptions(protocolOptions: protocol.FormatCodeSettings): FormatCodeSettings;
function convertCompilerOptions(protocolOptions: protocol.ExternalProjectCompilerOptions): CompilerOptions & protocol.CompileOnSaveMixin;
@@ -7505,6 +7507,7 @@ declare namespace ts.server {
private readonly throttledOperations;
private readonly hostConfiguration;
private safelist;
private legacySafelist;
private changedFiles;
private pendingProjectUpdates;
private pendingInferredProjectUpdate;
@@ -7613,7 +7616,7 @@ declare namespace ts.server {
private findExternalProjectByProjectName(projectFileName);
private convertConfigFileContentToProjectOptions(configFilename, cachedDirectoryStructureHost);
private exceededTotalSizeLimitForNonTsFiles<T>(name, options, fileNames, propertyReader);
private createExternalProject(projectFileName, files, options, typeAcquisition);
private createExternalProject(projectFileName, files, options, typeAcquisition, excludedFiles);
private sendProjectTelemetry(projectKey, project, projectOptions?);
private addFilesToNonInferredProjectAndUpdateGraph<T>(project, files, propertyReader, typeAcquisition);
private createConfiguredProject(configFileName);