Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
c517a927
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,发现更多精彩内容 >>
提交
c517a927
编写于
12月 12, 2018
作者:
G
Gen Lu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Revert #31132
上级
553cba01
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
37 addition
and
117 deletion
+37
-117
src/VisualStudio/Core/Def/Implementation/Experimentation/KeybindingResetDetector.cs
...Implementation/Experimentation/KeybindingResetDetector.cs
+36
-116
src/VisualStudio/Core/Def/Implementation/Experimentation/ReSharperStatus.cs
...ore/Def/Implementation/Experimentation/ReSharperStatus.cs
+1
-1
未找到文件。
src/VisualStudio/Core/Def/Implementation/Experimentation/KeybindingResetDetector.cs
浏览文件 @
c517a927
...
...
@@ -4,8 +4,6 @@
using
System.ComponentModel.Composition
;
using
System.Diagnostics
;
using
System.Runtime.InteropServices
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Editor.Shared.Utilities
;
using
Microsoft.CodeAnalysis.ErrorReporting
;
using
Microsoft.CodeAnalysis.Experimentation
;
...
...
@@ -68,19 +66,13 @@ internal sealed class KeybindingResetDetector : ForegroundThreadAffinitizedObjec
private
OleComponent
_oleComponent
;
private
uint
_priorityCommandTargetCookie
=
VSConstants
.
VSCOOKIE_NIL
;
private
CancellationTokenSource
_cancellationTokenSource
=
new
CancellationTokenSource
();
/// <summary>
/// If false, ReSharper is either not installed, or has been disabled in the extension manager.
/// If true, the ReSharper extension is enabled. ReSharper's internal status could be either suspended or enabled.
/// </summary>
private
bool
_resharperExtensionInstalledAndEnabled
=
false
;
private
bool
_infoBarOpen
=
false
;
private
bool
_isFirstRun
=
true
;
private
bool
_resharperExtensionEnabled
=
false
;
/// <summary>
/// Chain all update tasks so that task runs serially
/// </summary>
private
Task
_lastTask
=
Task
.
CompletedTask
;
private
bool
_infoBarOpen
=
false
;
[
ImportingConstructor
]
[
Obsolete
(
MefConstruction
.
ImportingConstructorMessage
,
error
:
true
)]
...
...
@@ -121,9 +113,9 @@ private void InitializeCore()
return
;
}
_resharperExtension
InstalledAnd
Enabled
=
extensionEnabled
!=
0
;
_resharperExtensionEnabled
=
extensionEnabled
!=
0
;
if
(
_resharperExtension
InstalledAnd
Enabled
)
if
(
_resharperExtensionEnabled
)
{
// We need to monitor for suspend/resume commands, so create and install the command target and the modal callback.
var
priorityCommandTargetRegistrar
=
_serviceProvider
.
GetService
<
IVsRegisterPriorityCommandTarget
,
SVsRegisterPriorityCommandTarget
>();
...
...
@@ -143,46 +135,16 @@ private void InitializeCore()
_oleComponent
.
ModalStateChanged
+=
OnModalStateChanged
;
}
// run it from background and fire and forget
StartUpdateStateMachine
();
UpdateStateMachine
();
}
private
void
Start
UpdateStateMachine
()
private
void
UpdateStateMachine
()
{
// cancel previous state machine update request
_cancellationTokenSource
.
Cancel
();
_cancellationTokenSource
=
new
CancellationTokenSource
();
var
cancellationToken
=
_cancellationTokenSource
.
Token
;
// make sure all state machine change work is serialized so that cancellation
// doesn't mess the state up.
_lastTask
=
_lastTask
.
ContinueWith
(
async
_
=>
{
await
UpdateStateMachineWorkerAsync
(
cancellationToken
).
ConfigureAwait
(
false
);
},
cancellationToken
,
TaskContinuationOptions
.
LazyCancellation
,
TaskScheduler
.
Default
).
Unwrap
();
}
AssertIsForeground
();
private
async
Task
UpdateStateMachineWorkerAsync
(
CancellationToken
cancellationToken
)
{
var
currentStatus
=
IsReSharperEnabled
();
var
options
=
_workspace
.
Options
;
var
lastStatus
=
options
.
GetOption
(
KeybindingResetOptions
.
ReSharperStatus
);
ReSharperStatus
currentStatus
;
try
{
currentStatus
=
await
IsReSharperRunningAsync
(
lastStatus
,
cancellationToken
)
.
ConfigureAwait
(
false
);
}
catch
(
OperationCanceledException
)
{
return
;
}
if
(!
_isFirstRun
&&
currentStatus
==
lastStatus
)
{
return
;
}
ReSharperStatus
lastStatus
=
options
.
GetOption
(
KeybindingResetOptions
.
ReSharperStatus
);
options
=
options
.
WithChangedOption
(
KeybindingResetOptions
.
ReSharperStatus
,
currentStatus
);
...
...
@@ -199,12 +161,6 @@ private async Task UpdateStateMachineWorkerAsync(CancellationToken cancellationT
// the extension, then reenables the extension. We will show the gold bar after the switch
// if there is still a pending show.
// If ReSharper was suspended and the user closed and reopened VS, we want to reset the gold bar
else
if
(
_isFirstRun
)
{
options
=
options
.
WithChangedOption
(
KeybindingResetOptions
.
NeedsReset
,
true
);
}
break
;
case
ReSharperStatus
.
Enabled
:
if
(
currentStatus
!=
ReSharperStatus
.
Enabled
)
...
...
@@ -218,16 +174,17 @@ private async Task UpdateStateMachineWorkerAsync(CancellationToken cancellationT
}
_workspace
.
Options
=
options
;
if
(
options
.
GetOption
(
KeybindingResetOptions
.
NeedsReset
))
{
ShowGoldBar
();
}
_isFirstRun
=
false
;
}
private
void
ShowGoldBar
()
{
AssertIsForeground
();
// If the gold bar is already open, do not show
if
(
_infoBarOpen
)
{
...
...
@@ -239,7 +196,7 @@ private void ShowGoldBar()
Debug
.
Assert
(
_experimentationService
.
IsExperimentEnabled
(
InternalFlightName
)
||
_experimentationService
.
IsExperimentEnabled
(
ExternalFlightName
));
var
message
=
ServicesVSResources
.
We_notice_you_suspended_0_Reset_keymappings_to_continue_to_navigate_and_refactor
;
string
message
=
ServicesVSResources
.
We_notice_you_suspended_0_Reset_keymappings_to_continue_to_navigate_and_refactor
;
KeybindingsResetLogger
.
Log
(
"InfoBarShown"
);
var
infoBarService
=
_workspace
.
Services
.
GetRequiredService
<
IInfoBarService
>();
infoBarService
.
ShowInfoBarInGlobalView
(
...
...
@@ -260,69 +217,37 @@ private void ShowGoldBar()
action
:
InfoBarClose
));
}
/// <summary>
/// Returns true if ReSharper is installed, enabled, and not suspended.
/// </summary>
private
async
Task
<
ReSharperStatus
>
IsReSharperRunningAsync
(
ReSharperStatus
lastStatus
,
CancellationToken
cancellationToken
)
private
ReSharperStatus
IsReSharperEnabled
()
{
AssertIsForeground
();
// Quick exit if resharper is either uninstalled or not enabled
if
(!
_resharperExtension
InstalledAnd
Enabled
)
if
(!
_resharperExtensionEnabled
)
{
return
ReSharperStatus
.
NotInstalledOrDisabled
;
}
await
EnsureOleCommandTargetAsync
().
ConfigureAwait
(
false
);
if
(
_oleCommandTarget
==
null
)
{
_oleCommandTarget
=
_serviceProvider
.
GetService
<
IOleCommandTarget
,
SUIHostCommandDispatcher
>();
}
var
cmds
=
new
OLECMD
[
1
];
cmds
[
0
].
cmdID
=
Resume
Id
;
cmds
[
0
].
cmdID
=
Suspend
Id
;
cmds
[
0
].
cmdf
=
0
;
for
(
var
count
=
0
;
count
<
10
;
count
++)
{
cancellationToken
.
ThrowIfCancellationRequested
();
var
hr
=
await
QueryStatusOnUIThreadAsync
().
ConfigureAwait
(
false
);
var
hr
=
_oleCommandTarget
.
QueryStatus
(
ReSharperCommandGroup
,
(
uint
)
cmds
.
Length
,
cmds
,
IntPtr
.
Zero
);
if
(
ErrorHandler
.
Failed
(
hr
))
{
// In the case of an error when attempting to get the status, pretend that ReSharper isn't enabled. We also
// shut down monitoring so we don't keep hitting this.
FatalError
.
ReportWithoutCrash
(
Marshal
.
GetExceptionForHR
(
hr
));
await
ShutdownAsync
().
ConfigureAwait
(
false
);
Shutdown
();
return
ReSharperStatus
.
NotInstalledOrDisabled
;
}
// When ReSharper is suspended, the ReSharper_Resume command has the Enabled | Supported flags.
if
(((
OLECMDF
)
cmds
[
0
].
cmdf
).
HasFlag
(
OLECMDF
.
OLECMDF_ENABLED
))
{
return
ReSharperStatus
.
Suspended
;
}
//otherwise sleep for a bit and check again
await
Task
.
Delay
(
TimeSpan
.
FromSeconds
(
2
),
cancellationToken
).
ConfigureAwait
(
false
);
}
// If resume button doesn't become active within a reasonable amount of time, assume ReSharper is Enabled
return
ReSharperStatus
.
Enabled
;
async
Task
<
int
>
QueryStatusOnUIThreadAsync
()
{
await
ThreadingContext
.
JoinableTaskFactory
.
SwitchToMainThreadAsync
(
cancellationToken
);
return
_oleCommandTarget
.
QueryStatus
(
ReSharperCommandGroup
,
(
uint
)
cmds
.
Length
,
cmds
,
IntPtr
.
Zero
);
}
async
Task
EnsureOleCommandTargetAsync
()
{
if
(
_oleCommandTarget
!=
null
)
{
return
;
}
await
ThreadingContext
.
JoinableTaskFactory
.
SwitchToMainThreadAsync
(
cancellationToken
);
_oleCommandTarget
=
_serviceProvider
.
GetService
<
IOleCommandTarget
,
SUIHostCommandDispatcher
>();
}
// When ReSharper is enabled, the ReSharper_Suspend command has the Enabled | Supported flags. When disabled, it has Invisible | Supported.
return
((
OLECMDF
)
cmds
[
0
].
cmdf
).
HasFlag
(
OLECMDF
.
OLECMDF_ENABLED
)
?
ReSharperStatus
.
Enabled
:
ReSharperStatus
.
Suspended
;
}
private
void
RestoreVsKeybindings
()
...
...
@@ -370,7 +295,7 @@ private void NeverShowAgain()
KeybindingsResetLogger
.
Log
(
"NeverShowAgain"
);
// The only external references to this object are as callbacks, which are removed by the Shutdown method.
ThreadingContext
.
JoinableTaskFactory
.
Run
(
ShutdownAsync
);
Shutdown
(
);
}
private
void
InfoBarClose
()
...
...
@@ -394,7 +319,7 @@ public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pv
if
(
pguidCmdGroup
==
ReSharperCommandGroup
&&
nCmdID
>=
ResumeId
&&
nCmdID
<=
ToggleSuspendId
)
{
// Don't delay command processing to update resharper status
StartUpdateStateMachine
(
);
Task
.
Run
(()
=>
InvokeBelowInputPriorityAsync
(
UpdateStateMachine
)
);
}
// No matter the command, we never actually want to respond to it, so always return not supported. We're just monitoring.
...
...
@@ -410,24 +335,19 @@ private void OnModalStateChanged(object sender, StateChangedEventArgs args)
// extra QueryStatus.
if
(
args
.
TransitionType
==
StateTransitionType
.
Exit
)
{
StartUpdateStateMachine
(
);
InvokeBelowInputPriorityAsync
(
UpdateStateMachine
);
}
}
p
rivate
async
Task
ShutdownAsync
()
p
ublic
void
Shutdown
()
{
// we are shutting down, cancel any pending work.
_cancellationTokenSource
.
Cancel
();
await
ThreadingContext
.
JoinableTaskFactory
.
SwitchToMainThreadAsync
();
AssertIsForeground
();
if
(
_priorityCommandTargetCookie
!=
VSConstants
.
VSCOOKIE_NIL
)
{
var
priorityCommandTargetRegistrar
=
_serviceProvider
.
GetService
<
IVsRegisterPriorityCommandTarget
,
SVsRegisterPriorityCommandTarget
>();
var
cookie
=
_priorityCommandTargetCookie
;
_priorityCommandTargetCookie
=
VSConstants
.
VSCOOKIE_NIL
;
var
hr
=
priorityCommandTargetRegistrar
.
UnregisterPriorityCommandTarget
(
cookie
);
if
(
ErrorHandler
.
Failed
(
hr
))
{
FatalError
.
ReportWithoutCrash
(
Marshal
.
GetExceptionForHR
(
hr
));
...
...
src/VisualStudio/Core/Def/Implementation/Experimentation/ReSharperStatus.cs
浏览文件 @
c517a927
...
...
@@ -13,7 +13,7 @@ internal enum ReSharperStatus
/// </summary>
Suspended
,
/// <summary>
/// ReSharper is
installed and enabled
.
/// ReSharper is
running
.
/// </summary>
Enabled
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录