Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
5723a2d9
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,体验更适合开发者的 AI 搜索 >>
提交
5723a2d9
编写于
4月 01, 2016
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
simplify completion model, prep work for #3153
上级
2cbef4e3
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
77 addition
and
139 deletion
+77
-139
src/vs/editor/contrib/suggest/browser/completionModel.ts
src/vs/editor/contrib/suggest/browser/completionModel.ts
+52
-94
src/vs/editor/contrib/suggest/browser/suggestModel.ts
src/vs/editor/contrib/suggest/browser/suggestModel.ts
+2
-2
src/vs/editor/contrib/suggest/common/suggest.ts
src/vs/editor/contrib/suggest/common/suggest.ts
+9
-25
src/vs/workbench/api/node/extHostApiCommands.ts
src/vs/workbench/api/node/extHostApiCommands.ts
+6
-8
src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts
...s/workbench/test/node/api/extHostLanguageFeatures.test.ts
+8
-10
未找到文件。
src/vs/editor/contrib/suggest/browser/completionModel.ts
浏览文件 @
5723a2d9
...
...
@@ -14,137 +14,95 @@ import {ISuggestResult, ISuggestSupport, ISuggestion, ISuggestionFilter} from 'v
import
{
DefaultFilter
,
IMatch
}
from
'
vs/editor/common/modes/modesFilters
'
;
import
{
ISuggestResult2
}
from
'
../common/suggest
'
;
function
completionItemCompare
(
item
:
CompletionItem
,
otherItem
:
CompletionItem
):
number
{
const
suggestion
=
item
.
suggestion
;
const
otherSuggestion
=
otherItem
.
suggestion
;
if
(
typeof
suggestion
.
sortText
===
'
string
'
&&
typeof
otherSuggestion
.
sortText
===
'
string
'
)
{
const
one
=
suggestion
.
sortText
.
toLowerCase
();
const
other
=
otherSuggestion
.
sortText
.
toLowerCase
();
if
(
one
<
other
)
{
return
-
1
;
}
else
if
(
one
>
other
)
{
return
1
;
}
}
return
suggestion
.
label
.
toLowerCase
()
<
otherSuggestion
.
label
.
toLowerCase
()
?
-
1
:
1
;
}
export
class
CompletionItem
{
suggestion
:
ISuggestion
;
highlights
:
IMatch
[];
support
:
ISuggestSupport
;
container
:
ISuggestResult
;
constructor
(
public
group
:
CompletionGroup
,
suggestion
:
ISuggestion
,
container
:
ISuggestResult2
)
{
this
.
support
=
container
.
support
;
private
_filter
:
ISuggestionFilter
;
private
_support
:
ISuggestSupport
;
constructor
(
suggestion
:
ISuggestion
,
container
:
ISuggestResult2
)
{
this
.
_support
=
container
.
support
;
this
.
suggestion
=
suggestion
;
this
.
container
=
container
;
this
.
_filter
=
container
.
support
&&
container
.
support
.
getFilter
()
||
DefaultFilter
;
}
resolveDetails
(
resource
:
URI
,
position
:
IPosition
):
TPromise
<
ISuggestion
>
{
if
(
!
this
.
support
||
typeof
this
.
support
.
getSuggestionDetails
!==
'
function
'
)
{
if
(
!
this
.
_support
||
typeof
this
.
_
support
.
getSuggestionDetails
!==
'
function
'
)
{
return
TPromise
.
as
(
this
.
suggestion
);
}
return
this
.
support
.
getSuggestionDetails
(
resource
,
position
,
this
.
suggestion
);
return
this
.
_
support
.
getSuggestionDetails
(
resource
,
position
,
this
.
suggestion
);
}
updateDetails
(
value
:
ISuggestion
):
void
{
this
.
suggestion
=
assign
(
this
.
suggestion
,
value
);
}
}
export
class
CompletionGroup
{
private
_items
:
CompletionItem
[];
private
cache
:
CompletionItem
[];
private
cacheCurrentWord
:
string
;
filter
:
ISuggestionFilter
;
constructor
(
public
model
:
CompletionModel
,
raw
:
ISuggestResult2
[])
{
this
.
_items
=
raw
.
reduce
<
CompletionItem
[]
>
((
items
,
result
)
=>
{
return
items
.
concat
(
result
.
suggestions
.
map
(
suggestion
=>
new
CompletionItem
(
this
,
suggestion
,
result
))
);
},
[]).
sort
(
completionItemCompare
);
this
.
filter
=
DefaultFilter
;
if
(
this
.
_items
.
length
>
0
)
{
const
[
first
]
=
this
.
_items
;
if
(
first
.
support
)
{
this
.
filter
=
first
.
support
.
getFilter
&&
first
.
support
.
getFilter
()
||
this
.
filter
;
}
}
updateHighlights
(
word
:
string
):
boolean
{
this
.
highlights
=
this
.
_filter
(
word
,
this
.
suggestion
);
return
!
isFalsyOrEmpty
(
this
.
highlights
);
}
getItems
(
currentWord
:
string
):
CompletionItem
[]
{
if
(
currentWord
===
this
.
cacheCurrentWord
)
{
return
this
.
cache
;
}
static
compare
(
item
:
CompletionItem
,
otherItem
:
CompletionItem
):
number
{
const
suggestion
=
item
.
suggestion
;
const
otherSuggestion
=
otherItem
.
suggestion
;
let
set
:
CompletionItem
[];
if
(
typeof
suggestion
.
sortText
===
'
string
'
&&
typeof
otherSuggestion
.
sortText
===
'
string
'
)
{
const
one
=
suggestion
.
sortText
.
toLowerCase
();
const
other
=
otherSuggestion
.
sortText
.
toLowerCase
();
// try to narrow down when possible, instead of always filtering everything
if
(
this
.
cacheCurrentWord
&&
currentWord
.
substr
(
0
,
this
.
cacheCurrentWord
.
length
)
===
this
.
cacheCurrentWord
)
{
set
=
this
.
cache
;
}
else
{
set
=
this
.
_items
;
}
const
highlights
=
set
.
map
(
item
=>
this
.
filter
(
currentWord
,
item
.
suggestion
));
const
count
=
highlights
.
filter
(
h
=>
!
isFalsyOrEmpty
(
h
)).
length
;
if
(
count
===
0
)
{
return
[];
if
(
one
<
other
)
{
return
-
1
;
}
else
if
(
one
>
other
)
{
return
1
;
}
}
this
.
cacheCurrentWord
=
currentWord
;
this
.
cache
=
set
.
map
((
item
,
index
)
=>
assign
(
item
,
{
highlights
:
highlights
[
index
]
}))
.
filter
(
item
=>
!
isFalsyOrEmpty
(
item
.
highlights
));
return
this
.
cache
;
}
invalidateCache
():
void
{
this
.
cacheCurrentWord
=
null
;
return
suggestion
.
label
.
toLowerCase
()
<
otherSuggestion
.
label
.
toLowerCase
()
?
-
1
:
1
;
}
}
export
class
CompletionModel
{
private
groups
:
CompletionGroup
[]
;
private
cache
:
CompletionItem
[];
private
cacheCurrentWord
:
string
;
private
_currentWord
:
string
;
private
_items
:
CompletionItem
[]
=
[];
private
_filteredItems
:
CompletionItem
[]
=
undefined
;
constructor
(
public
raw
:
ISuggestResult2
[][],
public
currentWord
:
string
)
{
constructor
(
public
raw
:
ISuggestResult2
[],
currentWord
:
string
)
{
this
.
_currentWord
=
currentWord
;
for
(
let
container
of
raw
)
{
for
(
let
suggestion
of
container
.
suggestions
)
{
this
.
_items
.
push
(
new
CompletionItem
(
suggestion
,
container
));
}
}
this
.
_items
.
sort
(
CompletionItem
.
compare
);
}
this
.
groups
=
raw
.
filter
(
s
=>
!!
s
)
.
map
(
suggestResults
=>
new
CompletionGroup
(
this
,
suggestResults
));
get
currentWord
():
string
{
return
this
.
_currentWord
;
}
get
items
():
CompletionItem
[]
{
if
(
this
.
cacheCurrentWord
===
this
.
currentWord
)
{
return
this
.
cache
;
set
currentWord
(
value
:
string
)
{
if
(
this
.
_currentWord
!==
value
)
{
this
.
_filteredItems
=
undefined
;
this
.
_currentWord
=
value
;
}
}
const
result
=
this
.
groups
.
reduce
((
r
,
groups
)
=>
r
.
concat
(
groups
.
getItems
(
this
.
currentWord
)),
[]);
// let's only cache stuff that actually has results
if
(
result
.
length
>
0
)
{
this
.
cache
=
result
;
this
.
cacheCurrentWord
=
this
.
currentWord
;
get
items
():
CompletionItem
[]
{
if
(
!
this
.
_filteredItems
)
{
this
.
_filteredItems
=
[];
for
(
let
item
of
this
.
_items
)
{
if
(
item
.
updateHighlights
(
this
.
currentWord
))
{
this
.
_filteredItems
.
push
(
item
);
}
}
}
return
result
;
return
this
.
_filteredItems
;
}
}
\ No newline at end of file
src/vs/editor/contrib/suggest/browser/suggestModel.ts
浏览文件 @
5723a2d9
...
...
@@ -171,7 +171,7 @@ export class SuggestModel implements IDisposable {
private
requestPromise
:
TPromise
<
void
>
;
private
context
:
Context
;
private
raw
:
ISuggestResult2
[]
[]
;
private
raw
:
ISuggestResult2
[];
private
completionModel
:
CompletionModel
;
private
incomplete
:
boolean
;
...
...
@@ -319,7 +319,7 @@ export class SuggestModel implements IDisposable {
}
this
.
raw
=
all
;
this
.
incomplete
=
all
.
reduce
((
r
,
s
)
=>
r
||
s
.
reduce
((
r
,
s
)
=>
r
||
s
.
incomplete
,
false
),
fals
e
);
this
.
incomplete
=
all
.
some
(
result
=>
result
.
incomplet
e
);
this
.
onNewContext
(
new
Context
(
this
.
editor
,
auto
));
}).
then
(
null
,
onUnexpectedError
);
...
...
src/vs/editor/contrib/suggest/common/suggest.ts
浏览文件 @
5723a2d9
...
...
@@ -5,6 +5,7 @@
'
use strict
'
;
import
{
sequence
}
from
'
vs/base/common/async
'
;
import
{
isFalsyOrEmpty
}
from
'
vs/base/common/arrays
'
;
import
{
illegalArgument
,
onUnexpectedError
}
from
'
vs/base/common/errors
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
import
{
IModel
,
IPosition
}
from
'
vs/editor/common/editorCommon
'
;
...
...
@@ -23,37 +24,34 @@ export interface ISuggestResult2 extends ISuggestResult {
support
?:
ISuggestSupport
;
}
export
function
suggest
(
model
:
IModel
,
position
:
IPosition
,
triggerCharacter
:
string
,
groups
?:
ISuggestSupport
[][]):
TPromise
<
ISuggestResult2
[]
[]
>
{
export
function
suggest
(
model
:
IModel
,
position
:
IPosition
,
triggerCharacter
:
string
,
groups
?:
ISuggestSupport
[][]):
TPromise
<
ISuggestResult2
[]
>
{
if
(
!
groups
)
{
groups
=
SuggestRegistry
.
orderedGroups
(
model
);
}
const
resource
=
model
.
getAssociatedResource
();
const
suggestions
:
ISuggestResult
[]
[]
=
[];
const
result
:
ISuggestResult2
[]
=
[];
const
factory
=
groups
.
map
((
supports
,
index
)
=>
{
return
()
=>
{
// stop as soon as a group produced a result
if
(
suggestions
.
length
>
0
)
{
if
(
result
.
length
>
0
)
{
return
;
}
// for each support in the group ask for suggestions
const
promises
=
supports
.
map
(
support
=>
{
return
TPromise
.
join
(
supports
.
map
(
support
=>
{
return
support
.
suggest
(
resource
,
position
,
triggerCharacter
).
then
(
values
=>
{
if
(
!
values
)
{
return
;
}
const
result
:
ISuggestResult2
[]
=
[];
for
(
let
suggestResult
of
values
)
{
if
(
!
suggestResult
||
!
Array
.
isArray
(
suggestResult
.
suggestions
)
||
suggestResult
.
suggestions
.
length
===
0
)
{
if
(
!
suggestResult
||
isFalsyOrEmpty
(
suggestResult
.
suggestions
))
{
continue
;
}
...
...
@@ -65,30 +63,16 @@ export function suggest(model: IModel, position: IPosition, triggerCharacter: st
});
}
return
result
;
},
onUnexpectedError
);
});
return
TPromise
.
join
(
promises
).
then
(
values
=>
{
for
(
let
value
of
values
)
{
if
(
Array
.
isArray
(
value
)
&&
value
.
length
>
0
)
{
suggestions
.
push
(
value
);
}
}
});
}));
};
});
return
sequence
(
factory
).
then
(()
=>
{
// add snippets to the first group
const
snippets
=
SnippetsRegistry
.
getSnippets
(
model
,
position
);
if
(
suggestions
.
length
===
0
)
{
suggestions
.
push
([
snippets
]);
}
else
{
suggestions
[
0
].
push
(
snippets
);
}
return
suggestions
;
result
.
push
(
snippets
);
return
result
;
});
}
...
...
src/vs/workbench/api/node/extHostApiCommands.ts
浏览文件 @
5723a2d9
...
...
@@ -273,17 +273,15 @@ class ExtHostApiCommands {
position
:
position
&&
typeConverters
.
fromPosition
(
position
),
triggerCharacter
};
return
this
.
_commands
.
executeCommand
<
modes
.
ISuggestResult
[]
[]
>
(
'
_executeCompletionItemProvider
'
,
args
).
then
(
value
=>
{
return
this
.
_commands
.
executeCommand
<
modes
.
ISuggestResult
[]
>
(
'
_executeCompletionItemProvider
'
,
args
).
then
(
value
=>
{
if
(
value
)
{
let
items
:
types
.
CompletionItem
[]
=
[];
let
incomplete
:
boolean
;
for
(
let
group
of
value
)
{
for
(
let
suggestions
of
group
)
{
incomplete
=
suggestions
.
incomplete
||
incomplete
;
for
(
let
suggestion
of
suggestions
.
suggestions
)
{
const
item
=
typeConverters
.
Suggest
.
to
(
suggestions
,
position
,
suggestion
);
items
.
push
(
item
);
}
for
(
let
suggestions
of
value
)
{
incomplete
=
suggestions
.
incomplete
||
incomplete
;
for
(
let
suggestion
of
suggestions
.
suggestions
)
{
const
item
=
typeConverters
.
Suggest
.
to
(
suggestions
,
position
,
suggestion
);
items
.
push
(
item
);
}
}
return
new
types
.
CompletionList
(
<
any
>
items
,
incomplete
);
...
...
src/vs/workbench/test/node/api/extHostLanguageFeatures.test.ts
浏览文件 @
5723a2d9
...
...
@@ -825,8 +825,8 @@ suite('ExtHostLanguageFeatures', function() {
threadService
.
sync
().
then
(()
=>
{
suggest
(
model
,
{
lineNumber
:
1
,
column
:
1
},
'
,
'
).
then
(
value
=>
{
assert
.
equal
(
value
.
length
,
1
);
let
[
[
first
]
]
=
value
;
assert
.
ok
(
value
.
length
>=
1
);
// check for min because snippets and others contribute
let
[
first
]
=
value
;
assert
.
equal
(
first
.
suggestions
.
length
,
1
)
assert
.
equal
(
first
.
suggestions
[
0
].
codeSnippet
,
'
testing2
'
)
done
();
...
...
@@ -850,8 +850,8 @@ suite('ExtHostLanguageFeatures', function() {
threadService
.
sync
().
then
(()
=>
{
suggest
(
model
,
{
lineNumber
:
1
,
column
:
1
},
'
,
'
).
then
(
value
=>
{
assert
.
equal
(
value
.
length
,
1
);
let
[
[
first
]
]
=
value
;
assert
.
ok
(
value
.
length
>=
1
);
let
[
first
]
=
value
;
assert
.
equal
(
first
.
suggestions
.
length
,
1
)
assert
.
equal
(
first
.
suggestions
[
0
].
codeSnippet
,
'
weak-selector
'
)
done
();
...
...
@@ -876,8 +876,8 @@ suite('ExtHostLanguageFeatures', function() {
threadService
.
sync
().
then
(()
=>
{
suggest
(
model
,
{
lineNumber
:
1
,
column
:
1
},
'
,
'
).
then
(
value
=>
{
assert
.
equal
(
value
.
length
,
2
);
let
[
[
first
],
[
second
]
]
=
value
;
assert
.
ok
(
value
.
length
>=
2
);
let
[
first
,
second
]
=
value
;
assert
.
equal
(
first
.
suggestions
.
length
,
1
)
assert
.
equal
(
first
.
suggestions
[
0
].
codeSnippet
,
'
strong-2
'
)
// last wins
assert
.
equal
(
second
.
suggestions
[
0
].
codeSnippet
,
'
strong-1
'
)
...
...
@@ -905,8 +905,7 @@ suite('ExtHostLanguageFeatures', function() {
threadService
.
sync
().
then
(()
=>
{
suggest
(
model
,
{
lineNumber
:
1
,
column
:
1
},
'
,
'
).
then
(
value
=>
{
assert
.
equal
(
value
.
length
,
1
);
assert
.
equal
(
value
[
0
][
0
].
incomplete
,
undefined
);
assert
.
equal
(
value
[
0
].
incomplete
,
undefined
);
done
();
});
});
...
...
@@ -923,8 +922,7 @@ suite('ExtHostLanguageFeatures', function() {
return
threadService
.
sync
().
then
(()
=>
{
suggest
(
model
,
{
lineNumber
:
1
,
column
:
1
},
'
,
'
).
then
(
value
=>
{
assert
.
equal
(
value
.
length
,
1
);
assert
.
equal
(
value
[
0
][
0
].
incomplete
,
true
);
assert
.
equal
(
value
[
0
].
incomplete
,
true
);
});
});
});
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录