Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
a4159d46
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,发现更多精彩内容 >>
提交
a4159d46
编写于
12月 03, 2019
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Break out common code for 'populate switch'
上级
22e24f64
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
125 addition
and
70 deletion
+125
-70
src/EditorFeatures/CSharpTest/PopulateSwitch/PopulateSwitchStatementTests.cs
...CSharpTest/PopulateSwitch/PopulateSwitchStatementTests.cs
+2
-2
src/EditorFeatures/CSharpTest/PopulateSwitch/PopulateSwitchStatementTests_FixAllTests.cs
...opulateSwitch/PopulateSwitchStatementTests_FixAllTests.cs
+1
-1
src/EditorFeatures/VisualBasicTest/PopulateSwitch/PopulateSwitchStatementTests.vb
...lBasicTest/PopulateSwitch/PopulateSwitchStatementTests.vb
+2
-2
src/EditorFeatures/VisualBasicTest/PopulateSwitch/PopulateSwitchStatementTests_FixAllTests.vb
...opulateSwitch/PopulateSwitchStatementTests_FixAllTests.vb
+1
-1
src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs
...s/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs
+3
-1
src/Features/Core/Portable/PopulateSwitch/PopulateSwitchCodeFixProvider.cs
.../Portable/PopulateSwitch/PopulateSwitchCodeFixProvider.cs
+81
-52
src/Features/Core/Portable/PopulateSwitch/PopulateSwitchDiagnosticAnalyzer.cs
...rtable/PopulateSwitch/PopulateSwitchDiagnosticAnalyzer.cs
+35
-11
未找到文件。
src/EditorFeatures/CSharpTest/PopulateSwitch/PopulateSwitchTests.cs
→
src/EditorFeatures/CSharpTest/PopulateSwitch/PopulateSwitch
Statement
Tests.cs
浏览文件 @
a4159d46
...
...
@@ -10,10 +10,10 @@
namespace
Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.PopulateSwitch
{
public
partial
class
PopulateSwitchTests
:
AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
public
partial
class
PopulateSwitch
Statement
Tests
:
AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal
override
(
DiagnosticAnalyzer
,
CodeFixProvider
)
CreateDiagnosticProviderAndFixer
(
Workspace
workspace
)
=>
(
new
PopulateSwitch
DiagnosticAnalyzer
(),
new
PopulateSwitch
CodeFixProvider
());
=>
(
new
PopulateSwitch
StatementDiagnosticAnalyzer
(),
new
PopulateSwitchStatement
CodeFixProvider
());
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsPopulateSwitch
)]
public
async
Task
OnlyOnFirstToken
()
...
...
src/EditorFeatures/CSharpTest/PopulateSwitch/PopulateSwitchTests_FixAllTests.cs
→
src/EditorFeatures/CSharpTest/PopulateSwitch/PopulateSwitch
Statement
Tests_FixAllTests.cs
浏览文件 @
a4159d46
...
...
@@ -6,7 +6,7 @@
namespace
Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.PopulateSwitch
{
public
partial
class
PopulateSwitchTests
:
AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
public
partial
class
PopulateSwitch
Statement
Tests
:
AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
[
Fact
]
[
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsPopulateSwitch
)]
...
...
src/EditorFeatures/VisualBasicTest/PopulateSwitch/PopulateSwitchTests.vb
→
src/EditorFeatures/VisualBasicTest/PopulateSwitch/PopulateSwitch
Statement
Tests.vb
浏览文件 @
a4159d46
...
...
@@ -5,11 +5,11 @@ Imports Microsoft.CodeAnalysis.Diagnostics
Imports
Microsoft.CodeAnalysis.PopulateSwitch
Namespace
Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.PopulateSwitch
Partial
Public
Class
PopulateSwitchTests
Partial
Public
Class
PopulateSwitch
Statement
Tests
Inherits
AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
Friend
Overrides
Function
CreateDiagnosticProviderAndFixer
(
workspace
As
Workspace
)
As
(
DiagnosticAnalyzer
,
CodeFixProvider
)
Return
(
New
PopulateSwitch
DiagnosticAnalyzer
(),
New
PopulateSwitch
CodeFixProvider
())
Return
(
New
PopulateSwitch
StatementDiagnosticAnalyzer
(),
New
PopulateSwitchStatement
CodeFixProvider
())
End
Function
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsPopulateSwitch
)
>
...
...
src/EditorFeatures/VisualBasicTest/PopulateSwitch/PopulateSwitchTests_FixAllTests.vb
→
src/EditorFeatures/VisualBasicTest/PopulateSwitch/PopulateSwitch
Statement
Tests_FixAllTests.vb
浏览文件 @
a4159d46
Namespace
Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.PopulateSwitch
Partial
Public
Class
PopulateSwitchTests
Partial
Public
Class
PopulateSwitch
Statement
Tests
Inherits
AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
<
Fact
>
...
...
src/Features/Core/Portable/Diagnostics/Analyzers/IDEDiagnosticIds.cs
浏览文件 @
a4159d46
...
...
@@ -15,7 +15,7 @@ internal static class IDEDiagnosticIds
public
const
string
UseImplicitTypeDiagnosticId
=
"IDE0007"
;
public
const
string
UseExplicitTypeDiagnosticId
=
"IDE0008"
;
public
const
string
AddQualificationDiagnosticId
=
"IDE0009"
;
public
const
string
PopulateSwitchDiagnosticId
=
"IDE0010"
;
public
const
string
PopulateSwitch
Statement
DiagnosticId
=
"IDE0010"
;
public
const
string
AddBracesDiagnosticId
=
"IDE0011"
;
// IDE0012-IDE0015 deprecated and replaced with PreferBuiltInOrFrameworkTypeDiagnosticId (IDE0049)
...
...
@@ -115,6 +115,8 @@ internal static class IDEDiagnosticIds
public
const
string
UseSystemHashCode
=
"IDE0070"
;
public
const
string
PopulateExpressionStatementDiagnosticId
=
"IDE0071"
;
// Analyzer error Ids
public
const
string
AnalyzerChangedId
=
"IDE1001"
;
public
const
string
AnalyzerDependencyConflictId
=
"IDE1002"
;
...
...
src/Features/Core/Portable/PopulateSwitch/PopulateSwitchCodeFixProvider.cs
浏览文件 @
a4159d46
...
...
@@ -8,6 +8,7 @@
using
System.Linq
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Microsoft.CodeAnalysis
;
using
Microsoft.CodeAnalysis.CodeActions
;
using
Microsoft.CodeAnalysis.CodeFixes
;
using
Microsoft.CodeAnalysis.Diagnostics
;
...
...
@@ -21,19 +22,17 @@
namespace
Microsoft.CodeAnalysis.PopulateSwitch
{
[
ExportCodeFixProvider
(
LanguageNames
.
CSharp
,
LanguageNames
.
VisualBasic
,
Name
=
PredefinedCodeFixProviderNames
.
PopulateSwitch
),
Shared
]
[
ExtensionOrder
(
After
=
PredefinedCodeFixProviderNames
.
ImplementInterface
)]
internal
class
PopulateSwitchCodeFixProvider
:
SyntaxEditorBasedCodeFixProvider
internal
abstract
class
AbstractPopulateSwitchCodeFixProvider
<
TSwitchOperation
>
:
SyntaxEditorBasedCodeFixProvider
where
TSwitchOperation
:
IOperation
{
[
ImportingConstructor
]
public
PopulateSwitchCodeFixProvider
()
public
sealed
override
ImmutableArray
<
string
>
FixableDiagnosticIds
{
get
;
}
protected
AbstractPopulateSwitchCodeFixProvider
(
string
diagnosticId
)
{
FixableDiagnosticIds
=
ImmutableArray
.
Create
(
diagnosticId
);
}
public
override
ImmutableArray
<
string
>
FixableDiagnosticIds
=>
ImmutableArray
.
Create
(
IDEDiagnosticIds
.
PopulateSwitchDiagnosticId
);
internal
sealed
override
CodeFixCategory
CodeFixCategory
=>
CodeFixCategory
.
Custom
;
public
sealed
override
Task
RegisterCodeFixesAsync
(
CodeFixContext
context
)
...
...
@@ -129,8 +128,76 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
var
hasMissingDefaultCase
=
bool
.
Parse
(
diagnostic
.
Properties
[
PopulateSwitchHelpers
.
MissingDefaultCase
]);
var
switchLocation
=
diagnostic
.
AdditionalLocations
[
0
];
var
switchNode
=
switchLocation
.
FindNode
(
cancellationToken
);
var
switchStatement
=
(
ISwitchOperation
)
model
.
GetOperation
(
switchNode
,
cancellationToken
);
var
switchNode
=
switchLocation
.
FindNode
(
getInnermostNodeForTie
:
true
,
cancellationToken
);
var
switchStatement
=
(
TSwitchOperation
)
model
.
GetOperation
(
switchNode
,
cancellationToken
);
FixOneDiagnostic
(
document
,
editor
,
addCases
,
addDefaultCase
,
onlyOneDiagnostic
,
hasMissingCases
,
hasMissingDefaultCase
,
switchNode
,
switchStatement
);
}
protected
abstract
void
FixOneDiagnostic
(
Document
document
,
SyntaxEditor
editor
,
bool
addCases
,
bool
addDefaultCase
,
bool
onlyOneDiagnostic
,
bool
hasMissingCases
,
bool
hasMissingDefaultCase
,
SyntaxNode
switchNode
,
TSwitchOperation
switchStatement
);
protected
static
void
AddMissingBraces
(
Document
document
,
ref
SyntaxNode
root
,
ref
SyntaxNode
switchNode
)
{
// Parsing of the switch may have caused imbalanced braces. i.e. the switch
// may have consumed a brace that was intended for a higher level construct.
// So balance the tree first, then do the switch replacement.
var
syntaxFacts
=
document
.
GetLanguageService
<
ISyntaxFactsService
>();
syntaxFacts
.
AddFirstMissingCloseBrace
(
root
,
switchNode
,
out
var
newRoot
,
out
var
newSwitchNode
);
root
=
newRoot
;
switchNode
=
newSwitchNode
;
}
protected
override
Task
FixAllAsync
(
Document
document
,
ImmutableArray
<
Diagnostic
>
diagnostics
,
SyntaxEditor
editor
,
CancellationToken
cancellationToken
)
{
// If the user is performing a fix-all, then fix up all the issues we see. i.e.
// add missing cases and missing 'default' cases for any switches we reported an
// issue on.
return
FixWithEditorAsync
(
document
,
editor
,
diagnostics
,
addCases
:
true
,
addDefaultCase
:
true
,
cancellationToken
:
cancellationToken
);
}
private
class
MyCodeAction
:
CodeAction
.
DocumentChangeAction
{
public
MyCodeAction
(
string
title
,
Func
<
CancellationToken
,
Task
<
Document
>>
createChangedDocument
)
:
base
(
title
,
createChangedDocument
)
{
}
}
}
[
ExportCodeFixProvider
(
LanguageNames
.
CSharp
,
LanguageNames
.
VisualBasic
,
Name
=
PredefinedCodeFixProviderNames
.
PopulateSwitch
),
Shared
]
[
ExtensionOrder
(
After
=
PredefinedCodeFixProviderNames
.
ImplementInterface
)]
internal
class
PopulateSwitchStatementCodeFixProvider
:
AbstractPopulateSwitchCodeFixProvider
<
ISwitchOperation
>
{
[
ImportingConstructor
]
public
PopulateSwitchStatementCodeFixProvider
()
:
base
(
IDEDiagnosticIds
.
PopulateSwitchStatementDiagnosticId
)
{
}
protected
override
void
FixOneDiagnostic
(
Document
document
,
SyntaxEditor
editor
,
bool
addCases
,
bool
addDefaultCase
,
bool
onlyOneDiagnostic
,
bool
hasMissingCases
,
bool
hasMissingDefaultCase
,
SyntaxNode
switchNode
,
ISwitchOperation
switchStatement
)
{
var
enumType
=
switchStatement
.
Value
.
Type
;
var
generator
=
editor
.
Generator
;
...
...
@@ -144,7 +211,7 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
var
missingEnumMembers
=
PopulateSwitchHelpers
.
GetMissingEnumMembers
(
switchStatement
);
var
missingSections
=
from
e
in
missingEnumMembers
let
caseLabel
=
generator
.
MemberAccessExpression
(
generator
.
TypeExpression
(
enumType
),
e
.
Name
).
WithAdditionalAnnotations
(
Simplifier
.
Annotation
)
let
caseLabel
=
generator
.
MemberAccessExpression
(
generator
.
TypeExpression
(
enumType
),
e
.
Name
).
WithAdditionalAnnotations
<
SyntaxNode
>
(
Simplifier
.
Annotation
)
let
section
=
generator
.
SwitchSection
(
caseLabel
,
sectionStatements
)
select
section
;
...
...
@@ -160,7 +227,7 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
var
insertLocation
=
InsertPosition
(
switchStatement
);
var
newSwitchNode
=
generator
.
InsertSwitchSections
(
switchNode
,
insertLocation
,
newSections
)
.
WithAdditionalAnnotations
(
Formatter
.
Annotation
);
.
WithAdditionalAnnotations
<
SyntaxNode
>
(
Formatter
.
Annotation
);
if
(
onlyOneDiagnostic
)
{
...
...
@@ -171,7 +238,7 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
var
root
=
editor
.
OriginalRoot
;
AddMissingBraces
(
document
,
ref
root
,
ref
switchNode
);
var
newRoot
=
root
.
ReplaceNode
(
switchNode
,
newSwitchNode
);
var
newRoot
=
root
.
ReplaceNode
<
SyntaxNode
>
(
switchNode
,
newSwitchNode
);
editor
.
ReplaceNode
(
editor
.
OriginalRoot
,
newRoot
);
}
else
...
...
@@ -180,22 +247,6 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
}
}
private
void
AddMissingBraces
(
Document
document
,
ref
SyntaxNode
root
,
ref
SyntaxNode
switchNode
)
{
// Parsing of the switch may have caused imbalanced braces. i.e. the switch
// may have consumed a brace that was intended for a higher level construct.
// So balance the tree first, then do the switch replacement.
var
syntaxFacts
=
document
.
GetLanguageService
<
ISyntaxFactsService
>();
syntaxFacts
.
AddFirstMissingCloseBrace
(
root
,
switchNode
,
out
var
newRoot
,
out
var
newSwitchNode
);
root
=
newRoot
;
switchNode
=
newSwitchNode
;
}
private
int
InsertPosition
(
ISwitchOperation
switchStatement
)
{
// If the last section has a default label, then we want to be above that.
...
...
@@ -213,27 +264,5 @@ private int InsertPosition(ISwitchOperation switchStatement)
return
cases
.
Length
;
}
protected
override
Task
FixAllAsync
(
Document
document
,
ImmutableArray
<
Diagnostic
>
diagnostics
,
SyntaxEditor
editor
,
CancellationToken
cancellationToken
)
{
// If the user is performing a fix-all, then fix up all the issues we see. i.e.
// add missing cases and missing 'default' cases for any switches we reported an
// issue on.
return
FixWithEditorAsync
(
document
,
editor
,
diagnostics
,
addCases
:
true
,
addDefaultCase
:
true
,
cancellationToken
:
cancellationToken
);
}
private
class
MyCodeAction
:
CodeAction
.
DocumentChangeAction
{
public
MyCodeAction
(
string
title
,
Func
<
CancellationToken
,
Task
<
Document
>>
createChangedDocument
)
:
base
(
title
,
createChangedDocument
)
{
}
}
}
}
src/Features/Core/Portable/PopulateSwitch/PopulateSwitchDiagnosticAnalyzer.cs
浏览文件 @
a4159d46
// 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.Collections.Generic
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
Microsoft.CodeAnalysis.CodeStyle
;
...
...
@@ -9,15 +10,15 @@
namespace
Microsoft.CodeAnalysis.PopulateSwitch
{
[
DiagnosticAnalyzer
(
LanguageNames
.
CSharp
,
LanguageNames
.
VisualBasic
)]
internal
sealed
class
PopulateSwitchDiagnosticAnalyzer
:
internal
abstract
class
AbstractPopulateSwitchDiagnosticAnalyzer
<
TSwitchOperation
>
:
AbstractBuiltInCodeStyleDiagnosticAnalyzer
where
TSwitchOperation
:
IOperation
{
private
static
readonly
LocalizableString
s_localizableTitle
=
new
LocalizableResourceString
(
nameof
(
FeaturesResources
.
Add_missing_cases
),
FeaturesResources
.
ResourceManager
,
typeof
(
FeaturesResources
));
private
static
readonly
LocalizableString
s_localizableMessage
=
new
LocalizableResourceString
(
nameof
(
WorkspacesResources
.
Populate_switch
),
WorkspacesResources
.
ResourceManager
,
typeof
(
WorkspacesResources
));
p
ublic
PopulateSwitchDiagnosticAnalyzer
(
)
:
base
(
IDEDiagnosticIds
.
PopulateSwitchD
iagnosticId
,
p
rotected
AbstractPopulateSwitchDiagnosticAnalyzer
(
string
diagnosticId
)
:
base
(
d
iagnosticId
,
option
:
null
,
s_localizableTitle
,
s_localizableMessage
)
{
...
...
@@ -25,12 +26,19 @@ public PopulateSwitchDiagnosticAnalyzer()
#
region
Interface
methods
protected
override
void
InitializeWorker
(
AnalysisContext
context
)
=>
context
.
RegisterOperationAction
(
AnalyzeOperation
,
OperationKind
.
Switch
);
protected
abstract
OperationKind
OperationKind
{
get
;
}
protected
abstract
ICollection
<
ISymbol
>
GetMissingEnumMembers
(
TSwitchOperation
operation
);
protected
abstract
bool
HasDefaultCase
(
TSwitchOperation
operation
);
public
sealed
override
DiagnosticAnalyzerCategory
GetAnalyzerCategory
()
=>
DiagnosticAnalyzerCategory
.
SemanticSpanAnalysis
;
protected
sealed
override
void
InitializeWorker
(
AnalysisContext
context
)
=>
context
.
RegisterOperationAction
(
AnalyzeOperation
,
this
.
OperationKind
);
private
void
AnalyzeOperation
(
OperationAnalysisContext
context
)
{
var
switchOperation
=
(
I
SwitchOperation
)
context
.
Operation
;
var
switchOperation
=
(
T
SwitchOperation
)
context
.
Operation
;
var
switchBlock
=
switchOperation
.
Syntax
;
var
tree
=
switchBlock
.
SyntaxTree
;
...
...
@@ -54,18 +62,34 @@ private void AnalyzeOperation(OperationAnalysisContext context)
#
endregion
private
bool
SwitchIsIncomplete
(
ISwitchOperation
switchStatement
,
TSwitchOperation
operation
,
out
bool
missingCases
,
out
bool
missingDefaultCase
)
{
var
missingEnumMembers
=
PopulateSwitchHelpers
.
GetMissingEnumMembers
(
switchStatement
);
var
missingEnumMembers
=
GetMissingEnumMembers
(
operation
);
missingCases
=
missingEnumMembers
.
Count
>
0
;
missingDefaultCase
=
!
PopulateSwitchHelpers
.
HasDefaultCase
(
switchStatement
);
missingDefaultCase
=
!
HasDefaultCase
(
operation
);
// The switch is incomplete if we're missing any cases or we're missing a default case.
return
missingDefaultCase
||
missingCases
;
}
}
[
DiagnosticAnalyzer
(
LanguageNames
.
CSharp
,
LanguageNames
.
VisualBasic
)]
internal
sealed
class
PopulateSwitchStatementDiagnosticAnalyzer
:
AbstractPopulateSwitchDiagnosticAnalyzer
<
ISwitchOperation
>
{
public
PopulateSwitchStatementDiagnosticAnalyzer
()
:
base
(
IDEDiagnosticIds
.
PopulateSwitchStatementDiagnosticId
)
{
}
protected
override
OperationKind
OperationKind
=>
OperationKind
.
Switch
;
protected
override
ICollection
<
ISymbol
>
GetMissingEnumMembers
(
ISwitchOperation
operation
)
=>
PopulateSwitchHelpers
.
GetMissingEnumMembers
(
operation
);
public
override
DiagnosticAnalyzerCategory
GetAnalyzerCategory
()
=>
DiagnosticAnalyzerCategory
.
SemanticSpanAnalysis
;
protected
override
bool
HasDefaultCase
(
ISwitchOperation
operation
)
=>
PopulateSwitchHelpers
.
HasDefaultCase
(
operation
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录