Skip to content

Commit 3a8ebf1

Browse files
committed
Merge pull request #7954 from zhengbli/supportScriptKindOnServer
Add API support for LS host to specify script kind of a file to open
2 parents d960200 + cc58e2d commit 3a8ebf1

File tree

9 files changed

+80
-28
lines changed

9 files changed

+80
-28
lines changed

src/harness/fourslash.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -362,14 +362,14 @@ namespace FourSlash {
362362
}
363363

364364
// Opens a file given its 0-based index or fileName
365-
public openFile(index: number, content?: string): void;
366-
public openFile(name: string, content?: string): void;
367-
public openFile(indexOrName: any, content?: string) {
365+
public openFile(index: number, content?: string, scriptKindName?: string): void;
366+
public openFile(name: string, content?: string, scriptKindName?: string): void;
367+
public openFile(indexOrName: any, content?: string, scriptKindName?: string) {
368368
const fileToOpen: FourSlashFile = this.findFile(indexOrName);
369369
fileToOpen.fileName = ts.normalizeSlashes(fileToOpen.fileName);
370370
this.activeFile = fileToOpen;
371371
// Let the host know that this file is now open
372-
this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content);
372+
this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content, scriptKindName);
373373
}
374374

375375
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) {
@@ -2790,10 +2790,10 @@ namespace FourSlashInterface {
27902790
// Opens a file, given either its index as it
27912791
// appears in the test source, or its filename
27922792
// as specified in the test metadata
2793-
public file(index: number, content?: string): void;
2794-
public file(name: string, content?: string): void;
2795-
public file(indexOrName: any, content?: string): void {
2796-
this.state.openFile(indexOrName, content);
2793+
public file(index: number, content?: string, scriptKindName?: string): void;
2794+
public file(name: string, content?: string, scriptKindName?: string): void;
2795+
public file(indexOrName: any, content?: string, scriptKindName?: string): void {
2796+
this.state.openFile(indexOrName, content, scriptKindName);
27972797
}
27982798
}
27992799

src/harness/harnessLanguageService.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ namespace Harness.LanguageService {
163163
throw new Error("No script with name '" + fileName + "'");
164164
}
165165

166-
public openFile(fileName: string, content?: string): void {
166+
public openFile(fileName: string, content?: string, scriptKindName?: string): void {
167167
}
168168

169169
/**
@@ -528,9 +528,9 @@ namespace Harness.LanguageService {
528528
this.client = client;
529529
}
530530

531-
openFile(fileName: string, content?: string): void {
532-
super.openFile(fileName, content);
533-
this.client.openFile(fileName, content);
531+
openFile(fileName: string, content?: string, scriptKindName?: "TS" | "JS" | "TSX" | "JSX"): void {
532+
super.openFile(fileName, content, scriptKindName);
533+
this.client.openFile(fileName, content, scriptKindName);
534534
}
535535

536536
editScript(fileName: string, start: number, end: number, newText: string) {

src/server/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ namespace ts.server {
120120
return response;
121121
}
122122

123-
openFile(fileName: string, content?: string): void {
124-
var args: protocol.OpenRequestArgs = { file: fileName, fileContent: content };
123+
openFile(fileName: string, content?: string, scriptKindName?: "TS" | "JS" | "TSX" | "JSX"): void {
124+
var args: protocol.OpenRequestArgs = { file: fileName, fileContent: content, scriptKindName };
125125
this.processRequest(CommandNames.Open, args);
126126
}
127127

src/server/editorServices.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace ts.server {
3434
fileWatcher: FileWatcher;
3535
formatCodeOptions = ts.clone(CompilerService.defaultFormatCodeOptions);
3636
path: Path;
37+
scriptKind: ScriptKind;
3738

3839
constructor(private host: ServerHost, public fileName: string, public content: string, public isOpen = false) {
3940
this.path = toPath(fileName, host.getCurrentDirectory(), createGetCanonicalFileName(host.useCaseSensitiveFileNames));
@@ -215,8 +216,16 @@ namespace ts.server {
215216
return this.roots.map(root => root.fileName);
216217
}
217218

218-
getScriptKind() {
219-
return ScriptKind.Unknown;
219+
getScriptKind(fileName: string) {
220+
const info = this.getScriptInfo(fileName);
221+
if (!info) {
222+
return undefined;
223+
}
224+
225+
if (!info.scriptKind) {
226+
info.scriptKind = getScriptKindFromFileName(fileName);
227+
}
228+
return info.scriptKind;
220229
}
221230

222231
getScriptVersion(filename: string) {
@@ -1013,7 +1022,7 @@ namespace ts.server {
10131022
* @param filename is absolute pathname
10141023
* @param fileContent is a known version of the file content that is more up to date than the one on disk
10151024
*/
1016-
openFile(fileName: string, openedByClient: boolean, fileContent?: string) {
1025+
openFile(fileName: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind) {
10171026
fileName = ts.normalizePath(fileName);
10181027
let info = ts.lookUp(this.filenameToScriptInfo, fileName);
10191028
if (!info) {
@@ -1028,6 +1037,7 @@ namespace ts.server {
10281037
}
10291038
if (content !== undefined) {
10301039
info = new ScriptInfo(this.host, fileName, content, openedByClient);
1040+
info.scriptKind = scriptKind;
10311041
info.setFormatOptions(this.getFormatCodeOptions());
10321042
this.filenameToScriptInfo[fileName] = info;
10331043
if (!info.isOpen) {
@@ -1077,9 +1087,9 @@ namespace ts.server {
10771087
* @param filename is absolute pathname
10781088
* @param fileContent is a known version of the file content that is more up to date than the one on disk
10791089
*/
1080-
openClientFile(fileName: string, fileContent?: string) {
1090+
openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind) {
10811091
this.openOrUpdateConfiguredProjectForFile(fileName);
1082-
const info = this.openFile(fileName, /*openedByClient*/ true, fileContent);
1092+
const info = this.openFile(fileName, /*openedByClient*/ true, fileContent, scriptKind);
10831093
this.addOpenFile(info);
10841094
this.printProjects();
10851095
return info;

src/server/protocol.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,11 @@ declare namespace ts.server.protocol {
518518
* Then the known content will be used upon opening instead of the disk copy
519519
*/
520520
fileContent?: string;
521+
/**
522+
* Used to specify the script kind of the file explicitly. It could be one of the following:
523+
* "TS", "JS", "TSX", "JSX"
524+
*/
525+
scriptKindName?: "TS" | "JS" | "TSX" | "JSX";
521526
}
522527

523528
/**

src/server/session.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -529,9 +529,9 @@ namespace ts.server {
529529
* @param fileName is the name of the file to be opened
530530
* @param fileContent is a version of the file content that is known to be more up to date than the one on disk
531531
*/
532-
private openClientFile(fileName: string, fileContent?: string) {
532+
private openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind) {
533533
const file = ts.normalizePath(fileName);
534-
this.projectService.openClientFile(file, fileContent);
534+
this.projectService.openClientFile(file, fileContent, scriptKind);
535535
}
536536

537537
private getQuickInfo(line: number, offset: number, fileName: string): protocol.QuickInfoResponseBody {
@@ -967,7 +967,22 @@ namespace ts.server {
967967
},
968968
[CommandNames.Open]: (request: protocol.Request) => {
969969
const openArgs = <protocol.OpenRequestArgs>request.arguments;
970-
this.openClientFile(openArgs.file, openArgs.fileContent);
970+
let scriptKind: ScriptKind;
971+
switch (openArgs.scriptKindName) {
972+
case "TS":
973+
scriptKind = ScriptKind.TS;
974+
break;
975+
case "JS":
976+
scriptKind = ScriptKind.JS;
977+
break;
978+
case "TSX":
979+
scriptKind = ScriptKind.TSX;
980+
break;
981+
case "JSX":
982+
scriptKind = ScriptKind.JSX;
983+
break;
984+
}
985+
this.openClientFile(openArgs.file, openArgs.fileContent, scriptKind);
971986
return {responseRequired: false};
972987
},
973988
[CommandNames.Quickinfo]: (request: protocol.Request) => {

src/services/utilities.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -858,12 +858,15 @@ namespace ts {
858858
}
859859

860860
export function getScriptKind(fileName: string, host?: LanguageServiceHost): ScriptKind {
861-
// First check to see if the script kind can be determined from the file name
862-
var scriptKind = getScriptKindFromFileName(fileName);
863-
if (scriptKind === ScriptKind.Unknown && host && host.getScriptKind) {
864-
// Next check to see if the host can resolve the script kind
861+
// First check to see if the script kind was specified by the host. Chances are the host
862+
// may override the default script kind for the file extension.
863+
let scriptKind: ScriptKind;
864+
if (host && host.getScriptKind) {
865865
scriptKind = host.getScriptKind(fileName);
866866
}
867+
if (!scriptKind || scriptKind === ScriptKind.Unknown) {
868+
scriptKind = getScriptKindFromFileName(fileName);
869+
}
867870
return ensureScriptKind(fileName, scriptKind);
868871
}
869872
}

tests/cases/fourslash/fourslash.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ declare namespace FourSlashInterface {
110110
type(definitionIndex?: number): void;
111111
position(position: number, fileIndex?: number): any;
112112
position(position: number, fileName?: string): any;
113-
file(index: number, content?: string): any;
114-
file(name: string, content?: string): any;
113+
file(index: number, content?: string, scriptKindName?: string): any;
114+
file(name: string, content?: string, scriptKindName?: string): any;
115115
}
116116
class verifyNegatable {
117117
private negative;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// <reference path="../fourslash.ts"/>
2+
3+
// Because the fourslash runner automatically opens the first file with the default setting,
4+
// to test the openFile function, the targeted file cannot be the first one.
5+
6+
// @Filename: dumbFile.ts
7+
//// var x;
8+
9+
// @allowJs: true
10+
// @Filename: test.ts
11+
//// /**
12+
//// * @type {number}
13+
//// */
14+
//// var t;
15+
//// t.
16+
17+
goTo.file("test.ts", /*content*/ undefined, "JS");
18+
goTo.eof();
19+
verify.completionListContains("toExponential");

0 commit comments

Comments
 (0)