Skip to content

Commit

Permalink
Diagnostic manager (#502)
Browse files Browse the repository at this point in the history
* Add a DiagnosticManager

* fix merge issue

* Fix failing tests

* Handle enum mismatch for diagnostic severity

---------

Co-authored-by: Christian Holbrook <[email protected]>
  • Loading branch information
TwitchBronBron and Christian-Holbrook authored Oct 11, 2023
1 parent faeacd3 commit b5944cb
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 92 deletions.
38 changes: 0 additions & 38 deletions src/LogOutputManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,18 @@ import { util } from 'brighterscript';
describe('LogOutputManager ', () => {
let logOutputManagerMock: Sinon.SinonMock;
let logOutputManager: LogOutputManager;
let languagesMock: Sinon.SinonMock;
let outputChannelMock: Sinon.SinonMock;
let logDocumentLinkProviderMock: Sinon.SinonMock;
let collectionMock: Sinon.SinonMock;
let declarationProviderMock: Sinon.SinonMock;

beforeEach(() => {
sinon.restore();
const outputChannel = new vscode.OutputChannel();
const debugCollection = new vscode.DebugCollection();
const logDocumentLinkProvider = new LogDocumentLinkProvider();
const declarationProvider = new DeclarationProvider();
outputChannelMock = sinon.mock(outputChannel);
logDocumentLinkProviderMock = sinon.mock(logDocumentLinkProvider);
collectionMock = sinon.mock(debugCollection);
declarationProviderMock = sinon.mock(declarationProvider);
languagesMock = sinon.mock(vscode.languages);
languagesMock.expects('createDiagnosticCollection').returns(debugCollection);
collectionMock.expects('clear');
logOutputManager = new LogOutputManager(outputChannel, vscode.context, logDocumentLinkProvider, declarationProvider);
logOutputManagerMock = sinon.mock(logOutputManager);
});
Expand All @@ -55,73 +48,49 @@ describe('LogOutputManager ', () => {
});

it('tests onDidStartDebugSession clear flag', () => {
collectionMock.expects('clear').once();
logOutputManager.isClearingConsoleOnChannelStart = true;
logOutputManager.onDidStartDebugSession();
outputChannelMock.verify();
collectionMock.verify();
logOutputManagerMock.verify();
});

it('tests onDidStartDebugSession no clear flag', () => {
collectionMock.expects('clear').never();
logOutputManager.isClearingConsoleOnChannelStart = false;
logOutputManager.onDidStartDebugSession();
outputChannelMock.verify();
collectionMock.verify();
logOutputManagerMock.verify();
});

it('tests onDidReceiveDebugSessionCustomEvent - LaunchStartEvent - clear flag', async () => {
collectionMock.expects('clear').once();
logOutputManager.isClearingOutputOnLaunch = true;
await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: 'LaunchStartEvent' });
outputChannelMock.verify();
collectionMock.verify();
logOutputManagerMock.verify();
});

it('tests onDidReceiveDebugSessionCustomEvent - LaunchStartEvent - no clear flag', async () => {
collectionMock.expects('clear').never();
logOutputManager.isClearingOutputOnLaunch = false;
await logOutputManager.onDidReceiveDebugSessionCustomEvent(new LaunchStartEvent({} as any));
outputChannelMock.verify();
collectionMock.verify();
logOutputManagerMock.verify();
});

it('tests onDidReceiveDebugSessionCustomEvent - LogOutputEvent', async () => {
outputChannelMock.expects('appendLine').once();
await logOutputManager.onDidReceiveDebugSessionCustomEvent(new LogOutputEvent('test 1'));
outputChannelMock.verify();
collectionMock.verify();
logOutputManagerMock.verify();
});

it('tests onDidReceiveDebugSessionCustomEvent - error - empty', async () => {
await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: '', body: {} });
outputChannelMock.verify();
collectionMock.verify();
logOutputManagerMock.verify();
});

it('tests onDidReceiveDebugSessionCustomEvent - error - undefined', async () => {
await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: '' });
outputChannelMock.verify();
collectionMock.verify();
logOutputManagerMock.verify();
});

it('tests onDidReceiveDebugSessionCustomEvent - errors', async () => {
logOutputManagerMock.expects('addDiagnosticForError').once();
let compileErrors: BSDebugDiagnostic[] = [{
path: 'path1',
message: 'message1',
range: util.createRange(1, 2, 3, 4)
}];
await logOutputManager.onDidReceiveDebugSessionCustomEvent(new DiagnosticsEvent(compileErrors));
outputChannelMock.verify();
collectionMock.verify();
logOutputManagerMock.verify();
});

