add exclusivness to document filter

This commit is contained in:
Johannes Rieken 2018-05-03 11:37:58 +02:00
parent d7955610d4
commit fa0a49bbf2
7 changed files with 51 additions and 14 deletions

View file

@ -18,6 +18,16 @@ interface Entry<T> {
_time: number;
}
function isExclusive(selector: LanguageSelector): boolean {
if (typeof selector === 'string') {
return false;
} else if (Array.isArray(selector)) {
return selector.every(isExclusive);
} else {
return selector.exclusive;
}
}
export default class LanguageFeatureRegistry<T> {
private _clock: number = 0;
@ -142,6 +152,16 @@ export default class LanguageFeatureRegistry<T> {
for (let entry of this._entries) {
entry._score = score(entry.selector, model.uri, model.getLanguageIdentifier().language, shouldSynchronizeModel(model));
if (isExclusive(entry.selector) && entry._score > 0) {
// support for one exclusive selector that overwrites
// any other selector
for (let entry of this._entries) {
entry._score = 0;
}
entry._score = 1000;
break;
}
}
// needs sorting

View file

@ -16,6 +16,7 @@ export interface LanguageFilter {
* This provider is implemented in the UI thread.
*/
hasAccessToAllModels?: boolean;
exclusive?: boolean;
}
export type LanguageSelector = string | LanguageFilter | (string | LanguageFilter)[];
@ -43,8 +44,8 @@ export function score(selector: LanguageSelector, candidateUri: URI, candidateLa
}
// short-hand notion, desugars to
// 'fooLang' -> [{ language: 'fooLang', scheme: 'file' }, { language: 'fooLang', scheme: 'untitled' }]
// '*' -> { language: '*', scheme: '*' }
// 'fooLang' -> { language: 'fooLang'}
// '*' -> { language: '*' }
if (selector === '*') {
return 5;
} else if (selector === candidateLanguage) {

View file

@ -488,4 +488,12 @@ declare module 'vscode' {
}
//#endregion
//#region Joh -> exclusive document filters
export interface DocumentFilter {
exclusive?: boolean;
}
//#endregion
}

View file

@ -147,18 +147,23 @@ export function createApiFactory(
// we cannot say if the extension is doing it right or wrong...
let checkSelector = (function () {
let done = initData.environment.extensionDevelopmentPath !== extension.extensionFolderPath;
function inform(selector: vscode.DocumentSelector) {
console.info(`Extension '${extension.id}' uses a document selector without scheme. Learn more about this: https://go.microsoft.com/fwlink/?linkid=872305`);
done = true;
function informOnce(selector: vscode.DocumentSelector) {
if (!done) {
console.info(`Extension '${extension.id}' uses a document selector without scheme. Learn more about this: https://go.microsoft.com/fwlink/?linkid=872305`);
done = true;
}
}
return function perform(selector: vscode.DocumentSelector): vscode.DocumentSelector {
if (!done) {
if (Array.isArray(selector)) {
selector.forEach(perform);
} else if (typeof selector === 'string') {
inform(selector);
} else if (typeof selector.scheme === 'undefined') {
inform(selector);
if (Array.isArray(selector)) {
selector.forEach(perform);
} else if (typeof selector === 'string') {
informOnce(selector);
} else {
if (typeof selector.scheme === 'undefined') {
informOnce(selector);
}
if (!extension.enableProposedApi && typeof selector.exclusive === 'boolean') {
throwProposedApiError(extension);
}
}
return selector;

View file

@ -258,6 +258,7 @@ export interface ISerializedDocumentFilter {
language?: string;
scheme?: string;
pattern?: vscode.GlobPattern;
exclusive?: boolean;
}
export interface MainThreadLanguageFeaturesShape extends IDisposable {

View file

@ -887,7 +887,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
$serialized: true,
language: selector.language,
scheme: this._transformScheme(selector.scheme),
pattern: selector.pattern
pattern: selector.pattern,
exclusive: selector.exclusive
};
}

View file

@ -696,7 +696,8 @@ function doToLanguageSelector(selector: string | vscode.DocumentFilter): string
return {
language: selector.language,
scheme: selector.scheme,
pattern: toGlobPattern(selector.pattern)
pattern: toGlobPattern(selector.pattern),
exclusive: selector.exclusive
};
}