Skip to content

Commit f8a708c

Browse files
committed
fix: honor relocated breakpoints
1 parent 8808794 commit f8a708c

File tree

1 file changed

+52
-20
lines changed

1 file changed

+52
-20
lines changed

src/session.ts

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ const mergeEnv = (
538538
}
539539
merged[pathKey] = segments.join(path.delimiter);
540540
logger.debug(
541-
`Augmented PATH for diagnostic capture with ${binDirs.length} node_modules/.bin directorie(s).`
541+
`Augmented PATH for diagnostic capture with ${binDirs.length} node_modules/.bin directories(s).`
542542
);
543543
}
544544
return merged;
@@ -1274,6 +1274,7 @@ export const startDebuggingAndWaitForStop = async (
12741274
const validated: Array<{
12751275
bp: (typeof breakpointConfig.breakpoints)[number];
12761276
sb: vscode.SourceBreakpoint;
1277+
resolvedLine: number;
12771278
}> = [];
12781279
for (const bp of breakpointConfig.breakpoints) {
12791280
const absolutePath = path.isAbsolute(bp.path)
@@ -1312,7 +1313,7 @@ export const startDebuggingAndWaitForStop = async (
13121313
effectiveHitCondition,
13131314
adapterLogMessage
13141315
);
1315-
validated.push({ bp, sb: sourceBp });
1316+
validated.push({ bp, sb: sourceBp, resolvedLine: bp.line });
13161317
} catch (e) {
13171318
logger.error(
13181319
`Failed to open file for breakpoint path ${absolutePath}: ${
@@ -1321,6 +1322,34 @@ export const startDebuggingAndWaitForStop = async (
13211322
);
13221323
}
13231324
}
1325+
const updateResolvedBreakpointLine = (source: vscode.SourceBreakpoint) => {
1326+
const match = validated.find((entry) => entry.sb === source);
1327+
if (!match) {
1328+
return;
1329+
}
1330+
const nextResolvedLine = source.location.range.start.line + 1;
1331+
if (match.resolvedLine === nextResolvedLine) {
1332+
return;
1333+
}
1334+
logger.debug(
1335+
`Breakpoint ${source.location.uri.fsPath} resolved line changed from ${match.resolvedLine} to ${nextResolvedLine}.`
1336+
);
1337+
match.resolvedLine = nextResolvedLine;
1338+
};
1339+
let breakpointChangeDisposable: vscode.Disposable | undefined;
1340+
if (validated.length) {
1341+
breakpointChangeDisposable = vscode.debug.onDidChangeBreakpoints(
1342+
(event) => {
1343+
const candidates = [...event.added, ...event.changed].filter(
1344+
(bp): bp is vscode.SourceBreakpoint =>
1345+
bp instanceof vscode.SourceBreakpoint
1346+
);
1347+
for (const bp of candidates) {
1348+
updateResolvedBreakpointLine(bp);
1349+
}
1350+
}
1351+
);
1352+
}
13241353
// Optional serverReady breakpoint (declare early so scope is available later)
13251354
let serverReadySource: vscode.SourceBreakpoint | undefined;
13261355
if (
@@ -1898,10 +1927,10 @@ export const startDebuggingAndWaitForStop = async (
18981927
const isServerReadyHit =
18991928
!!serverReadySource && entryStop.line === serverReady?.trigger?.line;
19001929
// Decide whether to continue immediately (entry not at user breakpoint OR serverReady hit)
1901-
const entryLineZeroBased = entryStop.line ? entryStop.line - 1 : -1;
1902-
const hitRequestedBreakpoint = validated.some(
1903-
(v) => v.sb.location.range.start.line === entryLineZeroBased
1904-
);
1930+
const entryLineOneBased = entryStop.line ?? -1;
1931+
const hitRequestedBreakpoint =
1932+
entryLineOneBased > 0 &&
1933+
validated.some((v) => v.resolvedLine === entryLineOneBased);
19051934
logger.info(
19061935
`EntryStop diagnostics: line=${entryStop.line} serverReadyLine=${serverReady?.trigger?.line} isServerReadyHit=${isServerReadyHit} hitRequestedBreakpoint=${hitRequestedBreakpoint}`
19071936
);
@@ -2081,24 +2110,26 @@ export const startDebuggingAndWaitForStop = async (
20812110
const frameLine = debugContext.frame?.line;
20822111
if (framePath && typeof frameLine === "number") {
20832112
const normalizedFramePath = normalizeFsPath(framePath);
2084-
for (const { bp } of validated) {
2113+
for (const { bp, resolvedLine } of validated) {
20852114
const absPath = path.isAbsolute(bp.path)
20862115
? bp.path
20872116
: path.join(folderFsPath, bp.path);
2088-
if (
2089-
normalizeFsPath(absPath) === normalizedFramePath &&
2090-
bp.line === frameLine
2091-
) {
2092-
hitBreakpoint = {
2093-
path: absPath,
2094-
line: bp.line,
2095-
variableFilter: bp.variableFilter,
2096-
action: bp.action,
2097-
logMessage: bp.logMessage,
2098-
reasonCode: bp.reasonCode,
2099-
};
2100-
break;
2117+
if (normalizeFsPath(absPath) !== normalizedFramePath) {
2118+
continue;
2119+
}
2120+
const matchesLine = frameLine === bp.line || frameLine === resolvedLine;
2121+
if (!matchesLine) {
2122+
continue;
21012123
}
2124+
hitBreakpoint = {
2125+
path: absPath,
2126+
line: frameLine,
2127+
variableFilter: bp.variableFilter,
2128+
action: bp.action,
2129+
logMessage: bp.logMessage,
2130+
reasonCode: bp.reasonCode,
2131+
};
2132+
break;
21022133
}
21032134
}
21042135
// Build variable lookup for interpolation (for capture action log message expansion)
@@ -2251,6 +2282,7 @@ export const startDebuggingAndWaitForStop = async (
22512282
activeDebugPatternScan = undefined;
22522283
terminalCapture.dispose();
22532284
taskStartDisposable?.dispose();
2285+
breakpointChangeDisposable?.dispose();
22542286
// Restore original breakpoints, removing any added ones first
22552287
const current = vscode.debug.breakpoints;
22562288
if (current.length) {

0 commit comments

Comments
 (0)