Merge pull request #26197 from Microsoft/largeFileEvent
Send event on referencing large file
This commit is contained in:
commit
f2011ce755
|
@ -5,6 +5,7 @@ namespace ts.server {
|
|||
|
||||
// tslint:disable variable-name
|
||||
export const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground";
|
||||
export const LargeFileReferencedEvent = "largeFileReferenced";
|
||||
export const ConfigFileDiagEvent = "configFileDiag";
|
||||
export const ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
|
||||
export const ProjectInfoTelemetryEvent = "projectInfo";
|
||||
|
@ -16,6 +17,11 @@ namespace ts.server {
|
|||
data: { openFiles: string[]; };
|
||||
}
|
||||
|
||||
export interface LargeFileReferencedEvent {
|
||||
eventName: typeof LargeFileReferencedEvent;
|
||||
data: { file: string; fileSize: number; maxFileSize: number; };
|
||||
}
|
||||
|
||||
export interface ConfigFileDiagEvent {
|
||||
eventName: typeof ConfigFileDiagEvent;
|
||||
data: { triggerFile: string, configFileName: string, diagnostics: ReadonlyArray<Diagnostic> };
|
||||
|
@ -92,7 +98,7 @@ namespace ts.server {
|
|||
readonly checkJs: boolean;
|
||||
}
|
||||
|
||||
export type ProjectServiceEvent = ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
|
||||
export type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
|
||||
|
||||
export type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void;
|
||||
|
||||
|
@ -645,6 +651,19 @@ namespace ts.server {
|
|||
this.eventHandler(event);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
sendLargeFileReferencedEvent(file: string, fileSize: number) {
|
||||
if (!this.eventHandler) {
|
||||
return;
|
||||
}
|
||||
|
||||
const event: LargeFileReferencedEvent = {
|
||||
eventName: LargeFileReferencedEvent,
|
||||
data: { file, fileSize, maxFileSize }
|
||||
};
|
||||
this.eventHandler(event);
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
delayUpdateProjectGraphAndEnsureProjectStructureForOpenFiles(project: Project) {
|
||||
this.delayUpdateProjectGraph(project);
|
||||
|
|
|
@ -2436,6 +2436,27 @@ namespace ts.server.protocol {
|
|||
openFiles: string[];
|
||||
}
|
||||
|
||||
export type LargeFileReferencedEventName = "largeFileReferenced";
|
||||
export interface LargeFileReferencedEvent extends Event {
|
||||
event: LargeFileReferencedEventName;
|
||||
body: LargeFileReferencedEventBody;
|
||||
}
|
||||
|
||||
export interface LargeFileReferencedEventBody {
|
||||
/**
|
||||
* name of the large file being loaded
|
||||
*/
|
||||
file: string;
|
||||
/**
|
||||
* size of the file
|
||||
*/
|
||||
fileSize: number;
|
||||
/**
|
||||
* max file size allowed on the server
|
||||
*/
|
||||
maxFileSize: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments for reload request.
|
||||
*/
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace ts.server {
|
|||
*/
|
||||
private pendingReloadFromDisk: boolean;
|
||||
|
||||
constructor(private readonly host: ServerHost, private readonly fileName: NormalizedPath, initialVersion?: ScriptInfoVersion) {
|
||||
constructor(private readonly host: ServerHost, private readonly fileName: NormalizedPath, initialVersion: ScriptInfoVersion | undefined, private readonly info: ScriptInfo) {
|
||||
this.version = initialVersion || { svc: 0, text: 0 };
|
||||
}
|
||||
|
||||
|
@ -164,9 +164,17 @@ namespace ts.server {
|
|||
|
||||
private getFileText(tempFileName?: string) {
|
||||
let text: string;
|
||||
const getText = () => text === undefined ? (text = this.host.readFile(tempFileName || this.fileName) || "") : text;
|
||||
const size = this.host.getFileSize ? this.host.getFileSize(tempFileName || this.fileName) : getText().length;
|
||||
return size > maxFileSize ? "" : getText();
|
||||
const fileName = tempFileName || this.fileName;
|
||||
const getText = () => text === undefined ? (text = this.host.readFile(fileName) || "") : text;
|
||||
const fileSize = this.host.getFileSize ? this.host.getFileSize(fileName) : getText().length;
|
||||
if (fileSize > maxFileSize) {
|
||||
Debug.assert(!!this.info.containingProjects.length);
|
||||
const service = this.info.containingProjects[0].projectService;
|
||||
service.logger.info(`Skipped loading contents of large file ${fileName} for info ${this.info.fileName}: fileSize: ${fileSize}`);
|
||||
this.info.containingProjects[0].projectService.sendLargeFileReferencedEvent(fileName, fileSize);
|
||||
return "";
|
||||
}
|
||||
return getText();
|
||||
}
|
||||
|
||||
private switchToScriptVersionCache(): ScriptVersionCache {
|
||||
|
@ -248,7 +256,7 @@ namespace ts.server {
|
|||
initialVersion?: ScriptInfoVersion) {
|
||||
this.isDynamic = isDynamicFileName(fileName);
|
||||
|
||||
this.textStorage = new TextStorage(host, fileName, initialVersion);
|
||||
this.textStorage = new TextStorage(host, fileName, initialVersion, this);
|
||||
if (hasMixedContent || this.isDynamic) {
|
||||
this.textStorage.reload("");
|
||||
this.realpath = this.path;
|
||||
|
|
|
@ -559,6 +559,10 @@ namespace ts.server {
|
|||
const { openFiles } = event.data;
|
||||
this.projectsUpdatedInBackgroundEvent(openFiles);
|
||||
break;
|
||||
case LargeFileReferencedEvent:
|
||||
const { file, fileSize, maxFileSize } = event.data;
|
||||
this.event<protocol.LargeFileReferencedEventBody>({ file, fileSize, maxFileSize }, "largeFileReferenced");
|
||||
break;
|
||||
case ConfigFileDiagEvent:
|
||||
const { triggerFile, configFileName: configFile, diagnostics } = event.data;
|
||||
const bakedDiags = map(diagnostics, diagnostic => formatConfigFileDiag(diagnostic, /*includeFileName*/ true));
|
||||
|
|
|
@ -13,9 +13,9 @@ namespace ts.textStorage {
|
|||
it("text based storage should be have exactly the same as script version cache", () => {
|
||||
|
||||
const host = projectSystem.createServerHost([f]);
|
||||
|
||||
const ts1 = new server.TextStorage(host, server.asNormalizedPath(f.path));
|
||||
const ts2 = new server.TextStorage(host, server.asNormalizedPath(f.path));
|
||||
// Since script info is not used in these tests, just cheat by passing undefined
|
||||
const ts1 = new server.TextStorage(host, server.asNormalizedPath(f.path), /*initialVersion*/ undefined, /*info*/undefined!);
|
||||
const ts2 = new server.TextStorage(host, server.asNormalizedPath(f.path), /*initialVersion*/ undefined, /*info*/undefined!);
|
||||
|
||||
ts1.useScriptVersionCache_TestOnly();
|
||||
ts2.useText();
|
||||
|
@ -48,7 +48,8 @@ namespace ts.textStorage {
|
|||
|
||||
it("should switch to script version cache if necessary", () => {
|
||||
const host = projectSystem.createServerHost([f]);
|
||||
const ts1 = new server.TextStorage(host, server.asNormalizedPath(f.path));
|
||||
// Since script info is not used in these tests, just cheat by passing undefined
|
||||
const ts1 = new server.TextStorage(host, server.asNormalizedPath(f.path), /*initialVersion*/ undefined, /*info*/undefined!);
|
||||
|
||||
ts1.getSnapshot();
|
||||
assert.isTrue(!ts1.hasScriptVersionCache_TestOnly(), "should not have script version cache - 1");
|
||||
|
|
|
@ -2843,7 +2843,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) {
|
||||
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectsUpdatedInBackgroundEvent || e.eventName === server.ProjectInfoTelemetryEvent || e.eventName === server.OpenFileInfoTelemetryEvent || e.eventName === server.LargeFileReferencedEvent) {
|
||||
return;
|
||||
}
|
||||
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
|
||||
|
@ -9028,6 +9028,27 @@ export const x = 10;`
|
|||
fileSize: server.maxFileSize + 1
|
||||
};
|
||||
|
||||
function createSessionWithEventHandler(host: TestServerHost) {
|
||||
const largeFileReferencedEvents: server.LargeFileReferencedEvent[] = [];
|
||||
const session = createSession(host, {
|
||||
eventHandler: e => {
|
||||
if (e.eventName === server.LargeFileReferencedEvent) {
|
||||
largeFileReferencedEvents.push(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { session, verifyLargeFileReferencedEvent };
|
||||
|
||||
function verifyLargeFileReferencedEvent() {
|
||||
assert.equal(largeFileReferencedEvents.length, 1);
|
||||
assert.deepEqual(largeFileReferencedEvents, [{
|
||||
eventName: server.LargeFileReferencedEvent,
|
||||
data: { file: largeFile.path, fileSize: largeFile.fileSize, maxFileSize: server.maxFileSize }
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
it("when large file is included by tsconfig", () => {
|
||||
const file: File = {
|
||||
path: `${projectRoot}/src/file.ts`,
|
||||
|
@ -9039,13 +9060,15 @@ export const x = 10;`
|
|||
};
|
||||
const files = [file, largeFile, libFile, tsconfig];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host);
|
||||
service.openClientFile(file.path);
|
||||
service.checkNumberOfProjects({ configuredProjects: 1 });
|
||||
const { session, verifyLargeFileReferencedEvent } = createSessionWithEventHandler(host);
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([file], session);
|
||||
checkNumberOfProjects(service, { configuredProjects: 1 });
|
||||
const project = service.configuredProjects.get(tsconfig.path)!;
|
||||
checkProjectActualFiles(project, [file.path, libFile.path, largeFile.path, tsconfig.path]);
|
||||
const info = service.getScriptInfo(largeFile.path)!;
|
||||
assert.equal(info.cacheSourceFile.sourceFile.text, "");
|
||||
verifyLargeFileReferencedEvent();
|
||||
});
|
||||
|
||||
it("when large file is included by module resolution", () => {
|
||||
|
@ -9055,13 +9078,15 @@ export const x = 10;`
|
|||
};
|
||||
const files = [file, largeFile, libFile];
|
||||
const host = createServerHost(files);
|
||||
const service = createProjectService(host);
|
||||
service.openClientFile(file.path);
|
||||
service.checkNumberOfProjects({ inferredProjects: 1 });
|
||||
const { session, verifyLargeFileReferencedEvent } = createSessionWithEventHandler(host);
|
||||
const service = session.getProjectService();
|
||||
openFilesForSession([file], session);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const project = service.inferredProjects[0];
|
||||
checkProjectActualFiles(project, [file.path, libFile.path, largeFile.path]);
|
||||
const info = service.getScriptInfo(largeFile.path)!;
|
||||
assert.equal(info.cacheSourceFile.sourceFile.text, "");
|
||||
verifyLargeFileReferencedEvent();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -7660,6 +7660,25 @@ declare namespace ts.server.protocol {
|
|||
*/
|
||||
openFiles: string[];
|
||||
}
|
||||
type LargeFileReferencedEventName = "largeFileReferenced";
|
||||
interface LargeFileReferencedEvent extends Event {
|
||||
event: LargeFileReferencedEventName;
|
||||
body: LargeFileReferencedEventBody;
|
||||
}
|
||||
interface LargeFileReferencedEventBody {
|
||||
/**
|
||||
* name of the large file being loaded
|
||||
*/
|
||||
file: string;
|
||||
/**
|
||||
* size of the file
|
||||
*/
|
||||
fileSize: number;
|
||||
/**
|
||||
* max file size allowed on the server
|
||||
*/
|
||||
maxFileSize: number;
|
||||
}
|
||||
/**
|
||||
* Arguments for reload request.
|
||||
*/
|
||||
|
@ -8380,6 +8399,7 @@ declare namespace ts.server {
|
|||
declare namespace ts.server {
|
||||
const maxProgramSizeForNonTsFiles: number;
|
||||
const ProjectsUpdatedInBackgroundEvent = "projectsUpdatedInBackground";
|
||||
const LargeFileReferencedEvent = "largeFileReferenced";
|
||||
const ConfigFileDiagEvent = "configFileDiag";
|
||||
const ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
|
||||
const ProjectInfoTelemetryEvent = "projectInfo";
|
||||
|
@ -8390,6 +8410,14 @@ declare namespace ts.server {
|
|||
openFiles: string[];
|
||||
};
|
||||
}
|
||||
interface LargeFileReferencedEvent {
|
||||
eventName: typeof LargeFileReferencedEvent;
|
||||
data: {
|
||||
file: string;
|
||||
fileSize: number;
|
||||
maxFileSize: number;
|
||||
};
|
||||
}
|
||||
interface ConfigFileDiagEvent {
|
||||
eventName: typeof ConfigFileDiagEvent;
|
||||
data: {
|
||||
|
@ -8460,7 +8488,7 @@ declare namespace ts.server {
|
|||
interface OpenFileInfo {
|
||||
readonly checkJs: boolean;
|
||||
}
|
||||
type ProjectServiceEvent = ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
|
||||
type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
|
||||
type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void;
|
||||
interface SafeList {
|
||||
[name: string]: {
|
||||
|
|
Loading…
Reference in a new issue