(
vm: &VirtualMachine,
source_file: &SourceFile,
object: PyObjectRef,
name: &str,
)
| 190 | } |
| 191 | |
| 192 | fn range_from_object( |
| 193 | vm: &VirtualMachine, |
| 194 | source_file: &SourceFile, |
| 195 | object: PyObjectRef, |
| 196 | name: &str, |
| 197 | ) -> PyResult<TextRange> { |
| 198 | let start_row = get_int_field(vm, &object, "lineno", name)?; |
| 199 | let start_column = get_int_field(vm, &object, "col_offset", name)?; |
| 200 | // end_lineno and end_col_offset are optional, default to start values |
| 201 | let end_row = |
| 202 | get_opt_int_field(vm, &object, "end_lineno")?.unwrap_or_else(|| start_row.clone()); |
| 203 | let end_column = |
| 204 | get_opt_int_field(vm, &object, "end_col_offset")?.unwrap_or_else(|| start_column.clone()); |
| 205 | |
| 206 | // lineno=0 or negative values as a special case (no location info). |
| 207 | // Use default values (line 1, col 0) when lineno <= 0. |
| 208 | let start_row_val: i32 = start_row.try_to_primitive(vm)?; |
| 209 | let end_row_val: i32 = end_row.try_to_primitive(vm)?; |
| 210 | let start_col_val: i32 = start_column.try_to_primitive(vm)?; |
| 211 | let end_col_val: i32 = end_column.try_to_primitive(vm)?; |
| 212 | |
| 213 | if start_row_val > end_row_val { |
| 214 | return Err(vm.new_value_error(format!( |
| 215 | "AST node line range ({}, {}) is not valid", |
| 216 | start_row_val, end_row_val |
| 217 | ))); |
| 218 | } |
| 219 | if (start_row_val < 0 && end_row_val != start_row_val) |
| 220 | || (start_col_val < 0 && end_col_val != start_col_val) |
| 221 | { |
| 222 | return Err(vm.new_value_error(format!( |
| 223 | "AST node column range ({}, {}) for line range ({}, {}) is not valid", |
| 224 | start_col_val, end_col_val, start_row_val, end_row_val |
| 225 | ))); |
| 226 | } |
| 227 | if start_row_val == end_row_val && start_col_val > end_col_val { |
| 228 | return Err(vm.new_value_error(format!( |
| 229 | "line {}, column {}-{} is not a valid range", |
| 230 | start_row_val, start_col_val, end_col_val |
| 231 | ))); |
| 232 | } |
| 233 | |
| 234 | let location = PySourceRange { |
| 235 | start: PySourceLocation { |
| 236 | row: Row(if start_row_val > 0 { |
| 237 | OneIndexed::new(start_row_val as usize).unwrap_or(OneIndexed::MIN) |
| 238 | } else { |
| 239 | OneIndexed::MIN |
| 240 | }), |
| 241 | column: Column(TextSize::new(start_col_val.max(0) as u32)), |
| 242 | }, |
| 243 | end: PySourceLocation { |
| 244 | row: Row(if end_row_val > 0 { |
| 245 | OneIndexed::new(end_row_val as usize).unwrap_or(OneIndexed::MIN) |
| 246 | } else { |
| 247 | OneIndexed::MIN |
| 248 | }), |
| 249 | column: Column(TextSize::new(end_col_val.max(0) as u32)), |
no test coverage detected