提交 c17f1492 编写于 作者: T Tomas Vik

refactor: show commenting range for old MR diff file

上级 a8d6bb8e
import { TreeItem, Uri } from 'vscode';
import { posix as path } from 'path';
import { toReviewUri } from '../../review/review_uri';
import { toReviewUri, ReviewParams } from '../../review/review_uri';
import { PROGRAMMATIC_COMMANDS, VS_COMMANDS } from '../../command_names';
import { ADDED, DELETED, RENAMED, MODIFIED } from '../../constants';
......@@ -63,23 +63,25 @@ export class ChangedFileItem extends TreeItem {
};
return;
}
const emptyFileUri = toReviewUri({ workspacePath: workspace.uri, projectId: mr.project_id });
const commonParams: ReviewParams = {
workspacePath: workspace.uri,
projectId: mr.project_id,
mrId: mr.id,
};
const emptyFileUri = toReviewUri(commonParams);
const baseFileUri = file.new_file
? emptyFileUri
: toReviewUri({
...commonParams,
path: file.old_path,
commit: mrVersion.base_commit_sha,
workspacePath: workspace.uri,
projectId: mr.project_id,
});
const headFileUri = file.deleted_file
? emptyFileUri
: toReviewUri({
...commonParams,
path: file.new_path,
commit: mrVersion.head_commit_sha,
workspacePath: workspace.uri,
projectId: mr.project_id,
});
this.command = {
......
......@@ -7,6 +7,7 @@ import { GqlDiscussion, GqlTextDiffDiscussion } from '../../gitlab/gitlab_new_se
import { handleError } from '../../log';
import { UserFriendlyError } from '../../errors/user_friendly_error';
import { GitLabCommentThread } from '../../review/gitlab_comment_thread';
import { CommentingRangeProvider } from '../../review/commenting_range_provider';
const isTextDiffDiscussion = (discussion: GqlDiscussion): discussion is GqlTextDiffDiscussion => {
const firstNote = discussion.notes.nodes[0];
......@@ -38,8 +39,10 @@ export class MrItemModel extends ItemModel {
arguments: [this.mr, this.workspace.uri],
title: 'Show MR Overview',
};
const gitlabService = await createGitLabNewService(this.workspace.uri);
const mrVersion = await gitlabService.getMrDiff(this.mr);
try {
await this.getMrDiscussions();
await this.getMrDiscussions(mrVersion);
} catch (e) {
handleError(
new UserFriendlyError(
......@@ -50,16 +53,21 @@ export class MrItemModel extends ItemModel {
),
);
}
const changedFiles = await this.getChangedFiles();
const changedFiles = mrVersion.diffs.map(
d => new ChangedFileItem(this.mr, mrVersion, d, this.workspace),
);
return [overview, ...changedFiles];
}
private async getMrDiscussions(): Promise<void> {
private async getMrDiscussions(mrVersion: RestMrVersion): Promise<void> {
const commentController = vscode.comments.createCommentController(
this.mr.references.full,
this.mr.title,
);
commentController.commentingRangeProvider = new CommentingRangeProvider(this.mr, mrVersion);
const gitlabService = await createGitLabNewService(this.workspace.uri);
const discussions = await gitlabService.getDiscussions({
......@@ -77,10 +85,4 @@ export class MrItemModel extends ItemModel {
});
this.setDisposableChildren([...threads, commentController]);
}
private async getChangedFiles(): Promise<vscode.TreeItem[]> {
const gitlabService = await createGitLabNewService(this.workspace.uri);
const mrVersion = await gitlabService.getMrDiff(this.mr);
return mrVersion.diffs.map(d => new ChangedFileItem(this.mr, mrVersion, d, this.workspace));
}
}
import * as vscode from 'vscode';
import { mr, mrVersion } from '../test_utils/entities';
import { CommentingRangeProvider } from './commenting_range_provider';
import { toReviewUri } from './review_uri';
describe('CommentingRangeProvider', () => {
let commentingRangeProvider: CommentingRangeProvider;
beforeEach(() => {
commentingRangeProvider = new CommentingRangeProvider(mr, mrVersion);
});
it('returns empty array for different URI schema', () => {
const testDocument = {
uri: vscode.Uri.parse('https://example.com'),
} as vscode.TextDocument;
expect(commentingRangeProvider.provideCommentingRanges(testDocument)).toEqual([]);
});
it('returns full range (all lines in the document) for old file', () => {
const testDocument = {
uri: toReviewUri({
path: `/path`,
mrId: mr.id,
projectId: mr.project_id,
commit: mrVersion.base_commit_sha,
workspacePath: '/',
}),
lineCount: 200,
} as vscode.TextDocument;
expect(commentingRangeProvider.provideCommentingRanges(testDocument)).toEqual([
new vscode.Range(new vscode.Position(0, 0), new vscode.Position(199, 0)),
]);
});
it('returns empty array for new file', () => {
const testDocument = {
uri: toReviewUri({
path: `/path`,
mrId: mr.id,
projectId: mr.project_id,
commit: mrVersion.head_commit_sha,
workspacePath: '/',
}),
lineCount: 200,
} as vscode.TextDocument;
expect(commentingRangeProvider.provideCommentingRanges(testDocument)).toEqual([]);
});
});
import * as vscode from 'vscode';
import { REVIEW_URI_SCHEME } from '../constants';
import { fromReviewUri } from './review_uri';
export class CommentingRangeProvider implements vscode.CommentingRangeProvider {
private mr: RestIssuable;
private mrVersion: RestMrVersion;
constructor(mr: RestIssuable, mrVersion: RestMrVersion) {
this.mr = mr;
this.mrVersion = mrVersion;
}
provideCommentingRanges(document: vscode.TextDocument): vscode.Range[] {
const { uri } = document;
if (uri.scheme !== REVIEW_URI_SCHEME) return [];
const params = fromReviewUri(uri);
if (params.mrId !== this.mr.id || params.projectId !== this.mr.project_id || !params.path) {
return [];
}
const oldFile = params.commit === this.mrVersion.base_commit_sha;
if (oldFile) {
return [
new vscode.Range(new vscode.Position(0, 0), new vscode.Position(document.lineCount - 1, 0)),
];
}
return [];
}
}
......@@ -14,6 +14,7 @@ describe('GitContentProvider', () => {
commit: 'abcdef',
path: '/review',
projectId: 1234,
mrId: 2345,
workspacePath: 'path/to/workspace',
};
......
......@@ -30,6 +30,7 @@ const uriFromPosition = (
position: GqlTextPosition,
workspaceFolder: string,
gitlabProjectId: number,
mrId: number,
) => {
const onOldVersion = position.oldLine !== null;
const path = onOldVersion ? position.oldPath : position.newPath;
......@@ -39,6 +40,7 @@ const uriFromPosition = (
commit,
workspacePath: workspaceFolder,
projectId: gitlabProjectId,
mrId,
});
};
......@@ -152,7 +154,7 @@ export class GitLabCommentThread {
}: CreateThreadOptions): GitLabCommentThread {
const { position } = firstNoteFrom(discussion);
const vsThread = commentController.createCommentThread(
uriFromPosition(position, workspaceFolder, mr.project_id),
uriFromPosition(position, workspaceFolder, mr.project_id, mr.id),
commentRangeFromPosition(position),
// the comments need to know about the thread, so we first
// create empty thread to be able to create comments
......
......@@ -5,6 +5,7 @@ describe('review_uri.ts', () => {
commit: 'abcdef',
path: '/review',
projectId: 1234,
mrId: 2345,
workspacePath: 'path/to/workspace',
};
......@@ -13,7 +14,7 @@ describe('review_uri.ts', () => {
const result = toReviewUri(reviewUriParams);
expect(result.toString()).toEqual(
'gl-review:///review{"commit":"abcdef","workspacePath":"path/to/workspace","projectId":1234}#',
'gl-review:///review{"commit":"abcdef","mrId":2345,"projectId":1234,"workspacePath":"path/to/workspace"}#',
);
});
});
......
import { Uri } from 'vscode';
import { REVIEW_URI_SCHEME } from '../constants';
interface ReviewParams {
export interface ReviewParams {
path?: string;
commit?: string;
workspacePath: string;
projectId: number;
mrId: number;
}
export function toReviewUri({ path = '', commit, workspacePath, projectId }: ReviewParams): Uri {
export function toReviewUri({
path = '',
commit,
workspacePath,
projectId,
mrId,
}: ReviewParams): Uri {
const query = { commit, workspacePath, projectId, mrId };
return Uri.file(path).with({
scheme: REVIEW_URI_SCHEME,
query: JSON.stringify({ commit, workspacePath, projectId }),
query: JSON.stringify(query, Object.keys(query).sort()),
});
}
export function fromReviewUri(uri: Uri): ReviewParams {
const { commit, workspacePath, projectId } = JSON.parse(uri.query);
const { commit, workspacePath, projectId, mrId } = JSON.parse(uri.query);
return {
path: uri.path || undefined,
commit,
workspacePath,
projectId,
mrId,
};
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册