Skip to content

Commit 0a8d84f

Browse files
committed
Handle host configuration for watch options
1 parent 3777897 commit 0a8d84f

File tree

5 files changed

+205
-66
lines changed

5 files changed

+205
-66
lines changed

src/compiler/commandLineParser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2812,7 +2812,8 @@ namespace ts {
28122812
return defaultOptions;
28132813
}
28142814

2815-
function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Push<Diagnostic>): CompilerOptionsValue {
2815+
/*@internal*/
2816+
export function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Push<Diagnostic>): CompilerOptionsValue {
28162817
if (isCompilerOptionsValue(opt, value)) {
28172818
const optType = opt.type;
28182819
if (optType === "list" && isArray(value)) {

src/server/editorServices.ts

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -251,17 +251,18 @@ namespace ts.server {
251251
return <any>protocolOptions;
252252
}
253253

254-
export function convertWatchOptions(protocolOptions: protocol.ExternalProjectCompilerOptions): WatchOptions | undefined {
255-
let result: WatchOptions | undefined;
256-
debugger;
257-
watchOptionsConverters.forEach((mappedValues, id) => {
258-
const propertyValue = protocolOptions[id];
254+
export function convertWatchOptions(protocolOptions: protocol.ExternalProjectCompilerOptions, currentDirectory?: string): WatchOptionsAndErrors | undefined {
255+
let watchOptions: WatchOptions | undefined;
256+
let errors: Diagnostic[] | undefined;
257+
optionsForWatch.forEach(option => {
258+
const propertyValue = protocolOptions[option.name];
259259
if (propertyValue === undefined) return;
260-
(result || (result = {}))[id] = isString(propertyValue) ?
261-
mappedValues.get(propertyValue.toLowerCase()) :
262-
propertyValue;
260+
const mappedValues = watchOptionsConverters.get(option.name);
261+
(watchOptions || (watchOptions = {}))[option.name] = mappedValues ?
262+
isString(propertyValue) ? mappedValues.get(propertyValue.toLowerCase()) : propertyValue :
263+
convertJsonOption(option, propertyValue, currentDirectory || "", errors || (errors = []));
263264
});
264-
return result;
265+
return watchOptions && { watchOptions, errors };
265266
}
266267

267268
export function tryConvertScriptKindName(scriptKindName: protocol.ScriptKindName | ScriptKind): ScriptKind {
@@ -560,6 +561,11 @@ namespace ts.server {
560561
changes: Iterator<TextChange>;
561562
}
562563

564+
export interface WatchOptionsAndErrors {
565+
watchOptions: WatchOptions;
566+
errors: Diagnostic[] | undefined;
567+
}
568+
563569
export class ProjectService {
564570

565571
/*@internal*/
@@ -616,8 +622,8 @@ namespace ts.server {
616622

617623
private compilerOptionsForInferredProjects: CompilerOptions | undefined;
618624
private compilerOptionsForInferredProjectsPerProjectRoot = createMap<CompilerOptions>();
619-
private watchOptionsForInferredProjects: WatchOptions | undefined;
620-
private watchOptionsForInferredProjectsPerProjectRoot = createMap<WatchOptions | false>();
625+
private watchOptionsForInferredProjects: WatchOptionsAndErrors | undefined;
626+
private watchOptionsForInferredProjectsPerProjectRoot = createMap<WatchOptionsAndErrors | false>();
621627
/**
622628
* Project size for configured or external projects
623629
*/
@@ -949,7 +955,7 @@ namespace ts.server {
949955
Debug.assert(projectRootPath === undefined || this.useInferredProjectPerProjectRoot, "Setting compiler options per project root path is only supported when useInferredProjectPerProjectRoot is enabled");
950956

951957
const compilerOptions = convertCompilerOptions(projectCompilerOptions);
952-
const watchOptions = convertWatchOptions(projectCompilerOptions);
958+
const watchOptions = convertWatchOptions(projectCompilerOptions, projectRootPath);
953959

954960
// always set 'allowNonTsExtensions' for inferred projects since user cannot configure it from the outside
955961
// previously we did not expose a way for user to change these settings and this option was enabled by default
@@ -977,7 +983,8 @@ namespace ts.server {
977983
project.projectRootPath === canonicalProjectRootPath :
978984
!project.projectRootPath || !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath)) {
979985
project.setCompilerOptions(compilerOptions);
980-
project.setWatchOptions(watchOptions);
986+
project.setWatchOptions(watchOptions?.watchOptions);
987+
project.setProjectErrors(watchOptions?.errors);
981988
project.compileOnSaveEnabled = compilerOptions.compileOnSave!;
982989
project.markAsDirty();
983990
this.delayUpdateProjectGraph(project);
@@ -1860,7 +1867,7 @@ namespace ts.server {
18601867

18611868
private createExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typeAcquisition: TypeAcquisition, excludedFiles: NormalizedPath[]) {
18621869
const compilerOptions = convertCompilerOptions(options);
1863-
const watchOptions = convertWatchOptions(options);
1870+
const watchOptionsAndErrors = convertWatchOptions(options, getDirectoryPath(normalizeSlashes(projectFileName)));
18641871
const project = new ExternalProject(
18651872
projectFileName,
18661873
this,
@@ -1870,8 +1877,9 @@ namespace ts.server {
18701877
options.compileOnSave === undefined ? true : options.compileOnSave,
18711878
/*projectFilePath*/ undefined,
18721879
this.currentPluginConfigOverrides,
1873-
watchOptions
1880+
watchOptionsAndErrors?.watchOptions
18741881
);
1882+
project.setProjectErrors(watchOptionsAndErrors?.errors);
18751883
project.excludedFiles = excludedFiles;
18761884

18771885
this.addFilesToNonInferredProject(project, files, externalFilePropertyReader, typeAcquisition);
@@ -2246,14 +2254,16 @@ namespace ts.server {
22462254

22472255
private createInferredProject(currentDirectory: string | undefined, isSingleInferredProject?: boolean, projectRootPath?: NormalizedPath): InferredProject {
22482256
const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects!; // TODO: GH#18217
2249-
let watchOptions: WatchOptions | false | undefined;
2257+
let watchOptionsAndErrors: WatchOptionsAndErrors | false | undefined;
22502258
if (projectRootPath) {
2251-
watchOptions = this.watchOptionsForInferredProjectsPerProjectRoot.get(projectRootPath);
2259+
watchOptionsAndErrors = this.watchOptionsForInferredProjectsPerProjectRoot.get(projectRootPath);
22522260
}
2253-
if (watchOptions === undefined) {
2254-
watchOptions = this.watchOptionsForInferredProjects;
2261+
if (watchOptionsAndErrors === undefined) {
2262+
watchOptionsAndErrors = this.watchOptionsForInferredProjects;
22552263
}
2256-
const project = new InferredProject(this, this.documentRegistry, compilerOptions, watchOptions || undefined, projectRootPath, currentDirectory, this.currentPluginConfigOverrides);
2264+
watchOptionsAndErrors = watchOptionsAndErrors || undefined;
2265+
const project = new InferredProject(this, this.documentRegistry, compilerOptions, watchOptionsAndErrors?.watchOptions, projectRootPath, currentDirectory, this.currentPluginConfigOverrides);
2266+
project.setProjectErrors(watchOptionsAndErrors?.errors);
22572267
if (isSingleInferredProject) {
22582268
this.inferredProjects.unshift(project);
22592269
}
@@ -2705,7 +2715,7 @@ namespace ts.server {
27052715
}
27062716

27072717
if (args.watchOptions) {
2708-
this.hostConfiguration.watchOptions = convertWatchOptions(args.watchOptions);
2718+
this.hostConfiguration.watchOptions = convertWatchOptions(args.watchOptions)?.watchOptions;
27092719
this.logger.info(`Host watch options changed to ${JSON.stringify(this.hostConfiguration.watchOptions)}, it will be take effect for next watches.`);
27102720
}
27112721
}
@@ -3579,17 +3589,18 @@ namespace ts.server {
35793589
externalProject.excludedFiles = excludedFiles;
35803590
if (!tsConfigFiles) {
35813591
const compilerOptions = convertCompilerOptions(proj.options);
3582-
const watchOptions = convertWatchOptions(proj.options);
3592+
const watchOptionsAndErrors = convertWatchOptions(proj.options, externalProject.getCurrentDirectory());
35833593
const lastFileExceededProgramSize = this.getFilenameForExceededTotalSizeLimitForNonTsFiles(proj.projectFileName, compilerOptions, proj.rootFiles, externalFilePropertyReader);
35843594
if (lastFileExceededProgramSize) {
35853595
externalProject.disableLanguageService(lastFileExceededProgramSize);
35863596
}
35873597
else {
35883598
externalProject.enableLanguageService();
35893599
}
3600+
externalProject.setProjectErrors(watchOptionsAndErrors?.errors);
35903601
// external project already exists and not config files were added - update the project and return;
35913602
// The graph update here isnt postponed since any file open operation needs all updated external projects
3592-
this.updateRootAndOptionsOfNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, compilerOptions, proj.typeAcquisition, proj.options.compileOnSave, watchOptions);
3603+
this.updateRootAndOptionsOfNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, compilerOptions, proj.typeAcquisition, proj.options.compileOnSave, watchOptionsAndErrors?.watchOptions);
35933604
externalProject.updateGraph();
35943605
return;
35953606
}

src/server/project.ts

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ namespace ts.server {
189189
*/
190190
private projectStateVersion = 0;
191191

192+
protected projectErrors: Diagnostic[] | undefined;
193+
192194
protected isInitialLoadPending: () => boolean = returnFalse;
193195

194196
/*@internal*/
@@ -565,11 +567,18 @@ namespace ts.server {
565567
* Get the errors that dont have any file name associated
566568
*/
567569
getGlobalProjectErrors(): readonly Diagnostic[] {
568-
return emptyArray;
570+
return filter(this.projectErrors, diagnostic => !diagnostic.file) || emptyArray;
569571
}
570572

573+
/**
574+
* Get all the project errors
575+
*/
571576
getAllProjectErrors(): readonly Diagnostic[] {
572-
return emptyArray;
577+
return this.projectErrors || emptyArray;
578+
}
579+
580+
setProjectErrors(projectErrors: Diagnostic[] | undefined) {
581+
this.projectErrors = projectErrors;
573582
}
574583

575584
getLanguageService(ensureSynchronized = true): LanguageService {
@@ -742,6 +751,7 @@ namespace ts.server {
742751
this.resolutionCache = undefined!;
743752
this.cachedUnresolvedImportsPerFile = undefined!;
744753
this.directoryStructureHost = undefined!;
754+
this.projectErrors = undefined;
745755

746756
// Clean up file watchers waiting for missing files
747757
if (this.missingFilesMap) {
@@ -1966,8 +1976,6 @@ namespace ts.server {
19661976
/** Ref count to the project when opened from external project */
19671977
private externalProjectRefCount = 0;
19681978

1969-
private projectErrors: Diagnostic[] | undefined;
1970-
19711979
private projectReferences: readonly ProjectReference[] | undefined;
19721980

19731981
/** Potential project references before the project is actually loaded (read config file) */
@@ -2135,24 +2143,6 @@ namespace ts.server {
21352143
this.enableGlobalPlugins(options, pluginConfigOverrides);
21362144
}
21372145

2138-
/**
2139-
* Get the errors that dont have any file name associated
2140-
*/
2141-
getGlobalProjectErrors(): readonly Diagnostic[] {
2142-
return filter(this.projectErrors, diagnostic => !diagnostic.file) || emptyArray;
2143-
}
2144-
2145-
/**
2146-
* Get all the project errors
2147-
*/
2148-
getAllProjectErrors(): readonly Diagnostic[] {
2149-
return this.projectErrors || emptyArray;
2150-
}
2151-
2152-
setProjectErrors(projectErrors: Diagnostic[]) {
2153-
this.projectErrors = projectErrors;
2154-
}
2155-
21562146
setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void {
21572147
this.typeAcquisition = this.removeLocalTypingsFromTypeAcquisition(newTypeAcquisition);
21582148
}
@@ -2186,7 +2176,6 @@ namespace ts.server {
21862176
}
21872177

21882178
this.stopWatchingWildCards();
2189-
this.projectErrors = undefined;
21902179
this.configFileSpecs = undefined;
21912180
this.openFileWatchTriggered.clear();
21922181
this.compilerHost = undefined;

0 commit comments

Comments
 (0)