@sussudio/platform
Version:
Internal APIs for VS Code's service injection the base services.
127 lines (126 loc) • 4.51 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate =
(this && this.__decorate) ||
function (decorators, target, key, desc) {
var c = arguments.length,
r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc,
d;
if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function')
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param =
(this && this.__param) ||
function (paramIndex, decorator) {
return function (target, key) {
decorator(target, key, paramIndex);
};
};
import { IUriIdentityService } from './uriIdentity.mjs';
import { registerSingleton } from '../../instantiation/common/extensions.mjs';
import { IFileService } from '../../files/common/files.mjs';
import { ExtUri, normalizePath } from '@sussudio/base/common/resources.mjs';
import { SkipList } from '@sussudio/base/common/skipList.mjs';
import { Event } from '@sussudio/base/common/event.mjs';
import { DisposableStore } from '@sussudio/base/common/lifecycle.mjs';
class Entry {
uri;
static _clock = 0;
time = Entry._clock++;
constructor(uri) {
this.uri = uri;
}
touch() {
this.time = Entry._clock++;
return this;
}
}
let UriIdentityService = class UriIdentityService {
_fileService;
extUri;
_dispooables = new DisposableStore();
_canonicalUris;
_limit = 2 ** 16;
constructor(_fileService) {
this._fileService = _fileService;
const schemeIgnoresPathCasingCache = new Map();
// assume path casing matters unless the file system provider spec'ed the opposite.
// for all other cases path casing matters, e.g for
// * virtual documents
// * in-memory uris
// * all kind of "private" schemes
const ignorePathCasing = (uri) => {
let ignorePathCasing = schemeIgnoresPathCasingCache.get(uri.scheme);
if (ignorePathCasing === undefined) {
// retrieve once and then case per scheme until a change happens
ignorePathCasing =
_fileService.hasProvider(uri) &&
!this._fileService.hasCapability(uri, 1024 /* FileSystemProviderCapabilities.PathCaseSensitive */);
schemeIgnoresPathCasingCache.set(uri.scheme, ignorePathCasing);
}
return ignorePathCasing;
};
this._dispooables.add(
Event.any(
_fileService.onDidChangeFileSystemProviderRegistrations,
_fileService.onDidChangeFileSystemProviderCapabilities,
)((e) => {
// remove from cache
schemeIgnoresPathCasingCache.delete(e.scheme);
}),
);
this.extUri = new ExtUri(ignorePathCasing);
this._canonicalUris = new SkipList((a, b) => this.extUri.compare(a, b, true), this._limit);
}
dispose() {
this._dispooables.dispose();
this._canonicalUris.clear();
}
asCanonicalUri(uri) {
// (1) normalize URI
if (this._fileService.hasProvider(uri)) {
uri = normalizePath(uri);
}
// (2) find the uri in its canonical form or use this uri to define it
const item = this._canonicalUris.get(uri);
if (item) {
return item.touch().uri.with({ fragment: uri.fragment });
}
// this uri is first and defines the canonical form
this._canonicalUris.set(uri, new Entry(uri));
this._checkTrim();
return uri;
}
_checkTrim() {
if (this._canonicalUris.size < this._limit) {
return;
}
// get all entries, sort by touch (MRU) and re-initalize
// the uri cache and the entry clock. this is an expensive
// operation and should happen rarely
const entries = [...this._canonicalUris.entries()].sort((a, b) => {
if (a[1].touch < b[1].touch) {
return 1;
} else if (a[1].touch > b[1].touch) {
return -1;
} else {
return 0;
}
});
Entry._clock = 0;
this._canonicalUris.clear();
const newSize = this._limit * 0.5;
for (let i = 0; i < newSize; i++) {
this._canonicalUris.set(entries[i][0], entries[i][1].touch());
}
}
};
UriIdentityService = __decorate([__param(0, IFileService)], UriIdentityService);
export { UriIdentityService };
registerSingleton(IUriIdentityService, UriIdentityService, 1 /* InstantiationType.Delayed */);