In src/backend/adapter.ts, the setFunctionBreakPointsRequest method incorrectly treated breakpoint results as arrays, accessing them with result[0] and result[1], when they are actually objects (or null for failed breakpoints).
The addBreakPoint method in src/backend/mi2/mi2.ts returns:
- A breakpoint object with properties like
number,line,filewhen successful nullwhen parsing fails or GDB returns an error
However, setFunctionBreakPointsRequest was treating results as if they were arrays:
if (result[0]) {
breakpoints.push({ line: result[1].line });
}This is incorrect because:
resultis not an array - it's either an object ornullresult[0]andresult[1]would always beundefinedfor objects- No null-checking was performed
const results = (await Promise.all(promises)).filter((r) => r !== null);
response.body = {
breakpoints: results.map((bp: any) => ({
line: bp.line,
id: bp.number,
verified: true,
})),
};This correctly:
- Filters out
nullresults - Accesses object properties (
bp.line,bp.number)
results.forEach((result) => {
if (result[0]) { // ❌ Treating object as array
breakpoints.push({ line: result[1].line }); // ❌ Array access
}
});This incorrectly:
- Treats result as an array
- Doesn't properly check for
null - Would fail to add any breakpoints
results.forEach((result) => {
// Filter out null results (failed breakpoints) and use breakpoint object properties
if (result !== null) {
breakpoints.push({
line: result.line,
id: result.number,
verified: true
});
}
});This correctly:
- Checks for
nullexplicitly - Accesses object properties (
result.line,result.number) - Includes
idandverifiedfields for consistency withsetBreakPointsRequest
// Success case
{
number: 5, // Breakpoint number from GDB
line: 10, // Line number
file: 'test.c', // File path
condition?: string, // Optional condition
countCondition?: string // Optional hit count
}
// Failure case
nullThe result is not structured as:
[boolean, { line: number }] // ❌ WRONG- Function breakpoints would never be properly registered
result[0]would always beundefinedfor object resultsresult[1]would cause runtime errors when accessed- Breakpoints would silently fail to work
- Function breakpoints are properly registered
- Null results are filtered out
- Object properties are correctly accessed
- Consistent behavior with file breakpoints
Created comprehensive tests in __tests__/backend/breakpoint-error-handling.test.ts:
-
Null Return Handling (3 tests)
- Parsing failures return
null - GDB errors return
null - Successful breakpoints return objects
- Parsing failures return
-
Adapter Result Handling (4 tests)
- Filtering null results
- Handling all-null results
- Mapping to DAP format
- Mixed null and valid results
-
Object Structure (3 tests)
- Consistent object structure
- Not an array
- Property access vs index access
-
Error Scenarios (3 tests)
- Invalid file paths
- Invalid line numbers
- Missing optional fields
-
Type Safety (3 tests)
- Null vs valid distinction
- Promise type handling
✓ 16 new tests added
✓ All 96 tests passing
✓ 100% pass rate
- Type Safety: Poor (treating objects as arrays)
- Null Handling: Missing
- Consistency: Inconsistent with other methods
- Maintainability: Confusing code
- Type Safety: Good (proper object property access)
- Null Handling: Explicit null checks
- Consistency: Matches
setBreakPointsRequestpattern - Maintainability: Clear and understandable
- Set function breakpoints in GDB
- Verify breakpoints are hit
- Test with invalid function names (should handle gracefully)
- Test with conditional function breakpoints
- Test with multiple function breakpoints
npm test
# Test Suites: 3 passed, 3 total
# Tests: 96 passed, 96 totalnpm run build
# extension (webpack 5.105.4) compiled successfully
# adapter (webpack 5.105.4) compiled successfullysrc/backend/adapter.ts- FixedsetFunctionBreakPointsRequest__tests__/backend/breakpoint-error-handling.test.ts- Added comprehensive tests
src/backend/mi2/mi2.ts- Already returns correct formatsrc/backend/adapter.ts-setBreakPointsRequestalready correct
- Explicit Null Checks: Use
result !== nullinstead of truthy checks - Object Property Access: Use dot notation (
result.line) not array access - Consistent Patterns: Match existing correct implementations
- Comprehensive Testing: Cover success, failure, and edge cases
- Type Safety: Treat values according to their actual types
- No breaking changes
- Function breakpoints will now work correctly
- Previously broken functionality is now fixed
- Always check return type of
addBreakPoint(object or null) - Use
.filter(r => r !== null)before processing results - Access properties by name, not by index
- Follow the pattern in
setBreakPointsRequestfor consistency
-
Stronger Typing:
interface Breakpoint { number: number; line: number; file: string; condition?: string; countCondition?: string; } addBreakPoint(bp: any): Promise<Breakpoint | null>
-
Error Objects Instead of Null:
interface BreakpointResult { success: boolean; breakpoint?: Breakpoint; error?: string; }
-
Validation:
function isValidBreakpoint(bp: any): bp is Breakpoint { return bp !== null && typeof bp.number === 'number' && typeof bp.line === 'number'; }
Fixed critical bug where function breakpoints were treated as arrays instead of objects, causing them to fail silently. The fix:
- ✅ Properly checks for
nullresults - ✅ Accesses object properties correctly
- ✅ Maintains consistency with other breakpoint methods
- ✅ Includes comprehensive test coverage
- ✅ No breaking changes
Status: ✅ Fixed, tested, and verified