Skip to content

Commit

Permalink
Tests and clean up to path scraping
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdp committed Jan 22, 2025
1 parent 6b115ff commit f370e1f
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 7 deletions.
169 changes: 168 additions & 1 deletion src/debugSession/BrightScriptDebugSession.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { DefaultFiles, rokuDeploy } from 'roku-deploy';
import type { AddProjectParams, ComponentLibraryConstructorParams } from '../managers/ProjectManager';
import { ComponentLibraryProject, Project } from '../managers/ProjectManager';
import { RendezvousTracker } from '../RendezvousTracker';
import { ClientToServerCustomEventName, isCustomRequestEvent } from './Events';
import { ClientToServerCustomEventName, isCustomRequestEvent, LogOutputEvent } from './Events';
import { EventEmitter } from 'eventemitter3';

const sinon = sinonActual.createSandbox();
Expand Down Expand Up @@ -1164,5 +1164,172 @@ describe('BrightScriptDebugSession', () => {
expect(getVarStub.calledWith('person.name', frameId, true));
});
});

describe('sendLogOutput', () => {

async function doTest(input: string, output: string, locations: Array<{ filePath: string; lineNumber: number; columnIndex?: number }>) {
const getSourceLocationStub = sinon.stub(session.projectManager, 'getSourceLocation').callsFake(() => {
return Promise.resolve(locations.shift() as any);
});

const sendEventStub = sinon.stub(session, 'sendEvent');

await session['sendLogOutput'](input);

expect(
sendEventStub.getCalls().filter(x => x.args[0] instanceof LogOutputEvent).map(call => call.args[0].body.line).join('')
).to.eql(output);
sendEventStub.restore();
getSourceLocationStub.restore();
}

it('modifies pkg locations if found multiline', async () => {
await doTest(
`{
backtrace: "
file/line: pkg:/components/services/NetworkBase.bs:251
Function networkbase_runtaskthread() As Void
file/line: pkg:/components/services/NetworkBase.bs:654
Function networkbase_processresponse(message As Object) As Object
file/line: pkg:/source/sgnode.bs:109
Function sgnode_createnode(nodetype As String, fields As Dynamic) As Object"
message: "Divide by Zero."
number: 20
rethrown: false
}`,
`{
backtrace: "
file/line: file://c:/project/components/services/NetworkBase.bs:260
Function networkbase_runtaskthread() As Void
file/line: file://c:/project/components/services/NetworkBase.bs:700
Function networkbase_processresponse(message As Object) As Object
file/line: file://c:/project/components/services/sgnode.bs:100
Function sgnode_createnode(nodetype As String, fields As Dynamic) As Object"
message: "Divide by Zero."
number: 20
rethrown: false
}`,
[
{ filePath: `c:/project/components/services/NetworkBase.bs`, lineNumber: 260 },
{ filePath: `c:/project/components/services/NetworkBase.bs`, lineNumber: 700 },
{ filePath: `c:/project/components/services/sgnode.bs`, lineNumber: 100 }
]
);
});

it('modifies windows pkg locations with just line', async () => {
await doTest(
` pkg:/components/services/NetworkBase.bs:251`,
` file://c:/project/components/services/NetworkBase.bs:260`,
[{ filePath: `c:/project/components/services/NetworkBase.bs`, lineNumber: 260 }]
);
await doTest(
` pkg:/components/services/NetworkBase.bs(251)`,
` file://C:/project/components/services/NetworkBase.bs:260`,
[{ filePath: `C:/project/components/services/NetworkBase.bs`, lineNumber: 260 }]
);
await doTest(
` ...rvices/NetworkBase.bs:251`,
` file://c:/project/components/services/NetworkBase.bs:260`,
[{ filePath: `c:/project/components/services/NetworkBase.bs`, lineNumber: 260 }]
);
await doTest(
` ...rvices/NetworkBase.bs(251)`,
` file://c:/project/components/services/NetworkBase.bs:260`,
[{ filePath: `c:/project/components/services/NetworkBase.bs`, lineNumber: 260 }]
);
});

it('modifies windows pkg locations with line and column', async () => {
await doTest(
` pkg:/components/services/NetworkBase.bs:251:10`,
` file://c:/project/components/services/NetworkBase.bs:260:12`,
[{ filePath: `c:/project/components/services/NetworkBase.bs`, lineNumber: 260, columnIndex: 11 }]
);
await doTest(
` pkg:/components/services/NetworkBase.bs(251:10)`,
` file://C:/project/components/services/NetworkBase.bs:260:12`,
[{ filePath: `C:/project/components/services/NetworkBase.bs`, lineNumber: 260, columnIndex: 11 }]
);
await doTest(
` ...rvices/NetworkBase.bs:251:10`,
` file://c:/project/components/services/NetworkBase.bs:260:12`,
[{ filePath: `c:/project/components/services/NetworkBase.bs`, lineNumber: 260, columnIndex: 11 }]
);
await doTest(
` ...rvices/NetworkBase.bs(251:10)`,
` file://c:/project/components/services/NetworkBase.bs:260:12`,
[{ filePath: `c:/project/components/services/NetworkBase.bs`, lineNumber: 260, columnIndex: 11 }]
);
});

it('modifies mac/linx pkg locations with just line', async () => {
await doTest(
` pkg:/components/services/NetworkBase.bs:251`,
` file://project/components/services/NetworkBase.bs:260`,
[{ filePath: `/project/components/services/NetworkBase.bs`, lineNumber: 260 }]
);
await doTest(
` pkg:/components/services/NetworkBase.bs(251)`,
` file://project/components/services/NetworkBase.bs:260`,
[{ filePath: `/project/components/services/NetworkBase.bs`, lineNumber: 260 }]
);
await doTest(
` ...rvices/NetworkBase.bs:251`,
` file://project/components/services/NetworkBase.bs:260`,
[{ filePath: `/project/components/services/NetworkBase.bs`, lineNumber: 260 }]
);
await doTest(
` ...rvices/NetworkBase.bs(251)`,
` file://project/components/services/NetworkBase.bs:260`,
[{ filePath: `/project/components/services/NetworkBase.bs`, lineNumber: 260 }]
);
});

it('modifies mac/linx pkg locations line and column', async () => {
await doTest(
` pkg:/components/services/NetworkBase.bs:251:10`,
` file://project/components/services/NetworkBase.bs:260:12`,
[{ filePath: `/project/components/services/NetworkBase.bs`, lineNumber: 260, columnIndex: 11 }]
);
await doTest(
` pkg:/components/services/NetworkBase.bs(251:10)`,
` file://project/components/services/NetworkBase.bs:260:12`,
[{ filePath: `/project/components/services/NetworkBase.bs`, lineNumber: 260, columnIndex: 11 }]
);
await doTest(
` ...rvices/NetworkBase.bs:251:10`,
` file://project/components/services/NetworkBase.bs:260:12`,
[{ filePath: `/project/components/services/NetworkBase.bs`, lineNumber: 260, columnIndex: 11 }]
);
await doTest(
` ...rvices/NetworkBase.bs(251:10)`,
` file://project/components/services/NetworkBase.bs:260:12`,
[{ filePath: `/project/components/services/NetworkBase.bs`, lineNumber: 260, columnIndex: 11 }]
);
});

it('does not modify path', async () => {
await doTest(
` pkg:/components/services/NetworkBase.bs`,
` pkg:/components/services/NetworkBase.bs`,
[undefined]
);
await doTest(
` pkg:/components/services/NetworkBase.bs:251`,
` pkg:/components/services/NetworkBase.bs:251`,
[undefined]
);
await doTest(
` pkg:/components/services/NetworkBase.bs:251:10`,
` pkg:/components/services/NetworkBase.bs:251:10`,
[undefined]
);
});
});
});
});
55 changes: 49 additions & 6 deletions src/debugSession/BrightScriptDebugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,6 @@ export class BrightScriptDebugSession extends BaseDebugSession {
}

