| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- import { Emitter } from '../../base/common/event.js';
- import { toDisposable } from '../../base/common/lifecycle.js';
- import { shouldSynchronizeModel } from './model.js';
- import { score } from './languageSelector.js';
- function isExclusive(selector) {
- if (typeof selector === 'string') {
- return false;
- }
- else if (Array.isArray(selector)) {
- return selector.every(isExclusive);
- }
- else {
- return !!selector.exclusive; // TODO: microsoft/TypeScript#42768
- }
- }
- class MatchCandidate {
- constructor(uri, languageId, notebookUri, notebookType) {
- this.uri = uri;
- this.languageId = languageId;
- this.notebookUri = notebookUri;
- this.notebookType = notebookType;
- }
- equals(other) {
- var _a, _b;
- return this.notebookType === other.notebookType
- && this.languageId === other.languageId
- && this.uri.toString() === other.uri.toString()
- && ((_a = this.notebookUri) === null || _a === void 0 ? void 0 : _a.toString()) === ((_b = other.notebookUri) === null || _b === void 0 ? void 0 : _b.toString());
- }
- }
- export class LanguageFeatureRegistry {
- constructor(_notebookInfoResolver) {
- this._notebookInfoResolver = _notebookInfoResolver;
- this._clock = 0;
- this._entries = [];
- this._onDidChange = new Emitter();
- this.onDidChange = this._onDidChange.event;
- }
- register(selector, provider) {
- let entry = {
- selector,
- provider,
- _score: -1,
- _time: this._clock++
- };
- this._entries.push(entry);
- this._lastCandidate = undefined;
- this._onDidChange.fire(this._entries.length);
- return toDisposable(() => {
- if (entry) {
- const idx = this._entries.indexOf(entry);
- if (idx >= 0) {
- this._entries.splice(idx, 1);
- this._lastCandidate = undefined;
- this._onDidChange.fire(this._entries.length);
- entry = undefined;
- }
- }
- });
- }
- has(model) {
- return this.all(model).length > 0;
- }
- all(model) {
- if (!model) {
- return [];
- }
- this._updateScores(model);
- const result = [];
- // from registry
- for (const entry of this._entries) {
- if (entry._score > 0) {
- result.push(entry.provider);
- }
- }
- return result;
- }
- ordered(model) {
- const result = [];
- this._orderedForEach(model, entry => result.push(entry.provider));
- return result;
- }
- orderedGroups(model) {
- const result = [];
- let lastBucket;
- let lastBucketScore;
- this._orderedForEach(model, entry => {
- if (lastBucket && lastBucketScore === entry._score) {
- lastBucket.push(entry.provider);
- }
- else {
- lastBucketScore = entry._score;
- lastBucket = [entry.provider];
- result.push(lastBucket);
- }
- });
- return result;
- }
- _orderedForEach(model, callback) {
- this._updateScores(model);
- for (const entry of this._entries) {
- if (entry._score > 0) {
- callback(entry);
- }
- }
- }
- _updateScores(model) {
- var _a, _b;
- const notebookInfo = (_a = this._notebookInfoResolver) === null || _a === void 0 ? void 0 : _a.call(this, model.uri);
- // use the uri (scheme, pattern) of the notebook info iff we have one
- // otherwise it's the model's/document's uri
- const candidate = notebookInfo
- ? new MatchCandidate(model.uri, model.getLanguageId(), notebookInfo.uri, notebookInfo.type)
- : new MatchCandidate(model.uri, model.getLanguageId(), undefined, undefined);
- if ((_b = this._lastCandidate) === null || _b === void 0 ? void 0 : _b.equals(candidate)) {
- // nothing has changed
- return;
- }
- this._lastCandidate = candidate;
- for (const entry of this._entries) {
- entry._score = score(entry.selector, candidate.uri, candidate.languageId, shouldSynchronizeModel(model), candidate.notebookUri, candidate.notebookType);
- if (isExclusive(entry.selector) && entry._score > 0) {
- // support for one exclusive selector that overwrites
- // any other selector
- for (const entry of this._entries) {
- entry._score = 0;
- }
- entry._score = 1000;
- break;
- }
- }
- // needs sorting
- this._entries.sort(LanguageFeatureRegistry._compareByScoreAndTime);
- }
- static _compareByScoreAndTime(a, b) {
- if (a._score < b._score) {
- return 1;
- }
- else if (a._score > b._score) {
- return -1;
- }
- // De-prioritize built-in providers
- if (isBuiltinSelector(a.selector) && !isBuiltinSelector(b.selector)) {
- return 1;
- }
- else if (!isBuiltinSelector(a.selector) && isBuiltinSelector(b.selector)) {
- return -1;
- }
- if (a._time < b._time) {
- return 1;
- }
- else if (a._time > b._time) {
- return -1;
- }
- else {
- return 0;
- }
- }
- }
- function isBuiltinSelector(selector) {
- if (typeof selector === 'string') {
- return false;
- }
- if (Array.isArray(selector)) {
- return selector.some(isBuiltinSelector);
- }
- return Boolean(selector.isBuiltin);
- }
|