Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/api/common/extHostDocumentContentProviders.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { onUnexpectedError } from '../../../base/common/errors.js';
7
import { URI, UriComponents } from '../../../base/common/uri.js';
8
import { IDisposable } from '../../../base/common/lifecycle.js';
9
import { Disposable } from './extHostTypes.js';
10
import type * as vscode from 'vscode';
11
import { MainContext, ExtHostDocumentContentProvidersShape, MainThreadDocumentContentProvidersShape, IMainContext } from './extHost.protocol.js';
12
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors.js';
13
import { Schemas } from '../../../base/common/network.js';
14
import { ILogService } from '../../../platform/log/common/log.js';
15
import { CancellationToken } from '../../../base/common/cancellation.js';
16
import { splitLines } from '../../../base/common/strings.js';
17
18
export class ExtHostDocumentContentProvider implements ExtHostDocumentContentProvidersShape {
19
20
private static _handlePool = 0;
21
22
private readonly _documentContentProviders = new Map<number, vscode.TextDocumentContentProvider>();
23
private readonly _proxy: MainThreadDocumentContentProvidersShape;
24
25
constructor(
26
mainContext: IMainContext,
27
private readonly _documentsAndEditors: ExtHostDocumentsAndEditors,
28
private readonly _logService: ILogService,
29
) {
30
this._proxy = mainContext.getProxy(MainContext.MainThreadDocumentContentProviders);
31
}
32
33
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider): vscode.Disposable {
34
// todo@remote
35
// check with scheme from fs-providers!
36
if (Object.keys(Schemas).indexOf(scheme) >= 0) {
37
throw new Error(`scheme '${scheme}' already registered`);
38
}
39
40
const handle = ExtHostDocumentContentProvider._handlePool++;
41
42
this._documentContentProviders.set(handle, provider);
43
this._proxy.$registerTextContentProvider(handle, scheme);
44
45
let subscription: IDisposable | undefined;
46
if (typeof provider.onDidChange === 'function') {
47
48
let lastEvent: Promise<void> | undefined;
49
50
subscription = provider.onDidChange(async uri => {
51
if (uri.scheme !== scheme) {
52
this._logService.warn(`Provider for scheme '${scheme}' is firing event for schema '${uri.scheme}' which will be IGNORED`);
53
return;
54
}
55
if (!this._documentsAndEditors.getDocument(uri)) {
56
// ignore event if document isn't open
57
return;
58
}
59
60
if (lastEvent) {
61
await lastEvent;
62
}
63
64
const thisEvent = this.$provideTextDocumentContent(handle, uri)
65
.then(async value => {
66
if (!value && typeof value !== 'string') {
67
return;
68
}
69
70
const document = this._documentsAndEditors.getDocument(uri);
71
if (!document) {
72
// disposed in the meantime
73
return;
74
}
75
76
// create lines and compare
77
const lines = splitLines(value);
78
79
// broadcast event when content changed
80
if (!document.equalLines(lines)) {
81
return this._proxy.$onVirtualDocumentChange(uri, value);
82
}
83
})
84
.catch(onUnexpectedError)
85
.finally(() => {
86
if (lastEvent === thisEvent) {
87
lastEvent = undefined;
88
}
89
});
90
91
lastEvent = thisEvent;
92
});
93
}
94
return new Disposable(() => {
95
if (this._documentContentProviders.delete(handle)) {
96
this._proxy.$unregisterTextContentProvider(handle);
97
}
98
if (subscription) {
99
subscription.dispose();
100
subscription = undefined;
101
}
102
});
103
}
104
105
$provideTextDocumentContent(handle: number, uri: UriComponents): Promise<string | null | undefined> {
106
const provider = this._documentContentProviders.get(handle);
107
if (!provider) {
108
return Promise.reject(new Error(`unsupported uri-scheme: ${uri.scheme}`));
109
}
110
return Promise.resolve(provider.provideTextDocumentContent(URI.revive(uri), CancellationToken.None));
111
}
112
}
113
114