Skip to content

Add survey event #26455

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion src/server/editorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace ts.server {

// tslint:disable variable-name
export const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground";
export const SurveyReady = "surveyReady";
export const LargeFileReferencedEvent = "largeFileReferenced";
export const ConfigFileDiagEvent = "configFileDiag";
export const ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
Expand All @@ -17,6 +18,11 @@ namespace ts.server {
data: { openFiles: string[]; };
}

export interface SurveyReady {
eventName: typeof SurveyReady;
data: { surveyId: string; };
}

export interface LargeFileReferencedEvent {
eventName: typeof LargeFileReferencedEvent;
data: { file: string; fileSize: number; maxFileSize: number; };
Expand Down Expand Up @@ -98,7 +104,7 @@ namespace ts.server {
readonly checkJs: boolean;
}

export type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
export type ProjectServiceEvent = LargeFileReferencedEvent | SurveyReady | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;

export type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void;

Expand Down Expand Up @@ -456,6 +462,9 @@ namespace ts.server {
/** Tracks projects that we have already sent telemetry for. */
private readonly seenProjects = createMap<true>();

/** Tracks projects that we have already sent survey events for. */
private readonly seenSurveyProjects = createMap<true>();

/*@internal*/
readonly watchFactory: WatchFactory<WatchType, Project>;

Expand Down Expand Up @@ -657,6 +666,14 @@ namespace ts.server {
this.eventHandler(event);
}

/* @internal */
sendSurveyReadyEvent(surveyId: string) {
if (!this.eventHandler) {
return;
}
this.eventHandler({ eventName: SurveyReady, data: { surveyId } });
}

/* @internal */
sendLargeFileReferencedEvent(file: string, fileSize: number) {
if (!this.eventHandler) {
Expand Down Expand Up @@ -1471,6 +1488,20 @@ namespace ts.server {
return project;
}

/*@internal*/
sendSurveyReady(project: ExternalProject | ConfiguredProject): void {
if (this.seenSurveyProjects.has(project.projectName)) {
return;
}

if (project.getCompilerOptions().checkJs !== undefined) {
const name = "checkJs";
this.logger.info(`Survey ${name} is ready`);
this.sendSurveyReadyEvent(name);
this.seenSurveyProjects.set(project.projectName, true);
}
}

/*@internal*/
sendProjectTelemetry(project: ExternalProject | ConfiguredProject): void {
if (this.seenProjects.has(project.projectName)) {
Expand Down
2 changes: 2 additions & 0 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,7 @@ namespace ts.server {
result = super.updateGraph();
}
this.projectService.sendProjectTelemetry(this);
this.projectService.sendSurveyReady(this);
return result;
}

Expand Down Expand Up @@ -1565,6 +1566,7 @@ namespace ts.server {
updateGraph() {
const result = super.updateGraph();
this.projectService.sendProjectTelemetry(this);
this.projectService.sendSurveyReady(this);
return result;
}

Expand Down
12 changes: 12 additions & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2436,6 +2436,18 @@ namespace ts.server.protocol {
openFiles: string[];
}

export type SurveyReadyEventName = "surveyReady";

export interface SurveyReadyEvent extends Event {
event: SurveyReadyEventName;
body: SurveyReadyEventBody;
}

export interface SurveyReadyEventBody {
/** Name of the survey. This is an internal machine- and programmer-friendly name */
surveyId: string;
}

export type LargeFileReferencedEventName = "largeFileReferenced";
export interface LargeFileReferencedEvent extends Event {
event: LargeFileReferencedEventName;
Expand Down
4 changes: 4 additions & 0 deletions src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,10 @@ namespace ts.server {
diagnostics: bakedDiags
}, "configFileDiag");
break;
case SurveyReady:
const { surveyId } = event.data;
this.event<protocol.SurveyReadyEventBody>({ surveyId }, "surveyReady");
break;
case ProjectLanguageServiceStateEvent: {
const eventName: protocol.ProjectLanguageServiceStateEventName = "projectLanguageServiceState";
this.event<protocol.ProjectLanguageServiceStateEventBody>({
Expand Down
117 changes: 116 additions & 1 deletion src/testRunner/unittests/tsserverProjectSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2846,7 +2846,7 @@ namespace ts.projectSystem {
const session = createSession(host, {
canUseEvents: true,
eventHandler: e => {
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectsUpdatedInBackgroundEvent || e.eventName === server.ProjectInfoTelemetryEvent || e.eventName === server.OpenFileInfoTelemetryEvent || e.eventName === server.LargeFileReferencedEvent) {
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectsUpdatedInBackgroundEvent || e.eventName === server.ProjectInfoTelemetryEvent || e.eventName === server.OpenFileInfoTelemetryEvent || e.eventName === server.LargeFileReferencedEvent || e.eventName === server.SurveyReady) {
return;
}
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
Expand Down Expand Up @@ -3496,6 +3496,121 @@ namespace ts.projectSystem {
}
});

function createSessionWithEventHandler(host: TestServerHost) {
const surveyEvents: server.SurveyReady[] = [];
const session = createSession(host, {
eventHandler: e => {
if (e.eventName === server.SurveyReady) {
surveyEvents.push(e);
}
}
});

return { session, verifySurveyReadyEvent };

function verifySurveyReadyEvent(numberOfEvents: number) {
assert.equal(surveyEvents.length, numberOfEvents);
const expectedEvents = numberOfEvents === 0 ? [] : [{
eventName: server.SurveyReady,
data: { surveyId: "checkJs" }
}];
assert.deepEqual(surveyEvents, expectedEvents);
}
}

it("doesn't log an event when checkJs isn't set", () => {
const projectRoot = "/user/username/projects/project";
const file: File = {
path: `${projectRoot}/src/file.ts`,
content: "export var y = 10;"
};
const tsconfig: File = {
path: `${projectRoot}/tsconfig.json`,
content: JSON.stringify({ compilerOptions: { } }),
};
const host = createServerHost([file, tsconfig]);
const { session, verifySurveyReadyEvent } = createSessionWithEventHandler(host);
const service = session.getProjectService();
openFilesForSession([file], session);
checkNumberOfProjects(service, { configuredProjects: 1 });
const project = service.configuredProjects.get(tsconfig.path)!;
checkProjectActualFiles(project, [file.path, tsconfig.path]);

verifySurveyReadyEvent(0);
});

it("logs an event when checkJs is set", () => {
const projectRoot = "/user/username/projects/project";
const file: File = {
path: `${projectRoot}/src/file.ts`,
content: "export var y = 10;"
};
const tsconfig: File = {
path: `${projectRoot}/tsconfig.json`,
content: JSON.stringify({ compilerOptions: { checkJs: true } }),
};
const host = createServerHost([file, tsconfig]);
const { session, verifySurveyReadyEvent } = createSessionWithEventHandler(host);
openFilesForSession([file], session);

verifySurveyReadyEvent(1);
});

it("logs an event when checkJs is set, only the first time", () => {
const projectRoot = "/user/username/projects/project";
const file: File = {
path: `${projectRoot}/src/file.ts`,
content: "export var y = 10;"
};
const rando: File = {
path: `/rando/calrissian.ts`,
content: "export function f() { }"
};
const tsconfig: File = {
path: `${projectRoot}/tsconfig.json`,
content: JSON.stringify({ compilerOptions: { checkJs: true } }),
};
const host = createServerHost([file, tsconfig]);
const { session, verifySurveyReadyEvent } = createSessionWithEventHandler(host);
openFilesForSession([file], session);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You want to check verifySurveyReadyEvent(1); here

verifySurveyReadyEvent(1);

closeFilesForSession([file], session);
openFilesForSession([rando], session);
openFilesForSession([file], session);

verifySurveyReadyEvent(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And verifySurveyReadyEvent(0) here ?

Copy link
Member Author

@sandersn sandersn Aug 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I only call createSessionWithEventHandler once, so I expect verifySurveyReadyEvent(1), verifySurveyReadyEvent(1) in the case that re-opening the project doesn't fire the survey event twice. It would be 1, then 2, if re-opening the project does fire the survey event twice.

So I think this line of code is already correct.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because createSessionWithEventHandler creates an array to push events into, so the length of the array never goes down as long as you are working with a verifySurveyReadyEvent from a single call to createSessionWithEventHandler.

});

it("logs an event when checkJs is set after closing and reopening", () => {
const projectRoot = "/user/username/projects/project";
const file: File = {
path: `${projectRoot}/src/file.ts`,
content: "export var y = 10;"
};
const rando: File = {
path: `/rando/calrissian.ts`,
content: "export function f() { }"
};
const tsconfig: File = {
path: `${projectRoot}/tsconfig.json`,
content: JSON.stringify({ }),
};
const host = createServerHost([file, tsconfig]);
const { session, verifySurveyReadyEvent } = createSessionWithEventHandler(host);
openFilesForSession([file], session);

verifySurveyReadyEvent(0);

closeFilesForSession([file], session);
openFilesForSession([rando], session);
host.writeFile(tsconfig.path, JSON.stringify({ compilerOptions: { checkJs: true } }));
openFilesForSession([file], session);

verifySurveyReadyEvent(1);
});

describe("CompileOnSaveAffectedFileListRequest with and without projectFileName in request", () => {
const projectRoot = "/user/username/projects/myproject";
const core: File = {
Expand Down
20 changes: 19 additions & 1 deletion tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7460,6 +7460,15 @@ declare namespace ts.server.protocol {
*/
openFiles: string[];
}
type SurveyReadyEventName = "surveyReady";
interface SurveyReadyEvent extends Event {
event: SurveyReadyEventName;
body: SurveyReadyEventBody;
}
interface SurveyReadyEventBody {
/** Name of the survey. This is an internal machine- and programmer-friendly name */
surveyId: string;
}
type LargeFileReferencedEventName = "largeFileReferenced";
interface LargeFileReferencedEvent extends Event {
event: LargeFileReferencedEventName;
Expand Down Expand Up @@ -8201,6 +8210,7 @@ declare namespace ts.server {
declare namespace ts.server {
const maxProgramSizeForNonTsFiles: number;
const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground";
const SurveyReady = "surveyReady";
const LargeFileReferencedEvent = "largeFileReferenced";
const ConfigFileDiagEvent = "configFileDiag";
const ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
Expand All @@ -8212,6 +8222,12 @@ declare namespace ts.server {
openFiles: string[];
};
}
interface SurveyReady {
eventName: typeof SurveyReady;
data: {
surveyId: string;
};
}
interface LargeFileReferencedEvent {
eventName: typeof LargeFileReferencedEvent;
data: {
Expand Down Expand Up @@ -8290,7 +8306,7 @@ declare namespace ts.server {
interface OpenFileInfo {
readonly checkJs: boolean;
}
type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
type ProjectServiceEvent = LargeFileReferencedEvent | SurveyReady | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void;
interface SafeList {
[name: string]: {
Expand Down Expand Up @@ -8409,6 +8425,8 @@ declare namespace ts.server {
readonly syntaxOnly?: boolean;
/** Tracks projects that we have already sent telemetry for. */
private readonly seenProjects;
/** Tracks projects that we have already sent survey events for. */
private readonly seenSurveyProjects;
constructor(opts: ProjectServiceOptions);
toPath(fileName: string): Path;
private loadTypesMap;
Expand Down