Merge branch 'pvb/codeaction/api' into interfaceFixes

This commit is contained in:
Paul van Brenk
2016-10-11 17:37:22 -07:00
9 changed files with 514 additions and 60 deletions
+3 -3
View File
@@ -2223,9 +2223,9 @@ namespace ts {
if (currentFlow) {
node.flowNode = currentFlow;
}
checkStrictModeFunctionName(<FunctionExpression>node);
const bindingName = (<FunctionExpression>node).name ? (<FunctionExpression>node).name.text : "__function";
return bindAnonymousDeclaration(<FunctionExpression>node, SymbolFlags.Function, bindingName);
checkStrictModeFunctionName(node);
const bindingName = node.name ? node.name.text : "__function";
return bindAnonymousDeclaration(node, SymbolFlags.Function, bindingName);
}
function bindPropertyOrMethodOrAccessor(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
+1 -1
View File
@@ -5352,7 +5352,7 @@ namespace ts {
parseExpected(SyntaxKind.EqualsToken);
node.type = parseType();
parseSemicolon();
return finishNode(node);
return addJSDocComment(finishNode(node));
}
// In an ambient declaration, the grammar only allows integer literals as initializers.
+192 -4
View File
@@ -1,4 +1,4 @@
/// <reference path="..\harness.ts" />
/// <reference path="..\harness.ts" />
/// <reference path="../../server/typingsInstaller/typingsInstaller.ts" />
namespace ts.projectSystem {
@@ -136,6 +136,19 @@ namespace ts.projectSystem {
return map(fileNames, toExternalFile);
}
export class TestServerEventManager {
private events: server.ProjectServiceEvent[] = [];
handler: server.ProjectServiceEventHandler = (event: server.ProjectServiceEvent) => {
this.events.push(event);
}
checkEventCountOfType(eventType: "context" | "configFileDiag", expectedCount: number) {
const eventsOfType = filter(this.events, e => e.eventName === eventType);
assert.equal(eventsOfType.length, expectedCount, `The actual event counts of type ${eventType} is ${eventsOfType.length}, while expected ${expectedCount}`);
}
}
export interface TestServerHostCreationParameters {
useCaseSensitiveFileNames?: boolean;
executingFilePath?: string;
@@ -159,11 +172,11 @@ namespace ts.projectSystem {
return host;
}
export function createSession(host: server.ServerHost, typingsInstaller?: server.ITypingsInstaller) {
export function createSession(host: server.ServerHost, typingsInstaller?: server.ITypingsInstaller, projectServiceEventHandler?: server.ProjectServiceEventHandler) {
if (typingsInstaller === undefined) {
typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
}
return new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
return new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ projectServiceEventHandler !== undefined, projectServiceEventHandler);
}
export interface CreateProjectServiceParameters {
@@ -2084,7 +2097,7 @@ namespace ts.projectSystem {
const projectFileName = "externalProject";
const host = createServerHost([f]);
const projectService = createProjectService(host);
// create a project
// create a project
projectService.openExternalProject({ projectFileName, rootFiles: [toExternalFile(f.path)], options: {} });
projectService.checkNumberOfProjects({ externalProjects: 1 });
@@ -2121,4 +2134,179 @@ namespace ts.projectSystem {
projectService.inferredProjects[0].getLanguageService().getProgram();
});
});
describe("rename a module file and rename back", () => {
it("should restore the states for inferred projects", () => {
const moduleFile = {
path: "/a/b/moduleFile.ts",
content: "export function bar() { };"
};
const file1 = {
path: "/a/b/file1.ts",
content: "import * as T from './moduleFile'; T.bar();"
};
const host = createServerHost([moduleFile, file1]);
const session = createSession(host);
openFilesForSession([file1], session);
const getErrRequest = makeSessionRequest<server.protocol.SemanticDiagnosticsSyncRequestArgs>(
server.CommandNames.SemanticDiagnosticsSync,
{ file: file1.path }
);
let diags = <server.protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
assert.equal(diags.length, 0);
const moduleFileOldPath = moduleFile.path;
const moduleFileNewPath = "/a/b/moduleFile1.ts";
moduleFile.path = moduleFileNewPath;
host.reloadFS([moduleFile, file1]);
host.triggerFileWatcherCallback(moduleFileOldPath);
host.triggerDirectoryWatcherCallback("/a/b", moduleFile.path);
host.runQueuedTimeoutCallbacks();
diags = <server.protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
assert.equal(diags.length, 1);
moduleFile.path = moduleFileOldPath;
host.reloadFS([moduleFile, file1]);
host.triggerFileWatcherCallback(moduleFileNewPath);
host.triggerDirectoryWatcherCallback("/a/b", moduleFile.path);
host.runQueuedTimeoutCallbacks();
// Make a change to trigger the program rebuild
const changeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(
server.CommandNames.Change,
{ file: file1.path, line: 1, offset: 44, endLine: 1, endOffset: 44, insertString: "\n" }
);
session.executeCommand(changeRequest);
host.runQueuedTimeoutCallbacks();
diags = <server.protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
assert.equal(diags.length, 0);
});
it("should restore the states for configured projects", () => {
const moduleFile = {
path: "/a/b/moduleFile.ts",
content: "export function bar() { };"
};
const file1 = {
path: "/a/b/file1.ts",
content: "import * as T from './moduleFile'; T.bar();"
};
const configFile = {
path: "/a/b/tsconfig.json",
content: `{}`
};
const host = createServerHost([moduleFile, file1, configFile]);
const session = createSession(host);
openFilesForSession([file1], session);
const getErrRequest = makeSessionRequest<server.protocol.SemanticDiagnosticsSyncRequestArgs>(
server.CommandNames.SemanticDiagnosticsSync,
{ file: file1.path }
);
let diags = <server.protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
assert.equal(diags.length, 0);
const moduleFileOldPath = moduleFile.path;
const moduleFileNewPath = "/a/b/moduleFile1.ts";
moduleFile.path = moduleFileNewPath;
host.reloadFS([moduleFile, file1, configFile]);
host.triggerFileWatcherCallback(moduleFileOldPath);
host.triggerDirectoryWatcherCallback("/a/b", moduleFile.path);
host.runQueuedTimeoutCallbacks();
diags = <server.protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
assert.equal(diags.length, 1);
moduleFile.path = moduleFileOldPath;
host.reloadFS([moduleFile, file1, configFile]);
host.triggerFileWatcherCallback(moduleFileNewPath);
host.triggerDirectoryWatcherCallback("/a/b", moduleFile.path);
host.runQueuedTimeoutCallbacks();
diags = <server.protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
assert.equal(diags.length, 0);
});
});
describe("add the missing module file for inferred project", () => {
it("should remove the `module not found` error", () => {
const moduleFile = {
path: "/a/b/moduleFile.ts",
content: "export function bar() { };"
};
const file1 = {
path: "/a/b/file1.ts",
content: "import * as T from './moduleFile'; T.bar();"
};
const host = createServerHost([file1]);
const session = createSession(host);
openFilesForSession([file1], session);
const getErrRequest = makeSessionRequest<server.protocol.SemanticDiagnosticsSyncRequestArgs>(
server.CommandNames.SemanticDiagnosticsSync,
{ file: file1.path }
);
let diags = <server.protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
assert.equal(diags.length, 1);
host.reloadFS([file1, moduleFile]);
host.triggerDirectoryWatcherCallback(getDirectoryPath(file1.path), moduleFile.path);
host.runQueuedTimeoutCallbacks();
// Make a change to trigger the program rebuild
const changeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(
server.CommandNames.Change,
{ file: file1.path, line: 1, offset: 44, endLine: 1, endOffset: 44, insertString: "\n" }
);
session.executeCommand(changeRequest);
// Recheck
diags = <server.protocol.Diagnostic[]>session.executeCommand(getErrRequest).response;
assert.equal(diags.length, 0);
});
});
describe("Configure file diagnostics events", () => {
it("are generated when the config file has errors", () => {
const serverEventManager = new TestServerEventManager();
const file = {
path: "/a/b/app.ts",
content: "let x = 10"
};
const configFile = {
path: "/a/b/tsconfig.json",
content: `{
"compilerOptions": {
"foo": "bar",
"allowJS": true
}
}`
};
const host = createServerHost([file, configFile]);
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
openFilesForSession([file], session);
serverEventManager.checkEventCountOfType("configFileDiag", 1);
});
it("are generated when the config file doesn't have errors", () => {
const serverEventManager = new TestServerEventManager();
const file = {
path: "/a/b/app.ts",
content: "let x = 10"
};
const configFile = {
path: "/a/b/tsconfig.json",
content: `{
"compilerOptions": {}
}`
};
const host = createServerHost([file, configFile]);
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
openFilesForSession([file], session);
serverEventManager.checkEventCountOfType("configFileDiag", 1);
});
});
}
+12 -6
View File
@@ -180,6 +180,8 @@ namespace ts.server {
private toCanonicalFileName: (f: string) => string;
public lastDeletedFile: ScriptInfo;
constructor(public readonly host: ServerHost,
public readonly logger: Logger,
public readonly cancellationToken: HostCancellationToken,
@@ -272,7 +274,7 @@ namespace ts.server {
else {
projectsToUpdate = [];
for (const f of this.changedFiles) {
projectsToUpdate = projectsToUpdate.concat(f.containingProjects);
projectsToUpdate = projectsToUpdate.concat(f.containingProjects);
}
}
this.updateProjectGraphs(projectsToUpdate);
@@ -342,6 +344,7 @@ namespace ts.server {
if (!info.isOpen) {
this.filenameToScriptInfo.remove(info.path);
this.lastDeletedFile = info;
// capture list of projects since detachAllProjects will wipe out original list
const containingProjects = info.containingProjects.slice();
@@ -350,6 +353,7 @@ namespace ts.server {
// update projects to make sure that set of referenced files is correct
this.updateProjectGraphs(containingProjects);
this.lastDeletedFile = undefined;
if (!this.eventHandler) {
return;
@@ -755,12 +759,14 @@ namespace ts.server {
}
private reportConfigFileDiagnostics(configFileName: string, diagnostics: Diagnostic[], triggerFile?: string) {
if (diagnostics && diagnostics.length > 0) {
this.eventHandler({
eventName: "configFileDiag",
data: { configFileName, diagnostics, triggerFile }
});
if (!this.eventHandler) {
return;
}
this.eventHandler({
eventName: "configFileDiag",
data: { configFileName, diagnostics: diagnostics || [], triggerFile }
});
}
private createAndAddConfiguredProject(configFileName: NormalizedPath, projectOptions: ProjectOptions, configFileErrors: Diagnostic[], clientFileName?: string) {
+7 -3
View File
@@ -52,7 +52,7 @@ namespace ts.server {
};
}
private resolveNamesWithLocalCache<T extends { failedLookupLocations: string[] }, R>(
private resolveNamesWithLocalCache<T extends { failedLookupLocations: string[] }, R extends { resolvedFileName?: string }>(
names: string[],
containingFile: string,
cache: ts.FileMap<Map<T>>,
@@ -65,6 +65,7 @@ namespace ts.server {
const newResolutions: Map<T> = createMap<T>();
const resolvedModules: R[] = [];
const compilerOptions = this.getCompilationSettings();
const lastDeletedFileName = this.project.projectService.lastDeletedFile && this.project.projectService.lastDeletedFile.fileName;
for (const name of names) {
// check if this is a duplicate entry in the list
@@ -94,8 +95,11 @@ namespace ts.server {
return false;
}
if (getResult(resolution)) {
// TODO: consider checking failedLookupLocations
const result = getResult(resolution);
if (result) {
if (result.resolvedFileName && result.resolvedFileName === lastDeletedFileName) {
return false;
}
return true;
}
+274 -31
View File
@@ -1,4 +1,4 @@
/**
/**
* Declaration module describing the TypeScript Server protocol
*/
declare namespace ts.server.protocol {
@@ -98,19 +98,38 @@ declare namespace ts.server.protocol {
projectFileName?: string;
}
/**
* A request to get TODO comments from the file
*/
export interface TodoCommentRequest extends FileRequest {
arguments: TodoCommentRequestArgs;
}
/**
* Arguments for TodoCommentRequest request.
*/
export interface TodoCommentRequestArgs extends FileRequestArgs {
/**
* Array of target TodoCommentDescriptors that describes TODO comments to be found
*/
descriptors: TodoCommentDescriptor[];
}
/**
* A request to get indentation for a location in file
*/
export interface IndentationRequest extends FileLocationRequest {
arguments: IndentationRequestArgs;
}
/**
* Arguments for IndentationRequest request.
*/
export interface IndentationRequestArgs extends FileLocationRequestArgs {
/**
* An optional set of settings to be used when computing indentation.
* If argument is omitted - then it will use settings for file that were previously set via 'configure' request or global settings.
*/
options?: EditorSettings;
}
@@ -125,17 +144,26 @@ declare namespace ts.server.protocol {
}
/**
* A request to get the project information of the current file
* A request to get the project information of the current file.
*/
export interface ProjectInfoRequest extends Request {
arguments: ProjectInfoRequestArgs;
}
export interface ProjectRequest extends Request {
arguments: ProjectRequestArgs;
/**
* A request to retrieve compiler options diagnostics for a project
*/
export interface CompilerOptionsDiagnosticsRequest extends Request {
arguments: CompilerOptionsDiagnosticsRequestArgs;
}
export interface ProjectRequestArgs {
/**
* Arguments for CompilerOptionsDiagnosticsRequest request.
*/
export interface CompilerOptionsDiagnosticsRequestArgs {
/**
* Name of the project to retrieve compiler options diagnostics.
*/
projectFileName: string;
}
@@ -158,6 +186,11 @@ declare namespace ts.server.protocol {
languageServiceDisabled?: boolean;
}
/**
* Represents diagnostic info that includes location of diagnostic in two forms
* - start position and length of the error span
* - startLocation and endLocation - a pair of Location objects that store start/end line and offset of the error span.
*/
export interface DiagnosticWithLinePosition {
message: string;
start: number;
@@ -257,13 +290,25 @@ declare namespace ts.server.protocol {
arguments: FileLocationRequestArgs;
}
export interface FileSpanRequestArgs extends FileRequestArgs {
start: number;
length: number;
/**
* A request to get semantic diagnostics for a span in the file
*/
export interface SemanticDiagnosticsRequest extends FileRequest {
arguments: SemanticDiagnosticsRequestArgs;
}
export interface FileSpanRequest extends FileRequest {
arguments: FileSpanRequestArgs;
/**
* Arguments for SemanticDiagnosticsRequest request.
*/
export interface SemanticDiagnosticsRequestArgs extends FileRequestArgs {
/**
* Start position of the span.
*/
start: number;
/**
* Length of the span.
*/
length: number;
}
/**
@@ -355,11 +400,20 @@ declare namespace ts.server.protocol {
body?: FileSpan[];
}
/**
* Request to get brace completion for a location in the file.
*/
export interface BraceCompletionRequest extends FileLocationRequest {
arguments: BraceCompletionRequestArgs;
}
/**
* Argument for BraceCompletionRequest request.
*/
export interface BraceCompletionRequestArgs extends FileLocationRequestArgs {
/**
* Kind of opening brace
*/
openingBrace: string;
}
@@ -391,10 +445,17 @@ declare namespace ts.server.protocol {
arguments: DocumentHighlightsRequestArgs;
}
/**
* Span augmented with extra information that denotes the kind of the highlighting to be used for span.
* Kind is taken from HighlightSpanKind type.
*/
export interface HighlightSpan extends TextSpan {
kind: string;
}
/**
* Represents a set of highligh spans for a give name
*/
export interface DocumentHighlightsItem {
/**
* File containing highlight spans.
@@ -407,6 +468,9 @@ declare namespace ts.server.protocol {
highlightSpans: HighlightSpan[];
}
/**
* Response for a DocumentHighlightsRequest request.
*/
export interface DocumentHighlightsResponse extends Response {
body?: DocumentHighlightsItem[];
}
@@ -470,8 +534,17 @@ declare namespace ts.server.protocol {
body?: ReferencesResponseBody;
}
/**
* Argument for RenameRequest request.
*/
export interface RenameRequestArgs extends FileLocationRequestArgs {
/**
* Should text at specified location be found/changed in comments?
*/
findInComments?: boolean;
/**
* Should text at specified location be found/changed in strings?
*/
findInStrings?: boolean;
}
@@ -549,17 +622,53 @@ declare namespace ts.server.protocol {
body?: RenameResponseBody;
}
/**
* Represents a file in external project.
* External project is project whose set of files, compilation options and open\close state
* is maintained by the client (i.e. if all this data come from .csproj file in Visual Studio).
* External project will exist even if all files in it are closed and should be closed explicity.
* If external project includes one or more tsconfig.json/jsconfig.json files then tsserver will
* create configured project for every config file but will maintain a link that these projects were created
* as a result of opening external project so they should be removed once external project is closed.
*/
export interface ExternalFile {
/**
* Name of file file
*/
fileName: string;
/**
* Script kind of the file
*/
scriptKind?: ScriptKind;
/**
* Whether file has mixed content (i.e. .cshtml file that combines html markup with C#/JavaScript)
*/
hasMixedContent?: boolean;
/**
* Content of the file
*/
content?: string;
}
/**
* Represent an external project
*/
export interface ExternalProject {
/**
* Project name
*/
projectFileName: string;
/**
* List of root files in project
*/
rootFiles: ExternalFile[];
/**
* Compiler options for the project
*/
options: ExternalProjectCompilerOptions;
/**
* Explicitly specified typing options for the project
*/
typingOptions?: TypingOptions;
}
@@ -568,18 +677,45 @@ declare namespace ts.server.protocol {
* compiler settings.
*/
export interface ExternalProjectCompilerOptions extends CompilerOptions {
/**
* If compile on save is enabled for the project
*/
compileOnSave?: boolean;
}
/**
* Contains information about current project version
*/
export interface ProjectVersionInfo {
/**
* Project name
*/
projectName: string;
/**
* true if project is inferred or false if project is external or configured
*/
isInferred: boolean;
/**
* Project version
*/
version: number;
/**
* Current set of compiler options for project
*/
options: CompilerOptions;
}
/**
* Represents a set of changes that happen in project
*/
export interface ProjectChanges {
/**
* List of added files
*/
added: string[];
/**
* List of removed files
*/
removed: string[];
}
@@ -591,17 +727,41 @@ declare namespace ts.server.protocol {
* otherwise - assume that nothing is changed
*/
export interface ProjectFiles {
/**
* Information abount project verison
*/
info?: ProjectVersionInfo;
/**
* List of files in project (might be omitted if current state of project can be computed using only information from 'changes')
*/
files?: string[];
/**
* Set of changes in project (omitted if the entire set of files in project should be replaced)
*/
changes?: ProjectChanges;
}
/**
* Combines project information with project level errors.
*/
export interface ProjectFilesWithDiagnostics extends ProjectFiles {
/**
* List of errors in project
*/
projectErrors: DiagnosticWithLinePosition[];
}
/**
* Represents set of changes in open file
*/
export interface ChangedOpenFile {
/**
* Name of file
*/
fileName: string;
/**
* List of changes that should be applied to known open file
*/
changes: ts.TextChange[];
}
@@ -735,54 +895,117 @@ declare namespace ts.server.protocol {
arguments: OpenRequestArgs;
}
type OpenExternalProjectArgs = ExternalProject;
/**
* Request to open or update external project
*/
export interface OpenExternalProjectRequest extends Request {
arguments: OpenExternalProjectArgs;
}
export interface CloseExternalProjectRequestArgs {
projectFileName: string;
}
/**
* Arguments to OpenExternalProjectRequest request
*/
type OpenExternalProjectArgs = ExternalProject;
/**
* Request to open multiple external projects
*/
export interface OpenExternalProjectsRequest extends Request {
arguments: OpenExternalProjectsArgs;
}
/**
* Arguments to OpenExternalProjectsRequest
*/
export interface OpenExternalProjectsArgs {
/**
* List of external projects to open or update
*/
projects: ExternalProject[];
}
/**
* Request to close external project.
*/
export interface CloseExternalProjectRequest extends Request {
arguments: CloseExternalProjectRequestArgs;
}
/**
* Arguments to CloseExternalProjectRequest request
*/
export interface CloseExternalProjectRequestArgs {
/**
* Name of the project to close
*/
projectFileName: string;
}
/**
* Request to check if given list of projects is up-to-date and synchronize them if necessary
*/
export interface SynchronizeProjectListRequest extends Request {
arguments: SynchronizeProjectListRequestArgs;
}
/**
* Arguments to SynchronizeProjectListRequest
*/
export interface SynchronizeProjectListRequestArgs {
/**
* List of last known projects
*/
knownProjects: protocol.ProjectVersionInfo[];
}
/**
* Request to synchronize list of open files with the client
*/
export interface ApplyChangedToOpenFilesRequest extends Request {
arguments: ApplyChangedToOpenFilesRequestArgs;
}
/**
* Arguments to ApplyChangedToOpenFilesRequest
*/
export interface ApplyChangedToOpenFilesRequestArgs {
/**
* List of newly open files
*/
openFiles?: ExternalFile[];
/**
* List of open files files that were changes
*/
changedFiles?: ChangedOpenFile[];
/**
* List of files that were closed
*/
closedFiles?: string[];
}
export interface SetCompilerOptionsForInferredProjectsArgs {
options: ExternalProjectCompilerOptions;
}
/**
* Request to set compiler options for inferred projects.
* External projects are opened / closed explicitly.
* Configured projects are opened when user opens loose file that has 'tsconfig.json' or 'jsconfig.json' anywhere in one of containing folders.
* This configuration file will be used to obtain a list of files and configuration settings for the project.
* Inferred projects are created when user opens a loose file that is not the part of external project
* or configured project and will contain only open file and transitive closure of referenced files if 'useOneInferredProject' is false,
* or all open loose files and its transitive closure of referenced files if 'useOneInferredProject' is true.
*/
export interface SetCompilerOptionsForInferredProjectsRequest extends Request {
arguments: SetCompilerOptionsForInferredProjectsArgs;
}
/**
* Argument for SetCompilerOptionsForInferredProjectsRequest request.
*/
export interface SetCompilerOptionsForInferredProjectsArgs {
/**
* Compiler options to be used with inferred projects.
*/
options: ExternalProjectCompilerOptions;
}
/**
* Exit request; value of command field is "exit". Ask the server process
* to exit.
@@ -800,23 +1023,48 @@ declare namespace ts.server.protocol {
export interface CloseRequest extends FileRequest {
}
/**
* Request to obtain the list of files that should be regenerated if target file is recompiled.
* NOTE: this us query-only operation and does not generate any output on disk.
*/
export interface CompileOnSaveAffectedFileListRequest extends FileRequest {
}
/**
* Contains a list of files that should be regenerated in a project
*/
export interface CompileOnSaveAffectedFileListSingleProject {
/**
* Project name
*/
projectFileName: string;
/**
* List of files names that should be recompiled
*/
fileNames: string[];
}
/**
* Response for CompileOnSaveAffectedFileListRequest request;
*/
export interface CompileOnSaveAffectedFileListResponse extends Response {
body: CompileOnSaveAffectedFileListSingleProject[];
}
/**
* Request to recompile the file. All generated outputs (.js, .d.ts or .js.map files) is written on disk.
*/
export interface CompileOnSaveEmitFileRequest extends FileRequest {
args: CompileOnSaveEmitFileRequestArgs;
}
/**
* Arguments for CompileOnSaveEmitFileRequest
*/
export interface CompileOnSaveEmitFileRequestArgs extends FileRequestArgs {
/**
* if true - then file should be recompiled even if it does not have any changes.
*/
forced?: boolean;
}
@@ -885,7 +1133,14 @@ declare namespace ts.server.protocol {
*/
endOffset: number;
/**
* End position of the range for which to format text in file.
*/
endPosition?: number;
/**
* Format options to be used.
*/
options?: ts.FormatCodeOptions;
}
@@ -1592,16 +1847,4 @@ declare namespace ts.server.protocol {
export interface NavBarResponse extends Response {
body?: NavigationBarItem[];
}
export interface CodeAction {
/**
* Description of the code action to display in the UI of the editor.
*/
description: string;
/**
* Changes to apply to each file as part of the code action.
*/
changes: FileCodeEdits[];
}
}
+17 -11
View File
@@ -159,6 +159,8 @@ namespace ts.server {
private immediateId: any;
private changeSeq = 0;
private eventHander: ProjectServiceEventHandler;
constructor(
private host: ServerHost,
cancellationToken: HostCancellationToken,
@@ -167,17 +169,18 @@ namespace ts.server {
private byteLength: (buf: string, encoding?: string) => number,
private hrtime: (start?: number[]) => number[],
protected logger: Logger,
protected readonly canUseEvents: boolean) {
protected readonly canUseEvents: boolean,
eventHandler?: ProjectServiceEventHandler) {
const eventHandler: ProjectServiceEventHandler = canUseEvents
? event => this.handleEvent(event)
this.eventHander = canUseEvents
? eventHandler || (event => this.defaultEventHandler(event))
: undefined;
this.projectService = new ProjectService(host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, eventHandler);
this.projectService = new ProjectService(host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, this.eventHander);
this.gcTimer = new GcTimer(host, /*delay*/ 7000, logger);
}
private handleEvent(event: ProjectServiceEvent) {
private defaultEventHandler(event: ProjectServiceEvent) {
switch (event.eventName) {
case "context":
const { project, fileName } = event.data;
@@ -346,7 +349,7 @@ namespace ts.server {
}
}
private getEncodedSemanticClassifications(args: protocol.FileSpanRequestArgs) {
private getEncodedSemanticClassifications(args: protocol.SemanticDiagnosticsRequestArgs) {
const { file, project } = this.getFileAndProject(args);
return project.getLanguageService().getEncodedSemanticClassifications(file, args);
}
@@ -355,7 +358,7 @@ namespace ts.server {
return projectFileName && this.projectService.findProject(projectFileName);
}
private getCompilerOptionsDiagnostics(args: protocol.ProjectRequestArgs) {
private getCompilerOptionsDiagnostics(args: protocol.CompilerOptionsDiagnosticsRequestArgs) {
const project = this.getProject(args.projectFileName);
return this.convertToDiagnosticsWithLinePosition(project.getLanguageService().getCompilerOptionsDiagnostics(), /*scriptInfo*/ undefined);
}
@@ -738,8 +741,11 @@ namespace ts.server {
*/
private openClientFile(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind) {
const { configFileName, configFileErrors } = this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind);
if (configFileErrors) {
this.configFileDiagnosticEvent(fileName, configFileName, configFileErrors);
if (this.eventHander) {
this.eventHander({
eventName: "configFileDiag",
data: { fileName, configFileName, diagnostics: configFileErrors || [] }
});
}
}
@@ -1485,10 +1491,10 @@ namespace ts.server {
[CommandNames.SignatureHelpFull]: (request: protocol.SignatureHelpRequest) => {
return this.requiredResponse(this.getSignatureHelpItems(request.arguments, /*simplifiedResult*/ false));
},
[CommandNames.CompilerOptionsDiagnosticsFull]: (request: protocol.ProjectRequest) => {
[CommandNames.CompilerOptionsDiagnosticsFull]: (request: protocol.CompilerOptionsDiagnosticsRequest) => {
return this.requiredResponse(this.getCompilerOptionsDiagnostics(request.arguments));
},
[CommandNames.EncodedSemanticClassificationsFull]: (request: protocol.FileSpanRequest) => {
[CommandNames.EncodedSemanticClassificationsFull]: (request: protocol.SemanticDiagnosticsRequest) => {
return this.requiredResponse(this.getEncodedSemanticClassifications(request.arguments));
},
[CommandNames.Cleanup]: (request: protocol.Request) => {
+1 -1
View File
@@ -324,7 +324,7 @@ namespace ts.NavigationBar {
}
// More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times.
const collator: { compare(a: string, b: string): number } = typeof Intl === "undefined" ? undefined : new Intl.Collator();
const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator() : undefined;
// Intl is missing in Safari, and node 0.10 treats "a" as greater than "B".
const localeCompareIsCorrect = collator && collator.compare("a", "B") < 0;
const localeCompareFix: (a: string, b: string) => number = localeCompareIsCorrect ? collator.compare : function(a, b) {
@@ -0,0 +1,7 @@
///<reference path="fourslash.ts" />
/////** DOC */
////type /**/T = number
goTo.marker();
verify.quickInfoIs("type T = number", "DOC ");