Skip to content

Commit 44fe222

Browse files
author
Sander Ronde
committed
Add debug logging
1 parent 84403af commit 44fe222

File tree

16 files changed

+278
-2
lines changed

16 files changed

+278
-2
lines changed

client/src/extension.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type {
1818
ServerOptions,
1919
} from 'vscode-languageclient/node';
2020
import { LanguageClient, TransportKind } from 'vscode-languageclient/node';
21+
import { debug, initDebugReceiver } from './notificationReceivers/debug';
2122
import { DocumentManager } from './notificationSenders/documentManager';
2223
import { ErrorManager } from './notificationReceivers/errorManager';
2324
import { ZombieKiller } from './notificationReceivers/zombieKiller';
@@ -85,11 +86,13 @@ async function startLanguageServer(
8586

8687
export async function activate(context: ExtensionContext): Promise<void> {
8788
log(context, CLIENT_PREFIX, 'Initializing PHPStan extension');
89+
debug('lifecycle', 'Initializing PHPStan extension');
8890
const outputChannel = createOutputChannel();
8991

9092
const telemetry = new Telemetry();
9193
telemetry.report(context);
9294
const client = await startLanguageServer(context, outputChannel);
95+
initDebugReceiver(client);
9396
const statusBar = new StatusBar(context, client);
9497
const watcher = new DocumentManager(client);
9598
const errorManager = new ErrorManager(client);

client/src/lib/commands.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import { commands, Commands } from '../../../shared/commands/defs';
88
// eslint-disable-next-line node/no-extraneous-import
99
import { autoRegisterCommand } from 'vscode-generate-package-json';
1010
import type { LanguageClient } from 'vscode-languageclient/node';
11+
import { getDebugData } from '../notificationReceivers/debug';
1112
import { getEditorConfiguration } from './editorConfig';
1213
import { showError } from './errorUtil';
14+
1315
import { launchSetup } from './setup';
1416
import * as vscode from 'vscode';
1517

@@ -151,4 +153,24 @@ export function registerListeners(
151153
}
152154
)
153155
);
156+
157+
context.subscriptions.push(
158+
autoRegisterCommand(
159+
Commands.DOWNLOAD_DEBUG_DATA,
160+
async () => {
161+
const debugData = getDebugData();
162+
const json = JSON.stringify(debugData, null, '\t');
163+
const timestamp = Date.now();
164+
const uri = vscode.Uri.joinPath(
165+
vscode.workspace.workspaceFolders?.[0]?.uri ??
166+
vscode.Uri.file(''),
167+
`phpstan-vscode-debug-${timestamp}.json`
168+
);
169+
await vscode.workspace.fs.writeFile(uri, Buffer.from(json));
170+
171+
await vscode.commands.executeCommand('vscode.open', uri);
172+
},
173+
commands
174+
)
175+
);
154176
}

client/src/lib/notificationChannels.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type {
22
CommandNotificationType,
3+
DebugNotificationType,
34
ErrorNotificationType,
45
LogNotificationType,
56
PHPStanProNotificationType,
@@ -36,3 +37,6 @@ export const phpstanProNotification =
3637
new NotificationType<PHPStanProNotificationType>(
3738
NotificationChannel.PHPSTAN_PRO
3839
);
40+
export const debugNotification = new NotificationType<DebugNotificationType>(
41+
NotificationChannel.DEBUG
42+
);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { LanguageClient } from 'vscode-languageclient/node';
2+
3+
import { debugNotification } from '../lib/notificationChannels';
4+
import type { Disposable } from 'vscode';
5+
6+
const sessionDebugData: {
7+
type: string;
8+
data: unknown[];
9+
timestamp: string;
10+
timestampMs: number;
11+
}[] = [];
12+
13+
export function debug(type: string, ...data: unknown[]): void {
14+
const now = new Date();
15+
sessionDebugData.push({
16+
type,
17+
data,
18+
timestamp: now.toISOString(),
19+
timestampMs: now.getTime(),
20+
});
21+
}
22+
23+
export function initDebugReceiver(client: LanguageClient): Disposable {
24+
return client.onNotification(debugNotification, (params) => {
25+
debug(params.debugData.type, ...params.debugData.data);
26+
});
27+
}
28+
29+
export function getDebugData(): {
30+
type: string;
31+
data: unknown[];
32+
timestamp: string;
33+
timestampMs: number;
34+
}[] {
35+
return sessionDebugData;
36+
}
37+
38+
export * from '../../../shared/debug';

client/src/notificationReceivers/statusBar.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { assertUnreachable } from '../../../shared/util';
88
import { log, STATUS_BAR_PREFIX } from '../lib/log';
99
import type { Disposable } from 'vscode';
1010
import * as vscode from 'vscode';
11+
import { debug } from './debug';
1112

1213
export class StatusBar implements Disposable {
1314
private _runningOperation: {
@@ -36,6 +37,9 @@ export class StatusBar implements Disposable {
3637
"notification:'",
3738
JSON.stringify(params)
3839
);
40+
debug('statusBar', {
41+
params,
42+
});
3943

4044
if (!getEditorConfiguration().get('phpstan.enableStatusBar')) {
4145
return;

client/src/notificationSenders/documentManager.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import type { WatcherNotificationFileData } from '../../../shared/notificationChannels';
2+
import { debug, sanitizeFilePath } from '../notificationReceivers/debug';
23
import { watcherNotification } from '../lib/notificationChannels';
34
import type { LanguageClient } from 'vscode-languageclient/node';
45
import { getEditorConfiguration } from '../lib/editorConfig';
56
import type { Disposable } from 'vscode';
7+
import { createHash } from 'crypto';
8+
import * as fs from 'fs/promises';
69
import * as vscode from 'vscode';
7-
810
type PartialDocument = Pick<
911
vscode.TextDocument,
1012
'uri' | 'getText' | 'isDirty' | 'languageId'
@@ -54,11 +56,18 @@ export class DocumentManager implements Disposable {
5456

5557
private async _onDocumentChange(e: vscode.TextDocument): Promise<void> {
5658
if (this._isConfigFile(e)) {
59+
debug('configChange', {
60+
filePath: sanitizeFilePath(e.uri.fsPath),
61+
});
5762
await this._client.sendNotification(watcherNotification, {
5863
operation: 'onConfigChange',
5964
});
6065
}
6166
if (this._shouldSyncDocument(e)) {
67+
debug('documentChange', {
68+
checking: true,
69+
filePath: sanitizeFilePath(e.uri.fsPath),
70+
});
6271
await this._client.sendNotification(watcherNotification, {
6372
operation: 'change',
6473
file: this._toSendData(e),
@@ -67,16 +76,40 @@ export class DocumentManager implements Disposable {
6776
}
6877

6978
private async _onDocumentSave(e: vscode.TextDocument): Promise<void> {
70-
if (this._shouldSyncDocument(e)) {
79+
const fileContents = e.getText();
80+
const fileContentsHash = createHash('sha256')
81+
.update(fileContents)
82+
.digest('hex');
83+
const onDiskContents = await fs.readFile(e.uri.fsPath, 'utf-8');
84+
const onDiskContentsHash = createHash('sha256')
85+
.update(onDiskContents)
86+
.digest('hex');
87+
if (fileContentsHash !== onDiskContentsHash) {
88+
debug('documentSave', {
89+
filePath: sanitizeFilePath(e.uri.fsPath),
90+
});
7191
await this._client.sendNotification(watcherNotification, {
7292
operation: 'save',
7393
file: this._toSendData(e),
7494
});
95+
const postSaveContents = await fs.readFile(e.uri.fsPath, 'utf-8');
96+
const postSaveContentsHash = createHash('sha256')
97+
.update(postSaveContents)
98+
.digest('hex');
99+
debug('documentSave', {
100+
filePath: sanitizeFilePath(e.uri.fsPath),
101+
postSaveContentsHash,
102+
fileContentsHash,
103+
onDiskContentsHash,
104+
});
75105
}
76106
}
77107

78108
private async _onDocumentActive(e: vscode.TextDocument): Promise<void> {
79109
if (this._shouldSyncDocument(e)) {
110+
debug('documentActive', {
111+
filePath: sanitizeFilePath(e.uri.fsPath),
112+
});
80113
await this._client.sendNotification(watcherNotification, {
81114
operation: 'setActive',
82115
file: this._toSendData(e),
@@ -89,6 +122,10 @@ export class DocumentManager implements Disposable {
89122
check: boolean
90123
): Promise<void> {
91124
if (this._shouldSyncDocument(e)) {
125+
debug('documentOpen', {
126+
filePath: sanitizeFilePath(e.uri.fsPath),
127+
check,
128+
});
92129
await this._client.sendNotification(watcherNotification, {
93130
operation: 'open',
94131
file: this._toSendData(e),
@@ -99,6 +136,9 @@ export class DocumentManager implements Disposable {
99136

100137
private async _onDocumentClose(e: PartialDocument): Promise<void> {
101138
if (this._shouldSyncDocument(e)) {
139+
debug('documentClose', {
140+
filePath: sanitizeFilePath(e.uri.fsPath),
141+
});
102142
await this._client.sendNotification(watcherNotification, {
103143
operation: 'close',
104144
file: this._toSendData(e),
@@ -107,6 +147,7 @@ export class DocumentManager implements Disposable {
107147
}
108148

109149
public async watch(): Promise<void> {
150+
debug('watch', 'Starting document watch');
110151
await Promise.all(
111152
vscode.workspace.textDocuments.map((doc) => {
112153
return this._onDocumentOpen(doc, false);
@@ -153,6 +194,7 @@ export class DocumentManager implements Disposable {
153194
}
154195

155196
public dispose(): void {
197+
debug('dispose', 'Disposing document manager');
156198
this._disposables.forEach((d) => void d.dispose());
157199
this._disposables = [];
158200
}

package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@
207207
"command": "phpstan.launchSetup",
208208
"title": "Launch setup"
209209
},
210+
{
211+
"command": "phpstan.downloadDebugData",
212+
"title": "Download debug data"
213+
},
210214
{
211215
"command": "cmd.phpstan.scanFileForErrors",
212216
"title": "PHPStan: Scan current file for errors"
@@ -234,6 +238,10 @@
234238
{
235239
"command": "cmd.phpstan.launchSetup",
236240
"title": "PHPStan: Launch setup"
241+
},
242+
{
243+
"command": "cmd.phpstan.downloadDebugData",
244+
"title": "PHPStan: Download debug data"
237245
}
238246
],
239247
"menus": {
@@ -266,6 +274,10 @@
266274
"command": "phpstan.launchSetup",
267275
"when": "false"
268276
},
277+
{
278+
"command": "phpstan.downloadDebugData",
279+
"when": "false"
280+
},
269281
{
270282
"command": "cmd.phpstan.scanFileForErrors",
271283
"when": "true"
@@ -293,6 +305,10 @@
293305
{
294306
"command": "cmd.phpstan.launchSetup",
295307
"when": "true"
308+
},
309+
{
310+
"command": "cmd.phpstan.downloadDebugData",
311+
"when": "true"
296312
}
297313
]
298314
},

server/src/lib/debug.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { debugNotification } from './notificationChannels';
2+
import type { _Connection } from 'vscode-languageserver';
3+
4+
export function debug(
5+
connection: _Connection,
6+
type: string,
7+
...data: unknown[]
8+
): void {
9+
void connection.sendNotification(debugNotification, {
10+
debugData: {
11+
type,
12+
data,
13+
},
14+
});
15+
}
16+
17+
export * from '../../../shared/debug';

server/src/lib/documentManager.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { Disposable } from 'vscode-languageserver';
88
import { getEditorConfiguration } from './editorConfig';
99
import type { Watcher } from './watcher';
1010
import * as phpParser from 'php-parser';
11+
import { debug } from '../lib/debug';
1112
import { URI } from 'vscode-uri';
1213

1314
class DocumentManagerFileData implements WatcherNotificationFileData {
@@ -98,6 +99,9 @@ export class DocumentManager implements AsyncDisposable {
9899
watcherNotification,
99100
// eslint-disable-next-line @typescript-eslint/no-misused-promises
100101
async (data) => {
102+
debug(this._classConfig.connection, 'documentManager', {
103+
data,
104+
});
101105
switch (data.operation) {
102106
case 'close':
103107
this._documents.delete(data.file.uri);

server/src/lib/notificationChannels.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type {
22
CommandNotificationType,
3+
DebugNotificationType,
34
ErrorNotificationType,
45
LogNotificationType,
56
PHPStanProNotificationType,
@@ -36,3 +37,7 @@ export const phpstanProNotification =
3637
new NotificationType<PHPStanProNotificationType>(
3738
NotificationChannel.PHPSTAN_PRO
3839
);
40+
41+
export const debugNotification = new NotificationType<DebugNotificationType>(
42+
NotificationChannel.DEBUG
43+
);

0 commit comments

Comments
 (0)