Simplify event sent on background project update since its anyways just to update the error list
This commit is contained in:
parent
b536f9dade
commit
4f7c0e5e1c
|
@ -35,8 +35,6 @@ namespace ts {
|
||||||
|
|
||||||
/** Emit the changed files and clear the cache of the changed files */
|
/** Emit the changed files and clear the cache of the changed files */
|
||||||
emitChangedFiles(program: Program): EmitOutputDetailed[];
|
emitChangedFiles(program: Program): EmitOutputDetailed[];
|
||||||
/** Get the changed files since last query and then clear the cache of changed files */
|
|
||||||
getChangedProgramFiles(program: Program): ChangedProgramFiles;
|
|
||||||
/** When called gets the semantic diagnostics for the program. It also caches the diagnostics and manage them */
|
/** When called gets the semantic diagnostics for the program. It also caches the diagnostics and manage them */
|
||||||
getSemanticDiagnostics(program: Program, cancellationToken?: CancellationToken): Diagnostic[];
|
getSemanticDiagnostics(program: Program, cancellationToken?: CancellationToken): Diagnostic[];
|
||||||
|
|
||||||
|
@ -103,7 +101,6 @@ namespace ts {
|
||||||
getFilesAffectedBy,
|
getFilesAffectedBy,
|
||||||
emitFile,
|
emitFile,
|
||||||
emitChangedFiles,
|
emitChangedFiles,
|
||||||
getChangedProgramFiles,
|
|
||||||
getSemanticDiagnostics,
|
getSemanticDiagnostics,
|
||||||
clear
|
clear
|
||||||
};
|
};
|
||||||
|
@ -273,30 +270,6 @@ namespace ts {
|
||||||
return diagnostics || emptyArray;
|
return diagnostics || emptyArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getChangedProgramFiles(program: Program): ChangedProgramFiles {
|
|
||||||
ensureProgramGraph(program);
|
|
||||||
|
|
||||||
let filesToEmit: string[];
|
|
||||||
const changedFiles = createMap<string>();
|
|
||||||
enumerateChangedFilesEmitOutput(program, /*emitOnlyDtsFiles*/ true,
|
|
||||||
// All the changed files are required to get diagnostics
|
|
||||||
(changedFileName, changedFilePath) => addFileForDiagnostics(changedFileName, changedFilePath),
|
|
||||||
// Emitted file is for emit as well as diagnostic
|
|
||||||
(_emitOutput, sourceFile) => {
|
|
||||||
(filesToEmit || (filesToEmit = [])).push(sourceFile.fileName);
|
|
||||||
addFileForDiagnostics(sourceFile.fileName, sourceFile.path);
|
|
||||||
});
|
|
||||||
changedFileNames.clear();
|
|
||||||
return {
|
|
||||||
filesToEmit: filesToEmit || emptyArray,
|
|
||||||
changedFiles: arrayFrom(changedFiles.values())
|
|
||||||
};
|
|
||||||
|
|
||||||
function addFileForDiagnostics(fileName: string, path: Path) {
|
|
||||||
changedFiles.set(path, fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear() {
|
function clear() {
|
||||||
isModuleEmit = undefined;
|
isModuleEmit = undefined;
|
||||||
emitHandler = undefined;
|
emitHandler = undefined;
|
||||||
|
|
|
@ -2158,7 +2158,7 @@ namespace ts.projectSystem {
|
||||||
const session = createSession(host, {
|
const session = createSession(host, {
|
||||||
canUseEvents: true,
|
canUseEvents: true,
|
||||||
eventHandler: e => {
|
eventHandler: e => {
|
||||||
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectChangedEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
|
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectsUpdatedInBackgroundEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
|
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
|
||||||
|
@ -4819,7 +4819,7 @@ namespace ts.projectSystem {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("ProjectChangedEvent", () => {
|
describe("ProjectsChangedInBackground", () => {
|
||||||
function verifyFiles(caption: string, actual: ReadonlyArray<string>, expected: ReadonlyArray<string>) {
|
function verifyFiles(caption: string, actual: ReadonlyArray<string>, expected: ReadonlyArray<string>) {
|
||||||
assert.equal(actual.length, expected.length, `Incorrect number of ${caption}. Actual: ${actual} Expected: ${expected}`);
|
assert.equal(actual.length, expected.length, `Incorrect number of ${caption}. Actual: ${actual} Expected: ${expected}`);
|
||||||
const seen = createMap<true>();
|
const seen = createMap<true>();
|
||||||
|
@ -4830,7 +4830,7 @@ namespace ts.projectSystem {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createVerifyInitialOpen(session: TestSession, verifyProjectChangedEventHandler: (events: server.ProjectChangedEvent[]) => void) {
|
function createVerifyInitialOpen(session: TestSession, verifyProjectsUpdatedInBackgroundEventHandler: (events: server.ProjectsUpdatedInBackgroundEvent[]) => void) {
|
||||||
return (file: FileOrFolder) => {
|
return (file: FileOrFolder) => {
|
||||||
session.executeCommandSeq(<protocol.OpenRequest>{
|
session.executeCommandSeq(<protocol.OpenRequest>{
|
||||||
command: server.CommandNames.Open,
|
command: server.CommandNames.Open,
|
||||||
|
@ -4838,17 +4838,17 @@ namespace ts.projectSystem {
|
||||||
file: file.path
|
file: file.path
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
verifyProjectChangedEventHandler([]);
|
verifyProjectsUpdatedInBackgroundEventHandler([]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ProjectChangeEventVerifier {
|
interface ProjectsUpdatedInBackgroundEventVerifier {
|
||||||
session: TestSession;
|
session: TestSession;
|
||||||
verifyProjectChangedEventHandler(events: server.ProjectChangedEvent[]): void;
|
verifyProjectsUpdatedInBackgroundEventHandler(events: server.ProjectsUpdatedInBackgroundEvent[]): void;
|
||||||
verifyInitialOpen(file: FileOrFolder): void;
|
verifyInitialOpen(file: FileOrFolder): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyProjectChangedEvent(createSession: (host: TestServerHost) => ProjectChangeEventVerifier) {
|
function verifyProjectsUpdatedInBackgroundEvent(createSession: (host: TestServerHost) => ProjectsUpdatedInBackgroundEventVerifier) {
|
||||||
it("when adding new file", () => {
|
it("when adding new file", () => {
|
||||||
const commonFile1: FileOrFolder = {
|
const commonFile1: FileOrFolder = {
|
||||||
path: "/a/b/file1.ts",
|
path: "/a/b/file1.ts",
|
||||||
|
@ -4866,32 +4866,26 @@ namespace ts.projectSystem {
|
||||||
path: "/a/b/tsconfig.json",
|
path: "/a/b/tsconfig.json",
|
||||||
content: `{}`
|
content: `{}`
|
||||||
};
|
};
|
||||||
|
const openFiles = [commonFile1.path];
|
||||||
const host = createServerHost([commonFile1, libFile, configFile]);
|
const host = createServerHost([commonFile1, libFile, configFile]);
|
||||||
const { session, verifyProjectChangedEventHandler, verifyInitialOpen } = createSession(host, );
|
const { verifyProjectsUpdatedInBackgroundEventHandler, verifyInitialOpen } = createSession(host, );
|
||||||
const projectService = session.getProjectService();
|
|
||||||
verifyInitialOpen(commonFile1);
|
verifyInitialOpen(commonFile1);
|
||||||
|
|
||||||
host.reloadFS([commonFile1, libFile, configFile, commonFile2]);
|
host.reloadFS([commonFile1, libFile, configFile, commonFile2]);
|
||||||
host.runQueuedTimeoutCallbacks();
|
host.runQueuedTimeoutCallbacks();
|
||||||
// Since this is first event
|
verifyProjectsUpdatedInBackgroundEventHandler([{
|
||||||
const project = projectService.configuredProjects.get(configFile.path);
|
eventName: server.ProjectsUpdatedInBackgroundEvent,
|
||||||
verifyProjectChangedEventHandler([{
|
|
||||||
eventName: server.ProjectChangedEvent,
|
|
||||||
data: {
|
data: {
|
||||||
project,
|
openFiles
|
||||||
changedFiles: [libFile.path, commonFile1.path, commonFile2.path],
|
|
||||||
filesToEmit: [commonFile1.path, commonFile2.path]
|
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
host.reloadFS([commonFile1, commonFile2, libFile, configFile, commonFile3]);
|
host.reloadFS([commonFile1, commonFile2, libFile, configFile, commonFile3]);
|
||||||
host.runQueuedTimeoutCallbacks();
|
host.runQueuedTimeoutCallbacks();
|
||||||
verifyProjectChangedEventHandler([{
|
verifyProjectsUpdatedInBackgroundEventHandler([{
|
||||||
eventName: server.ProjectChangedEvent,
|
eventName: server.ProjectsUpdatedInBackgroundEvent,
|
||||||
data: {
|
data: {
|
||||||
project,
|
openFiles
|
||||||
changedFiles: [commonFile3.path],
|
|
||||||
filesToEmit: [commonFile3.path]
|
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
|
@ -4914,36 +4908,30 @@ namespace ts.projectSystem {
|
||||||
content: "export let y = 1"
|
content: "export let y = 1"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openFiles = [f1.path];
|
||||||
const files = [f1, config, libFile];
|
const files = [f1, config, libFile];
|
||||||
const host = createServerHost(files);
|
const host = createServerHost(files);
|
||||||
const { session, verifyInitialOpen, verifyProjectChangedEventHandler } = createSession(host);
|
const { verifyInitialOpen, verifyProjectsUpdatedInBackgroundEventHandler } = createSession(host);
|
||||||
const projectService = session.getProjectService();
|
|
||||||
verifyInitialOpen(f1);
|
verifyInitialOpen(f1);
|
||||||
|
|
||||||
files.push(f2);
|
files.push(f2);
|
||||||
host.reloadFS(files);
|
host.reloadFS(files);
|
||||||
host.runQueuedTimeoutCallbacks();
|
host.runQueuedTimeoutCallbacks();
|
||||||
|
|
||||||
// Since this is first event
|
verifyProjectsUpdatedInBackgroundEventHandler([{
|
||||||
const project = projectService.configuredProjects.get(config.path);
|
eventName: server.ProjectsUpdatedInBackgroundEvent,
|
||||||
verifyProjectChangedEventHandler([{
|
|
||||||
eventName: server.ProjectChangedEvent,
|
|
||||||
data: {
|
data: {
|
||||||
project,
|
openFiles
|
||||||
changedFiles: [libFile.path, f1.path, f2.path],
|
|
||||||
filesToEmit: [f1.path, f2.path]
|
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
f2.content = "export let x = 11";
|
f2.content = "export let x = 11";
|
||||||
host.reloadFS(files);
|
host.reloadFS(files);
|
||||||
host.runQueuedTimeoutCallbacks();
|
host.runQueuedTimeoutCallbacks();
|
||||||
verifyProjectChangedEventHandler([{
|
verifyProjectsUpdatedInBackgroundEventHandler([{
|
||||||
eventName: server.ProjectChangedEvent,
|
eventName: server.ProjectsUpdatedInBackgroundEvent,
|
||||||
data: {
|
data: {
|
||||||
project,
|
openFiles
|
||||||
changedFiles: [f2.path],
|
|
||||||
filesToEmit: [f2.path]
|
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
|
@ -4970,14 +4958,12 @@ namespace ts.projectSystem {
|
||||||
interface InitialStateParams {
|
interface InitialStateParams {
|
||||||
/** custom config file options */
|
/** custom config file options */
|
||||||
configObj?: any;
|
configObj?: any;
|
||||||
/** list of files emitted/changed on first update graph */
|
|
||||||
firstCompilationEmitFiles?: string[];
|
|
||||||
/** Additional files and folders to add */
|
/** Additional files and folders to add */
|
||||||
getAdditionalFileOrFolder?(): FileOrFolder[];
|
getAdditionalFileOrFolder?(): FileOrFolder[];
|
||||||
/** initial list of files to reload in fs and first file in this list being the file to open */
|
/** initial list of files to reload in fs and first file in this list being the file to open */
|
||||||
firstReloadFileList?: string[];
|
firstReloadFileList?: string[];
|
||||||
}
|
}
|
||||||
function getInitialState({ configObj = {}, getAdditionalFileOrFolder, firstReloadFileList, firstCompilationEmitFiles }: InitialStateParams = {}) {
|
function getInitialState({ configObj = {}, getAdditionalFileOrFolder, firstReloadFileList }: InitialStateParams = {}) {
|
||||||
const moduleFile1: FileOrFolder = {
|
const moduleFile1: FileOrFolder = {
|
||||||
path: moduleFile1Path,
|
path: moduleFile1Path,
|
||||||
content: "export function Foo() { };",
|
content: "export function Foo() { };",
|
||||||
|
@ -5015,20 +5001,19 @@ namespace ts.projectSystem {
|
||||||
const host = createServerHost([filesToReload[0], configFile]);
|
const host = createServerHost([filesToReload[0], configFile]);
|
||||||
|
|
||||||
// Initial project creation
|
// Initial project creation
|
||||||
const { session, verifyProjectChangedEventHandler, verifyInitialOpen } = createSession(host);
|
const { session, verifyProjectsUpdatedInBackgroundEventHandler, verifyInitialOpen } = createSession(host);
|
||||||
const projectService = session.getProjectService();
|
const openFiles = [filesToReload[0].path];
|
||||||
verifyInitialOpen(filesToReload[0]);
|
verifyInitialOpen(filesToReload[0]);
|
||||||
|
|
||||||
// Since this is first event, it will have all the files
|
// Since this is first event, it will have all the files
|
||||||
const firstFilesExpected = firstCompilationEmitFiles && getFiles(firstCompilationEmitFiles) || filesToReload;
|
verifyProjectsUpdatedInBackgroundEvent(filesToReload);
|
||||||
verifyProjectChangedEvent(firstFilesExpected, filesToReload);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile,
|
moduleFile1, file1Consumer1, file1Consumer2, moduleFile2, globalFile3, configFile,
|
||||||
files,
|
files,
|
||||||
updateContentOfOpenFile,
|
updateContentOfOpenFile,
|
||||||
verifyProjectChangedEvent,
|
verifyNoProjectsUpdatedInBackgroundEvent,
|
||||||
verifyAffectedAllFiles,
|
verifyProjectsUpdatedInBackgroundEvent
|
||||||
};
|
};
|
||||||
|
|
||||||
function getFiles(filelist: string[]) {
|
function getFiles(filelist: string[]) {
|
||||||
|
@ -5039,28 +5024,21 @@ namespace ts.projectSystem {
|
||||||
return find(files, file => file.path === fileName);
|
return find(files, file => file.path === fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyAffectedAllFiles() {
|
function verifyNoProjectsUpdatedInBackgroundEvent(filesToReload?: FileOrFolder[]) {
|
||||||
verifyProjectChangedEvent(filter(files, f => f !== libFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
function verifyProjectChangedEvent(filesToEmit: FileOrFolder[], filesToReload?: FileOrFolder[], additionalChangedFiles?: FileOrFolder[]) {
|
|
||||||
host.reloadFS(filesToReload || files);
|
host.reloadFS(filesToReload || files);
|
||||||
host.runQueuedTimeoutCallbacks();
|
host.runQueuedTimeoutCallbacks();
|
||||||
if (filesToEmit.length) {
|
verifyProjectsUpdatedInBackgroundEventHandler([]);
|
||||||
const project = projectService.configuredProjects.get(configFile.path);
|
}
|
||||||
const changedFiles = mapDefined(additionalChangedFiles ? filesToEmit.concat(additionalChangedFiles) : filesToEmit, f => f !== configFile ? f.path : undefined);
|
|
||||||
verifyProjectChangedEventHandler([{
|
function verifyProjectsUpdatedInBackgroundEvent(filesToReload?: FileOrFolder[]) {
|
||||||
eventName: server.ProjectChangedEvent,
|
host.reloadFS(filesToReload || files);
|
||||||
data: {
|
host.runQueuedTimeoutCallbacks();
|
||||||
project,
|
verifyProjectsUpdatedInBackgroundEventHandler([{
|
||||||
changedFiles,
|
eventName: server.ProjectsUpdatedInBackgroundEvent,
|
||||||
filesToEmit: mapDefined(filesToEmit, f => f !== libFile && f !== configFile ? f.path : undefined)
|
data: {
|
||||||
}
|
openFiles
|
||||||
}]);
|
}
|
||||||
}
|
}]);
|
||||||
else {
|
|
||||||
verifyProjectChangedEventHandler([]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateContentOfOpenFile(file: FileOrFolder, newContent: string) {
|
function updateContentOfOpenFile(file: FileOrFolder, newContent: string) {
|
||||||
|
@ -5080,35 +5058,35 @@ namespace ts.projectSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
it("should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", () => {
|
it("should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", () => {
|
||||||
const { moduleFile1, file1Consumer1, file1Consumer2, verifyProjectChangedEvent } = getInitialState();
|
const { moduleFile1, verifyProjectsUpdatedInBackgroundEvent } = getInitialState();
|
||||||
|
|
||||||
// Change the content of moduleFile1 to `export var T: number;export function Foo() { };`
|
// Change the content of moduleFile1 to `export var T: number;export function Foo() { };`
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1, file1Consumer1, file1Consumer2]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
|
|
||||||
// Change the content of moduleFile1 to `export var T: number;export function Foo() { console.log('hi'); };`
|
// Change the content of moduleFile1 to `export var T: number;export function Foo() { console.log('hi'); };`
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { console.log('hi'); };`;
|
moduleFile1.content = `export var T: number;export function Foo() { console.log('hi'); };`;
|
||||||
verifyProjectChangedEvent([moduleFile1]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be up-to-date with the reference map changes", () => {
|
it("should be up-to-date with the reference map changes", () => {
|
||||||
const { moduleFile1, file1Consumer1, file1Consumer2, updateContentOfOpenFile, verifyProjectChangedEvent } = getInitialState();
|
const { moduleFile1, file1Consumer1, updateContentOfOpenFile, verifyProjectsUpdatedInBackgroundEvent, verifyNoProjectsUpdatedInBackgroundEvent } = getInitialState();
|
||||||
|
|
||||||
// Change file1Consumer1 content to `export let y = Foo();`
|
// Change file1Consumer1 content to `export let y = Foo();`
|
||||||
updateContentOfOpenFile(file1Consumer1, "export let y = Foo();");
|
updateContentOfOpenFile(file1Consumer1, "export let y = Foo();");
|
||||||
verifyProjectChangedEvent([]);
|
verifyNoProjectsUpdatedInBackgroundEvent();
|
||||||
|
|
||||||
// Change the content of moduleFile1 to `export var T: number;export function Foo() { };`
|
// Change the content of moduleFile1 to `export var T: number;export function Foo() { };`
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1, file1Consumer2, file1Consumer1]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
|
|
||||||
// Add the import statements back to file1Consumer1
|
// Add the import statements back to file1Consumer1
|
||||||
updateContentOfOpenFile(file1Consumer1, `import {Foo} from "./moduleFile1";let y = Foo();`);
|
updateContentOfOpenFile(file1Consumer1, `import {Foo} from "./moduleFile1";let y = Foo();`);
|
||||||
verifyProjectChangedEvent([]);
|
verifyNoProjectsUpdatedInBackgroundEvent();
|
||||||
|
|
||||||
// Change the content of moduleFile1 to `export var T: number;export var T2: string;export function Foo() { };`
|
// Change the content of moduleFile1 to `export var T: number;export var T2: string;export function Foo() { };`
|
||||||
moduleFile1.content = `export var T: number;export var T2: string;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export var T2: string;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1, file1Consumer2, file1Consumer1]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
|
|
||||||
// Multiple file edits in one go:
|
// Multiple file edits in one go:
|
||||||
|
|
||||||
|
@ -5116,69 +5094,68 @@ namespace ts.projectSystem {
|
||||||
// Change the content of moduleFile1 to `export var T: number;export function Foo() { };`
|
// Change the content of moduleFile1 to `export var T: number;export function Foo() { };`
|
||||||
updateContentOfOpenFile(file1Consumer1, `export let y = Foo();`);
|
updateContentOfOpenFile(file1Consumer1, `export let y = Foo();`);
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1, file1Consumer1, file1Consumer2]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be up-to-date with deleted files", () => {
|
it("should be up-to-date with deleted files", () => {
|
||||||
const { moduleFile1, file1Consumer1, file1Consumer2, files, verifyProjectChangedEvent } = getInitialState();
|
const { moduleFile1, file1Consumer2, files, verifyProjectsUpdatedInBackgroundEvent } = getInitialState();
|
||||||
|
|
||||||
// Change the content of moduleFile1 to `export var T: number;export function Foo() { };`
|
// Change the content of moduleFile1 to `export var T: number;export function Foo() { };`
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
||||||
|
|
||||||
// Delete file1Consumer2
|
// Delete file1Consumer2
|
||||||
const filesToLoad = filter(files, file => file !== file1Consumer2);
|
const filesToLoad = filter(files, file => file !== file1Consumer2);
|
||||||
verifyProjectChangedEvent([moduleFile1, file1Consumer1], filesToLoad, [file1Consumer2]);
|
verifyProjectsUpdatedInBackgroundEvent(filesToLoad);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should be up-to-date with newly created files", () => {
|
it("should be up-to-date with newly created files", () => {
|
||||||
const { moduleFile1, file1Consumer1, file1Consumer2, files, verifyProjectChangedEvent, } = getInitialState();
|
const { moduleFile1, files, verifyProjectsUpdatedInBackgroundEvent, } = getInitialState();
|
||||||
|
|
||||||
const file1Consumer3: FileOrFolder = {
|
const file1Consumer3: FileOrFolder = {
|
||||||
path: "/a/b/file1Consumer3.ts",
|
path: "/a/b/file1Consumer3.ts",
|
||||||
content: `import {Foo} from "./moduleFile1"; let y = Foo();`
|
content: `import {Foo} from "./moduleFile1"; let y = Foo();`
|
||||||
};
|
};
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1, file1Consumer1, file1Consumer3, file1Consumer2], files.concat(file1Consumer3));
|
verifyProjectsUpdatedInBackgroundEvent(files.concat(file1Consumer3));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should detect changes in non-root files", () => {
|
it("should detect changes in non-root files", () => {
|
||||||
const { moduleFile1, file1Consumer1, verifyProjectChangedEvent } = getInitialState({
|
const { moduleFile1, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({
|
||||||
configObj: { files: [file1Consumer1Path] },
|
configObj: { files: [file1Consumer1Path] },
|
||||||
firstCompilationEmitFiles: [file1Consumer1Path, moduleFile1Path, libFile.path]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1, file1Consumer1]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
|
|
||||||
// change file1 internal, and verify only file1 is affected
|
// change file1 internal, and verify only file1 is affected
|
||||||
moduleFile1.content += "var T1: number;";
|
moduleFile1.content += "var T1: number;";
|
||||||
verifyProjectChangedEvent([moduleFile1]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return all files if a global file changed shape", () => {
|
it("should return all files if a global file changed shape", () => {
|
||||||
const { globalFile3, verifyAffectedAllFiles } = getInitialState();
|
const { globalFile3, verifyProjectsUpdatedInBackgroundEvent } = getInitialState();
|
||||||
|
|
||||||
globalFile3.content += "var T2: string;";
|
globalFile3.content += "var T2: string;";
|
||||||
verifyAffectedAllFiles();
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should always return the file itself if '--isolatedModules' is specified", () => {
|
it("should always return the file itself if '--isolatedModules' is specified", () => {
|
||||||
const { moduleFile1, verifyProjectChangedEvent } = getInitialState({
|
const { moduleFile1, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({
|
||||||
configObj: { compilerOptions: { isolatedModules: true } }
|
configObj: { compilerOptions: { isolatedModules: true } }
|
||||||
});
|
});
|
||||||
|
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should always return the file itself if '--out' or '--outFile' is specified", () => {
|
it("should always return the file itself if '--out' or '--outFile' is specified", () => {
|
||||||
const outFilePath = "/a/b/out.js";
|
const outFilePath = "/a/b/out.js";
|
||||||
const { moduleFile1, verifyProjectChangedEvent } = getInitialState({
|
const { moduleFile1, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({
|
||||||
configObj: { compilerOptions: { module: "system", outFile: outFilePath } }
|
configObj: { compilerOptions: { module: "system", outFile: outFilePath } }
|
||||||
});
|
});
|
||||||
|
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return cascaded affected file list", () => {
|
it("should return cascaded affected file list", () => {
|
||||||
|
@ -5186,21 +5163,21 @@ namespace ts.projectSystem {
|
||||||
path: "/a/b/file1Consumer1Consumer1.ts",
|
path: "/a/b/file1Consumer1Consumer1.ts",
|
||||||
content: `import {y} from "./file1Consumer1";`
|
content: `import {y} from "./file1Consumer1";`
|
||||||
};
|
};
|
||||||
const { moduleFile1, file1Consumer1, file1Consumer2, updateContentOfOpenFile, verifyProjectChangedEvent } = getInitialState({
|
const { moduleFile1, file1Consumer1, updateContentOfOpenFile, verifyNoProjectsUpdatedInBackgroundEvent, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({
|
||||||
getAdditionalFileOrFolder: () => [file1Consumer1Consumer1]
|
getAdditionalFileOrFolder: () => [file1Consumer1Consumer1]
|
||||||
});
|
});
|
||||||
|
|
||||||
updateContentOfOpenFile(file1Consumer1, file1Consumer1.content + "export var T: number;");
|
updateContentOfOpenFile(file1Consumer1, file1Consumer1.content + "export var T: number;");
|
||||||
verifyProjectChangedEvent([]);
|
verifyNoProjectsUpdatedInBackgroundEvent();
|
||||||
|
|
||||||
// Doesnt change the shape of file1Consumer1
|
// Doesnt change the shape of file1Consumer1
|
||||||
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
moduleFile1.content = `export var T: number;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1, file1Consumer1, file1Consumer2, file1Consumer1Consumer1]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
|
|
||||||
// Change both files before the timeout
|
// Change both files before the timeout
|
||||||
updateContentOfOpenFile(file1Consumer1, file1Consumer1.content + "export var T2: number;");
|
updateContentOfOpenFile(file1Consumer1, file1Consumer1.content + "export var T2: number;");
|
||||||
moduleFile1.content = `export var T2: number;export function Foo() { };`;
|
moduleFile1.content = `export var T2: number;export function Foo() { };`;
|
||||||
verifyProjectChangedEvent([moduleFile1, file1Consumer1, file1Consumer2, file1Consumer1Consumer1]);
|
verifyProjectsUpdatedInBackgroundEvent();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should work fine for files with circular references", () => {
|
it("should work fine for files with circular references", () => {
|
||||||
|
@ -5216,13 +5193,13 @@ namespace ts.projectSystem {
|
||||||
/// <reference path="./file1.ts" />
|
/// <reference path="./file1.ts" />
|
||||||
export var t2 = 10;`
|
export var t2 = 10;`
|
||||||
};
|
};
|
||||||
const { configFile, verifyProjectChangedEvent } = getInitialState({
|
const { configFile, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({
|
||||||
getAdditionalFileOrFolder: () => [file1, file2],
|
getAdditionalFileOrFolder: () => [file1, file2],
|
||||||
firstReloadFileList: [file1.path, libFile.path, file2.path, configFilePath]
|
firstReloadFileList: [file1.path, libFile.path, file2.path, configFilePath]
|
||||||
});
|
});
|
||||||
|
|
||||||
file2.content += "export var t3 = 10;";
|
file2.content += "export var t3 = 10;";
|
||||||
verifyProjectChangedEvent([file1, file2], [file1, file2, libFile, configFile]);
|
verifyProjectsUpdatedInBackgroundEvent([file1, file2, libFile, configFile]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should detect removed code file", () => {
|
it("should detect removed code file", () => {
|
||||||
|
@ -5232,12 +5209,12 @@ namespace ts.projectSystem {
|
||||||
/// <reference path="./moduleFile1.ts" />
|
/// <reference path="./moduleFile1.ts" />
|
||||||
export var x = Foo();`
|
export var x = Foo();`
|
||||||
};
|
};
|
||||||
const { configFile, verifyProjectChangedEvent, moduleFile1 } = getInitialState({
|
const { configFile, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({
|
||||||
getAdditionalFileOrFolder: () => [referenceFile1],
|
getAdditionalFileOrFolder: () => [referenceFile1],
|
||||||
firstReloadFileList: [referenceFile1.path, libFile.path, moduleFile1Path, configFilePath]
|
firstReloadFileList: [referenceFile1.path, libFile.path, moduleFile1Path, configFilePath]
|
||||||
});
|
});
|
||||||
|
|
||||||
verifyProjectChangedEvent([referenceFile1], [libFile, referenceFile1, configFile], [moduleFile1]);
|
verifyProjectsUpdatedInBackgroundEvent([libFile, referenceFile1, configFile]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should detect non-existing code file", () => {
|
it("should detect non-existing code file", () => {
|
||||||
|
@ -5247,16 +5224,16 @@ namespace ts.projectSystem {
|
||||||
/// <reference path="./moduleFile2.ts" />
|
/// <reference path="./moduleFile2.ts" />
|
||||||
export var x = Foo();`
|
export var x = Foo();`
|
||||||
};
|
};
|
||||||
const { configFile, moduleFile2, updateContentOfOpenFile, verifyProjectChangedEvent } = getInitialState({
|
const { configFile, moduleFile2, updateContentOfOpenFile, verifyNoProjectsUpdatedInBackgroundEvent, verifyProjectsUpdatedInBackgroundEvent } = getInitialState({
|
||||||
getAdditionalFileOrFolder: () => [referenceFile1],
|
getAdditionalFileOrFolder: () => [referenceFile1],
|
||||||
firstReloadFileList: [referenceFile1.path, libFile.path, configFilePath]
|
firstReloadFileList: [referenceFile1.path, libFile.path, configFilePath]
|
||||||
});
|
});
|
||||||
|
|
||||||
updateContentOfOpenFile(referenceFile1, referenceFile1.content + "export var yy = Foo();");
|
updateContentOfOpenFile(referenceFile1, referenceFile1.content + "export var yy = Foo();");
|
||||||
verifyProjectChangedEvent([], [libFile, referenceFile1, configFile]);
|
verifyNoProjectsUpdatedInBackgroundEvent([libFile, referenceFile1, configFile]);
|
||||||
|
|
||||||
// Create module File2 and see both files are saved
|
// Create module File2 and see both files are saved
|
||||||
verifyProjectChangedEvent([referenceFile1, moduleFile2], [libFile, moduleFile2, referenceFile1, configFile]);
|
verifyProjectsUpdatedInBackgroundEvent([libFile, moduleFile2, referenceFile1, configFile]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5280,9 +5257,10 @@ namespace ts.projectSystem {
|
||||||
};
|
};
|
||||||
|
|
||||||
const projectFiles = [file1, file3, libFile, configFile];
|
const projectFiles = [file1, file3, libFile, configFile];
|
||||||
|
const openFiles = [file1.path];
|
||||||
const watchedRecursiveDirectories = ["/a/b/project", "/a/b/node_modules", "/a/node_modules", "/node_modules"];
|
const watchedRecursiveDirectories = ["/a/b/project", "/a/b/node_modules", "/a/node_modules", "/node_modules"];
|
||||||
const host = createServerHost(projectFiles);
|
const host = createServerHost(projectFiles);
|
||||||
const { session, verifyInitialOpen, verifyProjectChangedEventHandler } = createSession(host);
|
const { session, verifyInitialOpen, verifyProjectsUpdatedInBackgroundEventHandler } = createSession(host);
|
||||||
const projectService = session.getProjectService();
|
const projectService = session.getProjectService();
|
||||||
verifyInitialOpen(file1);
|
verifyInitialOpen(file1);
|
||||||
checkNumberOfProjects(projectService, { configuredProjects: 1 });
|
checkNumberOfProjects(projectService, { configuredProjects: 1 });
|
||||||
|
@ -5298,12 +5276,10 @@ namespace ts.projectSystem {
|
||||||
|
|
||||||
// Since this is first event
|
// Since this is first event
|
||||||
verifyProject();
|
verifyProject();
|
||||||
verifyProjectChangedEventHandler([{
|
verifyProjectsUpdatedInBackgroundEventHandler([{
|
||||||
eventName: server.ProjectChangedEvent,
|
eventName: server.ProjectsUpdatedInBackgroundEvent,
|
||||||
data: {
|
data: {
|
||||||
project,
|
openFiles
|
||||||
changedFiles: [libFile.path, file1.path, file3.path],
|
|
||||||
filesToEmit: [file1.path, file3.path]
|
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
@ -5313,13 +5289,10 @@ namespace ts.projectSystem {
|
||||||
watchedRecursiveDirectories.length = 2;
|
watchedRecursiveDirectories.length = 2;
|
||||||
verifyProject();
|
verifyProject();
|
||||||
|
|
||||||
const changedFiles = [file1.path, file2.path];
|
verifyProjectsUpdatedInBackgroundEventHandler([{
|
||||||
verifyProjectChangedEventHandler([{
|
eventName: server.ProjectsUpdatedInBackgroundEvent,
|
||||||
eventName: server.ProjectChangedEvent,
|
|
||||||
data: {
|
data: {
|
||||||
project,
|
openFiles
|
||||||
changedFiles,
|
|
||||||
filesToEmit: changedFiles
|
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
|
@ -5341,13 +5314,13 @@ namespace ts.projectSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("when event handler is set in the session", () => {
|
describe("when event handler is set in the session", () => {
|
||||||
verifyProjectChangedEvent(createSessionWithProjectChangedEventHandler);
|
verifyProjectsUpdatedInBackgroundEvent(createSessionWithProjectChangedEventHandler);
|
||||||
|
|
||||||
function createSessionWithProjectChangedEventHandler(host: TestServerHost): ProjectChangeEventVerifier {
|
function createSessionWithProjectChangedEventHandler(host: TestServerHost): ProjectsUpdatedInBackgroundEventVerifier {
|
||||||
const projectChangedEvents: server.ProjectChangedEvent[] = [];
|
const projectChangedEvents: server.ProjectsUpdatedInBackgroundEvent[] = [];
|
||||||
const session = createSession(host, {
|
const session = createSession(host, {
|
||||||
eventHandler: e => {
|
eventHandler: e => {
|
||||||
if (e.eventName === server.ProjectChangedEvent) {
|
if (e.eventName === server.ProjectsUpdatedInBackgroundEvent) {
|
||||||
projectChangedEvents.push(e);
|
projectChangedEvents.push(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5355,34 +5328,24 @@ namespace ts.projectSystem {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
session,
|
session,
|
||||||
verifyProjectChangedEventHandler,
|
verifyProjectsUpdatedInBackgroundEventHandler,
|
||||||
verifyInitialOpen: createVerifyInitialOpen(session, verifyProjectChangedEventHandler)
|
verifyInitialOpen: createVerifyInitialOpen(session, verifyProjectsUpdatedInBackgroundEventHandler)
|
||||||
};
|
};
|
||||||
|
|
||||||
function eventToString(event: server.ProjectChangedEvent) {
|
function eventToString(event: server.ProjectsUpdatedInBackgroundEvent) {
|
||||||
const eventToModify = event && {
|
return JSON.stringify(event && { eventName: event.eventName, data: event.data });
|
||||||
eventName: event.eventName,
|
|
||||||
data: {
|
|
||||||
project: event.data.project.getProjectName(),
|
|
||||||
changedFiles: event.data.changedFiles,
|
|
||||||
filesToEmit: event.data.filesToEmit
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return JSON.stringify(eventToModify);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function eventsToString(events: ReadonlyArray<server.ProjectChangedEvent>) {
|
function eventsToString(events: ReadonlyArray<server.ProjectsUpdatedInBackgroundEvent>) {
|
||||||
return "[" + map(events, eventToString).join(",") + "]";
|
return "[" + map(events, eventToString).join(",") + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyProjectChangedEventHandler(expectedEvents: ReadonlyArray<server.ProjectChangedEvent>) {
|
function verifyProjectsUpdatedInBackgroundEventHandler(expectedEvents: ReadonlyArray<server.ProjectsUpdatedInBackgroundEvent>) {
|
||||||
assert.equal(projectChangedEvents.length, expectedEvents.length, `Incorrect number of events Actual: ${eventsToString(projectChangedEvents)} Expected: ${eventsToString(expectedEvents)}`);
|
assert.equal(projectChangedEvents.length, expectedEvents.length, `Incorrect number of events Actual: ${eventsToString(projectChangedEvents)} Expected: ${eventsToString(expectedEvents)}`);
|
||||||
forEach(projectChangedEvents, (actualEvent, i) => {
|
forEach(projectChangedEvents, (actualEvent, i) => {
|
||||||
const expectedEvent = expectedEvents[i];
|
const expectedEvent = expectedEvents[i];
|
||||||
assert.strictEqual(actualEvent.eventName, expectedEvent.eventName);
|
assert.strictEqual(actualEvent.eventName, expectedEvent.eventName);
|
||||||
assert.strictEqual(actualEvent.data.project, expectedEvent.data.project);
|
verifyFiles("openFiles", actualEvent.data.openFiles, expectedEvent.data.openFiles);
|
||||||
verifyFiles("changedFiles", actualEvent.data.changedFiles, expectedEvent.data.changedFiles);
|
|
||||||
verifyFiles("filesToEmit", actualEvent.data.filesToEmit, expectedEvent.data.filesToEmit);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verified the events, reset them
|
// Verified the events, reset them
|
||||||
|
@ -5392,41 +5355,37 @@ namespace ts.projectSystem {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when event handler is not set but session is created with canUseEvents = true", () => {
|
describe("when event handler is not set but session is created with canUseEvents = true", () => {
|
||||||
verifyProjectChangedEvent(createSessionThatUsesEvents);
|
verifyProjectsUpdatedInBackgroundEvent(createSessionThatUsesEvents);
|
||||||
|
|
||||||
function createSessionThatUsesEvents(host: TestServerHost): ProjectChangeEventVerifier {
|
function createSessionThatUsesEvents(host: TestServerHost): ProjectsUpdatedInBackgroundEventVerifier {
|
||||||
const session = createSession(host, { canUseEvents: true });
|
const session = createSession(host, { canUseEvents: true });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
session,
|
session,
|
||||||
verifyProjectChangedEventHandler,
|
verifyProjectsUpdatedInBackgroundEventHandler,
|
||||||
verifyInitialOpen: createVerifyInitialOpen(session, verifyProjectChangedEventHandler)
|
verifyInitialOpen: createVerifyInitialOpen(session, verifyProjectsUpdatedInBackgroundEventHandler)
|
||||||
};
|
};
|
||||||
|
|
||||||
function verifyProjectChangedEventHandler(expected: ReadonlyArray<server.ProjectChangedEvent>) {
|
function verifyProjectsUpdatedInBackgroundEventHandler(expected: ReadonlyArray<server.ProjectsUpdatedInBackgroundEvent>) {
|
||||||
const expectedEvents: protocol.ProjectChangedEventBody[] = map(expected, e => {
|
const expectedEvents: protocol.ProjectsUpdatedInBackgroundEventBody[] = map(expected, e => {
|
||||||
return {
|
return {
|
||||||
projectName: e.data.project.getProjectName(),
|
openFiles: e.data.openFiles
|
||||||
changedFiles: e.data.changedFiles,
|
|
||||||
fileNamesToEmit: e.data.filesToEmit
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const outputEventRegex = /Content\-Length: [\d]+\r\n\r\n/;
|
const outputEventRegex = /Content\-Length: [\d]+\r\n\r\n/;
|
||||||
const events: protocol.ProjectStructureChangedEvent[] = filter(
|
const events: protocol.ProjectsUpdatedInBackgroundEvent[] = filter(
|
||||||
map(
|
map(
|
||||||
host.getOutput(), s => convertToObject(
|
host.getOutput(), s => convertToObject(
|
||||||
ts.parseJsonText("json.json", s.replace(outputEventRegex, "")),
|
ts.parseJsonText("json.json", s.replace(outputEventRegex, "")),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
e => e.event === server.ProjectChangedEvent
|
e => e.event === server.ProjectsUpdatedInBackgroundEvent
|
||||||
);
|
);
|
||||||
assert.equal(events.length, expectedEvents.length, `Incorrect number of events Actual: ${map(events, e => e.body)} Expected: ${expectedEvents}`);
|
assert.equal(events.length, expectedEvents.length, `Incorrect number of events Actual: ${map(events, e => e.body)} Expected: ${expectedEvents}`);
|
||||||
forEach(events, (actualEvent, i) => {
|
forEach(events, (actualEvent, i) => {
|
||||||
const expectedEvent = expectedEvents[i];
|
const expectedEvent = expectedEvents[i];
|
||||||
assert.strictEqual(actualEvent.body.projectName, expectedEvent.projectName);
|
verifyFiles("openFiles", actualEvent.body.openFiles, expectedEvent.openFiles);
|
||||||
verifyFiles("changedFiles", actualEvent.body.changedFiles, expectedEvent.changedFiles);
|
|
||||||
verifyFiles("fileNamesToEmit", actualEvent.body.fileNamesToEmit, expectedEvent.fileNamesToEmit);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verified the events, reset them
|
// Verified the events, reset them
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
namespace ts.server {
|
namespace ts.server {
|
||||||
export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
|
export const maxProgramSizeForNonTsFiles = 20 * 1024 * 1024;
|
||||||
|
|
||||||
export const ProjectChangedEvent = "projectChanged";
|
export const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground";
|
||||||
export const ConfigFileDiagEvent = "configFileDiag";
|
export const ConfigFileDiagEvent = "configFileDiag";
|
||||||
export const ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
|
export const ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
|
||||||
export const ProjectInfoTelemetryEvent = "projectInfo";
|
export const ProjectInfoTelemetryEvent = "projectInfo";
|
||||||
|
|
||||||
export interface ProjectChangedEvent {
|
export interface ProjectsUpdatedInBackgroundEvent {
|
||||||
eventName: typeof ProjectChangedEvent;
|
eventName: typeof ProjectsUpdatedInBackgroundEvent;
|
||||||
data: { project: Project; filesToEmit: string[]; changedFiles: string[] };
|
data: { openFiles: string[]; };
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConfigFileDiagEvent {
|
export interface ConfigFileDiagEvent {
|
||||||
|
@ -76,7 +76,7 @@ namespace ts.server {
|
||||||
readonly dts: number;
|
readonly dts: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProjectServiceEvent = ProjectChangedEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent;
|
export type ProjectServiceEvent = ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent;
|
||||||
|
|
||||||
export interface ProjectServiceEventHandler {
|
export interface ProjectServiceEventHandler {
|
||||||
(event: ProjectServiceEvent): void;
|
(event: ProjectServiceEvent): void;
|
||||||
|
@ -517,9 +517,14 @@ namespace ts.server {
|
||||||
if (this.pendingProjectUpdates.size !== 0) {
|
if (this.pendingProjectUpdates.size !== 0) {
|
||||||
this.delayInferredProjectsRefresh();
|
this.delayInferredProjectsRefresh();
|
||||||
}
|
}
|
||||||
else if (this.pendingInferredProjectUpdate) {
|
else {
|
||||||
this.pendingInferredProjectUpdate = false;
|
if (this.pendingInferredProjectUpdate) {
|
||||||
this.refreshInferredProjects();
|
this.pendingInferredProjectUpdate = false;
|
||||||
|
this.refreshInferredProjects();
|
||||||
|
}
|
||||||
|
// Send the event to notify that there were background project updates
|
||||||
|
// send current list of open files
|
||||||
|
this.sendProjectsUpdatedInBackgroundEvent();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -531,27 +536,18 @@ namespace ts.server {
|
||||||
if (this.pendingProjectUpdates.delete(projectName)) {
|
if (this.pendingProjectUpdates.delete(projectName)) {
|
||||||
project.updateGraph();
|
project.updateGraph();
|
||||||
}
|
}
|
||||||
// Send the update event to notify about the project changes
|
|
||||||
this.sendProjectChangedEvent(project);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendProjectChangedEvent(project: Project) {
|
private sendProjectsUpdatedInBackgroundEvent() {
|
||||||
if (project.isClosed() || !this.eventHandler || !project.languageServiceEnabled) {
|
if (!this.eventHandler) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { filesToEmit, changedFiles } = project.getChangedFiles();
|
const event: ProjectsUpdatedInBackgroundEvent = {
|
||||||
if (changedFiles.length === 0) {
|
eventName: ProjectsUpdatedInBackgroundEvent,
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const event: ProjectChangedEvent = {
|
|
||||||
eventName: ProjectChangedEvent,
|
|
||||||
data: {
|
data: {
|
||||||
project,
|
openFiles: this.openFiles.map(f => f.fileName)
|
||||||
filesToEmit: filesToEmit as string[],
|
|
||||||
changedFiles: changedFiles as string[]
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.eventHandler(event);
|
this.eventHandler(event);
|
||||||
|
|
|
@ -457,12 +457,6 @@ namespace ts.server {
|
||||||
return !emitSkipped;
|
return !emitSkipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
getChangedFiles() {
|
|
||||||
Debug.assert(this.languageServiceEnabled);
|
|
||||||
this.ensureBuilder();
|
|
||||||
return this.builder.getChangedProgramFiles(this.program);
|
|
||||||
}
|
|
||||||
|
|
||||||
enableLanguageService() {
|
enableLanguageService() {
|
||||||
if (this.languageServiceEnabled) {
|
if (this.languageServiceEnabled) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2040,27 +2040,17 @@ namespace ts.server.protocol {
|
||||||
languageServiceEnabled: boolean;
|
languageServiceEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ProjectChangedEventName = "projectChanged";
|
export type ProjectsUpdatedInBackgroundEventName = "projectsUpdatedInBackground";
|
||||||
export interface ProjectStructureChangedEvent extends Event {
|
export interface ProjectsUpdatedInBackgroundEvent extends Event {
|
||||||
event: ProjectChangedEventName;
|
event: ProjectsUpdatedInBackgroundEventName;
|
||||||
body: ProjectChangedEventBody;
|
body: ProjectsUpdatedInBackgroundEventBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProjectChangedEventBody {
|
export interface ProjectsUpdatedInBackgroundEventBody {
|
||||||
/**
|
/**
|
||||||
* Project name that has changes
|
* Current set of open files
|
||||||
*/
|
*/
|
||||||
projectName: string;
|
openFiles: string[];
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum set of file names to emit
|
|
||||||
*/
|
|
||||||
fileNamesToEmit: string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of files that have changed/added/removed or could have been affected by the changed files
|
|
||||||
*/
|
|
||||||
changedFiles: string[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -332,9 +332,9 @@ namespace ts.server {
|
||||||
|
|
||||||
private defaultEventHandler(event: ProjectServiceEvent) {
|
private defaultEventHandler(event: ProjectServiceEvent) {
|
||||||
switch (event.eventName) {
|
switch (event.eventName) {
|
||||||
case ProjectChangedEvent:
|
case ProjectsUpdatedInBackgroundEvent:
|
||||||
const { project, filesToEmit, changedFiles } = event.data;
|
const { openFiles } = event.data;
|
||||||
this.projectChangedEvent(project, filesToEmit, changedFiles);
|
this.projectsUpdatedInBackgroundEvent(openFiles);
|
||||||
break;
|
break;
|
||||||
case ConfigFileDiagEvent:
|
case ConfigFileDiagEvent:
|
||||||
const { triggerFile, configFileName: configFile, diagnostics } = event.data;
|
const { triggerFile, configFileName: configFile, diagnostics } = event.data;
|
||||||
|
@ -364,21 +364,19 @@ namespace ts.server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private projectChangedEvent(project: Project, fileNamesToEmit: string[], changedFiles: string[]): void {
|
private projectsUpdatedInBackgroundEvent(openFiles: string[]): void {
|
||||||
this.projectService.logger.info(`got project changed event, updating diagnostics for ${changedFiles}`);
|
this.projectService.logger.info(`got projects updated in background, updating diagnostics for ${openFiles}`);
|
||||||
if (changedFiles.length) {
|
if (openFiles.length) {
|
||||||
const checkList = this.createCheckList(changedFiles, project);
|
const checkList = this.createCheckList(openFiles);
|
||||||
|
|
||||||
// For now only queue error checking for open files. We can change this to include non open files as well
|
// For now only queue error checking for open files. We can change this to include non open files as well
|
||||||
this.errorCheck.startNew(next => this.updateErrorCheck(next, checkList, 100, /*requireOpen*/ true));
|
this.errorCheck.startNew(next => this.updateErrorCheck(next, checkList, 100, /*requireOpen*/ true));
|
||||||
|
|
||||||
|
|
||||||
// Send project changed event
|
// Send project changed event
|
||||||
this.event<protocol.ProjectChangedEventBody>({
|
this.event<protocol.ProjectsUpdatedInBackgroundEventBody>({
|
||||||
projectName: project.getProjectName(),
|
openFiles
|
||||||
changedFiles,
|
}, "projectsUpdatedInBackground");
|
||||||
fileNamesToEmit
|
|
||||||
}, "projectChanged");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue