diff --git a/package-lock.json b/package-lock.json index b340a313..ccea03a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,8 +28,8 @@ "node-cache": "^4.2.0", "node-ssdp": "^4.0.0", "pretty-bytes": "^5.6.0", - "roku-debug": "^0.15.0", - "roku-deploy": "^3.8.1", + "roku-debug": "^0.16.0", + "roku-deploy": "^3.9.2", "roku-test-automation": "2.0.0-beta.5", "semver": "^7.1.3", "source-map": "^0.7.3", @@ -8763,12 +8763,12 @@ } }, "node_modules/roku-debug": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/roku-debug/-/roku-debug-0.15.0.tgz", - "integrity": "sha512-jRZLNqm0KoTCy2fXsp26LLRG4cp9piCbNNBEp8n78o5yQZNxI7sw+VBGK7UvV3hnNaifuWNS3KT/S161SVB3cw==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/roku-debug/-/roku-debug-0.16.0.tgz", + "integrity": "sha512-mqtqcQZS+dNVkojKE2ugx+fLgKrQwpZwtvtrkdJkG0ZfSdwdgAc9ZNFTqLyutgILsY1f6Ixlae6zsOBk3iroTw==", "dependencies": { "@rokucommunity/logger": "^0.3.0", - "brighterscript": "^0.56.0", + "brighterscript": "^0.60.0", "dateformat": "^4.6.3", "eol": "^0.9.1", "eventemitter3": "^4.0.7", @@ -8777,7 +8777,7 @@ "natural-orderby": "^2.0.3", "replace-in-file": "^6.3.2", "replace-last": "^1.2.6", - "roku-deploy": "^3.7.1", + "roku-deploy": "^3.9.2", "semver": "^7.3.5", "serialize-error": "^8.1.0", "smart-buffer": "^4.2.0", @@ -8800,9 +8800,9 @@ } }, "node_modules/roku-debug/node_modules/brighterscript": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.56.0.tgz", - "integrity": "sha512-SG8Oj3pDjtsbq1eZRnAI96T3PVSIDORPh8QfBtXVMPRG2ntJd2OfySpHsaItt5K9oveZi1OjPPguRGL7xaU0MQ==", + "version": "0.60.0", + "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.60.0.tgz", + "integrity": "sha512-LdwiUODQBzB5qd9TwAUFMyTNXzLU7pubYEUg4ZBH13/lKByqCQKPjYnC2NHQI4YHimgoXW9YqkDmWsZI9di2NQ==", "dependencies": { "@rokucommunity/bslib": "^0.1.1", "@xml-tools/parser": "^1.0.7", @@ -8825,7 +8825,7 @@ "p-settle": "^2.1.0", "parse-ms": "^2.1.0", "require-relative": "^0.8.7", - "roku-deploy": "^3.7.1", + "roku-deploy": "^3.9.2", "serialize-error": "^7.0.1", "source-map": "^0.7.3", "vscode-languageserver": "7.0.0", @@ -9020,9 +9020,9 @@ "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" }, "node_modules/roku-deploy": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.8.1.tgz", - "integrity": "sha512-b8Q2IvBdEka4XIBNLU9CumPDto8X5zCmWQwwFfBPkJqwDnJ4U47GqKCJp1dHdmAY9H/JRYIj2TmFE4cTOUiTNw==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.9.2.tgz", + "integrity": "sha512-2LZyR4EhaFrka1gVmcuJO/f42tqz4clGImboVLCNem1q/PcFV5cnXNZRfqDI+MZ/n8eJto71JlZkcc7TDLt/EQ==", "dependencies": { "chalk": "^2.4.2", "dateformat": "^3.0.3", @@ -9032,9 +9032,9 @@ "is-glob": "^4.0.3", "jsonc-parser": "^2.3.0", "jszip": "^3.6.0", - "minimatch": "^3.0.4", "moment": "^2.29.1", "parse-ms": "^2.1.0", + "picomatch": "^2.2.1", "request": "^2.88.0", "temp-dir": "^2.0.0", "xml2js": "^0.4.23" @@ -18244,12 +18244,12 @@ } }, "roku-debug": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/roku-debug/-/roku-debug-0.15.0.tgz", - "integrity": "sha512-jRZLNqm0KoTCy2fXsp26LLRG4cp9piCbNNBEp8n78o5yQZNxI7sw+VBGK7UvV3hnNaifuWNS3KT/S161SVB3cw==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/roku-debug/-/roku-debug-0.16.0.tgz", + "integrity": "sha512-mqtqcQZS+dNVkojKE2ugx+fLgKrQwpZwtvtrkdJkG0ZfSdwdgAc9ZNFTqLyutgILsY1f6Ixlae6zsOBk3iroTw==", "requires": { "@rokucommunity/logger": "^0.3.0", - "brighterscript": "^0.56.0", + "brighterscript": "^0.60.0", "dateformat": "^4.6.3", "eol": "^0.9.1", "eventemitter3": "^4.0.7", @@ -18258,7 +18258,7 @@ "natural-orderby": "^2.0.3", "replace-in-file": "^6.3.2", "replace-last": "^1.2.6", - "roku-deploy": "^3.7.1", + "roku-deploy": "^3.9.2", "semver": "^7.3.5", "serialize-error": "^8.1.0", "smart-buffer": "^4.2.0", @@ -18278,9 +18278,9 @@ } }, "brighterscript": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.56.0.tgz", - "integrity": "sha512-SG8Oj3pDjtsbq1eZRnAI96T3PVSIDORPh8QfBtXVMPRG2ntJd2OfySpHsaItt5K9oveZi1OjPPguRGL7xaU0MQ==", + "version": "0.60.0", + "resolved": "https://registry.npmjs.org/brighterscript/-/brighterscript-0.60.0.tgz", + "integrity": "sha512-LdwiUODQBzB5qd9TwAUFMyTNXzLU7pubYEUg4ZBH13/lKByqCQKPjYnC2NHQI4YHimgoXW9YqkDmWsZI9di2NQ==", "requires": { "@rokucommunity/bslib": "^0.1.1", "@xml-tools/parser": "^1.0.7", @@ -18303,7 +18303,7 @@ "p-settle": "^2.1.0", "parse-ms": "^2.1.0", "require-relative": "^0.8.7", - "roku-deploy": "^3.7.1", + "roku-deploy": "^3.9.2", "serialize-error": "^7.0.1", "source-map": "^0.7.3", "vscode-languageserver": "7.0.0", @@ -18449,9 +18449,9 @@ } }, "roku-deploy": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.8.1.tgz", - "integrity": "sha512-b8Q2IvBdEka4XIBNLU9CumPDto8X5zCmWQwwFfBPkJqwDnJ4U47GqKCJp1dHdmAY9H/JRYIj2TmFE4cTOUiTNw==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/roku-deploy/-/roku-deploy-3.9.2.tgz", + "integrity": "sha512-2LZyR4EhaFrka1gVmcuJO/f42tqz4clGImboVLCNem1q/PcFV5cnXNZRfqDI+MZ/n8eJto71JlZkcc7TDLt/EQ==", "requires": { "chalk": "^2.4.2", "dateformat": "^3.0.3", @@ -18461,9 +18461,9 @@ "is-glob": "^4.0.3", "jsonc-parser": "^2.3.0", "jszip": "^3.6.0", - "minimatch": "^3.0.4", "moment": "^2.29.1", "parse-ms": "^2.1.0", + "picomatch": "^2.2.1", "request": "^2.88.0", "temp-dir": "^2.0.0", "xml2js": "^0.4.23" diff --git a/package.json b/package.json index 45222cb4..f89428f5 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,8 @@ "node-cache": "^4.2.0", "node-ssdp": "^4.0.0", "pretty-bytes": "^5.6.0", - "roku-debug": "^0.15.0", - "roku-deploy": "^3.8.1", + "roku-debug": "^0.16.0", + "roku-deploy": "^3.9.2", "roku-test-automation": "2.0.0-beta.5", "semver": "^7.1.3", "source-map": "^0.7.3", diff --git a/src/LogOutputManager.spec.ts b/src/LogOutputManager.spec.ts index 8327deda..dc3dcea4 100644 --- a/src/LogOutputManager.spec.ts +++ b/src/LogOutputManager.spec.ts @@ -20,6 +20,9 @@ Module.prototype.require = function hijacked(file) { import { DeclarationProvider } from './DeclarationProvider'; import { LogDocumentLinkProvider } from './LogDocumentLinkProvider'; import { LogLine, LogOutputManager } from './LogOutputManager'; +import type { BSDebugDiagnostic } from 'roku-debug'; +import { DiagnosticsEvent, LaunchStartEvent, LogOutputEvent } from 'roku-debug'; +import { util } from 'brighterscript'; describe('LogOutputManager ', () => { let logOutputManagerMock: Sinon.SinonMock; @@ -69,34 +72,34 @@ describe('LogOutputManager ', () => { logOutputManagerMock.verify(); }); - it('tests onDidReceiveDebugSessionCustomEvent - BSLaunchStartEvent - clear flag', async () => { + it('tests onDidReceiveDebugSessionCustomEvent - LaunchStartEvent - clear flag', async () => { collectionMock.expects('clear').once(); logOutputManager.isClearingOutputOnLaunch = true; - await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: 'BSLaunchStartEvent' }); + await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: 'LaunchStartEvent' }); outputChannelMock.verify(); collectionMock.verify(); logOutputManagerMock.verify(); }); - it('tests onDidReceiveDebugSessionCustomEvent - BSLaunchStartEvent - no clear flag', async () => { + it('tests onDidReceiveDebugSessionCustomEvent - LaunchStartEvent - no clear flag', async () => { collectionMock.expects('clear').never(); logOutputManager.isClearingOutputOnLaunch = false; - await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: 'BSLaunchStartEvent' }); + await logOutputManager.onDidReceiveDebugSessionCustomEvent(new LaunchStartEvent({} as any)); outputChannelMock.verify(); collectionMock.verify(); logOutputManagerMock.verify(); }); - it('tests onDidReceiveDebugSessionCustomEvent - BSLogOutputEvent', async () => { + it('tests onDidReceiveDebugSessionCustomEvent - LogOutputEvent', async () => { outputChannelMock.expects('appendLine').once(); - await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: 'BSLogOutputEvent', body: 'test1' }); + await logOutputManager.onDidReceiveDebugSessionCustomEvent(new LogOutputEvent('test 1')); outputChannelMock.verify(); collectionMock.verify(); logOutputManagerMock.verify(); }); it('tests onDidReceiveDebugSessionCustomEvent - error - empty', async () => { - await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: '', body: [] }); + await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: '', body: {} }); outputChannelMock.verify(); collectionMock.verify(); logOutputManagerMock.verify(); @@ -111,8 +114,12 @@ describe('LogOutputManager ', () => { it('tests onDidReceiveDebugSessionCustomEvent - errors', async () => { logOutputManagerMock.expects('addDiagnosticForError').once(); - let compileErrors = [{ path: 'path1', message: 'message1' }]; - await logOutputManager.onDidReceiveDebugSessionCustomEvent({ event: '', body: compileErrors }); + 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(); diff --git a/src/LogOutputManager.ts b/src/LogOutputManager.ts index 1e9938f0..39e7dc30 100644 --- a/src/LogOutputManager.ts +++ b/src/LogOutputManager.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import type { DiagnosticCollection } from 'vscode'; -import type { BrightScriptDebugCompileError } from 'roku-debug'; +import type { BSDebugDiagnostic } from 'roku-debug'; +import { isChanperfEvent, isDiagnosticsEvent, isLaunchStartEvent, isLogOutputEvent, isPopupMessageEvent, isRendezvousEvent } from 'roku-debug'; import type { DeclarationProvider } from './DeclarationProvider'; import type { LogDocumentLinkProvider } from './LogDocumentLinkProvider'; import { CustomDocumentLink } from './LogDocumentLinkProvider'; @@ -130,16 +131,18 @@ export class LogOutputManager { } public async onDidReceiveDebugSessionCustomEvent(e: { event: string; body?: any }) { - if (e.event === 'BSRendezvousEvent' || e.event === 'BSChanperfEvent') { + if (isRendezvousEvent(e) || isChanperfEvent(e)) { // No need to handle rendezvous type events return; } - if (e.event === 'BSLogOutputEvent') { - this.appendLine(e.body); - } else if (e.event === 'BSPopupMessageEvent') { + if (isLogOutputEvent(e)) { + this.appendLine(e.body.line); + + } else if (isPopupMessageEvent(e)) { this.showMessage(e.body.message, e.body.severity); - } else if (e.event === 'BSLaunchStartEvent') { + + } else if (isLaunchStartEvent(e)) { this.isInMicroDebugger = false; this.isNextBreakpointSkipped = false; if (this.isFocusingOutputOnLaunch) { @@ -149,14 +152,15 @@ export class LogOutputManager { if (this.isClearingOutputOnLaunch) { this.clearOutput(); } - } else if (e.body && Array.isArray(e.body)) { + + } else if (isDiagnosticsEvent(e)) { let errorsByPath = {}; - for (const compileError of e.body) { - if (compileError.path) { - if (!errorsByPath[compileError.path]) { - errorsByPath[compileError.path] = []; + for (const diagnostic of e.body.diagnostics) { + if (diagnostic.path) { + if (!errorsByPath[diagnostic.path]) { + errorsByPath[diagnostic.path] = []; } - errorsByPath[compileError.path].push(compileError); + errorsByPath[diagnostic.path].push(diagnostic); } } for (const path in errorsByPath) { @@ -177,8 +181,7 @@ export class LogOutputManager { methods[severity](message); } - public async addDiagnosticForError(path: string, compileErrors: BrightScriptDebugCompileError[]) { - + public async addDiagnosticForError(path: string, diagnostics: BSDebugDiagnostic[]) { //TODO get the actual folder let documentUri: vscode.Uri; let uri = vscode.Uri.file(path); @@ -193,25 +196,21 @@ export class LogOutputManager { // const currentDocumentUri = document.uri; // console.log("currentDocumentUri " + currentDocumentUri); if (documentUri !== undefined) { - let diagnostics: vscode.Diagnostic[] = []; - for (const compileError of compileErrors) { - - const path: string = compileError.path; - const message: string = compileError.message; - const source: string = compileError.errorText; - const lineNumber: number = compileError.lineNumber; - const charStart: number = compileError.charStart; - const charEnd: number = compileError.charEnd; - - diagnostics.push({ - code: '', - message: message, - range: new vscode.Range(new vscode.Position(lineNumber, charStart), new vscode.Position(lineNumber, charEnd)), - severity: vscode.DiagnosticSeverity.Error, - source: source + 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, diagnostics); + this.collection.set(documentUri, result); } } diff --git a/src/extension.spec.ts b/src/extension.spec.ts index 7e07813e..bd9d1089 100644 --- a/src/extension.spec.ts +++ b/src/extension.spec.ts @@ -135,9 +135,9 @@ describe('extension', () => { }); describe('debugSessionCustomEventHandler', () => { - describe('BSChannelPublishedEvent', () => { + describe('ChannelPublishedEvent', () => { const e = { - event: 'BSChannelPublishedEvent', + event: 'ChannelPublishedEvent', body: { launchConfiguration: config } diff --git a/src/extension.ts b/src/extension.ts index 195355f0..bfda8f40 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -26,6 +26,7 @@ import { WhatsNewManager } from './managers/WhatsNewManager'; import { SceneGraphInspectorViewProvider } from './viewProviders/SceneGraphInspectorViewProvider'; import { RokuCommandsViewProvider } from './viewProviders/RokuCommandsViewProvider'; import { RokuRegistryViewProvider } from './viewProviders/RokuRegistryViewProvider'; +import { isChannelPublishedEvent, isChanperfEvent, isDiagnosticsEvent, isDebugServerLogOutputEvent, isLaunchStartEvent, isRendezvousEvent } from 'roku-debug'; const EXTENSION_ID = 'RokuCommunity.brightscript'; @@ -209,14 +210,15 @@ export class Extension { await languageServerPromise; } - private async debugSessionCustomEventHandler(e: vscode.DebugSessionCustomEvent, context: vscode.ExtensionContext, docLinkProvider: LogDocumentLinkProvider, logOutputManager: LogOutputManager, rendezvousViewProvider: RendezvousViewProvider) { - if (e.event === 'BSLaunchStartEvent') { - const config: BrightScriptLaunchConfiguration = e.body; + private async debugSessionCustomEventHandler(e: any, context: vscode.ExtensionContext, docLinkProvider: LogDocumentLinkProvider, logOutputManager: LogOutputManager, rendezvousViewProvider: RendezvousViewProvider) { + if (isLaunchStartEvent(e)) { + const config = e.body as BrightScriptLaunchConfiguration; await docLinkProvider.setLaunchConfig(config); logOutputManager.setLaunchConfig(config); this.registerWebViewProviders(context); - } else if (e.event === 'BSChannelPublishedEvent') { - const config: BrightScriptLaunchConfiguration = e.body.launchConfiguration; + + } else if (isChannelPublishedEvent(e)) { + const config = e.body.launchConfiguration as BrightScriptLaunchConfiguration; if (!config.injectRdbOnDeviceComponent) { void this.odc?.shutdown(); this.odc = undefined; @@ -226,13 +228,14 @@ export class Extension { this.setupRdbViewProviders(); void this.odc?.disableScreenSaver({ disableScreensaver: config.disableScreenSaver }); //write debug server log statements to the DebugServer output channel - } else if (e.event === 'BSDebugServerLogOutputEvent') { - this.extensionOutputChannel.appendLine(e.body); - } else if (e.event === 'BSRendezvousEvent') { + } else if (isDebugServerLogOutputEvent(e)) { + this.extensionOutputChannel.appendLine(e.body.line); + + } else if (isRendezvousEvent(e)) { rendezvousViewProvider.onDidReceiveDebugSessionCustomEvent(e); - } else if (e.event === 'BSChanperfEvent') { + } else if (isChanperfEvent(e)) { if (!e.body.error) { this.chanperfStatusBar.text = `$(dashboard)cpu: ${e.body.cpu.total}%, mem: ${prettyBytes(e.body.memory.total).replace(/ /g, '')}`; } else { @@ -241,14 +244,17 @@ export class Extension { this.chanperfStatusBar.show(); - } else if (!e.event) { - if (e.body[0]) { + } else if (isDiagnosticsEvent(e)) { + const diagnostics = e.body?.diagnostics ?? []; + const firstDiagnostic = diagnostics[0]; + if (firstDiagnostic) { // open the first file with a compile error - let uri = vscode.Uri.file(e.body[0].path); + let uri = vscode.Uri.file(firstDiagnostic.path); let doc = await vscode.workspace.openTextDocument(uri); - let line = (e.body[0].lineNumber - 1 > -1) ? e.body[0].lineNumber - 1 : 0; - let range = new vscode.Range(new vscode.Position(line, 0), new vscode.Position(line, 0)); - await vscode.window.showTextDocument(doc, { preview: false, selection: range }); + await vscode.window.showTextDocument(doc, { + preview: false, + selection: util.toRange(firstDiagnostic.range) + }); } } } diff --git a/src/util.ts b/src/util.ts index c1b7e834..de20d59e 100644 --- a/src/util.ts +++ b/src/util.ts @@ -291,6 +291,16 @@ class Util { setTimeout(resolve, milliseconds); }); } + + /** + * Convert an arbitrary range-like object into a proper vscode.Range instance + */ + public toRange(range: { start: { line: number; character: number }; end: { line: number; character: number } }) { + return new vscode.Range( + new vscode.Position(range.start.line, range.start.character), + new vscode.Position(range.end.line, range.end.character) + ); + } } const util = new Util(); diff --git a/src/viewProviders/RendezvousViewProvider.ts b/src/viewProviders/RendezvousViewProvider.ts index 439b7300..fd1c7af3 100644 --- a/src/viewProviders/RendezvousViewProvider.ts +++ b/src/viewProviders/RendezvousViewProvider.ts @@ -1,6 +1,7 @@ import * as arraySort from 'array-sort'; import * as vscode from 'vscode'; import type { RendezvousHistory } from 'roku-debug'; +import { isRendezvousEvent } from 'roku-debug'; export class RendezvousViewProvider implements vscode.TreeDataProvider { @@ -58,7 +59,7 @@ export class RendezvousViewProvider implements vscode.TreeDataProvider