Skip to content

Commit a40fab8

Browse files
author
Andy Hanson
committed
Support services settings
1 parent e26d4e4 commit a40fab8

16 files changed

+138
-70
lines changed

src/harness/fourslash.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,7 +1221,7 @@ Actual: ${stringify(fullActual)}`);
12211221
}
12221222

12231223
private getCompletionListAtCaret(options?: FourSlashInterface.CompletionsAtOptions): ts.CompletionInfo {
1224-
return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, options);
1224+
return this.languageService.getCompletionsAtPosition(this.activeFile.fileName, this.currentCaretPosition, options, options && options.settings);
12251225
}
12261226

12271227
private getCompletionEntryDetails(entryName: string, source?: string): ts.CompletionEntryDetails {
@@ -1818,7 +1818,7 @@ Actual: ${stringify(fullActual)}`);
18181818
}
18191819
else if (prevChar === " " && /A-Za-z_/.test(ch)) {
18201820
/* Completions */
1821-
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
1821+
this.languageService.getCompletionsAtPosition(this.activeFile.fileName, offset, ts.defaultCompletionOptions, ts.defaultServicesSettings);
18221822
}
18231823

18241824
if (i % checkCadence === 0) {
@@ -2393,7 +2393,7 @@ Actual: ${stringify(fullActual)}`);
23932393
public applyCodeActionFromCompletion(markerName: string, options: FourSlashInterface.VerifyCompletionActionOptions) {
23942394
this.goToMarker(markerName);
23952395

2396-
const actualCompletion = this.getCompletionListAtCaret({ includeExternalModuleExports: true, includeInsertTextCompletions: false }).entries.find(e =>
2396+
const actualCompletion = this.getCompletionListAtCaret({ ...ts.defaultCompletionOptions, includeExternalModuleExports: true }).entries.find(e =>
23972397
e.name === options.name && e.source === options.source);
23982398

23992399
if (!actualCompletion.hasAction) {
@@ -4618,6 +4618,7 @@ namespace FourSlashInterface {
46184618
export type ExpectedCompletionEntry = string | { name: string, insertText?: string, replacementSpan?: FourSlash.Range };
46194619
export interface CompletionsAtOptions extends ts.GetCompletionsAtPositionOptions {
46204620
isNewIdentifierLocation?: boolean;
4621+
settings?: ts.ServicesSettings;
46214622
}
46224623

46234624
export interface VerifyCompletionListContainsOptions extends ts.GetCompletionsAtPositionOptions {

src/harness/harnessLanguageService.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,8 @@ namespace Harness.LanguageService {
417417
getEncodedSemanticClassifications(fileName: string, span: ts.TextSpan): ts.Classifications {
418418
return unwrapJSONCallResult(this.shim.getEncodedSemanticClassifications(fileName, span.start, span.length));
419419
}
420-
getCompletionsAtPosition(fileName: string, position: number, options: ts.GetCompletionsAtPositionOptions | undefined): ts.CompletionInfo {
421-
return unwrapJSONCallResult(this.shim.getCompletionsAtPosition(fileName, position, options));
420+
getCompletionsAtPosition(fileName: string, position: number, options: ts.GetCompletionsAtPositionOptions | undefined, settings: ts.ServicesSettings): ts.CompletionInfo {
421+
return unwrapJSONCallResult(this.shim.getCompletionsAtPosition(fileName, position, options, settings));
422422
}
423423
getCompletionEntryDetails(fileName: string, position: number, entryName: string, options: ts.FormatCodeOptions | undefined, source: string | undefined): ts.CompletionEntryDetails {
424424
return unwrapJSONCallResult(this.shim.getCompletionEntryDetails(fileName, position, entryName, JSON.stringify(options), source));

src/harness/unittests/session.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ namespace ts.server {
145145

146146
session.onMessage(JSON.stringify(configureRequest));
147147

148-
assert.equal(session.getProjectService().getFormatCodeOptions().indentStyle, IndentStyle.Block);
148+
assert.equal(session.getProjectService().getFormatCodeOptions("" as NormalizedPath).indentStyle, IndentStyle.Block);
149149

150150
const setOptionsRequest: protocol.SetCompilerOptionsForInferredProjectsRequest = {
151151
command: CommandNames.CompilerOptionsForInferredProjects,

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,13 +1321,13 @@ namespace ts.projectSystem {
13211321
service.checkNumberOfProjects({ externalProjects: 1 });
13221322
checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]);
13231323

1324-
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
1324+
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultCompletionOptions, defaultServicesSettings);
13251325
// should contain completions for string
13261326
assert.isTrue(completions1.entries.some(e => e.name === "charAt"), "should contain 'charAt'");
13271327
assert.isFalse(completions1.entries.some(e => e.name === "toExponential"), "should not contain 'toExponential'");
13281328

13291329
service.closeClientFile(f2.path);
1330-
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
1330+
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 2, defaultCompletionOptions, defaultServicesSettings);
13311331
// should contain completions for string
13321332
assert.isFalse(completions2.entries.some(e => e.name === "charAt"), "should not contain 'charAt'");
13331333
assert.isTrue(completions2.entries.some(e => e.name === "toExponential"), "should contain 'toExponential'");
@@ -1353,11 +1353,11 @@ namespace ts.projectSystem {
13531353
service.checkNumberOfProjects({ externalProjects: 1 });
13541354
checkProjectActualFiles(service.externalProjects[0], [f1.path, f2.path, libFile.path]);
13551355

1356-
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
1356+
const completions1 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultCompletionOptions, defaultServicesSettings);
13571357
assert.isTrue(completions1.entries.some(e => e.name === "somelongname"), "should contain 'somelongname'");
13581358

13591359
service.closeClientFile(f2.path);
1360-
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
1360+
const completions2 = service.externalProjects[0].getLanguageService().getCompletionsAtPosition(f1.path, 0, defaultCompletionOptions, defaultServicesSettings);
13611361
assert.isFalse(completions2.entries.some(e => e.name === "somelongname"), "should not contain 'somelongname'");
13621362
const sf2 = service.externalProjects[0].getLanguageService().getProgram().getSourceFile(f2.path);
13631363
assert.equal(sf2.text, "");
@@ -1962,7 +1962,7 @@ namespace ts.projectSystem {
19621962

19631963
// Check identifiers defined in HTML content are available in .ts file
19641964
const project = configuredProjectAt(projectService, 0);
1965-
let completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 1, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
1965+
let completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 1, defaultCompletionOptions, defaultServicesSettings);
19661966
assert(completions && completions.entries[0].name === "hello", `expected entry hello to be in completion list`);
19671967

19681968
// Close HTML file
@@ -1976,7 +1976,7 @@ namespace ts.projectSystem {
19761976
checkProjectActualFiles(configuredProjectAt(projectService, 0), [file1.path, file2.path, config.path]);
19771977

19781978
// Check identifiers defined in HTML content are not available in .ts file
1979-
completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 5, { includeExternalModuleExports: false, includeInsertTextCompletions: false });
1979+
completions = project.getLanguageService().getCompletionsAtPosition(file1.path, 5, defaultCompletionOptions, defaultServicesSettings);
19801980
assert(completions && completions.entries[0].name !== "hello", `unexpected hello entry in completion list`);
19811981
});
19821982

@@ -2629,7 +2629,7 @@ namespace ts.projectSystem {
26292629
assert.equal(lastEvent.data.project, project, "project name");
26302630
assert.isFalse(lastEvent.data.languageServiceEnabled, "Language service state");
26312631

2632-
const options = projectService.getFormatCodeOptions();
2632+
const options = projectService.getFormatCodeOptions(f1.path as ts.server.NormalizedPath);
26332633
const edits = project.getLanguageService().getFormattingEditsForDocument(f1.path, options);
26342634
assert.deepEqual(edits, [{ span: createTextSpan(/*start*/ 7, /*length*/ 3), newText: " " }]);
26352635
});
@@ -3525,7 +3525,7 @@ namespace ts.projectSystem {
35253525
const projectService = createProjectService(host);
35263526
projectService.openClientFile(f1.path);
35273527

3528-
const defaultSettings = projectService.getFormatCodeOptions();
3528+
const defaultSettings = projectService.getFormatCodeOptions(f1.path as ts.server.NormalizedPath);
35293529

35303530
// set global settings
35313531
const newGlobalSettings1 = clone(defaultSettings);

src/server/editorServices.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ namespace ts.server {
200200

201201
export interface HostConfiguration {
202202
formatCodeOptions: FormatCodeSettings;
203+
servicesOptions: ServicesSettings;
203204
hostInfo: string;
204205
extraFileExtensions?: JsFileExtensionInfo[];
205206
}
@@ -442,6 +443,7 @@ namespace ts.server {
442443

443444
this.hostConfiguration = {
444445
formatCodeOptions: getDefaultFormatCodeSettings(this.host),
446+
servicesOptions: defaultServicesSettings,
445447
hostInfo: "Unknown host",
446448
extraFileExtensions: []
447449
};
@@ -703,15 +705,14 @@ namespace ts.server {
703705
return project.dirty && project.updateGraph();
704706
}
705707

706-
getFormatCodeOptions(file?: NormalizedPath) {
707-
let formatCodeSettings: FormatCodeSettings;
708-
if (file) {
709-
const info = this.getScriptInfoForNormalizedPath(file);
710-
if (info) {
711-
formatCodeSettings = info.getFormatCodeSettings();
712-
}
713-
}
714-
return formatCodeSettings || this.hostConfiguration.formatCodeOptions;
708+
getFormatCodeOptions(file: NormalizedPath) {
709+
const info = this.getScriptInfoForNormalizedPath(file);
710+
return info && info.getFormatCodeSettings() || this.hostConfiguration.formatCodeOptions;
711+
}
712+
713+
getServicesSettings(file: NormalizedPath) {
714+
const info = this.getScriptInfoForNormalizedPath(file);
715+
return info && info.getServicesSettings() || this.hostConfiguration.servicesOptions;
715716
}
716717

717718
private onSourceFileChanged(fileName: NormalizedPath, eventKind: FileWatcherEventKind) {
@@ -1829,7 +1830,7 @@ namespace ts.server {
18291830
if (args.file) {
18301831
const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file));
18311832
if (info) {
1832-
info.setFormatOptions(convertFormatOptions(args.formatOptions));
1833+
info.setSettings(convertFormatOptions(args.formatOptions), args.servicesOptions);
18331834
this.logger.info(`Host configuration update for file ${args.file}`);
18341835
}
18351836
}
@@ -1842,6 +1843,9 @@ namespace ts.server {
18421843
mergeMapLikes(this.hostConfiguration.formatCodeOptions, convertFormatOptions(args.formatOptions));
18431844
this.logger.info("Format host information updated");
18441845
}
1846+
if (args.servicesOptions) {
1847+
mergeMapLikes(this.hostConfiguration.servicesOptions, args.servicesOptions);
1848+
}
18451849
if (args.extraFileExtensions) {
18461850
this.hostConfiguration.extraFileExtensions = args.extraFileExtensions;
18471851
// We need to update the project structures again as it is possible that existing

src/server/protocol.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,8 @@ namespace ts.server.protocol {
12321232
*/
12331233
formatOptions?: FormatCodeSettings;
12341234

1235+
servicesOptions?: ServicesSettings;
1236+
12351237
/**
12361238
* The host's additional supported .js file extensions
12371239
*/
@@ -2588,6 +2590,10 @@ namespace ts.server.protocol {
25882590
insertSpaceBeforeTypeAnnotation?: boolean;
25892591
}
25902592

2593+
export interface ServicesSettings {
2594+
quote: '"' | "'";
2595+
}
2596+
25912597
export interface CompilerOptions {
25922598
allowJs?: boolean;
25932599
allowSyntheticDefaultImports?: boolean;

src/server/scriptInfo.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ namespace ts.server {
204204
* All projects that include this file
205205
*/
206206
readonly containingProjects: Project[] = [];
207-
private formatCodeSettings: FormatCodeSettings;
207+
private formatSettings: FormatCodeSettings | undefined;
208+
private servicesSettings: ServicesSettings | undefined;
208209

209210
/* @internal */
210211
fileWatcher: FileWatcher;
@@ -293,9 +294,8 @@ namespace ts.server {
293294
return this.realpath && this.realpath !== this.path ? this.realpath : undefined;
294295
}
295296

296-
getFormatCodeSettings() {
297-
return this.formatCodeSettings;
298-
}
297+
getFormatCodeSettings(): FormatCodeSettings { return this.formatSettings; }
298+
getServicesSettings(): ServicesSettings { return this.servicesSettings; }
299299

300300
attachToProject(project: Project): boolean {
301301
const isNew = !this.isAttached(project);
@@ -388,12 +388,19 @@ namespace ts.server {
388388
}
389389
}
390390

391-
setFormatOptions(formatSettings: FormatCodeSettings): void {
391+
setSettings(formatSettings: FormatCodeSettings, servicesSettings: ServicesSettings): void {
392392
if (formatSettings) {
393-
if (!this.formatCodeSettings) {
394-
this.formatCodeSettings = getDefaultFormatCodeSettings(this.host);
393+
if (!this.formatSettings) {
394+
this.formatSettings = getDefaultFormatCodeSettings(this.host);
395+
}
396+
mergeMapLikes(this.formatSettings, formatSettings);
397+
}
398+
399+
if (servicesSettings) {
400+
if (!this.servicesSettings) {
401+
this.servicesSettings = clone(defaultServicesSettings);
395402
}
396-
mergeMapLikes(this.formatCodeSettings, formatSettings);
403+
mergeMapLikes(this.servicesSettings, servicesSettings);
397404
}
398405
}
399406

0 commit comments

Comments
 (0)