Apply safelist exclusions even when include is not specified; recompute project contexts when installer reqs finish

This commit is contained in:
Ryan Cavanaugh
2017-11-16 12:37:40 -08:00
parent 1da35d9dca
commit a416826b64
6 changed files with 118 additions and 72 deletions

View File

@@ -2193,8 +2193,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[];
@@ -2209,8 +2214,10 @@ namespace ts.server {
// 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);
}
}
}
@@ -2248,12 +2255,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"));
@@ -2264,7 +2265,7 @@ namespace ts.server {
}
else {
let exclude = false;
if (typeAcquisition && (typeAcquisition.enable || typeAcquisition.enableAutoDiscovery)) {
if (typeAcquisition.enable || typeAcquisition.enableAutoDiscovery) {
const baseName = getBaseFileName(normalizedNames[i].toLowerCase());
if (fileExtensionIs(baseName, "js")) {
const inferredTypingName = removeFileExtension(baseName);
@@ -2272,7 +2273,14 @@ namespace ts.server {
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);
}
}
}
}
@@ -2292,6 +2300,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);

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;
}
}

View File

@@ -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`);
}