| 
1 | 1 | use anyhow::Context;  | 
2 |  | -use std::collections::HashMap;  | 
 | 2 | +use std::{collections::HashMap, path::PathBuf};  | 
3 | 3 | use transport::{  | 
4 | 4 |     requests, responses,  | 
5 | 5 |     types::{Source, SourceBreakpoint, ThreadId},  | 
@@ -156,34 +156,46 @@ impl DebuggerInternals {  | 
156 | 156 |             return Ok(());  | 
157 | 157 |         }  | 
158 | 158 | 
 
  | 
159 |  | -        let first_breakpoint = self.breakpoints.values().next().unwrap();  | 
160 |  | - | 
161 |  | -        let req = requests::RequestBody::SetBreakpoints(requests::SetBreakpoints {  | 
162 |  | -            source: Source {  | 
163 |  | -                name: first_breakpoint.name.clone(),  | 
164 |  | -                path: Some(first_breakpoint.path.clone()),  | 
 | 159 | +        // group breakpoints by source file and send in multiple batches  | 
 | 160 | +        let breakpoints_by_source = self.breakpoints_by_source();  | 
 | 161 | + | 
 | 162 | +        for (source, breakpoints) in &breakpoints_by_source {  | 
 | 163 | +            let req = requests::RequestBody::SetBreakpoints(requests::SetBreakpoints {  | 
 | 164 | +                source: Source {  | 
 | 165 | +                    name: Some(source.display().to_string()),  | 
 | 166 | +                    path: Some(source.clone()),  | 
 | 167 | +                    ..Default::default()  | 
 | 168 | +                },  | 
 | 169 | +                lines: Some(breakpoints.iter().map(|b| b.line).collect()),  | 
 | 170 | +                breakpoints: Some(  | 
 | 171 | +                    breakpoints  | 
 | 172 | +                        .iter()  | 
 | 173 | +                        .map(|b| SourceBreakpoint {  | 
 | 174 | +                            line: b.line,  | 
 | 175 | +                            ..Default::default()  | 
 | 176 | +                        })  | 
 | 177 | +                        .collect(),  | 
 | 178 | +                ),  | 
165 | 179 |                 ..Default::default()  | 
166 |  | -            },  | 
167 |  | -            lines: Some(self.breakpoints.values().map(|b| b.line).collect()),  | 
168 |  | -            breakpoints: Some(  | 
169 |  | -                self.breakpoints  | 
170 |  | -                    .values()  | 
171 |  | -                    .map(|b| SourceBreakpoint {  | 
172 |  | -                        line: b.line,  | 
173 |  | -                        ..Default::default()  | 
174 |  | -                    })  | 
175 |  | -                    .collect(),  | 
176 |  | -            ),  | 
177 |  | -            ..Default::default()  | 
178 |  | -        });  | 
179 |  | - | 
180 |  | -        let _ = self  | 
181 |  | -            .client  | 
182 |  | -            .send(req)  | 
183 |  | -            .context("broadcasting breakpoints to debugee")?;  | 
 | 180 | +            });  | 
 | 181 | + | 
 | 182 | +            let _ = self  | 
 | 183 | +                .client  | 
 | 184 | +                .send(req)  | 
 | 185 | +                .context("broadcasting breakpoints to debugee")?;  | 
 | 186 | +        }  | 
184 | 187 |         Ok(())  | 
185 | 188 |     }  | 
186 | 189 | 
 
  | 
 | 190 | +    fn breakpoints_by_source(&self) -> HashMap<PathBuf, Vec<Breakpoint>> {  | 
 | 191 | +        let mut out = HashMap::new();  | 
 | 192 | +        for breakpoint in self.breakpoints.values() {  | 
 | 193 | +            let file_breakpoints = out.entry(breakpoint.path.clone()).or_insert(Vec::new());  | 
 | 194 | +            file_breakpoints.push(breakpoint.clone());  | 
 | 195 | +        }  | 
 | 196 | +        out  | 
 | 197 | +    }  | 
 | 198 | + | 
187 | 199 |     fn next_id(&mut self) -> BreakpointId {  | 
188 | 200 |         self.current_breakpoint_id += 1;  | 
189 | 201 |         self.current_breakpoint_id  | 
 | 
0 commit comments