-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Expand file tree
/
Copy pathprovider.ts
More file actions
109 lines (91 loc) · 4.17 KB
/
provider.ts
File metadata and controls
109 lines (91 loc) · 4.17 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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
import * as vscode from 'vscode';
import ReferencesDocument from './referencesDocument';
export default class Provider implements vscode.TextDocumentContentProvider, vscode.DocumentLinkProvider {
static scheme = 'references';
private _onDidChange = new vscode.EventEmitter<vscode.Uri>();
private _documents = new Map<string, ReferencesDocument>();
private _editorDecoration = vscode.window.createTextEditorDecorationType({ textDecoration: 'underline' });
private _subscriptions: vscode.Disposable;
constructor() {
this._subscriptions = vscode.Disposable.from(
// Listen to the `closeTextDocument`-event which means we must
// clear the corresponding model object - `ReferencesDocument`
vscode.workspace.onDidCloseTextDocument(doc => this._documents.delete(doc.uri.toString())),
// This is necessary due to a race in ExtHostDocumentContentProvider where
// the onDidChange event may be triggered before the new document has been
// registered with ExtHostDocumentsAndEditors
vscode.workspace.onDidOpenTextDocument(doc => {
if (doc.uri.scheme === Provider.scheme) {
this._onDidChange.fire(doc.uri);
}
})
);
}
dispose() {
this._subscriptions.dispose();
this._documents.clear();
this._editorDecoration.dispose();
this._onDidChange.dispose();
}
// Expose an event to signal changes of _virtual_ documents
// to the editor
get onDidChange() {
return this._onDidChange.event;
}
// Provider method that takes an uri of the `references`-scheme and
// resolves its content by (1) running the reference search command
// and (2) formatting the results
provideTextDocumentContent(uri: vscode.Uri): string | Thenable<string> {
// already loaded?
const document = this._documents.get(uri.toString());
if (document) {
return document.value;
}
// Decode target-uri and target-position from the provided uri and execute the
// `reference provider` command (https://code.visualstudio.com/api/references/commands).
// From the result create a references document which is in charge of loading,
// printing, and formatting references
const [target, pos] = decodeLocation(uri);
return vscode.commands.executeCommand<vscode.Location[]>('vscode.executeReferenceProvider', target, pos).then(locations => {
locations = locations || [];
// sort by locations and shuffle to begin from target resource
let idx = 0;
locations.sort(Provider._compareLocations).find((loc, i) => loc.uri.toString() === target.toString() && !!(idx = i) && true);
locations.push(...locations.splice(0, idx));
// create document and return its early state
const document = new ReferencesDocument(uri, locations, this._onDidChange);
this._documents.set(uri.toString(), document);
return document.value;
});
}
private static _compareLocations(a: vscode.Location, b: vscode.Location): number {
if (a.uri.toString() < b.uri.toString()) {
return -1;
} else if (a.uri.toString() > b.uri.toString()) {
return 1;
} else {
return a.range.start.compareTo(b.range.start);
}
}
provideDocumentLinks(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.DocumentLink[] | undefined {
// While building the virtual document we have already created the links.
// Those are composed from the range inside the document and a target uri
// to which they point
const doc = this._documents.get(document.uri.toString());
if (doc) {
return doc.links;
}
}
}
let seq = 0;
export function encodeLocation(uri: vscode.Uri, pos: vscode.Position): vscode.Uri {
const query = JSON.stringify([uri.toString(), pos.line, pos.character]);
return vscode.Uri.parse(`${Provider.scheme}:References.locations?${query}#${seq++}`);
}
export function decodeLocation(uri: vscode.Uri): [vscode.Uri, vscode.Position] {
const [target, line, character] = JSON.parse(uri.query) as [string, number, number];
return [vscode.Uri.parse(target), new vscode.Position(line, character)];
}