Skip to content

Commit

Permalink
DocumentSelector matches on file and untitled only unless scheme is g…
Browse files Browse the repository at this point in the history
…iven, #21886
  • Loading branch information
jrieken committed Mar 7, 2017
1 parent 3ae62a8 commit fcc508f
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 39 deletions.
90 changes: 57 additions & 33 deletions src/vs/editor/common/modes/languageSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,62 +20,86 @@ export default function matches(selection: LanguageSelector, uri: URI, language:
return score(selection, uri, language) > 0;
}

export function score(selector: LanguageSelector, uri: URI, language: string): number {
export function score(selector: LanguageSelector, candidateUri: URI, candidateLanguage: string): number {

if (Array.isArray(selector)) {
// for each
let values = (<LanguageSelector[]>selector).map(item => score(item, uri, language));
return Math.max(...values);
// array -> take max individual value
let ret = 0;
for (const filter of selector) {
const value = score(filter, candidateUri, candidateLanguage);
if (value === 10) {
return value; // already at the highest
}
if (value > ret) {
ret = value;
}
}
return ret;

} else if (typeof selector === 'string') {
// compare language id
if (selector === language) {
return 10;
} else if (selector === '*') {
// short-hand notion, desugars to
// 'fooLang' -> [{ language: 'fooLang', scheme: 'file' }, { language: 'fooLang', scheme: 'untitled' }]
// '*' -> { language: '*', scheme: '*' }
if (selector === '*') {
return 5;
} else if (selector === candidateLanguage && _defaultSchemes[candidateUri.scheme]) {
return 10;
} else {
return 0;
}

} else if (selector) {
// all must match but only highest score counts
const filter = <LanguageFilter>selector;

let valueLanguage = 0;
let valueScheme = 0;
let valuePattern = 0;

// language id
if (filter.language) {
if (filter.language === language) {
valueLanguage = 10;
} else if (filter.language === '*') {
valueLanguage = 5;
// filter -> select accordingly, use defaults for scheme
const { language, pattern, scheme } = selector;

let ret = 0;

if (scheme) {
if (scheme === candidateUri.scheme) {
ret = 10;
} else if (scheme === '*') {
ret = 5;
} else {
return 0;
}
}

// scheme
if (filter.scheme) {
if (filter.scheme === uri.scheme) {
valueScheme = 10;
if (language) {
if (language === candidateLanguage) {
ret = 10;
} else if (language === '*') {
ret = Math.max(ret, 5);
} else {
return 0;
}
}

// match fsPath with pattern
if (filter.pattern) {
if (filter.pattern === uri.fsPath) {
valuePattern = 10;
} else if (matchGlobPattern(filter.pattern, uri.fsPath)) {
valuePattern = 5;
if (pattern) {
if (pattern === candidateUri.fsPath || matchGlobPattern(pattern, candidateUri.fsPath)) {
ret = 10;
} else {
return 0;
}
}

return Math.max(valueLanguage, valueScheme, valuePattern);
if (!_defaultSchemes[candidateUri.scheme] && !scheme && language !== '*') {
// undo match when the uri-scheme is special and not
// explicitly selected
return 0;
} else {
return ret;
}

} else {
return undefined;
}
return undefined;
}

interface DefaultSchemes {
file: 'file';
untitled: 'untitled';
}

const _defaultSchemes: DefaultSchemes = Object.create(null);
_defaultSchemes.file = 'file';
_defaultSchemes.untitled = 'untitled';
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { CodeActionProviderRegistry, LanguageIdentifier } from 'vs/editor/common
suite('QuickFix', () => {
const languageIdentifier = new LanguageIdentifier('foo-lang', 3);

let uri = URI.parse('fake:path');
let uri = URI.parse('untitled:path');
let model = Model.createFromString('foobar foo bar\nfarboo far boo', undefined, languageIdentifier, uri);
let markerService: MarkerService;
let editor: ICommonCodeEditor;
Expand Down
4 changes: 2 additions & 2 deletions src/vs/editor/contrib/suggest/test/common/suggest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ suite('Suggest', function () {
setup(function () {

model = Model.createFromString('FOO\nbar\BAR\nfoo', undefined, undefined, URI.parse('foo:bar/path'));
registration = SuggestRegistry.register({ pattern: 'bar/path' }, {
registration = SuggestRegistry.register({ pattern: 'bar/path', scheme: 'foo' }, {
provideCompletionItems() {
return {
incomplete: false,
Expand Down Expand Up @@ -98,7 +98,7 @@ suite('Suggest', function () {
};
}
};
const registration = SuggestRegistry.register({ pattern: 'bar/path' }, foo);
const registration = SuggestRegistry.register({ pattern: 'bar/path', scheme: 'foo' }, foo);

provideSuggestionItems(model, new Position(1, 1), undefined, [foo]).then(items => {
registration.dispose();
Expand Down
29 changes: 26 additions & 3 deletions src/vs/editor/test/common/modes/languageSelector.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@ suite('LanguageSelector', function () {
test('score, any language', function () {
assert.equal(score({ language: '*' }, model.uri, model.language), 5);
assert.equal(score('*', model.uri, model.language), 5);

assert.equal(score('*', URI.parse('foo:bar'), model.language), 5);
assert.equal(score('farboo', URI.parse('foo:bar'), model.language), 0);
});

test('score, default schemes', function () {

const uri = URI.parse('git:foo/file.txt');
const language = 'farboo';

assert.equal(score('*', uri, language), 5);
assert.equal(score('farboo', uri, language), 0);
assert.equal(score({ language: 'farboo', scheme: '' }, uri, language), 0);
assert.equal(score({ language: 'farboo', scheme: 'git' }, uri, language), 10);
assert.equal(score({ language: 'farboo', scheme: '*' }, uri, language), 10);
assert.equal(score({ language: 'farboo' }, uri, language), 0);
assert.equal(score({ language: '*' }, uri, language), 5);

assert.equal(score({ scheme: '*' }, uri, language), 5);
assert.equal(score({ scheme: 'git' }, uri, language), 10);
});

test('score, filter', function () {
Expand All @@ -34,8 +54,10 @@ suite('LanguageSelector', function () {
assert.equal(score({ language: 'farboo', scheme: 'file' }, model.uri, model.language), 10);
assert.equal(score({ language: 'farboo', scheme: 'http' }, model.uri, model.language), 0);

assert.equal(score({ pattern: '**/*.fb' }, model.uri, model.language), 5);
// assert.equal(score({ pattern: '/testbed/file.fb' }, model.uri, model.language), 10); fails on windows
assert.equal(score({ pattern: '**/*.fb' }, model.uri, model.language), 10);
assert.equal(score({ pattern: '**/*.fb', scheme: 'file' }, model.uri, model.language), 10);
assert.equal(score({ pattern: '**/*.fb' }, URI.parse('foo:bar'), model.language), 0);
assert.equal(score({ pattern: '**/*.fb', scheme: 'foo' }, URI.parse('foo:bar'), model.language), 0);
});

test('score, max(filters)', function () {
Expand All @@ -45,7 +67,8 @@ suite('LanguageSelector', function () {
assert.equal(score(match, model.uri, model.language), 10);
assert.equal(score(fail, model.uri, model.language), 0);
assert.equal(score([match, fail], model.uri, model.language), 10);
assert.equal(score([fail, fail], model.uri, model.language), 0);
assert.equal(score(['farboo', '*'], model.uri, model.language), 10);
assert.equal(score(['*', 'farboo'], model.uri, model.language), 10);
});
});
});

0 comments on commit fcc508f

Please sign in to comment.