GoLineToDingoLine converts a Go line to Dingo line using v2 line mappings. Returns the Dingo line and kind string if a mapping is found. For unmapped lines, uses cumulative delta to compute approximate Dingo line. Uses binary search for O(log N) performance instead of O(N) linear search.
(goLine int)
| 437 | // For unmapped lines, uses cumulative delta to compute approximate Dingo line. |
| 438 | // Uses binary search for O(log N) performance instead of O(N) linear search. |
| 439 | func (r *Reader) GoLineToDingoLine(goLine int) (dingoLine int, kind string) { |
| 440 | r.mu.RLock() |
| 441 | defer r.mu.RUnlock() |
| 442 | |
| 443 | // If no v2 mappings available, use simple proportional fallback |
| 444 | if len(r.lineMappings) == 0 { |
| 445 | return r.proportionalFallback(goLine), "" |
| 446 | } |
| 447 | |
| 448 | // Binary search for mapping containing goLine |
| 449 | // Mappings are sorted by GoLineStart in parseLineMappings |
| 450 | idx := sort.Search(len(r.lineMappings), func(i int) bool { |
| 451 | return r.lineMappings[i].GoLineEnd >= uint32(goLine) |
| 452 | }) |
| 453 | |
| 454 | // Check if we found a valid mapping |
| 455 | if idx < len(r.lineMappings) { |
| 456 | entry := &r.lineMappings[idx] |
| 457 | if uint32(goLine) >= entry.GoLineStart && uint32(goLine) <= entry.GoLineEnd { |
| 458 | // Found mapping - return Dingo line and kind |
| 459 | dingoLine = int(entry.DingoLine) |
| 460 | if entry.KindIdx >= uint16(len(r.kinds)) { |
| 461 | // Invalid kind index - return empty kind |
| 462 | return dingoLine, "" |
| 463 | } |
| 464 | kind = r.kinds[entry.KindIdx] |
| 465 | return dingoLine, kind |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | // No direct mapping found - compute using cumulative delta from previous mappings |
| 470 | return r.computeDeltaFallback(goLine, idx), "" |
| 471 | } |
| 472 | |
| 473 | // proportionalFallback returns a proportionally mapped Dingo line when no v2 mappings exist. |
| 474 | // Uses the ratio of Dingo/Go line counts for approximate mapping. |