* Parses a hunk, including its header or throws an error if the diff doesn't * contain a well-formed diff hunk at the current position. * * Expects that the position has been advanced to the beginning of a presumed * diff hunk header. * * @param linesConsumed The number of unified
(
linesConsumed: number,
hunkIndex: number,
previousHunk: DiffHunk | null
)
| 290 | * are only used to aid the app in line-selections. |
| 291 | */ |
| 292 | private parseHunk( |
| 293 | linesConsumed: number, |
| 294 | hunkIndex: number, |
| 295 | previousHunk: DiffHunk | null |
| 296 | ): DiffHunk { |
| 297 | const headerLine = this.readLine() |
| 298 | if (!headerLine) { |
| 299 | throw new Error('Expected hunk header but reached end of diff') |
| 300 | } |
| 301 | |
| 302 | const header = this.parseHunkHeader(headerLine) |
| 303 | const lines = new Array<DiffLine>() |
| 304 | lines.push(new DiffLine(headerLine, DiffLineType.Hunk, 1, null, null)) |
| 305 | |
| 306 | let c: DiffLinePrefix | null |
| 307 | |
| 308 | let rollingDiffBeforeCounter = header.oldStartLine |
| 309 | let rollingDiffAfterCounter = header.newStartLine |
| 310 | |
| 311 | let diffLineNumber = linesConsumed |
| 312 | while ((c = this.parseLinePrefix(this.peek()))) { |
| 313 | const line = this.readLine() |
| 314 | |
| 315 | if (!line) { |
| 316 | throw new Error('Expected unified diff line but reached end of diff') |
| 317 | } |
| 318 | |
| 319 | // A marker indicating that the last line in the original or the new file |
| 320 | // is missing a trailing newline. In other words, the presence of this marker |
| 321 | // means that the new and/or original file lacks a trailing newline. |
| 322 | // |
| 323 | // When we find it we have to look up the previous line and set the |
| 324 | // noTrailingNewLine flag |
| 325 | if (c === DiffPrefixNoNewline) { |
| 326 | // See https://github.com/git/git/blob/21f862b498925194f8f1ebe8203b7a7df756555b/apply.c#L1725-L1732 |
| 327 | if (line.length < 12) { |
| 328 | throw new Error( |
| 329 | `Expected "no newline at end of file" marker to be at least 12 bytes long` |
| 330 | ) |
| 331 | } |
| 332 | |
| 333 | const previousLineIndex = lines.length - 1 |
| 334 | const previousLine = lines[previousLineIndex] |
| 335 | lines[previousLineIndex] = previousLine.withNoTrailingNewLine(true) |
| 336 | |
| 337 | continue |
| 338 | } |
| 339 | |
| 340 | // We must increase `diffLineNumber` only when we're certain that the line |
| 341 | // is not a "no newline" marker. Otherwise, we'll end up with a wrong |
| 342 | // `diffLineNumber` for the next line. This could happen if the last line |
| 343 | // in the file doesn't have a newline before the change. |
| 344 | diffLineNumber++ |
| 345 | |
| 346 | let diffLine: DiffLine |
| 347 | |
| 348 | if (c === DiffPrefixAdd) { |
| 349 | diffLine = new DiffLine( |
no test coverage detected