1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IRelativePattern, match as matchGlobPattern } from 'vs/base/common/glob';
import { URI } from 'vs/base/common/uri';
import { normalize } from 'vs/base/common/path';
export interface LanguageFilter {
readonly language?: string;
readonly scheme?: string;
readonly pattern?: string | IRelativePattern;
readonly notebookType?: string;
/**
* This provider is implemented in the UI thread.
*/
readonly hasAccessToAllModels?: boolean;
readonly exclusive?: boolean;
}
export type LanguageSelector = string | LanguageFilter | ReadonlyArray<string | LanguageFilter>;
export function score(selector: LanguageSelector | undefined, candidateUri: URI, candidateLanguage: string, candidateIsSynchronized: boolean, candidateNotebookType: string | undefined): number {
if (Array.isArray(selector)) {
// array -> take max individual value
let ret = 0;
for (const filter of selector) {
const value = score(filter, candidateUri, candidateLanguage, candidateIsSynchronized, candidateNotebookType);
if (value === 10) {
return value; // already at the highest
}
if (value > ret) {
ret = value;
}
}
return ret;
} else if (typeof selector === 'string') {
if (!candidateIsSynchronized) {
return 0;
}
// short-hand notion, desugars to
// 'fooLang' -> { language: 'fooLang'}
// '*' -> { language: '*' }
if (selector === '*') {
return 5;
} else if (selector === candidateLanguage) {
return 10;
} else {
return 0;
}
} else if (selector) {
// filter -> select accordingly, use defaults for scheme
const { language, pattern, scheme, hasAccessToAllModels, notebookType } = selector as LanguageFilter; // TODO: microsoft/TypeScript#42768
if (!candidateIsSynchronized && !hasAccessToAllModels) {
return 0;
}
let ret = 0;
if (scheme) {
if (scheme === candidateUri.scheme) {
ret = 10;
} else if (scheme === '*') {
ret = 5;
} else {
return 0;
}
}
if (language) {
if (language === candidateLanguage) {
ret = 10;
} else if (language === '*') {
ret = Math.max(ret, 5);
} else {
return 0;
}
}
if (notebookType) {
if (notebookType === candidateNotebookType) {
ret = 10;
} else if (notebookType === '*' && candidateNotebookType !== undefined) {
ret = Math.max(ret, 5);
} else {
return 0;
}
}
if (pattern) {
let normalizedPattern: string | IRelativePattern;
if (typeof pattern === 'string') {
normalizedPattern = pattern;
} else {
// Since this pattern has a `base` property, we need
// to normalize this path first before passing it on
// because we will compare it against `Uri.fsPath`
// which uses platform specific separators.
// Refs: https://github.com/microsoft/vscode/issues/99938
normalizedPattern = { ...pattern, base: normalize(pattern.base) };
}
if (normalizedPattern === candidateUri.fsPath || matchGlobPattern(normalizedPattern, candidateUri.fsPath)) {
ret = 10;
} else {
return 0;
}
}
return ret;
} else {
return 0;
}
}
|