Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
82a31e8e
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
82a31e8e
编写于
3月 20, 2017
作者:
J
Johannes Rieken
提交者:
GitHub
3月 20, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #22884 from Microsoft/joh/fuzzy
fuzzyScore
上级
dda7717d
219a45c0
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
284 addition
and
98 deletion
+284
-98
src/vs/base/common/filters.ts
src/vs/base/common/filters.ts
+107
-0
src/vs/base/test/common/filters.perf.data.json
src/vs/base/test/common/filters.perf.data.json
+1
-0
src/vs/base/test/common/filters.perf.test.ts
src/vs/base/test/common/filters.perf.test.ts
+46
-0
src/vs/base/test/common/filters.test.ts
src/vs/base/test/common/filters.test.ts
+96
-1
src/vs/editor/contrib/suggest/browser/suggestWidget.ts
src/vs/editor/contrib/suggest/browser/suggestWidget.ts
+3
-2
src/vs/editor/contrib/suggest/common/completionModel.ts
src/vs/editor/contrib/suggest/common/completionModel.ts
+26
-90
src/vs/editor/contrib/suggest/test/common/completionModel.test.ts
...ditor/contrib/suggest/test/common/completionModel.test.ts
+5
-5
未找到文件。
src/vs/base/common/filters.ts
浏览文件 @
82a31e8e
...
...
@@ -357,3 +357,110 @@ export function matchesFuzzy(word: string, wordToMatchAgainst: string, enableSep
// Default Filter
return
enableSeparateSubstringMatching
?
fuzzySeparateFilter
(
word
,
wordToMatchAgainst
)
:
fuzzyContiguousFilter
(
word
,
wordToMatchAgainst
);
}
export
function
matchesFuzzy2
(
pattern
:
string
,
word
:
string
):
number
[]
{
pattern
=
pattern
.
toLowerCase
();
word
=
word
.
toLowerCase
();
let
matches
:
number
[]
=
[];
let
patternPos
=
0
;
let
wordPos
=
0
;
while
(
patternPos
<
pattern
.
length
&&
wordPos
<
word
.
length
)
{
if
(
pattern
[
patternPos
]
===
word
[
wordPos
])
{
patternPos
+=
1
;
matches
.
push
(
wordPos
);
}
wordPos
+=
1
;
}
if
(
patternPos
!==
pattern
.
length
)
{
return
undefined
;
}
return
matches
;
}
export
function
createMatches
(
position
:
number
[]):
IMatch
[]
{
let
ret
:
IMatch
[]
=
[];
let
last
:
IMatch
;
for
(
const
pos
of
position
)
{
if
(
last
&&
last
.
end
===
pos
)
{
last
.
end
+=
1
;
}
else
{
last
=
{
start
:
pos
,
end
:
pos
+
1
};
ret
.
push
(
last
);
}
}
return
ret
;
}
export
function
fuzzyMatchAndScore
(
pattern
:
string
,
word
:
string
):
[
number
,
number
[]]
{
if
(
!
pattern
)
{
return
[
-
1
,
[]];
}
let
matches
:
number
[]
=
[];
let
score
=
_matchRecursive
(
pattern
,
pattern
.
toLowerCase
(),
pattern
.
toUpperCase
(),
0
,
word
,
word
.
toLowerCase
(),
0
,
matches
);
if
(
score
<=
0
)
{
return
undefined
;
}
score
-=
Math
.
min
(
matches
[
0
],
3
)
*
3
;
// penalty for first matching character
score
-=
(
1
+
matches
[
matches
.
length
-
1
])
-
(
pattern
.
length
);
// penalty for all non matching characters between first and last
return
[
score
,
matches
];
}
export
function
_matchRecursive
(
pattern
:
string
,
lowPattern
:
string
,
upPattern
:
string
,
patternPos
:
number
,
word
:
string
,
lowWord
:
string
,
wordPos
:
number
,
matches
:
number
[]
):
number
{
if
(
patternPos
>=
lowPattern
.
length
)
{
return
0
;
}
const
lowPatternChar
=
lowPattern
[
patternPos
];
let
idx
=
-
1
;
let
value
=
0
;
if
((
patternPos
===
wordPos
&&
lowPatternChar
===
lowWord
[
wordPos
])
&&
((
value
=
_matchRecursive
(
pattern
,
lowPattern
,
upPattern
,
patternPos
+
1
,
word
,
lowWord
,
wordPos
+
1
,
matches
))
>=
0
)
)
{
matches
.
unshift
(
wordPos
);
return
(
pattern
[
patternPos
]
===
word
[
wordPos
]
?
17
:
11
)
+
value
;
}
if
((
idx
=
lowWord
.
indexOf
(
`_
${
lowPatternChar
}
`
,
wordPos
))
>=
0
&&
((
value
=
_matchRecursive
(
pattern
,
lowPattern
,
upPattern
,
patternPos
+
1
,
word
,
lowWord
,
idx
+
2
,
matches
))
>=
0
)
)
{
matches
.
unshift
(
idx
+
1
);
return
(
pattern
[
patternPos
]
===
word
[
idx
+
1
]
?
17
:
11
)
+
value
;
}
if
((
idx
=
word
.
indexOf
(
upPattern
[
patternPos
],
wordPos
))
>=
0
&&
((
value
=
_matchRecursive
(
pattern
,
lowPattern
,
upPattern
,
patternPos
+
1
,
word
,
lowWord
,
idx
+
1
,
matches
))
>=
0
)
)
{
matches
.
unshift
(
idx
);
return
(
pattern
[
patternPos
]
===
word
[
idx
]
?
17
:
11
)
+
value
;
}
if
(
patternPos
>
0
&&
(
idx
=
lowWord
.
indexOf
(
lowPatternChar
,
wordPos
))
>=
0
&&
((
value
=
_matchRecursive
(
pattern
,
lowPattern
,
upPattern
,
patternPos
+
1
,
word
,
lowWord
,
idx
+
1
,
matches
))
>=
0
)
)
{
matches
.
unshift
(
idx
);
return
1
+
value
;
}
return
-
1
;
}
src/vs/base/test/common/filters.perf.data.json
0 → 100644
浏览文件 @
82a31e8e
因为 它太大了无法显示 source diff 。你可以改为
查看blob
。
src/vs/base/test/common/filters.perf.test.ts
0 → 100644
浏览文件 @
82a31e8e
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
// import * as assert from 'assert';
import
*
as
filters
from
'
vs/base/common/filters
'
;
const
data
=
<
string
[]
>
require
.
__$__nodeRequire
(
require
.
toUrl
(
'
./filters.perf.data.json
'
));
const
patterns
=
[
'
cci
'
,
'
ida
'
,
'
pos
'
,
'
CCI
'
,
'
enbled
'
,
'
callback
'
,
'
gGame
'
,
'
cons
'
];
const
_enablePerf
=
false
;
function
perfSuite
(
name
:
string
,
callback
:
(
this
:
Mocha
.
ISuiteCallbackContext
)
=>
void
)
{
if
(
_enablePerf
)
{
suite
(
name
,
callback
);
}
}
perfSuite
(
'
Performance - fuzzyMatch
'
,
function
()
{
console
.
log
(
`Matching
${
data
.
length
}
items against
${
patterns
.
length
}
patterns...`
);
function
perfTest
(
name
:
string
,
match
:
(
pattern
:
string
,
word
:
string
)
=>
any
)
{
test
(
name
,
function
()
{
const
t1
=
Date
.
now
();
let
count
=
0
;
for
(
const
pattern
of
patterns
)
{
for
(
const
item
of
data
)
{
count
+=
1
;
match
(
pattern
,
item
);
}
}
console
.
log
(
name
,
Date
.
now
()
-
t1
,
`
${(
count
/
(
Date
.
now
()
-
t1
)).
toPrecision
(
6
)}
/ms`
);
});
}
perfTest
(
'
matchesFuzzy
'
,
filters
.
matchesFuzzy
);
perfTest
(
'
fuzzyContiguousFilter
'
,
filters
.
fuzzyContiguousFilter
);
perfTest
(
'
matchesFuzzy2
'
,
filters
.
matchesFuzzy2
);
perfTest
(
'
fuzzyMatchAndScore
'
,
filters
.
fuzzyMatchAndScore
);
});
src/vs/base/test/common/filters.test.ts
浏览文件 @
82a31e8e
...
...
@@ -5,7 +5,7 @@
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
IFilter
,
or
,
matchesPrefix
,
matchesStrictPrefix
,
matchesCamelCase
,
matchesSubString
,
matchesContiguousSubString
,
matchesWords
}
from
'
vs/base/common/filters
'
;
import
{
IFilter
,
or
,
matchesPrefix
,
matchesStrictPrefix
,
matchesCamelCase
,
matchesSubString
,
matchesContiguousSubString
,
matchesWords
,
fuzzyMatchAndScore
}
from
'
vs/base/common/filters
'
;
function
filterOk
(
filter
:
IFilter
,
word
:
string
,
wordToMatchAgainst
:
string
,
highlights
?:
{
start
:
number
;
end
:
number
;
}[])
{
let
r
=
filter
(
word
,
wordToMatchAgainst
);
...
...
@@ -192,4 +192,99 @@ suite('Filters', () => {
assert
.
ok
(
matchesWords
(
'
gipu
'
,
'
Category: Git: Pull
'
,
true
)
===
null
);
assert
.
deepEqual
(
matchesWords
(
'
pu
'
,
'
Category: Git: Pull
'
,
true
),
[{
start
:
15
,
end
:
17
}]);
});
test
(
'
fuzzyMatchAndScore
'
,
function
()
{
function
assertMatches
(
pattern
:
string
,
word
:
string
,
decoratedWord
:
string
,
filter
:
typeof
fuzzyMatchAndScore
)
{
let
r
=
filter
(
pattern
,
word
);
assert
.
ok
(
Boolean
(
r
)
===
Boolean
(
decoratedWord
));
if
(
r
)
{
const
[,
matches
]
=
r
;
let
pos
=
0
;
for
(
let
i
=
0
;
i
<
matches
.
length
;
i
++
)
{
let
actual
=
matches
[
i
];
let
expected
=
decoratedWord
.
indexOf
(
'
^
'
,
pos
)
-
i
;
assert
.
equal
(
actual
,
expected
);
pos
=
expected
+
1
+
i
;
}
}
}
assertMatches
(
'
no
'
,
'
match
'
,
undefined
,
fuzzyMatchAndScore
);
assertMatches
(
'
no
'
,
''
,
undefined
,
fuzzyMatchAndScore
);
assertMatches
(
'
BK
'
,
'
the_black_knight
'
,
'
the_^black_^knight
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
bkn
'
,
'
the_black_knight
'
,
'
the_^black_^k^night
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
bt
'
,
'
the_black_knight
'
,
'
the_^black_knigh^t
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
bti
'
,
'
the_black_knight
'
,
undefined
,
fuzzyMatchAndScore
);
assertMatches
(
'
LLL
'
,
'
SVisualLoggerLogsList
'
,
'
SVisual^Logger^Logs^List
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
LLLL
'
,
'
SVisualLoggerLogsList
'
,
undefined
,
fuzzyMatchAndScore
);
assertMatches
(
'
sllll
'
,
'
SVisualLoggerLogsList
'
,
'
^SVisua^l^Logger^Logs^List
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
sl
'
,
'
SVisualLoggerLogsList
'
,
'
^SVisual^LoggerLogsList
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
foobar
'
,
'
foobar
'
,
'
^f^o^o^b^a^r
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
fob
'
,
'
foobar
'
,
'
^f^oo^bar
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
ob
'
,
'
foobar
'
,
undefined
,
fuzzyMatchAndScore
);
assertMatches
(
'
gp
'
,
'
Git: Pull
'
,
'
^Git: ^Pull
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
gp
'
,
'
Git_Git_Pull
'
,
'
^Git_Git_^Pull
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
g p
'
,
'
Git: Pull
'
,
'
^Git:^ ^Pull
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
gip
'
,
'
Git: Pull
'
,
'
^G^it: ^Pull
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
is
'
,
'
isValid
'
,
'
^i^sValid
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
is
'
,
'
ImportStatement
'
,
'
^Import^Statement
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
lowrd
'
,
'
lowWord
'
,
'
^l^o^wWo^r^d
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
ccm
'
,
'
cacmelCase
'
,
'
^ca^c^melCase
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
ccm
'
,
'
camelCase
'
,
undefined
,
fuzzyMatchAndScore
);
assertMatches
(
'
ccm
'
,
'
camelCasecm
'
,
'
^camel^Casec^m
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
myvable
'
,
'
myvariable
'
,
'
^m^y^v^aria^b^l^e
'
,
fuzzyMatchAndScore
);
assertMatches
(
'
fdm
'
,
'
findModel
'
,
'
^fin^d^Model
'
,
fuzzyMatchAndScore
);
});
test
(
'
topScore
'
,
function
()
{
function
assertTopScore
(
pattern
:
string
,
expected
:
number
,
...
words
:
string
[])
{
let
topScore
=
Number
.
MIN_VALUE
;
let
topIdx
=
0
;
for
(
let
i
=
0
;
i
<
words
.
length
;
i
++
)
{
const
word
=
words
[
i
];
const
m
=
fuzzyMatchAndScore
(
pattern
,
word
);
if
(
m
)
{
const
[
score
]
=
m
;
if
(
score
>
topScore
)
{
topScore
=
score
;
topIdx
=
i
;
}
}
}
assert
.
equal
(
topIdx
,
expected
);
}
assertTopScore
(
'
cons
'
,
2
,
'
ArrayBufferConstructor
'
,
'
Console
'
,
'
console
'
);
assertTopScore
(
'
Foo
'
,
1
,
'
foo
'
,
'
Foo
'
,
'
foo
'
);
assertTopScore
(
'
CC
'
,
1
,
'
camelCase
'
,
'
CamelCase
'
);
assertTopScore
(
'
cC
'
,
0
,
'
camelCase
'
,
'
CamelCase
'
);
assertTopScore
(
'
cC
'
,
1
,
'
ccfoo
'
,
'
camelCase
'
);
assertTopScore
(
'
cC
'
,
1
,
'
ccfoo
'
,
'
camelCase
'
,
'
foo-cC-bar
'
);
// issue #17836
assertTopScore
(
'
p
'
,
0
,
'
parse
'
,
'
posix
'
,
'
pafdsa
'
,
'
path
'
,
'
p
'
);
assertTopScore
(
'
pa
'
,
0
,
'
parse
'
,
'
pafdsa
'
,
'
path
'
);
// issue #14583
assertTopScore
(
'
log
'
,
3
,
'
HTMLOptGroupElement
'
,
'
ScrollLogicalPosition
'
,
'
SVGFEMorphologyElement
'
,
'
log
'
);
assertTopScore
(
'
e
'
,
2
,
'
AbstractWorker
'
,
'
ActiveXObject
'
,
'
else
'
);
// issue #14446
assertTopScore
(
'
workbench.sideb
'
,
1
,
'
workbench.editor.defaultSideBySideLayout
'
,
'
workbench.sideBar.location
'
);
// issue #11423
assertTopScore
(
'
editor.r
'
,
2
,
'
diffEditor.renderSideBySide
'
,
'
editor.overviewRulerlanes
'
,
'
editor.renderControlCharacter
'
,
'
editor.renderWhitespace
'
);
// assertTopScore('editor.R', 1, 'diffEditor.renderSideBySide', 'editor.overviewRulerlanes', 'editor.renderControlCharacter', 'editor.renderWhitespace');
// assertTopScore('Editor.r', 0, 'diffEditor.renderSideBySide', 'editor.overviewRulerlanes', 'editor.renderControlCharacter', 'editor.renderWhitespace');
assertTopScore
(
'
-mo
'
,
1
,
'
-ms-ime-mode
'
,
'
-moz-columns
'
);
// // dupe, issue #14861
assertTopScore
(
'
convertModelPosition
'
,
0
,
'
convertModelPositionToViewPosition
'
,
'
convertViewToModelPosition
'
);
// // dupe, issue #14942
assertTopScore
(
'
is
'
,
0
,
'
isValidViewletId
'
,
'
import statement
'
);
});
});
src/vs/editor/contrib/suggest/browser/suggestWidget.ts
浏览文件 @
82a31e8e
...
...
@@ -7,6 +7,7 @@
import
'
vs/css!./suggest
'
;
import
*
as
nls
from
'
vs/nls
'
;
import
{
createMatches
}
from
'
vs/base/common/filters
'
;
import
*
as
strings
from
'
vs/base/common/strings
'
;
import
Event
,
{
Emitter
,
chain
}
from
'
vs/base/common/event
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
...
...
@@ -136,7 +137,7 @@ class Renderer implements IRenderer<ICompletionItem, ISuggestionTemplateData> {
}
}
data
.
highlightedLabel
.
set
(
suggestion
.
label
,
element
.
highlights
);
data
.
highlightedLabel
.
set
(
suggestion
.
label
,
createMatches
(
element
.
matches
)
);
data
.
typeLabel
.
textContent
=
(
suggestion
.
detail
||
''
).
replace
(
/
\n
.*$/m
,
''
);
data
.
documentation
.
textContent
=
suggestion
.
documentation
||
''
;
...
...
@@ -234,7 +235,7 @@ class SuggestionDetails {
return
;
}
this
.
titleLabel
.
set
(
item
.
suggestion
.
label
,
item
.
highlights
);
this
.
titleLabel
.
set
(
item
.
suggestion
.
label
,
createMatches
(
item
.
matches
)
);
this
.
type
.
innerText
=
item
.
suggestion
.
detail
||
''
;
this
.
docs
.
textContent
=
item
.
suggestion
.
documentation
;
this
.
back
.
onmousedown
=
e
=>
{
...
...
src/vs/editor/contrib/suggest/common/completionModel.ts
浏览文件 @
82a31e8e
...
...
@@ -5,14 +5,13 @@
'
use strict
'
;
import
{
isFalsyOrEmpty
}
from
'
vs/base/common/arrays
'
;
import
{
indexOfIgnoreCase
}
from
'
vs/base/common/strings
'
;
import
{
IMatch
,
fuzzyContiguousFilter
}
from
'
vs/base/common/filters
'
;
import
{
fuzzyMatchAndScore
}
from
'
vs/base/common/filters
'
;
import
{
ISuggestSupport
}
from
'
vs/editor/common/modes
'
;
import
{
ISuggestionItem
}
from
'
./suggest
'
;
export
interface
ICompletionItem
extends
ISuggestionItem
{
highlights
?:
IMatch
[];
matches
?:
number
[];
score
?:
number
;
}
export
interface
ICompletionStats
{
...
...
@@ -100,17 +99,17 @@ export class CompletionModel {
private
_createCachedState
():
void
{
this
.
_filteredItems
=
[];
this
.
_topScoreIdx
=
-
1
;
this
.
_topScoreIdx
=
0
;
this
.
_isIncomplete
=
false
;
this
.
_stats
=
{
suggestionCount
:
0
,
snippetCount
:
0
,
textCount
:
0
};
const
{
leadingLineContent
,
characterCountDelta
}
=
this
.
_lineContext
;
const
{
leadingLineContent
,
characterCountDelta
}
=
this
.
_lineContext
;
let
word
=
''
;
let
topScore
=
-
1
;
let
topScore
=
Number
.
MIN_VALUE
;
for
(
const
item
of
this
.
_items
)
{
const
{
suggestion
,
container
}
=
item
;
const
{
suggestion
,
container
}
=
item
;
// collect those supports that signaled having
// an incomplete result
...
...
@@ -124,36 +123,32 @@ export class CompletionModel {
word
=
wordLen
===
0
?
''
:
leadingLineContent
.
slice
(
-
wordLen
);
}
let
match
=
false
;
// compute highlights based on 'label'
item
.
highlights
=
fuzzyContiguousFilter
(
word
,
suggestion
.
label
);
match
=
item
.
highlights
!==
null
;
// no match on label nor codeSnippet -> check on filterText
if
(
!
match
&&
typeof
suggestion
.
filterText
===
'
string
'
)
{
if
(
!
isFalsyOrEmpty
(
fuzzyContiguousFilter
(
word
,
suggestion
.
filterText
)))
{
match
=
true
;
// try to compute highlights by stripping none-word
// characters from the end of the string
item
.
highlights
=
fuzzyContiguousFilter
(
word
.
replace
(
/^
\W
+|
\W
+$/
,
''
),
suggestion
.
label
);
let
match
=
fuzzyMatchAndScore
(
word
,
suggestion
.
label
);
if
(
!
match
)
{
if
(
typeof
suggestion
.
filterText
===
'
string
'
)
{
match
=
fuzzyMatchAndScore
(
word
,
suggestion
.
filterText
);
}
else
{
continue
;
}
if
(
match
)
{
match
=
fuzzyMatchAndScore
(
word
.
replace
(
/^
\W
+|
\W
+$/
,
''
),
suggestion
.
label
);
}
else
{
continue
;
}
}
if
(
!
match
)
{
continue
;
if
(
match
)
{
item
.
score
=
match
[
0
];
item
.
matches
=
match
[
1
];
if
(
item
.
score
>
topScore
)
{
topScore
=
item
.
score
;
this
.
_topScoreIdx
=
this
.
_filteredItems
.
length
;
}
}
this
.
_filteredItems
.
push
(
item
);
// compute score against word
const
score
=
CompletionModel
.
_scoreByHighlight
(
item
,
word
);
if
(
score
>
topScore
)
{
topScore
=
score
;
this
.
_topScoreIdx
=
this
.
_filteredItems
.
length
-
1
;
}
// update stats
this
.
_stats
.
suggestionCount
++
;
switch
(
suggestion
.
type
)
{
...
...
@@ -162,63 +157,4 @@ export class CompletionModel {
}
}
}
private
static
_base
=
100
;
private
static
_scoreByHighlight
(
item
:
ICompletionItem
,
currentWord
:
string
):
number
{
const
{
highlights
,
suggestion
}
=
item
;
if
(
isFalsyOrEmpty
(
highlights
))
{
return
0
;
}
let
caseSensitiveMatches
=
0
;
let
caseInsensitiveMatches
=
0
;
let
firstMatchStart
=
0
;
const
len
=
Math
.
min
(
CompletionModel
.
_base
,
suggestion
.
label
.
length
);
let
currentWordOffset
=
0
;
for
(
let
pos
=
0
,
idx
=
0
;
pos
<
len
;
pos
++
)
{
const
highlight
=
highlights
[
idx
];
if
(
pos
===
highlight
.
start
)
{
// reached a highlight: find highlighted part
// and count case-sensitive /case-insensitive matches
const
part
=
suggestion
.
label
.
substring
(
highlight
.
start
,
highlight
.
end
);
currentWordOffset
=
indexOfIgnoreCase
(
currentWord
,
part
,
currentWordOffset
);
if
(
currentWordOffset
>=
0
)
{
do
{
if
(
suggestion
.
label
[
pos
]
===
currentWord
[
currentWordOffset
])
{
caseSensitiveMatches
+=
1
;
}
else
{
caseInsensitiveMatches
+=
1
;
}
pos
+=
1
;
currentWordOffset
+=
1
;
}
while
(
pos
<
highlight
.
end
);
}
// proceed with next highlight, store first start,
// exit loop when no highlight is available
if
(
idx
===
0
)
{
firstMatchStart
=
highlight
.
start
;
}
idx
+=
1
;
if
(
idx
>=
highlights
.
length
)
{
break
;
}
}
}
// combine the 4 scoring values into one
// value using base_100. Values further left
// are more important
return
(
CompletionModel
.
_base
**
3
)
*
caseSensitiveMatches
+
(
CompletionModel
.
_base
**
2
)
*
caseInsensitiveMatches
+
(
CompletionModel
.
_base
**
1
)
*
(
CompletionModel
.
_base
-
firstMatchStart
)
+
(
CompletionModel
.
_base
**
0
)
*
(
CompletionModel
.
_base
-
highlights
.
length
);
}
}
src/vs/editor/contrib/suggest/test/common/completionModel.test.ts
浏览文件 @
82a31e8e
...
...
@@ -93,7 +93,7 @@ suite('CompletionModel', function () {
const
completeItem
=
createSuggestItem
(
'
foobar
'
,
1
,
false
,
{
lineNumber
:
1
,
column
:
2
});
const
incompleteItem
=
createSuggestItem
(
'
foofoo
'
,
1
,
true
,
{
lineNumber
:
1
,
column
:
2
});
const
model
=
new
CompletionModel
([
completeItem
,
incompleteItem
],
2
,
{
leadingLineContent
:
'
foo
'
,
characterCountDelta
:
0
});
const
model
=
new
CompletionModel
([
completeItem
,
incompleteItem
],
2
,
{
leadingLineContent
:
''
,
characterCountDelta
:
0
});
assert
.
equal
(
model
.
incomplete
,
true
);
assert
.
equal
(
model
.
items
.
length
,
2
);
...
...
@@ -134,16 +134,16 @@ suite('CompletionModel', function () {
assertTopScore
(
'
pa
'
,
0
,
'
parse
'
,
'
posix
'
,
'
sep
'
,
'
pafdsa
'
,
'
path
'
,
'
p
'
);
// issue #14583
assertTopScore
(
'
log
'
,
3
,
'
HTMLOptGroupElement
'
,
'
ScrollLogicalPosition
'
,
'
SVGFEMorphologyElement
'
,
'
log
'
);
assertTopScore
(
'
e
'
,
2
,
'
Abstract
Worker
'
,
'
Activ
eXObject
'
,
'
else
'
);
assertTopScore
(
'
log
'
,
2
,
'
HTMLOptGroupElement
'
,
'
ScrollLogicalPosition
'
,
'
log
'
);
assertTopScore
(
'
e
'
,
2
,
'
Abstract
Eorker
'
,
'
Activ_
eXObject
'
,
'
else
'
);
// issue #14446
assertTopScore
(
'
workbench.sideb
'
,
1
,
'
workbench.editor.defaultSideBySideLayout
'
,
'
workbench.sideBar.location
'
);
// issue #11423
assertTopScore
(
'
editor.r
'
,
2
,
'
diffEditor.renderSideBySide
'
,
'
editor.overviewRulerlanes
'
,
'
editor.renderControlCharacter
'
,
'
editor.renderWhitespace
'
);
assertTopScore
(
'
editor.R
'
,
1
,
'
diffEditor.renderSideBySide
'
,
'
editor.overviewRulerlanes
'
,
'
editor.renderControlCharacter
'
,
'
editor.renderWhitespace
'
);
assertTopScore
(
'
Editor.r
'
,
0
,
'
diffEditor.renderSideBySide
'
,
'
editor.overviewRulerlanes
'
,
'
editor.renderControlCharacter
'
,
'
editor.renderWhitespace
'
);
//
assertTopScore('editor.R', 1, 'diffEditor.renderSideBySide', 'editor.overviewRulerlanes', 'editor.renderControlCharacter', 'editor.renderWhitespace');
//
assertTopScore('Editor.r', 0, 'diffEditor.renderSideBySide', 'editor.overviewRulerlanes', 'editor.renderControlCharacter', 'editor.renderWhitespace');
assertTopScore
(
'
-mo
'
,
1
,
'
-ms-ime-mode
'
,
'
-moz-columns
'
);
// dupe, issue #14861
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录