Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/preferences/common/settingsFilesystemProvider.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 { NotSupportedError } from '../../../../base/common/errors.js';
7
import { IDisposable, Disposable } from '../../../../base/common/lifecycle.js';
8
import { Schemas } from '../../../../base/common/network.js';
9
import { URI } from '../../../../base/common/uri.js';
10
import { FileChangeType, FilePermission, FileSystemProviderCapabilities, FileSystemProviderErrorCode, FileType, IFileChange, IFileDeleteOptions, IFileOverwriteOptions, IFileSystemProviderWithFileReadWriteCapability, IStat, IWatchOptions } from '../../../../platform/files/common/files.js';
11
import { IPreferencesService } from '../../../services/preferences/common/preferences.js';
12
import { Event, Emitter } from '../../../../base/common/event.js';
13
import { Registry } from '../../../../platform/registry/common/platform.js';
14
import * as JSONContributionRegistry from '../../../../platform/jsonschemas/common/jsonContributionRegistry.js';
15
import { VSBuffer } from '../../../../base/common/buffer.js';
16
import { ILogService, LogLevel } from '../../../../platform/log/common/log.js';
17
import { isEqual } from '../../../../base/common/resources.js';
18
19
const schemaRegistry = Registry.as<JSONContributionRegistry.IJSONContributionRegistry>(JSONContributionRegistry.Extensions.JSONContribution);
20
21
22
export class SettingsFileSystemProvider extends Disposable implements IFileSystemProviderWithFileReadWriteCapability {
23
24
static readonly SCHEMA = Schemas.vscode;
25
26
protected readonly _onDidChangeFile = this._register(new Emitter<readonly IFileChange[]>());
27
readonly onDidChangeFile = this._onDidChangeFile.event;
28
29
private static SCHEMA_ASSOCIATIONS = URI.parse(`${Schemas.vscode}://schemas-associations/schemas-associations.json`);
30
31
constructor(
32
@IPreferencesService private readonly preferencesService: IPreferencesService,
33
@ILogService private readonly logService: ILogService
34
) {
35
super();
36
this._register(schemaRegistry.onDidChangeSchema(schemaUri => {
37
this._onDidChangeFile.fire([{ resource: URI.parse(schemaUri), type: FileChangeType.UPDATED }]);
38
}));
39
this._register(schemaRegistry.onDidChangeSchemaAssociations(() => {
40
this._onDidChangeFile.fire([{ resource: SettingsFileSystemProvider.SCHEMA_ASSOCIATIONS, type: FileChangeType.UPDATED }]);
41
}));
42
this._register(preferencesService.onDidDefaultSettingsContentChanged(uri => {
43
this._onDidChangeFile.fire([{ resource: uri, type: FileChangeType.UPDATED }]);
44
}));
45
}
46
47
readonly capabilities: FileSystemProviderCapabilities = FileSystemProviderCapabilities.Readonly + FileSystemProviderCapabilities.FileReadWrite;
48
49
async readFile(uri: URI): Promise<Uint8Array> {
50
if (uri.scheme !== SettingsFileSystemProvider.SCHEMA) {
51
throw new NotSupportedError();
52
}
53
let content: string | undefined;
54
if (uri.authority === 'schemas') {
55
content = this.getSchemaContent(uri);
56
} else if (uri.authority === SettingsFileSystemProvider.SCHEMA_ASSOCIATIONS.authority) {
57
content = JSON.stringify(schemaRegistry.getSchemaAssociations());
58
} else if (uri.authority === 'defaultsettings') {
59
content = this.preferencesService.getDefaultSettingsContent(uri);
60
}
61
if (content) {
62
return VSBuffer.fromString(content).buffer;
63
}
64
throw FileSystemProviderErrorCode.FileNotFound;
65
}
66
67
async stat(uri: URI): Promise<IStat> {
68
if (schemaRegistry.hasSchemaContent(uri.toString()) || this.preferencesService.hasDefaultSettingsContent(uri)) {
69
const currentTime = Date.now();
70
return {
71
type: FileType.File,
72
permissions: FilePermission.Readonly,
73
mtime: currentTime,
74
ctime: currentTime,
75
size: 0
76
};
77
}
78
if (isEqual(uri, SettingsFileSystemProvider.SCHEMA_ASSOCIATIONS)) {
79
const currentTime = Date.now();
80
return {
81
type: FileType.File,
82
permissions: FilePermission.Readonly,
83
mtime: currentTime,
84
ctime: currentTime,
85
size: 0
86
};
87
}
88
throw FileSystemProviderErrorCode.FileNotFound;
89
}
90
91
readonly onDidChangeCapabilities = Event.None;
92
93
watch(resource: URI, opts: IWatchOptions): IDisposable { return Disposable.None; }
94
95
async mkdir(resource: URI): Promise<void> { }
96
async readdir(resource: URI): Promise<[string, FileType][]> { return []; }
97
98
async rename(from: URI, to: URI, opts: IFileOverwriteOptions): Promise<void> { }
99
async delete(resource: URI, opts: IFileDeleteOptions): Promise<void> { }
100
101
async writeFile() {
102
throw new NotSupportedError();
103
}
104
105
private getSchemaContent(uri: URI): string {
106
const startTime = Date.now();
107
const content = schemaRegistry.getSchemaContent(uri.toString()) ?? '{}' /* Use empty schema if not yet registered */;
108
const logLevel = this.logService.getLevel();
109
if (logLevel === LogLevel.Debug || logLevel === LogLevel.Trace) {
110
const endTime = Date.now();
111
const uncompressed = JSON.stringify(schemaRegistry.getSchemaContributions().schemas[uri.toString()]);
112
this.logService.debug(`${uri.toString()}: ${uncompressed.length} -> ${content.length} (${Math.round((uncompressed.length - content.length) / uncompressed.length * 100)}%) Took ${endTime - startTime}ms`);
113
}
114
return content;
115
}
116
}
117
118