Add API support for LS host to specify script kind of a file to open

This commit is contained in:
zhengbli 2016-04-07 23:01:20 -07:00
parent 58efc2ee05
commit a2035a572e
9 changed files with 80 additions and 28 deletions

View file

@ -358,14 +358,14 @@ namespace FourSlash {
}
// Opens a file given its 0-based index or fileName
public openFile(index: number, content?: string): void;
public openFile(name: string, content?: string): void;
public openFile(indexOrName: any, content?: string) {
public openFile(index: number, content?: string, scriptKindName?: string): void;
public openFile(name: string, content?: string, scriptKindName?: string): void;
public openFile(indexOrName: any, content?: string, scriptKindName?: string) {
const fileToOpen: FourSlashFile = this.findFile(indexOrName);
fileToOpen.fileName = ts.normalizeSlashes(fileToOpen.fileName);
this.activeFile = fileToOpen;
// Let the host know that this file is now open
this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content);
this.languageServiceAdapterHost.openFile(fileToOpen.fileName, content, scriptKindName);
}
public verifyErrorExistsBetweenMarkers(startMarkerName: string, endMarkerName: string, negative: boolean) {
@ -2755,10 +2755,10 @@ namespace FourSlashInterface {
// Opens a file, given either its index as it
// appears in the test source, or its filename
// as specified in the test metadata
public file(index: number, content?: string): void;
public file(name: string, content?: string): void;
public file(indexOrName: any, content?: string): void {
this.state.openFile(indexOrName, content);
public file(index: number, content?: string, scriptKindName?: string): void;
public file(name: string, content?: string, scriptKindName?: string): void;
public file(indexOrName: any, content?: string, scriptKindName?: string): void {
this.state.openFile(indexOrName, content, scriptKindName);
}
}

View file

@ -157,7 +157,7 @@ namespace Harness.LanguageService {
throw new Error("No script with name '" + fileName + "'");
}
public openFile(fileName: string, content?: string): void {
public openFile(fileName: string, content?: string, scriptKindName?: string): void {
}
/**
@ -496,9 +496,9 @@ namespace Harness.LanguageService {
this.client = client;
}
openFile(fileName: string, content?: string): void {
super.openFile(fileName, content);
this.client.openFile(fileName, content);
openFile(fileName: string, content?: string, scriptKindName?: string): void {
super.openFile(fileName, content, scriptKindName);
this.client.openFile(fileName, content, scriptKindName);
}
editScript(fileName: string, start: number, end: number, newText: string) {

View file

@ -120,8 +120,8 @@ namespace ts.server {
return response;
}
openFile(fileName: string, content?: string): void {
var args: protocol.OpenRequestArgs = { file: fileName, fileContent: content };
openFile(fileName: string, content?: string, scriptKindName?: string): void {
var args: protocol.OpenRequestArgs = { file: fileName, fileContent: content, scriptKindName };
this.processRequest(CommandNames.Open, args);
}

View file

@ -34,6 +34,7 @@ namespace ts.server {
fileWatcher: FileWatcher;
formatCodeOptions = ts.clone(CompilerService.defaultFormatCodeOptions);
path: Path;
scriptKind: ScriptKind;
constructor(private host: ServerHost, public fileName: string, public content: string, public isOpen = false) {
this.path = toPath(fileName, host.getCurrentDirectory(), createGetCanonicalFileName(host.useCaseSensitiveFileNames));
@ -192,8 +193,16 @@ namespace ts.server {
return this.roots.map(root => root.fileName);
}
getScriptKind() {
return ScriptKind.Unknown;
getScriptKind(fileName: string) {
const info = this.getScriptInfo(fileName);
if (!info) {
return undefined;
}
if (!info.scriptKind) {
info.scriptKind = getScriptKindFromFileName(fileName);
}
return info.scriptKind;
}
getScriptVersion(filename: string) {
@ -988,7 +997,7 @@ namespace ts.server {
* @param filename is absolute pathname
* @param fileContent is a known version of the file content that is more up to date than the one on disk
*/
openFile(fileName: string, openedByClient: boolean, fileContent?: string) {
openFile(fileName: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind) {
fileName = ts.normalizePath(fileName);
let info = ts.lookUp(this.filenameToScriptInfo, fileName);
if (!info) {
@ -1003,6 +1012,7 @@ namespace ts.server {
}
if (content !== undefined) {
info = new ScriptInfo(this.host, fileName, content, openedByClient);
info.scriptKind = scriptKind;
info.setFormatOptions(this.getFormatCodeOptions());
this.filenameToScriptInfo[fileName] = info;
if (!info.isOpen) {
@ -1052,9 +1062,9 @@ namespace ts.server {
* @param filename is absolute pathname
* @param fileContent is a known version of the file content that is more up to date than the one on disk
*/
openClientFile(fileName: string, fileContent?: string) {
openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind) {
this.openOrUpdateConfiguredProjectForFile(fileName);
const info = this.openFile(fileName, /*openedByClient*/ true, fileContent);
const info = this.openFile(fileName, /*openedByClient*/ true, fileContent, scriptKind);
this.addOpenFile(info);
this.printProjects();
return info;

View file

@ -518,6 +518,11 @@ declare namespace ts.server.protocol {
* Then the known content will be used upon opening instead of the disk copy
*/
fileContent?: string;
/**
* Used to specify the script kind of the file explicitly. It could be one of the following:
* ".ts", ".js", ".tsx", ".jsx"
*/
scriptKindName?: string;
}
/**

View file

@ -529,9 +529,9 @@ namespace ts.server {
* @param fileName is the name of the file to be opened
* @param fileContent is a version of the file content that is known to be more up to date than the one on disk
*/
private openClientFile(fileName: string, fileContent?: string) {
private openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind) {
const file = ts.normalizePath(fileName);
this.projectService.openClientFile(file, fileContent);
this.projectService.openClientFile(file, fileContent, scriptKind);
}
private getQuickInfo(line: number, offset: number, fileName: string): protocol.QuickInfoResponseBody {
@ -967,7 +967,22 @@ namespace ts.server {
},
[CommandNames.Open]: (request: protocol.Request) => {
const openArgs = <protocol.OpenRequestArgs>request.arguments;
this.openClientFile(openArgs.file, openArgs.fileContent);
let scriptKind: ScriptKind;
switch (openArgs.scriptKindName) {
case ".ts":
scriptKind = ScriptKind.TS;
break;
case ".js":
scriptKind = ScriptKind.JS;
break;
case ".tsx":
scriptKind = ScriptKind.TSX;
break;
case ".jsx":
scriptKind = ScriptKind.JSX;
break;
}
this.openClientFile(openArgs.file, openArgs.fileContent, scriptKind);
return {responseRequired: false};
},
[CommandNames.Quickinfo]: (request: protocol.Request) => {

View file

@ -818,12 +818,15 @@ namespace ts {
}
export function getScriptKind(fileName: string, host?: LanguageServiceHost): ScriptKind {
// First check to see if the script kind can be determined from the file name
var scriptKind = getScriptKindFromFileName(fileName);
if (scriptKind === ScriptKind.Unknown && host && host.getScriptKind) {
// Next check to see if the host can resolve the script kind
// First check to see if the script kind was specified by the host. Chances are the host
// may override the default script kind for the file extension.
let scriptKind: ScriptKind;
if (host && host.getScriptKind) {
scriptKind = host.getScriptKind(fileName);
}
if (!scriptKind || scriptKind === ScriptKind.Unknown) {
scriptKind = getScriptKindFromFileName(fileName);
}
return ensureScriptKind(fileName, scriptKind);
}
}

View file

@ -110,8 +110,8 @@ declare namespace FourSlashInterface {
type(definitionIndex?: number): void;
position(position: number, fileIndex?: number): any;
position(position: number, fileName?: string): any;
file(index: number, content?: string): any;
file(name: string, content?: string): any;
file(index: number, content?: string, scriptKindName?: string): any;
file(name: string, content?: string, scriptKindName?: string): any;
}
class verifyNegatable {
private negative;

View file

@ -0,0 +1,19 @@
/// <reference path="../fourslash.ts"/>
// Because the fourslash runner automatically opens the first file with the default setting,
// to test the openFile function, the targeted file cannot be the first one.
// @Filename: dumbFile.ts
//// var x;
// @allowJs: true
// @Filename: test.ts
//// /**
//// * @type {number}
//// */
//// var t;
//// t.
goTo.file("test.ts", /*content*/ undefined, ".js");
goTo.eof();
verify.completionListContains("toExponential");