Skip to content

Support review comments in the per-commit diff view#8648

Open
daandemeyer wants to merge 1 commit intomicrosoft:mainfrom
daandemeyer:commit-review
Open

Support review comments in the per-commit diff view#8648
daandemeyer wants to merge 1 commit intomicrosoft:mainfrom
daandemeyer:commit-review

Conversation

@daandemeyer
Copy link
Copy Markdown

Until now, opening a file diff from the commits tree of a PR showed no commenting UI and no existing review comments — commenting only worked from the changed-files tree. This change adds full commenting support to the per-commit diff view, anchoring new comments to the commit being viewed.

Display side

  • Add a fourth thread map _commitFileChangeCommentThreads, keyed by ${path}@${originalCommitId} so multiple commits' threads on the same file don't collide.
  • For every non-outdated thread with a known originalCommitId, mirror it on a per-commit review://...?commit=...&isOutdated=true URI that matches the one CommitNode produces, in addition to its existing workspace/review-scheme entry.
  • Consolidate createOutdatedCommentThread with the new commit-scoped variant into a single createCommitAnchoredCommentThread (the URI shape is identical — only the call sites differ).
  • Replace _findMatchingThread with _findMatchingThreads / _removeMatchingThreads so changed/removed thread events update or dispose both the workspace/review mirror and the commit-scoped one.
  • provideCommentingRanges falls back to fetching the commit's patch via a new PullRequestModel.getCommitFileDiffHunks helper when findMatchedFileChangeForReviewDiffView returns no match (because commit-scoped URIs aren't in localFileChanges, which only tracks the PR head).
  • Wire the new map into onDidChangePendingReviewState and simplify updateCommentExpandState to iterate all four maps via a shared helper.

Write side

  • PullRequestModel.createReviewThread takes a new optional commitId parameter. When commitId !== HEAD, the model routes through a new private createReviewThreadOnCommit helper that uses the (deprecated but still-functional) addPullRequestReviewComment GraphQL mutation with explicit commitOID. This is necessary because addPullRequestReviewThread always anchors new threads to the PR head regardless of which commit the pending review was created on, so the deprecated path is the only way to anchor a new comment to a non-head commit. After the mutation, the threads cache is refreshed via getReviewThreads() so the new thread propagates through the existing onDidChangeReviewThreads pipeline.
  • The deprecated mutation only accepts a single integer position (the diff offset from the first hunk header), not line/side ranges, so a new computeDiffPositionForLine helper walks the commit's diff hunks to map a line number to a position. Multi-line ranges collapse to a single line at endLine in this fallback path.
  • New controller helpers getFileNameForThread, getCommitForThread and getCommentLinesForThread extract path, commit and line numbers from any thread URI. Crucially, for commit-scoped review URIs the filename comes from query.path rather than gitRelativeRootPath(uri.path), since CommitNode builds URIs via reviewPath() which produces a synthetic commit~ec597364/foo/bar prefix that nodePath.relative turns into garbage. Editor line numbers for review-scheme URIs are used directly (no mapping through workspace diffs), since they already match the file at the ref being viewed.
  • startReview (the controller method) and createOrReplyComment now forward getCommitForThread(thread) for both new threads and replies, so replying to a comment in a non-head commit's diff lands on the right commit too.

Until now, opening a file diff from the commits tree of a PR showed no
commenting UI and no existing review comments — commenting only worked
from the changed-files tree. This change adds full commenting support
to the per-commit diff view, anchoring new comments to the commit
being viewed.

Display side
------------
- Add a fourth thread map `_commitFileChangeCommentThreads`, keyed by
  `${path}@${originalCommitId}` so multiple commits' threads on the
  same file don't collide.
- For every non-outdated thread with a known `originalCommitId`,
  mirror it on a per-commit `review://...?commit=...&isOutdated=true`
  URI that matches the one `CommitNode` produces, in addition to its
  existing workspace/review-scheme entry.
- Consolidate `createOutdatedCommentThread` with the new commit-scoped
  variant into a single `createCommitAnchoredCommentThread` (the URI
  shape is identical — only the call sites differ).
- Replace `_findMatchingThread` with `_findMatchingThreads` /
  `_removeMatchingThreads` so changed/removed thread events update or
  dispose both the workspace/review mirror and the commit-scoped one.
- `provideCommentingRanges` falls back to fetching the commit's patch
  via a new `PullRequestModel.getCommitFileDiffHunks` helper when
  `findMatchedFileChangeForReviewDiffView` returns no match (because
  commit-scoped URIs aren't in `localFileChanges`, which only tracks
  the PR head).
- Wire the new map into `onDidChangePendingReviewState` and simplify
  `updateCommentExpandState` to iterate all four maps via a shared
  helper.

Write side
----------
- `PullRequestModel.createReviewThread` takes a new optional
  `commitId` parameter. When `commitId !== HEAD`, the model routes
  through a new private `createReviewThreadOnCommit` helper that uses
  the (deprecated but still-functional) `addPullRequestReviewComment`
  GraphQL mutation with explicit `commitOID`. This is necessary
  because `addPullRequestReviewThread` always anchors new threads to
  the PR head regardless of which commit the pending review was
  created on, so the deprecated path is the only way to anchor a new
  comment to a non-head commit. After the mutation, the threads cache
  is refreshed via `getReviewThreads()` so the new thread propagates
  through the existing `onDidChangeReviewThreads` pipeline.
- The deprecated mutation only accepts a single integer `position`
  (the diff offset from the first hunk header), not line/side ranges,
  so a new `computeDiffPositionForLine` helper walks the commit's diff
  hunks to map a line number to a position. Multi-line ranges collapse
  to a single line at `endLine` in this fallback path.
- New controller helpers `getFileNameForThread`, `getCommitForThread`
  and `getCommentLinesForThread` extract path, commit and line numbers
  from any thread URI. Crucially, for commit-scoped review URIs the
  filename comes from `query.path` rather than
  `gitRelativeRootPath(uri.path)`, since `CommitNode` builds URIs via
  `reviewPath()` which produces a synthetic `commit~ec597364/foo/bar`
  prefix that `nodePath.relative` turns into garbage. Editor line
  numbers for review-scheme URIs are used directly (no mapping
  through workspace diffs), since they already match the file at the
  ref being viewed.
- `startReview` (the controller method) and `createOrReplyComment`
  now forward `getCommitForThread(thread)` for both new threads and
  replies, so replying to a comment in a non-head commit's diff lands
  on the right commit too.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@daandemeyer
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant