Support using client watch in tsserver using events (#54662)

This commit is contained in:
Sheetal Nandi
2023-09-22 14:25:40 -07:00
committed by GitHub
parent 4c965433b6
commit 934216f968
12 changed files with 1372 additions and 28 deletions

View File

@@ -27,6 +27,7 @@ import {
Diagnostic,
directorySeparator,
DirectoryStructureHost,
DirectoryWatcherCallback,
DocumentPosition,
DocumentPositionMapper,
DocumentRegistry,
@@ -37,6 +38,7 @@ import {
FileExtensionInfo,
fileExtensionIs,
FileWatcher,
FileWatcherCallback,
FileWatcherEventKind,
find,
flatMap,
@@ -127,6 +129,7 @@ import {
version,
WatchDirectoryFlags,
WatchFactory,
WatchFactoryHost,
WatchLogLevel,
WatchOptions,
WatchType,
@@ -193,6 +196,9 @@ export const ConfigFileDiagEvent = "configFileDiag";
export const ProjectLanguageServiceStateEvent = "projectLanguageServiceState";
export const ProjectInfoTelemetryEvent = "projectInfo";
export const OpenFileInfoTelemetryEvent = "openFileInfo";
export const CreateFileWatcherEvent: protocol.CreateFileWatcherEventName = "createFileWatcher";
export const CreateDirectoryWatcherEvent: protocol.CreateDirectoryWatcherEventName = "createDirectoryWatcher";
export const CloseFileWatcherEvent: protocol.CloseFileWatcherEventName = "closeFileWatcher";
const ensureProjectForOpenFileSchedule = "*ensureProjectForOpenFiles*";
export interface ProjectsUpdatedInBackgroundEvent {
@@ -320,6 +326,21 @@ export interface OpenFileInfo {
readonly checkJs: boolean;
}
export interface CreateFileWatcherEvent {
readonly eventName: protocol.CreateFileWatcherEventName;
readonly data: protocol.CreateFileWatcherEventBody;
}
export interface CreateDirectoryWatcherEvent {
readonly eventName: protocol.CreateDirectoryWatcherEventName;
readonly data: protocol.CreateDirectoryWatcherEventBody;
}
export interface CloseFileWatcherEvent {
readonly eventName: protocol.CloseFileWatcherEventName;
readonly data: protocol.CloseFileWatcherEventBody;
}
export type ProjectServiceEvent =
| LargeFileReferencedEvent
| ProjectsUpdatedInBackgroundEvent
@@ -328,7 +349,10 @@ export type ProjectServiceEvent =
| ConfigFileDiagEvent
| ProjectLanguageServiceStateEvent
| ProjectInfoTelemetryEvent
| OpenFileInfoTelemetryEvent;
| OpenFileInfoTelemetryEvent
| CreateFileWatcherEvent
| CreateDirectoryWatcherEvent
| CloseFileWatcherEvent;
export type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void;
@@ -583,6 +607,7 @@ export interface ProjectServiceOptions {
useInferredProjectPerProjectRoot: boolean;
typingsInstaller?: ITypingsInstaller;
eventHandler?: ProjectServiceEventHandler;
canUseWatchEvents?: boolean;
suppressDiagnosticEvents?: boolean;
throttleWaitMilliseconds?: number;
globalPlugins?: readonly string[];
@@ -857,6 +882,109 @@ function createProjectNameFactoryWithCounter(nameFactory: (counter: number) => s
return () => nameFactory(nextId++);
}
interface HostWatcherMap<T> {
idToCallbacks: Map<number, Set<T>>;
pathToId: Map<Path, number>;
}
function getHostWatcherMap<T>(): HostWatcherMap<T> {
return { idToCallbacks: new Map(), pathToId: new Map() };
}
function createWatchFactoryHostUsingWatchEvents(service: ProjectService, canUseWatchEvents: boolean | undefined): WatchFactoryHost | undefined {
if (!canUseWatchEvents || !service.eventHandler || !service.session) return undefined;
const watchedFiles = getHostWatcherMap<FileWatcherCallback>();
const watchedDirectories = getHostWatcherMap<DirectoryWatcherCallback>();
const watchedDirectoriesRecursive = getHostWatcherMap<DirectoryWatcherCallback>();
let ids = 1;
service.session.addProtocolHandler(protocol.CommandTypes.WatchChange, req => {
onWatchChange((req as protocol.WatchChangeRequest).arguments);
return { responseRequired: false };
});
return {
watchFile,
watchDirectory,
getCurrentDirectory: () => service.host.getCurrentDirectory(),
useCaseSensitiveFileNames: service.host.useCaseSensitiveFileNames,
};
function watchFile(path: string, callback: FileWatcherCallback): FileWatcher {
return getOrCreateFileWatcher(
watchedFiles,
path,
callback,
id => ({ eventName: CreateFileWatcherEvent, data: { id, path } }),
);
}
function watchDirectory(path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher {
return getOrCreateFileWatcher(
recursive ? watchedDirectoriesRecursive : watchedDirectories,
path,
callback,
id => ({ eventName: CreateDirectoryWatcherEvent, data: { id, path, recursive: !!recursive } }),
);
}
function getOrCreateFileWatcher<T>(
{ pathToId, idToCallbacks }: HostWatcherMap<T>,
path: string,
callback: T,
event: (id: number) => CreateFileWatcherEvent | CreateDirectoryWatcherEvent,
) {
const key = service.toPath(path);
let id = pathToId.get(key);
if (!id) pathToId.set(key, id = ids++);
let callbacks = idToCallbacks.get(id);
if (!callbacks) {
idToCallbacks.set(id, callbacks = new Set());
// Add watcher
service.eventHandler!(event(id));
}
callbacks.add(callback);
return {
close() {
const callbacks = idToCallbacks.get(id!);
if (!callbacks?.delete(callback)) return;
if (callbacks.size) return;
idToCallbacks.delete(id!);
pathToId.delete(key);
service.eventHandler!({ eventName: CloseFileWatcherEvent, data: { id: id! } });
},
};
}
function onWatchChange({ id, path, eventType }: protocol.WatchChangeRequestArgs) {
// console.log(`typescript-vscode-watcher:: Invoke:: ${id}:: ${path}:: ${eventType}`);
onFileWatcherCallback(id, path, eventType);
onDirectoryWatcherCallback(watchedDirectories, id, path, eventType);
onDirectoryWatcherCallback(watchedDirectoriesRecursive, id, path, eventType);
}
function onFileWatcherCallback(
id: number,
eventPath: string,
eventType: "create" | "delete" | "update",
) {
watchedFiles.idToCallbacks.get(id)?.forEach(callback => {
const eventKind = eventType === "create" ?
FileWatcherEventKind.Created :
eventType === "delete" ?
FileWatcherEventKind.Deleted :
FileWatcherEventKind.Changed;
callback(eventPath, eventKind);
});
}
function onDirectoryWatcherCallback(
{ idToCallbacks }: HostWatcherMap<DirectoryWatcherCallback>,
id: number,
eventPath: string,
eventType: "create" | "delete" | "update",
) {
if (eventType === "update") return;
idToCallbacks.get(id)?.forEach(callback => {
callback(eventPath);
});
}
}
export class ProjectService {
/** @internal */
readonly typingsCache: TypingsCache;
@@ -961,7 +1089,8 @@ export class ProjectService {
public readonly typingsInstaller: ITypingsInstaller;
private readonly globalCacheLocationDirectoryPath: Path | undefined;
public readonly throttleWaitMilliseconds?: number;
private readonly eventHandler?: ProjectServiceEventHandler;
/** @internal */
readonly eventHandler?: ProjectServiceEventHandler;
private readonly suppressDiagnosticEvents?: boolean;
public readonly globalPlugins: readonly string[];
@@ -1065,7 +1194,12 @@ export class ProjectService {
watchFile: returnNoopFileWatcher,
watchDirectory: returnNoopFileWatcher,
} :
getWatchFactory(this.host, watchLogLevel, log, getDetailWatchInfo);
getWatchFactory(
createWatchFactoryHostUsingWatchEvents(this, opts.canUseWatchEvents) || this.host,
watchLogLevel,
log,
getDetailWatchInfo,
);
opts.incrementalVerifier?.(this);
}

View File

@@ -173,6 +173,7 @@ export const enum CommandTypes {
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
ProvideInlayHints = "provideInlayHints",
WatchChange = "watchChange",
}
/**
@@ -1956,6 +1957,17 @@ export interface CloseRequest extends FileRequest {
command: CommandTypes.Close;
}
export interface WatchChangeRequest extends Request {
command: CommandTypes.WatchChange;
arguments: WatchChangeRequestArgs;
}
export interface WatchChangeRequestArgs {
id: number;
path: string;
eventType: "create" | "delete" | "update";
}
/**
* 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.
@@ -3018,6 +3030,39 @@ export interface LargeFileReferencedEventBody {
maxFileSize: number;
}
export type CreateFileWatcherEventName = "createFileWatcher";
export interface CreateFileWatcherEvent extends Event {
readonly event: CreateFileWatcherEventName;
readonly body: CreateFileWatcherEventBody;
}
export interface CreateFileWatcherEventBody {
readonly id: number;
readonly path: string;
}
export type CreateDirectoryWatcherEventName = "createDirectoryWatcher";
export interface CreateDirectoryWatcherEvent extends Event {
readonly event: CreateDirectoryWatcherEventName;
readonly body: CreateDirectoryWatcherEventBody;
}
export interface CreateDirectoryWatcherEventBody {
readonly id: number;
readonly path: string;
readonly recursive: boolean;
}
export type CloseFileWatcherEventName = "closeFileWatcher";
export interface CloseFileWatcherEvent extends Event {
readonly event: CloseFileWatcherEventName;
readonly body: CloseFileWatcherEventBody;
}
export interface CloseFileWatcherEventBody {
readonly id: number;
}
/** @internal */
export type AnyEvent =
| RequestCompletedEvent
@@ -3029,7 +3074,10 @@ export type AnyEvent =
| ProjectLoadingStartEvent
| ProjectLoadingFinishEvent
| SurveyReadyEvent
| LargeFileReferencedEvent;
| LargeFileReferencedEvent
| CreateFileWatcherEvent
| CreateDirectoryWatcherEvent
| CloseFileWatcherEvent;
/**
* Arguments for reload request.

View File

@@ -139,11 +139,14 @@ import {
WithMetadata,
} from "./_namespaces/ts";
import {
CloseFileWatcherEvent,
ConfigFileDiagEvent,
ConfiguredProject,
convertFormatOptions,
convertScriptKindName,
convertUserPreferences,
CreateDirectoryWatcherEvent,
CreateFileWatcherEvent,
EmitResult,
emptyArray,
Errors,
@@ -949,6 +952,7 @@ export interface SessionOptions {
* If falsy, all events are suppressed.
*/
canUseEvents: boolean;
canUseWatchEvents?: boolean;
eventHandler?: ProjectServiceEventHandler;
/** Has no effect if eventHandler is also specified. */
suppressDiagnosticEvents?: boolean;
@@ -1026,6 +1030,7 @@ export class Session<TMessage = string> implements EventSender {
typesMapLocation: opts.typesMapLocation,
serverMode: opts.serverMode,
session: this,
canUseWatchEvents: opts.canUseWatchEvents,
incrementalVerifier: opts.incrementalVerifier,
};
this.projectService = new ProjectService(settings);
@@ -1080,39 +1085,37 @@ export class Session<TMessage = string> implements EventSender {
private defaultEventHandler(event: ProjectServiceEvent) {
switch (event.eventName) {
case ProjectsUpdatedInBackgroundEvent:
const { openFiles } = event.data;
this.projectsUpdatedInBackgroundEvent(openFiles);
this.projectsUpdatedInBackgroundEvent(event.data.openFiles);
break;
case ProjectLoadingStartEvent:
const { project, reason } = event.data;
this.event<protocol.ProjectLoadingStartEventBody>(
{ projectName: project.getProjectName(), reason },
ProjectLoadingStartEvent,
);
this.event<protocol.ProjectLoadingStartEventBody>({
projectName: event.data.project.getProjectName(),
reason: event.data.reason,
}, event.eventName);
break;
case ProjectLoadingFinishEvent:
const { project: finishProject } = event.data;
this.event<protocol.ProjectLoadingFinishEventBody>({ projectName: finishProject.getProjectName() }, ProjectLoadingFinishEvent);
this.event<protocol.ProjectLoadingFinishEventBody>({
projectName: event.data.project.getProjectName(),
}, event.eventName);
break;
case LargeFileReferencedEvent:
const { file, fileSize, maxFileSize } = event.data;
this.event<protocol.LargeFileReferencedEventBody>({ file, fileSize, maxFileSize }, LargeFileReferencedEvent);
case CreateFileWatcherEvent:
case CreateDirectoryWatcherEvent:
case CloseFileWatcherEvent:
this.event(event.data, event.eventName);
break;
case ConfigFileDiagEvent:
const { triggerFile, configFileName: configFile, diagnostics } = event.data;
const bakedDiags = map(diagnostics, diagnostic => formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ true));
this.event<protocol.ConfigFileDiagnosticEventBody>({
triggerFile,
configFile,
diagnostics: bakedDiags,
}, ConfigFileDiagEvent);
triggerFile: event.data.triggerFile,
configFile: event.data.configFileName,
diagnostics: map(event.data.diagnostics, diagnostic => formatDiagnosticToProtocol(diagnostic, /*includeFileName*/ true)),
}, event.eventName);
break;
case ProjectLanguageServiceStateEvent: {
const eventName: protocol.ProjectLanguageServiceStateEventName = ProjectLanguageServiceStateEvent;
this.event<protocol.ProjectLanguageServiceStateEventBody>({
projectName: event.data.project.getProjectName(),
languageServiceEnabled: event.data.languageServiceEnabled,
}, eventName);
}, event.eventName);
break;
}
case ProjectInfoTelemetryEvent: {

View File

@@ -153,6 +153,7 @@ import "./unittests/tsserver/events/largeFileReferenced";
import "./unittests/tsserver/events/projectLanguageServiceState";
import "./unittests/tsserver/events/projectLoading";
import "./unittests/tsserver/events/projectUpdatedInBackground";
import "./unittests/tsserver/events/watchEvents";
import "./unittests/tsserver/exportMapCache";
import "./unittests/tsserver/extends";
import "./unittests/tsserver/externalProjects";

View File

@@ -567,7 +567,7 @@ export function createSession(host: TestServerHost, opts: Partial<TestSessionOpt
return new TestSession({ ...sessionOptions, ...opts });
}
export function createSessionWithCustomEventHandler(host: TestServerHost, opts?: Partial<TestSessionOptions>) {
export function createSessionWithCustomEventHandler(host: TestServerHost, opts?: Partial<TestSessionOptions>, customAction?: (event: ts.server.ProjectServiceEvent) => void) {
const session = createSession(host, { eventHandler, logger: createLoggerWithInMemoryLogs(host), ...opts });
return session;
function eventHandler(event: ts.server.ProjectServiceEvent) {
@@ -578,6 +578,9 @@ export function createSessionWithCustomEventHandler(host: TestServerHost, opts?:
case ts.server.LargeFileReferencedEvent:
case ts.server.ProjectInfoTelemetryEvent:
case ts.server.OpenFileInfoTelemetryEvent:
case ts.server.CreateFileWatcherEvent:
case ts.server.CreateDirectoryWatcherEvent:
case ts.server.CloseFileWatcherEvent:
break;
// Convert project to project name
case ts.server.ProjectLoadingStartEvent:
@@ -593,6 +596,7 @@ export function createSessionWithCustomEventHandler(host: TestServerHost, opts?:
ts.Debug.assertNever(event);
}
session.event(data, `CustomHandler::${event.eventName}`);
customAction?.(event);
}
}

View File

@@ -623,7 +623,7 @@ export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost,
this.removeFileOrFolder(currentEntry);
}
private hasWatchChanges?: boolean;
hasWatchChanges?: boolean;
private createWatcher<T>(map: MultiMap<Path, T>, path: Path, callback: T): FileWatcher {
this.hasWatchChanges = true;
map.add(path, callback);
@@ -1115,7 +1115,7 @@ function diffFsEntry(baseline: string[], oldFsEntry: FSEntry | undefined, newFsE
}
}
function serializeMultiMap<T>(baseline: string[], caption: string, multiMap: MultiMap<string, T>, serialized: Map<string, T[]> | undefined) {
export function serializeMultiMap<T>(baseline: string[], caption: string, multiMap: MultiMap<string, T>, serialized: Map<string, T[]> | undefined) {
let hasChange = diffMap(baseline, caption, multiMap, serialized, /*deleted*/ false);
hasChange = diffMap(baseline, caption, serialized, multiMap, /*deleted*/ true) || hasChange;
if (hasChange) {

View File

@@ -0,0 +1,197 @@
import * as ts from "../../../_namespaces/ts";
import {
baselineTsserverLogs,
closeFilesForSession,
createLoggerWithInMemoryLogs,
createSession,
createSessionWithCustomEventHandler,
Logger,
openFilesForSession,
TestSession,
} from "../../helpers/tsserver";
import {
createServerHost,
libFile,
serializeMultiMap,
TestServerHost,
} from "../../helpers/virtualFileSystemWithWatch";
describe("unittests:: tsserver:: events:: watchEvents", () => {
interface TestServerHostWithCustomWatch extends TestServerHost {
factoryData: {
watchedFiles: ts.MultiMap<string, ts.server.protocol.CreateFileWatcherEventBody>;
watchedDirectories: ts.MultiMap<string, ts.server.protocol.CreateDirectoryWatcherEventBody>;
watchedDirectoriesRecursive: ts.MultiMap<string, ts.server.protocol.CreateDirectoryWatcherEventBody>;
watchFile(data: ts.server.protocol.CreateFileWatcherEventBody): void;
watchDirectory(data: ts.server.protocol.CreateDirectoryWatcherEventBody): void;
closeWatcher(data: ts.server.protocol.CloseFileWatcherEventBody): void;
};
}
function createTestServerHostWithCustomWatch(
logger: Logger,
) {
const idToClose = new Map<number, () => void>();
let serializedWatchedFiles: Map<string, ts.server.protocol.CreateFileWatcherEventBody[]> | undefined;
let serializedWatchedDirectories: Map<string, ts.server.protocol.CreateDirectoryWatcherEventBody[]> | undefined;
let serializedWatchedDirectoriesRecursive: Map<string, ts.server.protocol.CreateDirectoryWatcherEventBody[]> | undefined;
const host = logger.host as TestServerHostWithCustomWatch;
const originalSerializeWatches = host.serializeWatches;
host.serializeWatches = serializeWatches;
host.factoryData = {
watchedFiles: ts.createMultiMap(),
watchedDirectories: ts.createMultiMap(),
watchedDirectoriesRecursive: ts.createMultiMap(),
watchFile,
watchDirectory,
closeWatcher,
};
return host;
function watchFile(data: ts.server.protocol.CreateFileWatcherEventBody) {
logger.log(`Custom watchFile: ${data.id}: ${data.path}`);
ts.Debug.assert(!idToClose.has(data.id));
host.factoryData.watchedFiles.add(data.path, data);
host.hasWatchChanges = true;
idToClose.set(data.id, () => {
logger.log(`Custom watchFile:: Close:: ${data.id}: ${data.path}`);
host.factoryData.watchedFiles.remove(data.path, data);
});
}
function watchDirectory(data: ts.server.protocol.CreateDirectoryWatcherEventBody) {
logger.log(`Custom watchDirectory: ${data.id}: ${data.path} ${data.recursive}`);
ts.Debug.assert(!idToClose.has(data.id));
(data.recursive ? host.factoryData.watchedDirectoriesRecursive : host.factoryData.watchedDirectories).add(data.path, data);
host.hasWatchChanges = true;
idToClose.set(data.id, () => {
logger.log(`Custom watchDirectory:: Close:: ${data.id}: ${data.path} ${data.recursive}`);
(data.recursive ? host.factoryData.watchedDirectoriesRecursive : host.factoryData.watchedDirectories).remove(data.path, data);
});
}
function closeWatcher(data: ts.server.protocol.CloseFileWatcherEventBody) {
const close = idToClose.get(data.id);
if (close) {
idToClose.delete(data.id);
host.hasWatchChanges = true;
close();
}
}
function serializeWatches(baseline: string[] = []) {
const hasWatchChanges = host.hasWatchChanges;
originalSerializeWatches.call(host, baseline);
if (!hasWatchChanges) return baseline;
serializedWatchedFiles = serializeMultiMap(baseline, `Custom WatchedFiles`, host.factoryData.watchedFiles, serializedWatchedFiles);
serializedWatchedDirectories = serializeMultiMap(baseline, `Custom WatchedDirectories:Recursive`, host.factoryData.watchedDirectoriesRecursive, serializedWatchedDirectories);
serializedWatchedDirectoriesRecursive = serializeMultiMap(baseline, `Custom WatchedDirectories`, host.factoryData.watchedDirectories, serializedWatchedDirectoriesRecursive);
return baseline;
}
}
function updateFileOnHost(session: TestSession, file: string, log: string) {
// Change b.ts
session.logger.log(log);
session.testhost.writeFile(file, session.testhost.readFile("/user/username/projects/myproject/a.ts")!);
session.testhost.runQueuedTimeoutCallbacks();
}
function addFile(session: TestSession, path: string) {
updateFileOnHost(session, path, "Add file");
session.logger.log("Custom watch");
(session.logger.host as TestServerHostWithCustomWatch).factoryData.watchedDirectoriesRecursive.get("/user/username/projects/myproject")?.forEach(data =>
session.executeCommandSeq<ts.server.protocol.WatchChangeRequest>({
command: ts.server.protocol.CommandTypes.WatchChange,
arguments: { id: data.id, path, eventType: "create" },
})
);
session.testhost.runQueuedTimeoutCallbacks();
}
function changeFile(session: TestSession, path: string) {
updateFileOnHost(session, path, "Change File");
session.logger.log("Custom watch");
(session.logger.host as TestServerHostWithCustomWatch).factoryData.watchedFiles.get(path)?.forEach(data =>
session.executeCommandSeq<ts.server.protocol.WatchChangeRequest>({
command: ts.server.protocol.CommandTypes.WatchChange,
arguments: { id: data.id, path, eventType: "update" },
})
);
session.testhost.runQueuedTimeoutCallbacks();
}
function setup() {
const inputHost = createServerHost({
"/user/username/projects/myproject/tsconfig.json": "{}",
"/user/username/projects/myproject/a.ts": `export class a { prop = "hello"; foo() { return this.prop; } }`,
"/user/username/projects/myproject/b.ts": `export class b { prop = "hello"; foo() { return this.prop; } }`,
[libFile.path]: libFile.content,
});
const logger = createLoggerWithInMemoryLogs(inputHost);
const host = createTestServerHostWithCustomWatch(logger);
return { host, logger };
}
it("canUseWatchEvents", () => {
const { host, logger } = setup();
const session = createSessionWithCustomEventHandler(logger.host!, { canUseWatchEvents: true, logger }, handleWatchEvents);
openFilesForSession(["/user/username/projects/myproject/a.ts"], session);
// Directory watcher
addFile(session, "/user/username/projects/myproject/c.ts");
// File Watcher
changeFile(session, "/user/username/projects/myproject/b.ts");
// Close watcher
openFilesForSession(["/user/username/projects/myproject/b.ts"], session);
// Re watch
closeFilesForSession(["/user/username/projects/myproject/b.ts"], session);
baselineTsserverLogs("events/watchEvents", `canUseWatchEvents`, session);
function handleWatchEvents(event: ts.server.ProjectServiceEvent) {
switch (event.eventName) {
case ts.server.CreateFileWatcherEvent:
host.factoryData.watchFile(event.data);
break;
case ts.server.CreateDirectoryWatcherEvent:
host.factoryData.watchDirectory(event.data);
break;
case ts.server.CloseFileWatcherEvent:
host.factoryData.closeWatcher(event.data);
break;
default:
break;
}
}
});
it("canUseWatchEvents without canUseEvents", () => {
const { logger } = setup();
const session = createSession(logger.host!, { canUseEvents: false, logger });
openFilesForSession(["/user/username/projects/myproject/a.ts"], session);
// Directory watcher
addFile(session, "/user/username/projects/myproject/c.ts");
// File Watcher
changeFile(session, "/user/username/projects/myproject/b.ts");
// Close watcher
openFilesForSession(["/user/username/projects/myproject/b.ts"], session);
// Re watch
closeFilesForSession(["/user/username/projects/myproject/b.ts"], session);
// Shouldnt have watch change request
logger.msg = (s, type) => logger.info(`${type}:: ${s}`);
session.executeCommandSeq<ts.server.protocol.WatchChangeRequest>({
command: ts.server.protocol.CommandTypes.WatchChange,
arguments: { id: 1, path: "/user/username/projects/myproject/b.ts", eventType: "update" },
});
baselineTsserverLogs("events/watchEvents", `canUseWatchEvents without canUseEvents`, session);
});
});

View File

@@ -30,6 +30,7 @@ export interface StartSessionOptions {
useInferredProjectPerProjectRoot: SessionOptions["useInferredProjectPerProjectRoot"];
suppressDiagnosticEvents: SessionOptions["suppressDiagnosticEvents"];
noGetErrOnBackgroundUpdate: SessionOptions["noGetErrOnBackgroundUpdate"];
canUseWatchEvents: SessionOptions["canUseWatchEvents"];
serverMode: SessionOptions["serverMode"];
}

View File

@@ -57,6 +57,7 @@ function start({ args, logger, cancellationToken, serverMode, unknownServerMode,
useInferredProjectPerProjectRoot: hasArgument("--useInferredProjectPerProjectRoot"),
suppressDiagnosticEvents: hasArgument("--suppressDiagnosticEvents"),
noGetErrOnBackgroundUpdate: hasArgument("--noGetErrOnBackgroundUpdate"),
canUseWatchEvents: hasArgument("--canUseWatchEvents"),
serverMode,
},
logger,

View File

@@ -171,6 +171,7 @@ declare namespace ts {
ProvideCallHierarchyIncomingCalls = "provideCallHierarchyIncomingCalls",
ProvideCallHierarchyOutgoingCalls = "provideCallHierarchyOutgoingCalls",
ProvideInlayHints = "provideInlayHints",
WatchChange = "watchChange",
}
/**
* A TypeScript Server message
@@ -1504,6 +1505,15 @@ declare namespace ts {
interface CloseRequest extends FileRequest {
command: CommandTypes.Close;
}
interface WatchChangeRequest extends Request {
command: CommandTypes.WatchChange;
arguments: WatchChangeRequestArgs;
}
interface WatchChangeRequestArgs {
id: number;
path: string;
eventType: "create" | "delete" | "update";
}
/**
* 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.
@@ -2421,6 +2431,33 @@ declare namespace ts {
*/
maxFileSize: number;
}
type CreateFileWatcherEventName = "createFileWatcher";
interface CreateFileWatcherEvent extends Event {
readonly event: CreateFileWatcherEventName;
readonly body: CreateFileWatcherEventBody;
}
interface CreateFileWatcherEventBody {
readonly id: number;
readonly path: string;
}
type CreateDirectoryWatcherEventName = "createDirectoryWatcher";
interface CreateDirectoryWatcherEvent extends Event {
readonly event: CreateDirectoryWatcherEventName;
readonly body: CreateDirectoryWatcherEventBody;
}
interface CreateDirectoryWatcherEventBody {
readonly id: number;
readonly path: string;
readonly recursive: boolean;
}
type CloseFileWatcherEventName = "closeFileWatcher";
interface CloseFileWatcherEvent extends Event {
readonly event: CloseFileWatcherEventName;
readonly body: CloseFileWatcherEventBody;
}
interface CloseFileWatcherEventBody {
readonly id: number;
}
/**
* Arguments for reload request.
*/
@@ -3528,6 +3565,21 @@ declare namespace ts {
readonly eventName: typeof OpenFileInfoTelemetryEvent;
readonly data: OpenFileInfoTelemetryEventData;
}
const CreateFileWatcherEvent: protocol.CreateFileWatcherEventName;
interface CreateFileWatcherEvent {
readonly eventName: protocol.CreateFileWatcherEventName;
readonly data: protocol.CreateFileWatcherEventBody;
}
const CreateDirectoryWatcherEvent: protocol.CreateDirectoryWatcherEventName;
interface CreateDirectoryWatcherEvent {
readonly eventName: protocol.CreateDirectoryWatcherEventName;
readonly data: protocol.CreateDirectoryWatcherEventBody;
}
const CloseFileWatcherEvent: protocol.CloseFileWatcherEventName;
interface CloseFileWatcherEvent {
readonly eventName: protocol.CloseFileWatcherEventName;
readonly data: protocol.CloseFileWatcherEventBody;
}
interface ProjectInfoTelemetryEventData {
/** Cryptographically secure hash of project file location. */
readonly projectId: string;
@@ -3575,7 +3627,7 @@ declare namespace ts {
interface OpenFileInfo {
readonly checkJs: boolean;
}
type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ProjectLoadingStartEvent | ProjectLoadingFinishEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent;
type ProjectServiceEvent = LargeFileReferencedEvent | ProjectsUpdatedInBackgroundEvent | ProjectLoadingStartEvent | ProjectLoadingFinishEvent | ConfigFileDiagEvent | ProjectLanguageServiceStateEvent | ProjectInfoTelemetryEvent | OpenFileInfoTelemetryEvent | CreateFileWatcherEvent | CreateDirectoryWatcherEvent | CloseFileWatcherEvent;
type ProjectServiceEventHandler = (event: ProjectServiceEvent) => void;
interface SafeList {
[name: string]: {
@@ -3609,6 +3661,7 @@ declare namespace ts {
useInferredProjectPerProjectRoot: boolean;
typingsInstaller?: ITypingsInstaller;
eventHandler?: ProjectServiceEventHandler;
canUseWatchEvents?: boolean;
suppressDiagnosticEvents?: boolean;
throttleWaitMilliseconds?: number;
globalPlugins?: readonly string[];
@@ -3680,7 +3733,6 @@ declare namespace ts {
readonly typingsInstaller: ITypingsInstaller;
private readonly globalCacheLocationDirectoryPath;
readonly throttleWaitMilliseconds?: number;
private readonly eventHandler?;
private readonly suppressDiagnosticEvents?;
readonly globalPlugins: readonly string[];
readonly pluginProbeLocations: readonly string[];
@@ -3894,6 +3946,7 @@ declare namespace ts {
* If falsy, all events are suppressed.
*/
canUseEvents: boolean;
canUseWatchEvents?: boolean;
eventHandler?: ProjectServiceEventHandler;
/** Has no effect if eventHandler is also specified. */
suppressDiagnosticEvents?: boolean;

View File

@@ -0,0 +1,357 @@
currentDirectory:: / useCaseSensitiveFileNames: false
Info seq [hh:mm:ss:mss] Provided types map file "/a/lib/typesMap.json" doesn't exist
Before request
//// [/user/username/projects/myproject/tsconfig.json]
{}
//// [/user/username/projects/myproject/a.ts]
export class a { prop = "hello"; foo() { return this.prop; } }
//// [/user/username/projects/myproject/b.ts]
export class b { prop = "hello"; foo() { return this.prop; } }
//// [/a/lib/lib.d.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }
Info seq [hh:mm:ss:mss] request:
{
"command": "open",
"arguments": {
"file": "/user/username/projects/myproject/a.ts"
},
"seq": 1,
"type": "request"
}
Info seq [hh:mm:ss:mss] Search path: /user/username/projects/myproject
Info seq [hh:mm:ss:mss] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Creating configuration project /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file
Info seq [hh:mm:ss:mss] Config: /user/username/projects/myproject/tsconfig.json : {
"rootNames": [
"/user/username/projects/myproject/a.ts",
"/user/username/projects/myproject/b.ts"
],
"options": {
"configFilePath": "/user/username/projects/myproject/tsconfig.json"
}
}
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 1 undefined Config: /user/username/projects/myproject/tsconfig.json WatchType: Wild card directory
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 1 undefined Config: /user/username/projects/myproject/tsconfig.json WatchType: Wild card directory
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Version: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (3)
/a/lib/lib.d.ts Text-1 "/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }"
/user/username/projects/myproject/a.ts SVC-1-0 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/b.ts Text-1 "export class b { prop = \"hello\"; foo() { return this.prop; } }"
../../../../a/lib/lib.d.ts
Default library for target 'es5'
a.ts
Matched by default include pattern '**/*'
b.ts
Matched by default include pattern '**/*'
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (3)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] response:
{
"responseRequired": false
}
After request
PolledWatches::
/user/username/projects/myproject/node_modules/@types: *new*
{"pollingInterval":500}
/user/username/projects/node_modules/@types: *new*
{"pollingInterval":500}
FsWatches::
/a/lib/lib.d.ts: *new*
{}
/user/username/projects/myproject/b.ts: *new*
{}
/user/username/projects/myproject/tsconfig.json: *new*
{}
FsWatchesRecursive::
/user/username/projects/myproject: *new*
{}
Add file
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Triggered with /user/username/projects/myproject/c.ts :: WatchInfo: /user/username/projects/myproject 1 undefined Config: /user/username/projects/myproject/tsconfig.json WatchType: Wild card directory
Info seq [hh:mm:ss:mss] Scheduled: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/c.ts :: WatchInfo: /user/username/projects/myproject 1 undefined Config: /user/username/projects/myproject/tsconfig.json WatchType: Wild card directory
Before running Timeout callback:: count: 2
1: /user/username/projects/myproject/tsconfig.json
2: *ensureProjectForOpenFiles*
//// [/user/username/projects/myproject/c.ts]
export class a { prop = "hello"; foo() { return this.prop; } }
Info seq [hh:mm:ss:mss] Running: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/c.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Version: 2 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
/a/lib/lib.d.ts Text-1 "/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }"
/user/username/projects/myproject/a.ts SVC-1-0 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/b.ts Text-1 "export class b { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/c.ts Text-1 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
../../../../a/lib/lib.d.ts
Default library for target 'es5'
a.ts
Matched by default include pattern '**/*'
b.ts
Matched by default include pattern '**/*'
c.ts
Matched by default include pattern '**/*'
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Running: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Before ensureProjectForOpenFiles:
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] After ensureProjectForOpenFiles:
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
After running Timeout callback:: count: 0
PolledWatches::
/user/username/projects/myproject/node_modules/@types:
{"pollingInterval":500}
/user/username/projects/node_modules/@types:
{"pollingInterval":500}
FsWatches::
/a/lib/lib.d.ts:
{}
/user/username/projects/myproject/b.ts:
{}
/user/username/projects/myproject/c.ts: *new*
{}
/user/username/projects/myproject/tsconfig.json:
{}
FsWatchesRecursive::
/user/username/projects/myproject:
{}
Custom watch
Before running Timeout callback:: count: 0
After running Timeout callback:: count: 0
Change File
Info seq [hh:mm:ss:mss] FileWatcher:: Triggered with /user/username/projects/myproject/b.ts 1:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Scheduled: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/b.ts 1:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Before running Timeout callback:: count: 2
3: /user/username/projects/myproject/tsconfig.json
4: *ensureProjectForOpenFiles*
//// [/user/username/projects/myproject/b.ts]
export class a { prop = "hello"; foo() { return this.prop; } }
Info seq [hh:mm:ss:mss] Running: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Version: 3 structureChanged: false structureIsReused:: Completely Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
/a/lib/lib.d.ts Text-1 "/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }"
/user/username/projects/myproject/a.ts SVC-1-0 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/b.ts Text-2 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/c.ts Text-1 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Running: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Before ensureProjectForOpenFiles:
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] After ensureProjectForOpenFiles:
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
After running Timeout callback:: count: 0
Custom watch
Before running Timeout callback:: count: 0
After running Timeout callback:: count: 0
Before request
Info seq [hh:mm:ss:mss] request:
{
"command": "open",
"arguments": {
"file": "/user/username/projects/myproject/b.ts"
},
"seq": 2,
"type": "request"
}
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Search path: /user/username/projects/myproject
Info seq [hh:mm:ss:mss] For info: /user/username/projects/myproject/b.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/b.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] response:
{
"responseRequired": false
}
After request
PolledWatches::
/user/username/projects/myproject/node_modules/@types:
{"pollingInterval":500}
/user/username/projects/node_modules/@types:
{"pollingInterval":500}
FsWatches::
/a/lib/lib.d.ts:
{}
/user/username/projects/myproject/c.ts:
{}
/user/username/projects/myproject/tsconfig.json:
{}
FsWatches *deleted*::
/user/username/projects/myproject/b.ts:
{}
FsWatchesRecursive::
/user/username/projects/myproject:
{}
Before request
Info seq [hh:mm:ss:mss] request:
{
"command": "close",
"arguments": {
"file": "/user/username/projects/myproject/b.ts"
},
"seq": 3,
"type": "request"
}
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] response:
{
"responseRequired": false
}
After request
PolledWatches::
/user/username/projects/myproject/node_modules/@types:
{"pollingInterval":500}
/user/username/projects/node_modules/@types:
{"pollingInterval":500}
FsWatches::
/a/lib/lib.d.ts:
{}
/user/username/projects/myproject/b.ts: *new*
{}
/user/username/projects/myproject/c.ts:
{}
/user/username/projects/myproject/tsconfig.json:
{}
FsWatchesRecursive::
/user/username/projects/myproject:
{}
Before request
Info seq [hh:mm:ss:mss] request:
{
"command": "watchChange",
"arguments": {
"id": 1,
"path": "/user/username/projects/myproject/b.ts",
"eventType": "update"
},
"seq": 4,
"type": "request"
}
Info seq [hh:mm:ss:mss] Err:: Unrecognized JSON command:
{"command":"watchChange","arguments":{"id":1,"path":"/user/username/projects/myproject/b.ts","eventType":"update"},"seq":4,"type":"request"}
Info seq [hh:mm:ss:mss] response:
{
"seq": 0,
"type": "response",
"command": "unknown",
"request_seq": 4,
"success": false,
"performanceData": {
"updateGraphDurationMs": *
},
"message": "Unrecognized JSON command: watchChange"
}
Info seq [hh:mm:ss:mss] response:
{
"responseRequired": false
}
After request

View File

@@ -0,0 +1,545 @@
currentDirectory:: / useCaseSensitiveFileNames: false
Info seq [hh:mm:ss:mss] Provided types map file "/a/lib/typesMap.json" doesn't exist
Before request
//// [/user/username/projects/myproject/tsconfig.json]
{}
//// [/user/username/projects/myproject/a.ts]
export class a { prop = "hello"; foo() { return this.prop; } }
//// [/user/username/projects/myproject/b.ts]
export class b { prop = "hello"; foo() { return this.prop; } }
//// [/a/lib/lib.d.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }
Info seq [hh:mm:ss:mss] request:
{
"command": "open",
"arguments": {
"file": "/user/username/projects/myproject/a.ts"
},
"seq": 1,
"type": "request"
}
Info seq [hh:mm:ss:mss] Search path: /user/username/projects/myproject
Info seq [hh:mm:ss:mss] For info: /user/username/projects/myproject/a.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Creating configuration project /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/tsconfig.json 2000 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Config file
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::createFileWatcher",
"body": {
"id": 1,
"path": "/user/username/projects/myproject/tsconfig.json"
}
}
Custom watchFile: 1: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::projectLoadingStart",
"body": {
"project": "/user/username/projects/myproject/tsconfig.json",
"reason": "Creating possible configured project for /user/username/projects/myproject/a.ts to open"
}
}
Info seq [hh:mm:ss:mss] Config: /user/username/projects/myproject/tsconfig.json : {
"rootNames": [
"/user/username/projects/myproject/a.ts",
"/user/username/projects/myproject/b.ts"
],
"options": {
"configFilePath": "/user/username/projects/myproject/tsconfig.json"
}
}
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 1 undefined Config: /user/username/projects/myproject/tsconfig.json WatchType: Wild card directory
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::createDirectoryWatcher",
"body": {
"id": 2,
"path": "/user/username/projects/myproject",
"recursive": true
}
}
Custom watchDirectory: 2: /user/username/projects/myproject true
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject 1 undefined Config: /user/username/projects/myproject/tsconfig.json WatchType: Wild card directory
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::createFileWatcher",
"body": {
"id": 3,
"path": "/user/username/projects/myproject/b.ts"
}
}
Custom watchFile: 3: /user/username/projects/myproject/b.ts
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::createFileWatcher",
"body": {
"id": 4,
"path": "/a/lib/lib.d.ts"
}
}
Custom watchFile: 4: /a/lib/lib.d.ts
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::createDirectoryWatcher",
"body": {
"id": 5,
"path": "/user/username/projects/myproject/node_modules/@types",
"recursive": true
}
}
Custom watchDirectory: 5: /user/username/projects/myproject/node_modules/@types true
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/myproject/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::createDirectoryWatcher",
"body": {
"id": 6,
"path": "/user/username/projects/node_modules/@types",
"recursive": true
}
}
Custom watchDirectory: 6: /user/username/projects/node_modules/@types true
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /user/username/projects/node_modules/@types 1 undefined Project: /user/username/projects/myproject/tsconfig.json WatchType: Type roots
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Version: 1 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (3)
/a/lib/lib.d.ts Text-1 "/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }"
/user/username/projects/myproject/a.ts SVC-1-0 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/b.ts Text-1 "export class b { prop = \"hello\"; foo() { return this.prop; } }"
../../../../a/lib/lib.d.ts
Default library for target 'es5'
a.ts
Matched by default include pattern '**/*'
b.ts
Matched by default include pattern '**/*'
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::projectLoadingFinish",
"body": {
"project": "/user/username/projects/myproject/tsconfig.json"
}
}
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::projectInfo",
"body": {
"projectId": "4a33d78ee40d836c4f4e64c59aed976628aea0013be9585c5ff171dfc41baf98",
"fileStats": {
"js": 0,
"jsSize": 0,
"jsx": 0,
"jsxSize": 0,
"ts": 2,
"tsSize": 124,
"tsx": 0,
"tsxSize": 0,
"dts": 1,
"dtsSize": 334,
"deferred": 0,
"deferredSize": 0
},
"compilerOptions": {},
"typeAcquisition": {
"enable": false,
"include": false,
"exclude": false
},
"extends": false,
"files": false,
"include": false,
"exclude": false,
"compileOnSave": false,
"configFileName": "tsconfig.json",
"projectType": "configured",
"languageServiceEnabled": true,
"version": "FakeVersion"
}
}
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::configFileDiag",
"body": {
"configFileName": "/user/username/projects/myproject/tsconfig.json",
"diagnostics": [],
"triggerFile": "/user/username/projects/myproject/a.ts"
}
}
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (3)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] response:
{
"responseRequired": false
}
After request
Custom WatchedFiles::
/a/lib/lib.d.ts: *new*
{"id":4,"path":"/a/lib/lib.d.ts"}
/user/username/projects/myproject/b.ts: *new*
{"id":3,"path":"/user/username/projects/myproject/b.ts"}
/user/username/projects/myproject/tsconfig.json: *new*
{"id":1,"path":"/user/username/projects/myproject/tsconfig.json"}
Custom WatchedDirectories:Recursive::
/user/username/projects/myproject: *new*
{"id":2,"path":"/user/username/projects/myproject","recursive":true}
/user/username/projects/myproject/node_modules/@types: *new*
{"id":5,"path":"/user/username/projects/myproject/node_modules/@types","recursive":true}
/user/username/projects/node_modules/@types: *new*
{"id":6,"path":"/user/username/projects/node_modules/@types","recursive":true}
Add file
Before running Timeout callback:: count: 0
//// [/user/username/projects/myproject/c.ts]
export class a { prop = "hello"; foo() { return this.prop; } }
After running Timeout callback:: count: 0
Custom watch
Before request
Info seq [hh:mm:ss:mss] request:
{
"command": "watchChange",
"arguments": {
"id": 2,
"path": "/user/username/projects/myproject/c.ts",
"eventType": "create"
},
"seq": 2,
"type": "request"
}
Info seq [hh:mm:ss:mss] DirectoryWatcher:: Triggered with /user/username/projects/myproject/c.ts :: WatchInfo: /user/username/projects/myproject 1 undefined Config: /user/username/projects/myproject/tsconfig.json WatchType: Wild card directory
Info seq [hh:mm:ss:mss] Scheduled: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Triggered with /user/username/projects/myproject/c.ts :: WatchInfo: /user/username/projects/myproject 1 undefined Config: /user/username/projects/myproject/tsconfig.json WatchType: Wild card directory
Info seq [hh:mm:ss:mss] response:
{
"responseRequired": false
}
After request
Before running Timeout callback:: count: 2
1: /user/username/projects/myproject/tsconfig.json
2: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Running: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/c.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::createFileWatcher",
"body": {
"id": 7,
"path": "/user/username/projects/myproject/c.ts"
}
}
Custom watchFile: 7: /user/username/projects/myproject/c.ts
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Version: 2 structureChanged: true structureIsReused:: Not Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
/a/lib/lib.d.ts Text-1 "/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }"
/user/username/projects/myproject/a.ts SVC-1-0 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/b.ts Text-1 "export class b { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/c.ts Text-1 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
../../../../a/lib/lib.d.ts
Default library for target 'es5'
a.ts
Matched by default include pattern '**/*'
b.ts
Matched by default include pattern '**/*'
c.ts
Matched by default include pattern '**/*'
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Running: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Before ensureProjectForOpenFiles:
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] After ensureProjectForOpenFiles:
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::projectsUpdatedInBackground",
"body": {
"openFiles": [
"/user/username/projects/myproject/a.ts"
]
}
}
After running Timeout callback:: count: 0
Custom WatchedFiles::
/a/lib/lib.d.ts:
{"id":4,"path":"/a/lib/lib.d.ts"}
/user/username/projects/myproject/b.ts:
{"id":3,"path":"/user/username/projects/myproject/b.ts"}
/user/username/projects/myproject/c.ts: *new*
{"id":7,"path":"/user/username/projects/myproject/c.ts"}
/user/username/projects/myproject/tsconfig.json:
{"id":1,"path":"/user/username/projects/myproject/tsconfig.json"}
Custom WatchedDirectories:Recursive::
/user/username/projects/myproject:
{"id":2,"path":"/user/username/projects/myproject","recursive":true}
/user/username/projects/myproject/node_modules/@types:
{"id":5,"path":"/user/username/projects/myproject/node_modules/@types","recursive":true}
/user/username/projects/node_modules/@types:
{"id":6,"path":"/user/username/projects/node_modules/@types","recursive":true}
Change File
Before running Timeout callback:: count: 0
//// [/user/username/projects/myproject/b.ts]
export class a { prop = "hello"; foo() { return this.prop; } }
After running Timeout callback:: count: 0
Custom watch
Before request
Info seq [hh:mm:ss:mss] request:
{
"command": "watchChange",
"arguments": {
"id": 3,
"path": "/user/username/projects/myproject/b.ts",
"eventType": "update"
},
"seq": 3,
"type": "request"
}
Info seq [hh:mm:ss:mss] FileWatcher:: Triggered with /user/username/projects/myproject/b.ts 1:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] Scheduled: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Scheduled: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Elapsed:: *ms FileWatcher:: Triggered with /user/username/projects/myproject/b.ts 1:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] response:
{
"responseRequired": false
}
After request
Before running Timeout callback:: count: 2
3: /user/username/projects/myproject/tsconfig.json
4: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Running: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /user/username/projects/myproject/tsconfig.json Version: 3 structureChanged: false structureIsReused:: Completely Elapsed:: *ms
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
/a/lib/lib.d.ts Text-1 "/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }"
/user/username/projects/myproject/a.ts SVC-1-0 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/b.ts Text-2 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
/user/username/projects/myproject/c.ts Text-1 "export class a { prop = \"hello\"; foo() { return this.prop; } }"
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Running: *ensureProjectForOpenFiles*
Info seq [hh:mm:ss:mss] Before ensureProjectForOpenFiles:
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] After ensureProjectForOpenFiles:
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::projectsUpdatedInBackground",
"body": {
"openFiles": [
"/user/username/projects/myproject/a.ts"
]
}
}
After running Timeout callback:: count: 0
Before request
Info seq [hh:mm:ss:mss] request:
{
"command": "open",
"arguments": {
"file": "/user/username/projects/myproject/b.ts"
},
"seq": 4,
"type": "request"
}
Info seq [hh:mm:ss:mss] FileWatcher:: Close:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::closeFileWatcher",
"body": {
"id": 3
}
}
Custom watchFile:: Close:: 3: /user/username/projects/myproject/b.ts
Info seq [hh:mm:ss:mss] Search path: /user/username/projects/myproject
Info seq [hh:mm:ss:mss] For info: /user/username/projects/myproject/b.ts :: Config file name: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/b.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] response:
{
"responseRequired": false
}
After request
Custom WatchedFiles::
/a/lib/lib.d.ts:
{"id":4,"path":"/a/lib/lib.d.ts"}
/user/username/projects/myproject/c.ts:
{"id":7,"path":"/user/username/projects/myproject/c.ts"}
/user/username/projects/myproject/tsconfig.json:
{"id":1,"path":"/user/username/projects/myproject/tsconfig.json"}
Custom WatchedFiles *deleted*::
/user/username/projects/myproject/b.ts:
{"id":3,"path":"/user/username/projects/myproject/b.ts"}
Custom WatchedDirectories:Recursive::
/user/username/projects/myproject:
{"id":2,"path":"/user/username/projects/myproject","recursive":true}
/user/username/projects/myproject/node_modules/@types:
{"id":5,"path":"/user/username/projects/myproject/node_modules/@types","recursive":true}
/user/username/projects/node_modules/@types:
{"id":6,"path":"/user/username/projects/node_modules/@types","recursive":true}
Before request
Info seq [hh:mm:ss:mss] request:
{
"command": "close",
"arguments": {
"file": "/user/username/projects/myproject/b.ts"
},
"seq": 5,
"type": "request"
}
Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /user/username/projects/myproject/b.ts 500 undefined WatchType: Closed Script info
Info seq [hh:mm:ss:mss] event:
{
"seq": 0,
"type": "event",
"event": "CustomHandler::createFileWatcher",
"body": {
"id": 8,
"path": "/user/username/projects/myproject/b.ts"
}
}
Custom watchFile: 8: /user/username/projects/myproject/b.ts
Info seq [hh:mm:ss:mss] Project '/user/username/projects/myproject/tsconfig.json' (Configured)
Info seq [hh:mm:ss:mss] Files (4)
Info seq [hh:mm:ss:mss] -----------------------------------------------
Info seq [hh:mm:ss:mss] Open files:
Info seq [hh:mm:ss:mss] FileName: /user/username/projects/myproject/a.ts ProjectRootPath: undefined
Info seq [hh:mm:ss:mss] Projects: /user/username/projects/myproject/tsconfig.json
Info seq [hh:mm:ss:mss] response:
{
"responseRequired": false
}
After request
Custom WatchedFiles::
/a/lib/lib.d.ts:
{"id":4,"path":"/a/lib/lib.d.ts"}
/user/username/projects/myproject/b.ts: *new*
{"id":8,"path":"/user/username/projects/myproject/b.ts"}
/user/username/projects/myproject/c.ts:
{"id":7,"path":"/user/username/projects/myproject/c.ts"}
/user/username/projects/myproject/tsconfig.json:
{"id":1,"path":"/user/username/projects/myproject/tsconfig.json"}
Custom WatchedDirectories:Recursive::
/user/username/projects/myproject:
{"id":2,"path":"/user/username/projects/myproject","recursive":true}
/user/username/projects/myproject/node_modules/@types:
{"id":5,"path":"/user/username/projects/myproject/node_modules/@types","recursive":true}
/user/username/projects/node_modules/@types:
{"id":6,"path":"/user/username/projects/node_modules/@types","recursive":true}