private pendingSendLogPromise = Promise.resolve();
private deviceFilePathRegex = /(?:\s*)((?:\.\.\.|[A-Za-z_0-9]*pkg\:\/)[A-Za-z_0-9\/\.]+\.[A-Za-z_0-9\/]+\:(\d+))(?:\s*)/ig;

/**
* Send log output to the "client" (i.e. vscode)
Expand All @@ -679,25 +678,69 @@ export class BrightScriptDebugSession extends BaseDebugSession {
line += '\n';
}

let potentialPaths = line.matchAll(this.deviceFilePathRegex);
let potentialPaths = this.getPotentialPkgPaths(line);
for (let potentialPath of potentialPaths) {
let originalLocation = await this.projectManager.getSourceLocation(potentialPath[1], parseInt(potentialPath[2]));
let originalLocation = await this.projectManager.getSourceLocation(potentialPath.path, potentialPath.lineNumber, potentialPath.columnNumber);
if (originalLocation) {
let replacement: string;
if (originalLocation.filePath.startsWith('/')) {
replacement = `file:/${originalLocation.filePath}`;
replacement = `file:/${originalLocation.filePath}:${originalLocation.lineNumber}`;
} else {
replacement = `file://${originalLocation.filePath}`;
replacement = `file://${originalLocation.filePath}:${originalLocation.lineNumber}`;
}

line = line.replace(potentialPath[1], replacement);
if (potentialPath.columnNumber !== undefined) {
replacement += `:${originalLocation.columnIndex + 1}`;
}

line = line.replaceAll(potentialPath.fullMatch, replacement);
}
}

this.sendEvent(new OutputEvent(line, 'stdout'));
this.sendEvent(new LogOutputEvent(line));
}
});
return this.pendingSendLogPromise;
}

// https://regex101.com/r/ixpQiq/1
private deviceFilePathRegex = /((?:\.\.\.|[A-Za-z_0-9]*pkg\:\/)[A-Za-z_0-9 \/\.]+\.[A-Za-z_0-9 \/]+)(?:(?:\:)(\d+)(?:\:(\d+))?|\((\d+)(?:\:(\d+))?\))/ig;

/**
* Extracts potential package paths from a given line of text.
*
* This method uses a regular expression to find matches in the provided line
* and returns an array of objects containing details about each match.
*
* @param input - The line of text to search for potential package paths.
* @returns An array of objects, each containing:
* - `fullMatch`: The full matched string.
* - `path`: The extracted path from the match.
* - `lineNumber`: The line number extracted from the match.
* - `columnNumber`: The column number extracted from the match, or `undefined` if not found.
*/
private getPotentialPkgPaths(input: string): Array<{ fullMatch: string; path: string; lineNumber: number; columnNumber: number }> {
let matches = input.matchAll(this.deviceFilePathRegex);
let paths: ReturnType<BrightScriptDebugSession['getPotentialPkgPaths']> = [];
if (matches) {
for (let match of matches) {
let fullMatch = match[0];
let path = match[1];
let lineNumber = parseInt(match[2] ?? match[4]);
let columnNumber = parseInt(match[3] ?? match[5]);
if (isNaN(columnNumber)) {
columnNumber = undefined;
}
paths.push({
fullMatch: fullMatch,
path: path,
lineNumber: lineNumber,
columnNumber: columnNumber
});
}
}
return paths;
}

private async runAutomaticSceneGraphCommands(commands: string[]) {
Expand Down

0 comments on commit f370e1f

Please sign in to comment.