Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
afc5e65e
R
roslyn
项目概览
lwm1986
/
roslyn
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
roslyn
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
afc5e65e
编写于
11月 27, 2016
作者:
C
CyrusNajmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Remove blocking-wait from completoin when caret is moved.
上级
8f062669
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
87 addition
and
50 deletion
+87
-50
src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller.Session.cs
...lementation/IntelliSense/Completion/Controller.Session.cs
+1
-1
src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller.Session_FilterModel.cs
...IntelliSense/Completion/Controller.Session_FilterModel.cs
+42
-20
src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_CaretPositionChanged.cs
...ntelliSense/Completion/Controller_CaretPositionChanged.cs
+12
-25
src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_CommitUniqueCompletionListItem.cs
...e/Completion/Controller_CommitUniqueCompletionListItem.cs
+0
-1
src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb
...Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb
+29
-0
src/Features/Core/Portable/Completion/CompletionFilterReason.cs
...atures/Core/Portable/Completion/CompletionFilterReason.cs
+3
-3
未找到文件。
src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller.Session.cs
浏览文件 @
afc5e65e
...
...
@@ -14,7 +14,7 @@ internal partial class Session : Session<Controller, Model, ICompletionPresenter
// When we issue filter tasks, provide them with a (monotonically increasing) id. That
// way, when they run we can bail on computation if they've been superseded by another
// filter task.
// filter task.
private
int
_filterId
;
#
endregion
...
...
src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller.Session_FilterModel.cs
浏览文件 @
afc5e65e
...
...
@@ -98,20 +98,9 @@ internal partial class Session
return
null
;
}
var
filterState
=
model
.
FilterState
;
// If all the filters are on, or all the filters are off then we don't actually
// need to filter.
if
(
filterState
!=
null
)
{
if
(
filterState
.
Values
.
All
(
b
=>
b
)
||
filterState
.
Values
.
All
(
b
=>
!
b
))
{
filterState
=
null
;
}
}
// We want to dismiss the session if the caret ever moved outside our bounds.
// Do this before we check the _filterId. We don't want this work to not happen
// just becaus the user typed more text and added more filter items.
if
(
recheckCaretPosition
&&
Controller
.
IsCaretOutsideAllItemBounds
(
model
,
caretPosition
))
{
return
null
;
...
...
@@ -155,6 +144,7 @@ internal partial class Session
}
}
var
filterItemState
=
ComputeFilterItemState
(
model
);
foreach
(
var
currentItem
in
model
.
TotalItems
)
{
// Check if something new has happened and there's a later on filter operation
...
...
@@ -165,7 +155,7 @@ internal partial class Session
return
model
;
}
if
(
ItemIsFilteredOut
(
currentItem
,
filterState
))
if
(
ItemIsFilteredOut
(
currentItem
,
filter
Item
State
))
{
continue
;
}
...
...
@@ -207,10 +197,28 @@ internal partial class Session
}
return
HandleNormalFiltering
(
model
,
document
,
filterReason
,
textSnapshot
,
model
,
document
,
filterReason
,
caretPosition
,
helper
,
recentItems
,
filterText
,
filterResults
);
}
private
static
ImmutableDictionary
<
CompletionItemFilter
,
bool
>
ComputeFilterItemState
(
Model
model
)
{
var
filterState
=
model
.
FilterState
;
// If all the filters are on, or all the filters are off then we don't actually
// need to filter.
if
(
filterState
!=
null
)
{
if
(
filterState
.
Values
.
All
(
b
=>
b
)
||
filterState
.
Values
.
All
(
b
=>
!
b
))
{
filterState
=
null
;
}
}
return
filterState
;
}
private
Boolean
IsAfterDot
(
Model
model
,
ITextSnapshot
textSnapshot
,
Dictionary
<
TextSpan
,
string
>
textSpanToText
)
{
var
span
=
model
.
OriginalList
.
Span
;
...
...
@@ -226,7 +234,7 @@ private Boolean IsAfterDot(Model model, ITextSnapshot textSnapshot, Dictionary<T
Model
model
,
Document
document
,
CompletionFilterReason
filterReason
,
ITextSnapshot
textSnapshot
,
SnapshotPoint
caretPosition
,
CompletionHelper
helper
,
ImmutableArray
<
string
>
recentItems
,
string
filterText
,
...
...
@@ -255,7 +263,7 @@ private Boolean IsAfterDot(Model model, ITextSnapshot textSnapshot, Dictionary<T
var
bestOrFirstCompletionItem
=
bestCompletionItem
??
filterResults
.
First
().
CompletionItem
;
var
hardSelection
=
IsHardSelection
(
model
,
bestOrFirstCompletionItem
,
textSnapshot
,
helper
,
filterReason
);
model
,
bestOrFirstCompletionItem
,
caretPosition
,
helper
,
filterReason
);
// Determine if we should consider this item 'unique' or not. A unique item
// will be automatically committed if the user hits the 'invoke completion'
...
...
@@ -528,7 +536,7 @@ private static bool IsAllDigits(string filterText)
private
bool
IsHardSelection
(
Model
model
,
CompletionItem
bestFilterMatch
,
ITextSnapshot
textSnapshot
,
SnapshotPoint
caretPosition
,
CompletionHelper
completionHelper
,
CompletionFilterReason
reason
)
{
...
...
@@ -537,6 +545,8 @@ private static bool IsAllDigits(string filterText)
return
false
;
}
var
textSnapshot
=
caretPosition
.
Snapshot
;
// We don't have a builder and we have a best match. Normally this will be hard
// selected, except for a few cases. Specifically, if no filter text has been
// provided, and this is not a preselect match then we will soft select it. This
...
...
@@ -548,8 +558,8 @@ private static bool IsAllDigits(string filterText)
//
// Completion will comes up after = with 'integer' selected (Because of MRU). We do
// not want 'space' to commit this.
var
v
iewSpan
=
model
.
GetViewBufferSpan
(
bestFilterMatch
.
Span
);
var
fullFilterText
=
model
.
GetCurrentTextInSnapshot
(
v
iewSpan
,
textSnapshot
,
endPoint
:
null
);
var
itemV
iewSpan
=
model
.
GetViewBufferSpan
(
bestFilterMatch
.
Span
);
var
fullFilterText
=
model
.
GetCurrentTextInSnapshot
(
itemV
iewSpan
,
textSnapshot
,
endPoint
:
null
);
var
trigger
=
model
.
Trigger
;
var
shouldSoftSelect
=
ShouldSoftSelectItem
(
bestFilterMatch
,
fullFilterText
,
trigger
);
...
...
@@ -565,6 +575,18 @@ private static bool IsAllDigits(string filterText)
return
false
;
}
// Switch to soft selection, if user moved caret to the start of a non-empty filter span.
// This prevents commiting if user types a commit character at this position later, but still has the list if user types filter character
// i.e. blah| -> |blah -> !|blah
// We want the filter span non-empty because we still want completion in the following case:
//
// A a = new |
if
(
caretPosition
==
itemViewSpan
.
TextSpan
.
Start
&&
itemViewSpan
.
TextSpan
.
Length
>
0
)
{
return
false
;
}
// There was either filter text, or this was a preselect match. In either case, we
// can hard select this.
return
true
;
...
...
src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_CaretPositionChanged.cs
浏览文件 @
afc5e65e
...
...
@@ -25,36 +25,23 @@ internal override void OnCaretPositionChanged(object sender, EventArgs args)
// caret isn't within the bounds of the items, then we dismiss completion.
var
caretPoint
=
this
.
GetCaretPointInViewBuffer
();
var
model
=
sessionOpt
.
Computation
.
InitialUnfilteredModel
;
if
(
model
==
null
||
this
.
IsCaretOutsideAllItemBounds
(
model
,
caretPoint
))
{
// Completions hadn't even been computed yet or the caret is out of bounds.
// Just cancel everything we're doing.
this
.
StopModelComputation
();
return
;
}
// TODO(cyrusn): Find a way to allow the user to cancel out of this.
model
=
sessionOpt
.
WaitForModel
();
if
(
model
==
null
)
{
// Completions hadn't even been computed yet. Just cancel everything we're doing
// and move to the Inactive state.
this
.
StopModelComputation
();
return
;
}
if
(
model
.
SelectedItem
!=
null
&&
model
.
IsHardSelection
)
{
// Switch to soft selection, if user moved caret to the start of a non-empty filter span.
// This prevents commiting if user types a commit character at this position later, but still has the list if user types filter character
// i.e. blah| -> |blah -> !|blah
// We want the filter span non-empty because we still want completion in the following case:
// A a = new | -> A a = new (|
var
currentSpan
=
model
.
GetViewBufferSpan
(
model
.
SelectedItem
.
Span
).
TextSpan
;
if
(
caretPoint
==
currentSpan
.
Start
&&
currentSpan
.
Length
>
0
)
{
sessionOpt
.
SetModelIsHardSelection
(
false
);
}
}
// We're currently computing items. We'll need to make sure that the caret point
// hasn't moved outside all of the items. If so, we'd want to dismiss completions.
// Just refilter the list, asking it to make sure that the caret is still within
// bounds.
sessionOpt
.
FilterModel
(
CompletionFilterReason
.
CaretPositionChanged
,
dismissIfEmptyAllowed
:
false
,
recheckCaretPosition
:
true
,
filterState
:
null
);
}
internal
bool
IsCaretOutsideAllItemBounds
(
Model
model
,
SnapshotPoint
caretPoint
)
...
...
src/EditorFeatures/Core/Implementation/IntelliSense/Completion/Controller_CommitUniqueCompletionListItem.cs
浏览文件 @
afc5e65e
...
...
@@ -48,7 +48,6 @@ CommandState ICommandHandler<CommitUniqueCompletionListItemCommandArgs>.GetComma
// with how that convoluted code worked. So I'm not maintaining that behavior here. If
// we do want it through, it would be easy to get again simply by asking the model
// computation to remove all filtering.
if
(
model
.
IsUnique
)
{
// We had a unique item in the list. Commit it and dismiss this session.
...
...
src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb
浏览文件 @
afc5e65e
...
...
@@ -2570,5 +2570,34 @@ class C
Await
state
.
AssertSelectedCompletionItem
(
"ConfigureAwait"
)
End
Using
End
Function
<
WpfFact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
Completion
)
>
Public
Async
Function
MovingCaretToStartSoftSelects
()
As
Task
Using
state
=
TestState
.
CreateCSharpTestState
(
<
Document
>
using
System
;
class
C
{
void
M
()
{
$$
}
}
</
Document
>
)
state
.
SendTypeChars
(
"Conso"
)
Await
state
.
WaitForAsynchronousOperationsAsync
()
Await
state
.
AssertSelectedCompletionItem
(
displayText
:
=
"Console"
,
isHardSelected
:
=
True
)
For
Each
ch
In
"Conso"
state
.
SendLeftKey
()
Next
Await
state
.
AssertSelectedCompletionItem
(
displayText
:
=
"Console"
,
isHardSelected
:
=
False
)
state
.
SendRightKey
()
Await
state
.
AssertSelectedCompletionItem
(
displayText
:
=
"Console"
,
isHardSelected
:
=
True
)
End
Using
End
Function
End
Class
End
Namespace
\ No newline at end of file
src/Features/Core/Portable/Completion/CompletionFilterReason.cs
浏览文件 @
afc5e65e
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace
Microsoft.CodeAnalysis.Completion
{
internal
enum
CompletionFilterReason
...
...
@@ -8,6 +7,7 @@ internal enum CompletionFilterReason
Other
,
TypeChar
,
BackspaceOrDelete
,
ItemFiltersChanged
ItemFiltersChanged
,
CaretPositionChanged
,
}
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录