forked from microsoft/vscode-pull-request-github
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathissueLinkProvider.ts
More file actions
88 lines (83 loc) · 3.05 KB
/
Copy pathissueLinkProvider.ts
File metadata and controls
88 lines (83 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { ReposManagerState } from '../github/folderRepositoryManager';
import { RepositoriesManager } from '../github/repositoriesManager';
import { ISSUE_EXPRESSION, ParsedIssue, parseIssueExpressionOutput } from '../github/utils';
import { StateManager } from './stateManager';
import {
getIssue,
isComment,
MAX_LINE_LENGTH,
} from './util';
const MAX_LINE_COUNT = 2000;
class IssueDocumentLink extends vscode.DocumentLink {
constructor(
range: vscode.Range,
public readonly mappedLink: { readonly value: string; readonly parsed: ParsedIssue },
public readonly uri: vscode.Uri,
) {
super(range);
}
}
export class IssueLinkProvider implements vscode.DocumentLinkProvider {
constructor(private manager: RepositoriesManager, private stateManager: StateManager) { }
async provideDocumentLinks(
document: vscode.TextDocument,
_token: vscode.CancellationToken,
): Promise<vscode.DocumentLink[]> {
const links: vscode.DocumentLink[] = [];
const wraps: boolean = vscode.workspace.getConfiguration('editor', document).get('wordWrap', 'off') !== 'off';
for (let i = 0; i < Math.min(document.lineCount, MAX_LINE_COUNT); i++) {
let searchResult = -1;
let lineOffset = 0;
const line = document.lineAt(i).text;
const lineLength = wraps ? line.length : Math.min(line.length, MAX_LINE_LENGTH);
let lineSubstring = line.substring(0, lineLength);
while ((searchResult = lineSubstring.search(ISSUE_EXPRESSION)) >= 0) {
const match = lineSubstring.match(ISSUE_EXPRESSION);
const parsed = parseIssueExpressionOutput(match);
if (match && parsed) {
const startPosition = new vscode.Position(i, searchResult + lineOffset);
if (await isComment(document, startPosition)) {
const link = new IssueDocumentLink(
new vscode.Range(
startPosition,
new vscode.Position(i, searchResult + lineOffset + match[0].length - 1),
),
{ value: match[0], parsed },
document.uri,
);
links.push(link);
}
}
lineOffset += searchResult + (match ? match[0].length : 0);
lineSubstring = line.substring(lineOffset, line.length);
}
}
return links;
}
async resolveDocumentLink(
link: IssueDocumentLink,
_token: vscode.CancellationToken,
): Promise<vscode.DocumentLink | undefined> {
if (this.manager.state === ReposManagerState.RepositoriesLoaded) {
const folderManager = this.manager.getManagerForFile(link.uri);
if (!folderManager) {
return;
}
const issue = await getIssue(
this.stateManager,
folderManager,
link.mappedLink.value,
link.mappedLink.parsed,
);
if (issue) {
link.target = await vscode.env.asExternalUri(vscode.Uri.parse(issue.html_url));
}
return link;
}
}
}