Expand All @@ -130,13 +99,11 @@ describe('LogOutputManager ', () => {
logOutputManager.appendLine('test1', true);
logOutputManager.appendLine('test2', true);
logOutputManager.appendLine('test3', true);
collectionMock.expects('clear').once();
outputChannelMock.expects('clear').once();

logOutputManager.clearOutput();

outputChannelMock.verify();
collectionMock.verify();
});

it('tests output indexes are cleared', () => {
Expand All @@ -151,7 +118,6 @@ describe('LogOutputManager ', () => {
logOutputManager.markOutput();

logOutputManagerMock.verify();
collectionMock.verify();

logOutputManagerMock = sinon.mock(logOutputManager);
logOutputManager.clearOutput();
Expand All @@ -164,7 +130,6 @@ describe('LogOutputManager ', () => {
logOutputManager.markOutput();

logOutputManagerMock.verify();
collectionMock.verify();

});
});
Expand All @@ -175,7 +140,6 @@ describe('LogOutputManager ', () => {
.withExactArgs('test1').once();
logOutputManager.appendLine('test1', true);
outputChannelMock.verify();
collectionMock.verify();
});

it('splits multiple lines', () => {
Expand All @@ -187,7 +151,6 @@ describe('LogOutputManager ', () => {
logOutputManager.appendLine('test1\ntest2', true);

outputChannelMock.verify();
collectionMock.verify();
});
});

Expand All @@ -204,7 +167,6 @@ describe('LogOutputManager ', () => {
logOutputManager.markOutput();

logOutputManagerMock.verify();
collectionMock.verify();
});
});

Expand Down
53 changes: 0 additions & 53 deletions src/LogOutputManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as vscode from 'vscode';
import type { DiagnosticCollection } from 'vscode';
import type { BSDebugDiagnostic } from 'roku-debug';
import { isChanperfEvent, isDiagnosticsEvent, isLaunchStartEvent, isLogOutputEvent, isPopupMessageEvent, isRendezvousEvent } from 'roku-debug';
import type { DeclarationProvider } from './DeclarationProvider';
Expand All @@ -24,7 +23,6 @@ export class LogOutputManager {
docLinkProvider,
private declarationProvider: DeclarationProvider
) {
this.collection = vscode.languages.createDiagnosticCollection('BrightScript');
this.outputChannel = outputChannel;
this.docLinkProvider = docLinkProvider;

Expand Down Expand Up @@ -103,7 +101,6 @@ export class LogOutputManager {
public isClearingOutputOnLaunch: boolean;
public isClearingConsoleOnChannelStart: boolean;
public hyperlinkFormat: string;
private collection: DiagnosticCollection;
private outputChannel: vscode.OutputChannel;
private docLinkProvider: LogDocumentLinkProvider;
private debugStartRegex: RegExp;
Expand Down Expand Up @@ -247,22 +244,6 @@ export class LogOutputManager {
this.clearOutput();
}

} else if (isDiagnosticsEvent(e)) {
let errorsByPath = {};
for (const diagnostic of e.body.diagnostics) {
if (diagnostic.path) {
if (!errorsByPath[diagnostic.path]) {
errorsByPath[diagnostic.path] = [];
}
errorsByPath[diagnostic.path].push(diagnostic);
}
}
for (const path in errorsByPath) {
if (errorsByPath.hasOwnProperty(path)) {
const errors = errorsByPath[path];
await this.addDiagnosticForError(path, errors);
}
}
}
}

Expand Down Expand Up @@ -299,39 +280,6 @@ export class LogOutputManager {
methods[severity](message);
}

public async addDiagnosticForError(path: string, diagnostics: BSDebugDiagnostic[]) {
//TODO get the actual folder
let documentUri: vscode.Uri;
let uri = vscode.Uri.file(path);
let doc = await vscode.workspace.openTextDocument(uri); // calls back
if (doc !== undefined) {
documentUri = doc.uri;
}
// console.log("got " + documentUri);

//debug crap - for some reason - using this URI works - using the one from the path does not :()
// const document = vscode.window.activeTextEditor.document;
// const currentDocumentUri = document.uri;
// console.log("currentDocumentUri " + currentDocumentUri);
if (documentUri !== undefined) {
let result: vscode.Diagnostic[] = [];
for (const diagnostic of diagnostics) {
result.push({
code: diagnostic.code,
message: diagnostic.message,
source: diagnostic.source,
severity: diagnostic.severity,
tags: diagnostic.tags,
range: new vscode.Range(
new vscode.Position(diagnostic.range.start.line, diagnostic.range.start.character),
new vscode.Position(diagnostic.range.end.line, diagnostic.range.end.character)
)
});
}
this.collection.set(documentUri, result);
}
}

/**
* Log output methods
*/
Expand Down Expand Up @@ -487,7 +435,6 @@ export class LogOutputManager {
this.allLogLines = [];
this.displayedLogLines = [];
this.outputChannel.clear();
this.collection.clear();
this.docLinkProvider.resetCustomLinks();
}

Expand Down
21 changes: 20 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { isChannelPublishedEvent, isChanperfEvent, isDiagnosticsEvent, isDebugSe
import { RtaManager } from './managers/RtaManager';
import { WebviewViewProviderManager } from './managers/WebviewViewProviderManager';
import { ViewProviderId } from './viewProviders/ViewProviderId';
import { DiagnosticManager } from './managers/DiagnosticManager';

const EXTENSION_ID = 'RokuCommunity.brightscript';

Expand All @@ -44,6 +45,7 @@ export class Extension {
private brightScriptCommands: BrightScriptCommands;
private rtaManager: RtaManager;
private webviewViewProviderManager: WebviewViewProviderManager;
private diagnosticManager = new DiagnosticManager();

public async activate(context: vscode.ExtensionContext) {
const currentExtensionVersion = extensions.getExtension(EXTENSION_ID)?.packageJSON.version as string;
Expand Down Expand Up @@ -171,6 +173,7 @@ export class Extension {
if (e.type === 'brightscript') {
logOutputManager.onDidStartDebugSession();
}
this.diagnosticManager.clear();
});

vscode.debug.onDidTerminateDebugSession((e) => {
Expand All @@ -182,6 +185,7 @@ export class Extension {
void this.remoteControlManager.setRemoteControlMode(false, 'launch');
}
}
this.diagnosticManager.clear();
});

vscode.debug.onDidReceiveDebugSessionCustomEvent(async (e) => {
Expand All @@ -208,7 +212,7 @@ export class Extension {
context.subscriptions.push(vscode.languages.registerDefinitionProvider(xmlSelector, new BrightScriptXmlDefinitionProvider(definitionRepo)));

await this.whatsNewManager.showWelcomeOrWhatsNewIfRequired();
await languageServerPromise;
//await languageServerPromise;
}

private async debugSessionCustomEventHandler(e: any, context: vscode.ExtensionContext, docLinkProvider: LogDocumentLinkProvider, logOutputManager: LogOutputManager, rendezvousViewProvider: RendezvousViewProvider) {
Expand Down Expand Up @@ -249,6 +253,21 @@ export class Extension {
selection: util.toRange(firstDiagnostic.range)
});
}

let errorsByPath = {};
for (const diagnostic of e.body.diagnostics) {
if (diagnostic.path) {
if (!errorsByPath[diagnostic.path]) {
errorsByPath[diagnostic.path] = [];
}
errorsByPath[diagnostic.path].push(diagnostic);
}
}
for (const path in errorsByPath) {
if (errorsByPath.hasOwnProperty(path)) {
await this.diagnosticManager.addDiagnosticForError(path, errorsByPath[path]).catch(() => { });
}
}
}
}

Expand Down
42 changes: 42 additions & 0 deletions src/managers/DiagnosticManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { BSDebugDiagnostic } from 'roku-debug';
import * as vscode from 'vscode';

export class DiagnosticManager {

private collection = vscode.languages.createDiagnosticCollection('BrightScript');

public clear() {
this.collection.clear();
}

public async addDiagnosticForError(path: string, diagnostics: BSDebugDiagnostic[]) {
let documentUri: vscode.Uri;
let uri = vscode.Uri.file(path);
let doc = await vscode.workspace.openTextDocument(uri);
if (doc !== undefined) {
documentUri = doc.uri;
}

if (documentUri !== undefined) {
let result: vscode.Diagnostic[] = [];
for (const diagnostic of diagnostics) {

result.push({
code: diagnostic.code,
message: diagnostic.message,
source: diagnostic.source,
//the DiagnosticSeverity.Error from vscode-languageserver-types starts at 1, but vscode.DiagnosticSeverity.Error starts at 0. So subtract 1 to make them compatible
severity: diagnostic.severity - 1,
tags: diagnostic.tags,
range: new vscode.Range(
new vscode.Position(diagnostic.range.start.line, diagnostic.range.start.character),
new vscode.Position(diagnostic.range.end.line, diagnostic.range.end.character)
)
});
}
this.collection.set(documentUri, result);
}
}


}

0 comments on commit b5944cb

Please sign in to comment.