Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
45994993
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,发现更多精彩内容 >>
未验证
提交
45994993
编写于
5月 10, 2017
作者:
F
Fredric Silberberg
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Added initial user filtering
上级
b5c01a46
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
178 addition
and
9 deletion
+178
-9
src/Features/Core/Portable/Shared/TestHooks/FeatureAttribute_Names.cs
.../Core/Portable/Shared/TestHooks/FeatureAttribute_Names.cs
+1
-0
src/VisualStudio/Core/Def/Implementation/Experimentation/AnalyzerVsixSuggestedActionCallback.cs
...on/Experimentation/AnalyzerVsixSuggestedActionCallback.cs
+165
-9
src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs
src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs
+9
-0
src/VisualStudio/Core/Def/ServicesVSResources.resx
src/VisualStudio/Core/Def/ServicesVSResources.resx
+3
-0
未找到文件。
src/Features/Core/Portable/Shared/TestHooks/FeatureAttribute_Names.cs
浏览文件 @
45994993
...
...
@@ -4,6 +4,7 @@ namespace Microsoft.CodeAnalysis.Shared.TestHooks
{
internal
partial
class
FeatureAttribute
{
public
const
string
ABTest
=
nameof
(
ABTest
);
public
const
string
AutomaticEndConstructCorrection
=
nameof
(
AutomaticEndConstructCorrection
);
public
const
string
AutomaticPairCompletion
=
nameof
(
AutomaticPairCompletion
);
public
const
string
BraceHighlighting
=
nameof
(
BraceHighlighting
);
...
...
src/VisualStudio/Core/Def/Implementation/Experimentation/AnalyzerVsixSuggestedActionCallback.cs
浏览文件 @
45994993
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using
System
;
using
System.Collections.Generic
;
using
System.ComponentModel.Composition
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis.Editor
;
using
Microsoft.CodeAnalysis.Editor.Implementation.Suggestions
;
using
Microsoft.CodeAnalysis.Editor.Shared.Utilities
;
using
Microsoft.CodeAnalysis.Experiments
;
using
Microsoft.CodeAnalysis.Extensions
;
using
Microsoft.CodeAnalysis.Options
;
using
Microsoft.CodeAnalysis.Shared.TestHooks
;
namespace
Microsoft.VisualStudio.LanguageServices.Implementation.Experimentation
{
[
Export
(
typeof
(
ISuggestedActionCallback
))]
class
AnalyzerVsixSuggestedActionCallback
:
ISuggestedActionCallback
internal
class
AnalyzerVsixSuggestedActionCallback
:
ForegroundThreadAffinitizedObject
,
ISuggestedActionCallback
{
private
const
string
AnalyzerEnabledFlight
=
@"LiveCA/LiveCAcf"
;
private
const
string
AnalyzerVsixHyperlink
=
@"https://aka.ms/livecodeanalysis"
;
private
readonly
VisualStudioWorkspace
_workspace
;
private
readonly
IInfoBarService
_infoBarService
;
private
readonly
IForegroundNotificationService
_foregroundNotificationService
;
private
readonly
IAsynchronousOperationListener
_operationListener
;
private
readonly
object
_scheduleLock
=
new
object
();
private
bool
_checksRunning
=
false
;
[
ImportingConstructor
]
public
AnalyzerVsixSuggestedActionCallback
(
IInfoBarService
infoBarService
,
VisualStudioWorkspace
workspace
)
public
AnalyzerVsixSuggestedActionCallback
(
VisualStudioWorkspace
workspace
,
IForegroundNotificationService
foregroundNotificationService
,
[
ImportMany
]
IEnumerable
<
Lazy
<
IAsynchronousOperationListener
,
FeatureMetadata
>>
asyncListeners
)
{
_workspace
=
workspace
;
_infoBarService
=
infoBarService
;
_foregroundNotificationService
=
foregroundNotificationService
;
_operationListener
=
new
AggregateAsynchronousOperationListener
(
asyncListeners
,
FeatureAttribute
.
ABTest
);
}
public
void
OnSuggestedActionExecuted
(
SuggestedAction
action
)
{
AssertIsForeground
();
lock
(
_scheduleLock
)
{
if
(!
_checksRunning
)
{
_checksRunning
=
true
;
Task
.
Run
((
Action
)
SuggestedActionOccurred
);
}
}
}
private
void
SuggestedActionOccurred
()
{
// We don't need to do this work on the UI thread
AssertIsBackground
();
var
options
=
_workspace
.
Options
;
// If the user has previously clicked don't show again, then we bail out immediately
if
(
options
.
GetOption
(
AnalyzerABTestOptions
.
NeverShowAgain
))
{
// We purposefully do not set _checksRunning back to false. That way, we'll never check again this session
return
;
}
// Filter for valid A/B test candidates. Candidates fill the following critera:
// 1: Are a Dotnet user (as evidenced by the fact that this code is being run)
// 2: Have triggered a lightbulb on 3 separate days
// If the user hasn't met candidacy conditions, then we check them. Otherwise, proceed to info bar check
var
isCandidate
=
options
.
GetOption
(
AnalyzerABTestOptions
.
HasMetCandidacyRequirements
);
if
(!
isCandidate
)
{
// We store in UTC to avoid any timezone offset weirdness
var
lastTriggeredTime
=
DateTime
.
FromBinary
(
options
.
GetOption
(
AnalyzerABTestOptions
.
LastDayUsedSuggestionAction
));
var
currentTime
=
DateTime
.
UtcNow
;
var
span
=
currentTime
-
lastTriggeredTime
;
if
(
span
.
TotalDays
>=
1
)
{
options
=
options
.
WithChangedOption
(
AnalyzerABTestOptions
.
LastDayUsedSuggestionAction
,
currentTime
.
ToBinary
());
var
usageCount
=
options
.
GetOption
(
AnalyzerABTestOptions
.
UsedSuggestedActionCount
);
usageCount
++;
options
=
options
.
WithChangedOption
(
AnalyzerABTestOptions
.
UsedSuggestedActionCount
,
usageCount
);
if
(
usageCount
>=
3
)
{
isCandidate
=
true
;
options
=
options
.
WithChangedOption
(
AnalyzerABTestOptions
.
HasMetCandidacyRequirements
,
true
);
}
_workspace
.
Options
=
options
;
}
}
// If the user still isn't a candidate, then return. Otherwise, we move to checking if the infobar should be shown
if
(!
isCandidate
)
{
lock
(
_scheduleLock
)
{
_checksRunning
=
false
;
}
return
;
}
// Queue the show notification bar to the UI thread. This will set _checksRunning back to true after it has shown the infobar
_foregroundNotificationService
.
RegisterNotification
((
Action
)
ShowInfoBarIfNecessary
,
_operationListener
.
BeginAsyncOperation
(
nameof
(
ShowInfoBarIfNecessary
)));
}
private
void
ShowInfoBarIfNecessary
()
{
// We can only get the experimentation service on the UI thread
AssertIsForeground
();
var
experimentationService
=
_workspace
.
Services
.
GetRequiredService
<
IExperimentationService
>();
if
(
experimentationService
.
IsExperimentEnabled
(
AnalyzerEnabledFlight
))
{
_infoBarService
.
ShowInfoBarInGlobalView
(
ServicesVSResources
.
Analyzer_vsix_try_description
,
new
InfoBarUI
(
title
:
ServicesVSResources
.
Analyzer_vsix_hyperlink
,
kind
:
InfoBarUI
.
UIKind
.
HyperLink
,
action
:
new
Action
(
OpenInstallHyperlink
)));
// If we got true from the experimentation service, then we're in the treatment group, and the experiment is enabled.
// We determine if the infobar has been displayed in the past 24 hours. If it hasn't been displayed, then we do so now.
var
lastDayInfoBarShown
=
DateTime
.
FromBinary
(
_workspace
.
Options
.
GetOption
(
AnalyzerABTestOptions
.
LastDayInfoBarShown
));
var
utcNow
=
DateTime
.
UtcNow
;
var
timeSinceLastShown
=
utcNow
-
lastDayInfoBarShown
;
if
(
timeSinceLastShown
.
TotalDays
>=
1
)
{
_workspace
.
Options
=
_workspace
.
Options
.
WithChangedOption
(
AnalyzerABTestOptions
.
LastDayInfoBarShown
,
utcNow
.
ToBinary
());
var
infoBarService
=
_workspace
.
Services
.
GetRequiredService
<
IInfoBarService
>();
infoBarService
.
ShowInfoBarInGlobalView
(
ServicesVSResources
.
Analyzer_vsix_try_description
,
// Install link
new
InfoBarUI
(
title
:
ServicesVSResources
.
Analyzer_vsix_hyperlink
,
kind
:
InfoBarUI
.
UIKind
.
HyperLink
,
action
:
OpenInstallHyperlink
),
// Don't show the InfoBar again link
new
InfoBarUI
(
title
:
ServicesVSResources
.
Analyzer_vsix_do_not_show_again
,
kind
:
InfoBarUI
.
UIKind
.
Button
,
action
:
DoNotShowAgain
),
// This element isn't shown, it defines a callback that will be run on InfoBar close
new
InfoBarUI
(
title
:
string
.
Empty
,
kind
:
InfoBarUI
.
UIKind
.
Close
,
action
:
ReleaseChecks
));
}
}
else
{
lock
(
_scheduleLock
)
{
_checksRunning
=
false
;
}
}
}
private
void
ReleaseChecks
()
{
lock
(
_scheduleLock
)
{
_checksRunning
=
false
;
}
}
...
...
@@ -41,5 +165,37 @@ private void OpenInstallHyperlink()
{
System
.
Diagnostics
.
Process
.
Start
(
AnalyzerVsixHyperlink
);
}
private
void
DoNotShowAgain
()
{
_workspace
.
Options
=
_workspace
.
Options
.
WithChangedOption
(
AnalyzerABTestOptions
.
NeverShowAgain
,
true
);
}
}
internal
static
class
AnalyzerABTestOptions
{
private
const
string
LocalRegistryPath
=
@"Roslyn\Internal\Analyzers\AB\Vsix\"
;
[
ExportOption
]
public
static
readonly
Option
<
long
>
LastDayUsedSuggestionAction
=
new
Option
<
long
>(
nameof
(
AnalyzerABTestOptions
),
nameof
(
LastDayUsedSuggestionAction
),
defaultValue
:
DateTime
.
MinValue
.
ToBinary
(),
storageLocations
:
new
LocalUserProfileStorageLocation
(
LocalRegistryPath
+
nameof
(
LastDayUsedSuggestionAction
)));
[
ExportOption
]
public
static
readonly
Option
<
uint
>
UsedSuggestedActionCount
=
new
Option
<
uint
>(
nameof
(
AnalyzerABTestOptions
),
nameof
(
UsedSuggestedActionCount
),
defaultValue
:
0
,
storageLocations
:
new
LocalUserProfileStorageLocation
(
LocalRegistryPath
+
nameof
(
UsedSuggestedActionCount
)));
[
ExportOption
]
public
static
readonly
Option
<
bool
>
NeverShowAgain
=
new
Option
<
bool
>(
nameof
(
AnalyzerABTestOptions
),
nameof
(
NeverShowAgain
),
defaultValue
:
false
,
storageLocations
:
new
LocalUserProfileStorageLocation
(
LocalRegistryPath
+
nameof
(
NeverShowAgain
)));
[
ExportOption
]
public
static
readonly
Option
<
bool
>
HasMetCandidacyRequirements
=
new
Option
<
bool
>(
nameof
(
AnalyzerABTestOptions
),
nameof
(
HasMetCandidacyRequirements
),
defaultValue
:
false
,
storageLocations
:
new
LocalUserProfileStorageLocation
(
LocalRegistryPath
+
nameof
(
HasMetCandidacyRequirements
)));
[
ExportOption
]
public
static
readonly
Option
<
long
>
LastDayInfoBarShown
=
new
Option
<
long
>(
nameof
(
AnalyzerABTestOptions
),
nameof
(
LastDayInfoBarShown
),
defaultValue
:
DateTime
.
MinValue
.
ToBinary
(),
storageLocations
:
new
LocalUserProfileStorageLocation
(
LocalRegistryPath
+
nameof
(
LastDayInfoBarShown
)));
}
}
src/VisualStudio/Core/Def/ServicesVSResources.Designer.cs
浏览文件 @
45994993
...
...
@@ -226,6 +226,15 @@ internal class ServicesVSResources {
}
}
/// <summary>
/// Looks up a localized string similar to Do not show again.
/// </summary>
internal
static
string
Analyzer_vsix_do_not_show_again
{
get
{
return
ResourceManager
.
GetString
(
"Analyzer_vsix_do_not_show_again"
,
resourceCulture
);
}
}
/// <summary>
/// Looks up a localized string similar to Install.
/// </summary>
...
...
src/VisualStudio/Core/Def/ServicesVSResources.resx
浏览文件 @
45994993
...
...
@@ -918,4 +918,7 @@ Additional information: {1}</value>
<data
name=
"Analyzer_vsix_try_description"
xml:space=
"preserve"
>
<value>
Try the new analyzer extension!
</value>
</data>
<data
name=
"Analyzer_vsix_do_not_show_again"
xml:space=
"preserve"
>
<value>
Do not show again
</value>
</data>
</root>
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录