Add editor configurable filename-based ATA (#40952)

* add typeAcquisition:inferTypings

* remove unused property

* handle inferred and external projects separately

* update missed rename

* fix tests

* pass as external compilerOption

* update test

* remove hostConfig reference

* change option name

* remove extraneous property

* add inferredProjectCompilerOptions
This commit is contained in:
Jesse Trinity
2020-10-19 09:53:58 -07:00
committed by GitHub
parent 3918e6c535
commit 08e4f369fb
9 changed files with 162 additions and 48 deletions

View File

@@ -263,6 +263,16 @@ namespace ts.server {
return result;
}
export function convertTypeAcquisition(protocolOptions: protocol.InferredProjectCompilerOptions): TypeAcquisition | undefined {
let result: TypeAcquisition | undefined;
typeAcquisitionDeclarations.forEach((option) => {
const propertyValue = protocolOptions[option.name];
if (propertyValue === undefined) return;
(result || (result = {}))[option.name] = propertyValue;
});
return result;
}
export function tryConvertScriptKindName(scriptKindName: protocol.ScriptKindName | ScriptKind): ScriptKind {
return isString(scriptKindName) ? convertScriptKindName(scriptKindName) : scriptKindName;
}
@@ -642,6 +652,8 @@ namespace ts.server {
private compilerOptionsForInferredProjectsPerProjectRoot = new Map<string, CompilerOptions>();
private watchOptionsForInferredProjects: WatchOptions | undefined;
private watchOptionsForInferredProjectsPerProjectRoot = new Map<string, WatchOptions | false>();
private typeAcquisitionForInferredProjects: TypeAcquisition | undefined;
private typeAcquisitionForInferredProjectsPerProjectRoot = new Map<string, TypeAcquisition | undefined>();
/**
* Project size for configured or external projects
*/
@@ -982,11 +994,12 @@ namespace ts.server {
}
}
setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions, projectRootPath?: string): void {
setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.InferredProjectCompilerOptions, projectRootPath?: string): void {
Debug.assert(projectRootPath === undefined || this.useInferredProjectPerProjectRoot, "Setting compiler options per project root path is only supported when useInferredProjectPerProjectRoot is enabled");
const compilerOptions = convertCompilerOptions(projectCompilerOptions);
const watchOptions = convertWatchOptions(projectCompilerOptions);
const typeAcquisition = convertTypeAcquisition(projectCompilerOptions);
// always set 'allowNonTsExtensions' for inferred projects since user cannot configure it from the outside
// previously we did not expose a way for user to change these settings and this option was enabled by default
@@ -995,10 +1008,12 @@ namespace ts.server {
if (canonicalProjectRootPath) {
this.compilerOptionsForInferredProjectsPerProjectRoot.set(canonicalProjectRootPath, compilerOptions);
this.watchOptionsForInferredProjectsPerProjectRoot.set(canonicalProjectRootPath, watchOptions || false);
this.typeAcquisitionForInferredProjectsPerProjectRoot.set(canonicalProjectRootPath, typeAcquisition);
}
else {
this.compilerOptionsForInferredProjects = compilerOptions;
this.watchOptionsForInferredProjects = watchOptions;
this.typeAcquisitionForInferredProjects = typeAcquisition;
}
for (const project of this.inferredProjects) {
@@ -1015,6 +1030,7 @@ namespace ts.server {
!project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath)) {
project.setCompilerOptions(compilerOptions);
project.setWatchOptions(watchOptions);
project.setTypeAcquisition(typeAcquisition);
project.compileOnSaveEnabled = compilerOptions.compileOnSave!;
project.markAsDirty();
this.delayUpdateProjectGraph(project);
@@ -2298,13 +2314,18 @@ namespace ts.server {
private createInferredProject(currentDirectory: string | undefined, isSingleInferredProject?: boolean, projectRootPath?: NormalizedPath): InferredProject {
const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects!; // TODO: GH#18217
let watchOptions: WatchOptions | false | undefined;
let typeAcquisition: TypeAcquisition | undefined;
if (projectRootPath) {
watchOptions = this.watchOptionsForInferredProjectsPerProjectRoot.get(projectRootPath);
typeAcquisition = this.typeAcquisitionForInferredProjectsPerProjectRoot.get(projectRootPath);
}
if (watchOptions === undefined) {
watchOptions = this.watchOptionsForInferredProjects;
}
const project = new InferredProject(this, this.documentRegistry, compilerOptions, watchOptions || undefined, projectRootPath, currentDirectory, this.currentPluginConfigOverrides);
if (typeAcquisition === undefined) {
typeAcquisition = this.typeAcquisitionForInferredProjects;
}
const project = new InferredProject(this, this.documentRegistry, compilerOptions, watchOptions || undefined, projectRootPath, currentDirectory, this.currentPluginConfigOverrides, typeAcquisition);
if (isSingleInferredProject) {
this.inferredProjects.unshift(project);
}
@@ -3513,8 +3534,8 @@ namespace ts.server {
const { rootFiles } = proj;
const typeAcquisition = proj.typeAcquisition!;
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) {
if (typeAcquisition.enable === false || typeAcquisition.disableFilenameBasedTypeAcquisition) {
return [];
}

View File

@@ -249,6 +249,8 @@ namespace ts.server {
private symlinks: SymlinkCache | undefined;
/*@internal*/
autoImportProviderHost: AutoImportProviderProject | false | undefined;
/*@internal*/
protected typeAcquisition: TypeAcquisition | undefined;
/*@internal*/
constructor(
@@ -703,12 +705,11 @@ namespace ts.server {
getProjectName() {
return this.projectName;
}
abstract getTypeAcquisition(): TypeAcquisition;
protected removeLocalTypingsFromTypeAcquisition(newTypeAcquisition: TypeAcquisition): TypeAcquisition {
protected removeLocalTypingsFromTypeAcquisition(newTypeAcquisition: TypeAcquisition | undefined): TypeAcquisition {
if (!newTypeAcquisition || !newTypeAcquisition.include) {
// Nothing to filter out, so just return as-is
return newTypeAcquisition;
return newTypeAcquisition || {};
}
return { ...newTypeAcquisition, include: this.removeExistingTypings(newTypeAcquisition.include) };
}
@@ -1411,6 +1412,14 @@ namespace ts.server {
return this.watchOptions;
}
setTypeAcquisition(newTypeAcquisition: TypeAcquisition | undefined): void {
this.typeAcquisition = this.removeLocalTypingsFromTypeAcquisition(newTypeAcquisition);
}
getTypeAcquisition() {
return this.typeAcquisition || {};
}
/* @internal */
getChangesSinceVersion(lastKnownVersion?: number, includeProjectReferenceRedirectInfo?: boolean): ProjectFilesWithTSDiagnostics {
const includeProjectReferenceRedirectInfoIfRequested =
@@ -1786,7 +1795,8 @@ namespace ts.server {
watchOptions: WatchOptions | undefined,
projectRootPath: NormalizedPath | undefined,
currentDirectory: string | undefined,
pluginConfigOverrides: ESMap<string, any> | undefined) {
pluginConfigOverrides: ESMap<string, any> | undefined,
typeAcquisition: TypeAcquisition | undefined) {
super(InferredProject.newName(),
ProjectKind.Inferred,
projectService,
@@ -1799,6 +1809,7 @@ namespace ts.server {
watchOptions,
projectService.host,
currentDirectory);
this.typeAcquisition = typeAcquisition;
this.projectRootPath = projectRootPath && projectService.toCanonicalFileName(projectRootPath);
if (!projectRootPath && !projectService.useSingleInferredProject) {
this.canonicalCurrentDirectory = projectService.toCanonicalFileName(this.currentDirectory);
@@ -1844,7 +1855,7 @@ namespace ts.server {
}
getTypeAcquisition(): TypeAcquisition {
return {
return this.typeAcquisition || {
enable: allRootFilesAreJsOrDts(this),
include: ts.emptyArray,
exclude: ts.emptyArray
@@ -2026,7 +2037,6 @@ namespace ts.server {
* Otherwise it will create an InferredProject.
*/
export class ConfiguredProject extends Project {
private typeAcquisition: TypeAcquisition | undefined;
/* @internal */
configFileWatcher: FileWatcher | undefined;
private directoriesWatchedForWildcards: ESMap<string, WildcardDirectoryWatcher> | undefined;
@@ -2238,14 +2248,6 @@ namespace ts.server {
this.projectErrors = projectErrors;
}
setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void {
this.typeAcquisition = this.removeLocalTypingsFromTypeAcquisition(newTypeAcquisition);
}
getTypeAcquisition() {
return this.typeAcquisition || {};
}
/*@internal*/
watchWildcards(wildcardDirectories: ESMap<string, WatchDirectoryFlags>) {
updateWatchingWildcardDirectories(
@@ -2364,7 +2366,6 @@ namespace ts.server {
*/
export class ExternalProject extends Project {
excludedFiles: readonly NormalizedPath[] = [];
private typeAcquisition: TypeAcquisition | undefined;
/*@internal*/
constructor(public externalProjectName: string,
projectService: ProjectService,
@@ -2398,18 +2399,6 @@ namespace ts.server {
getExcludedFiles() {
return this.excludedFiles;
}
getTypeAcquisition() {
return this.typeAcquisition || {};
}
setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void {
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 = this.removeLocalTypingsFromTypeAcquisition(newTypeAcquisition);
}
}
/* @internal */

View File

@@ -1762,6 +1762,11 @@ namespace ts.server.protocol {
closedFiles?: string[];
}
/**
* External projects have a typeAcquisition option so they need to be added separately to compiler options for inferred projects.
*/
export type InferredProjectCompilerOptions = ExternalProjectCompilerOptions & TypeAcquisition;
/**
* Request to set compiler options for inferred projects.
* External projects are opened / closed explicitly.
@@ -1783,7 +1788,7 @@ namespace ts.server.protocol {
/**
* Compiler options to be used with inferred projects.
*/
options: ExternalProjectCompilerOptions;
options: InferredProjectCompilerOptions;
/**
* Specifies the project root path used to scope compiler options.