Skip to content
This repository has been archived by the owner on Apr 3, 2024. It is now read-only.

Commit

Permalink
feat: improve experience when multiple files match a breakpoint locat…
Browse files Browse the repository at this point in the history
…ion (#784)

The log message contains the requested path and the matching paths.  It
can be used to help users diagnose their ambiguous file errors.
  • Loading branch information
mctavish authored and JustinBeckwith committed Nov 21, 2019
1 parent 56fe969 commit 8b50f38
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 14 deletions.
9 changes: 8 additions & 1 deletion src/agent/util/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,15 @@ function resolveScripts(
// There should be no ambiguity resolution if project root is provided.
return fileStats[candidate] ? [candidate] : [];
}
const regexp = pathToRegExp(scriptPath);

// Try for an exact match using the working directory.
const candidate = path.join(config.workingDirectory || '', scriptPath);
if (fileStats[candidate]) {
return [candidate];
}

// Next try to match path.
const regexp = pathToRegExp(scriptPath);
const matches = Object.keys(fileStats).filter(regexp.test.bind(regexp));
if (matches.length === 1) {
return matches;
Expand Down
14 changes: 9 additions & 5 deletions src/agent/v8/inspector-debugapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,12 +378,13 @@ export class InspectorDebugApi implements debugapi.DebugApi {
// working directory.
let matchingScript;
// TODO: Address the case where `breakpoint.location` is `null`.
const scriptPath = mapInfo
? mapInfo.file
: path.normalize(
(breakpoint.location as stackdriver.SourceLocation).path
);
const scripts = utils.findScripts(
mapInfo
? mapInfo.file
: path.normalize(
(breakpoint.location as stackdriver.SourceLocation).path
),
scriptPath,
this.config,
this.fileStats,
this.logger
Expand All @@ -399,6 +400,9 @@ export class InspectorDebugApi implements debugapi.DebugApi {
// Found the script
matchingScript = scripts[0];
} else {
this.logger.warn(
`Unable to unambiguously find ${scriptPath}. Potential matches: ${scripts}`
);
return utils.setErrorStatusAndCallback(
cb,
breakpoint,
Expand Down
14 changes: 9 additions & 5 deletions src/agent/v8/legacy-debugapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,12 +335,13 @@ export class V8DebugApi implements debugapi.DebugApi {
// debuglet, we are going to assume that repository root === the starting
// working directory.
let matchingScript;
const scriptPath = mapInfo
? mapInfo.file
: path.normalize(
(breakpoint.location as stackdriver.SourceLocation).path
);
const scripts = utils.findScripts(
mapInfo
? mapInfo.file
: path.normalize(
(breakpoint.location as stackdriver.SourceLocation).path
),
scriptPath,
this.config,
this.fileStats,
this.logger
Expand All @@ -356,6 +357,9 @@ export class V8DebugApi implements debugapi.DebugApi {
// Found the script
matchingScript = scripts[0];
} else {
this.logger.warn(
`Unable to unambiguously find ${scriptPath}. Potential matches: ${scripts}`
);
return utils.setErrorStatusAndCallback(
cb,
breakpoint,
Expand Down
9 changes: 9 additions & 0 deletions test/mock-logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ export class MockLogger implements consoleLogLevel.Logger {
);
}

clear() {
this.traces = [];
this.debugs = [];
this.infos = [];
this.warns = [];
this.errors = [];
this.fatals = [];
}

trace(...args: Arguments) {
this.traces.push({type: 'trace', args});
}
Expand Down
48 changes: 45 additions & 3 deletions test/test-v8debugapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,7 @@ describe('v8debugapi', () => {
forceNewAgent_: true,
javascriptFileExtensions: ['.js', '.jsz'],
});
const logger = consoleLogLevel({
level: Debuglet.logLevelToName(config.logLevel),
});
const logger = new MockLogger();
let api: DebugApi;

beforeEach(done => {
Expand Down Expand Up @@ -288,6 +286,7 @@ describe('v8debugapi', () => {
}
});
afterEach(() => {
logger.clear();
assert(stateIsClean(api));
});

Expand Down Expand Up @@ -436,6 +435,32 @@ describe('v8debugapi', () => {
assert(
bp.status!.description.format === utils.messages.SOURCE_FILE_AMBIGUOUS
);

// Verify that a log message is emitted.
assert.strictEqual(
logger.warns.length,
1,
`Expected 1 warning log message, got ${logger.allCalls.length}`
);
const message = logger.warns[0].args[0];
let expectedSubstring = path.join('fixtures', 'a', 'hello.js');
assert.notStrictEqual(
message.indexOf(expectedSubstring),
-1,
`Missing text '${expectedSubstring}' in '${message}'`
);
expectedSubstring = path.join('fixtures', 'b', 'hello.js');
assert.notStrictEqual(
message.indexOf(expectedSubstring),
-1,
`Missing text '${expectedSubstring}' in '${message}'`
);
expectedSubstring = 'Unable to unambiguously find';
assert.notStrictEqual(
message.indexOf(expectedSubstring),
-1,
`Missing text '${expectedSubstring}' in '${message}'`
);
done();
});
});
Expand Down Expand Up @@ -1980,6 +2005,23 @@ describe('v8debugapi.findScripts', () => {
assert.strictEqual(logger.allCalls().length, 0);
});

it('should prefer exact path matches to ones involving subdirectories', () => {
const config = extend(true, {}, undefined!, {
workingDirectory: path.join('root'),
});

const logger = new MockLogger();

const fakeFileStats = {
[path.join('root', 'hello.js')]: {hash: 'fake', lines: 5},
[path.join('root', 'subdir', 'hello.js')]: {hash: 'fake', lines: 50},
};
const scriptPath = 'hello.js';
const result = utils.findScripts(scriptPath, config, fakeFileStats, logger);
assert.deepStrictEqual(result, [path.join('root', 'hello.js')]);
assert.strictEqual(logger.allCalls().length, 0);
});

it('should invoke pathResolver if provided', () => {
const config = extend(true, {}, undefined!, {
pathResolver(
Expand Down

0 comments on commit 8b50f38

Please sign in to comment.