mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'pvb/codeaction/api' into interfaceFixes
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+274
-31
@@ -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
@@ -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) => {
|
||||
|
||||
@@ -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 ");
|
||||
Reference in New Issue
Block a user