Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
04f88d26
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,发现更多精彩内容 >>
提交
04f88d26
编写于
4月 26, 2020
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'upstream/master' into removeCastParams
上级
8e3e3951
a2ec364d
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
85 addition
and
25 deletion
+85
-25
src/Analyzers/CSharp/Tests/UseSystemHashCode/UseSystemHashCodeTests.cs
.../CSharp/Tests/UseSystemHashCode/UseSystemHashCodeTests.cs
+51
-0
src/Analyzers/Core/Analyzers/UseSystemHashCode/Analyzer.cs
src/Analyzers/Core/Analyzers/UseSystemHashCode/Analyzer.cs
+8
-16
src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs
.../UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs
+20
-8
src/Analyzers/Core/CodeFixes/UseSystemHashCode/UseSystemHashCodeCodeFixProvider.cs
...xes/UseSystemHashCode/UseSystemHashCodeCodeFixProvider.cs
+1
-1
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/SpeculationAnalyzer.cs
...tensions/Compiler/CSharp/Utilities/SpeculationAnalyzer.cs
+5
-0
未找到文件。
src/Analyzers/CSharp/Tests/UseSystemHashCode/UseSystemHashCodeTests.cs
浏览文件 @
04f88d26
...
@@ -1260,6 +1260,57 @@ public override int GetHashCode()
...
@@ -1260,6 +1260,57 @@ public override int GetHashCode()
hash.Add(i);
hash.Add(i);
return hash.ToHashCode();
return hash.ToHashCode();
}
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseSystemHashCode
)]
public
async
Task
TestNotOnSingleReturnedMember
()
{
await
TestMissingAsync
(
@"namespace System { public struct HashCode { } }
class C
{
int j;
public override int $$GetHashCode()
{
return j;
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseSystemHashCode
)]
public
async
Task
TestNotOnSingleMemberWithInvokedGetHashCode
()
{
await
TestMissingAsync
(
@"namespace System { public struct HashCode { } }
class C
{
int j;
public override int $$GetHashCode()
{
return j.GetHashCode();
}
}"
);
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
CodeActionsUseSystemHashCode
)]
public
async
Task
TestNotOnSimpleBaseReturn
()
{
await
TestMissingAsync
(
@"namespace System { public struct HashCode { } }
class C
{
int j;
public override int $$GetHashCode()
{
return base.GetHashCode();
}
}"
);
}"
);
}
}
}
}
...
...
src/Analyzers/Core/Analyzers/UseSystemHashCode/Analyzer.cs
浏览文件 @
04f88d26
...
@@ -58,34 +58,23 @@ public static bool TryGetAnalyzer(Compilation compilation, [NotNullWhen(true)] o
...
@@ -58,34 +58,23 @@ public static bool TryGetAnalyzer(Compilation compilation, [NotNullWhen(true)] o
/// Analyzes the containing <c>GetHashCode</c> method to determine which fields and
/// Analyzes the containing <c>GetHashCode</c> method to determine which fields and
/// properties were combined to form a hash code for this type.
/// properties were combined to form a hash code for this type.
/// </summary>
/// </summary>
public
(
bool
accessesBase
,
ImmutableArray
<
ISymbol
>
members
)
GetHashedMembers
(
ISymbol
owningSymbol
,
IOperation
?
operation
)
public
(
bool
accessesBase
,
ImmutableArray
<
ISymbol
>
members
,
ImmutableArray
<
IOperation
>
statements
)
GetHashedMembers
(
ISymbol
owningSymbol
,
IOperation
?
operation
)
{
{
if
(!(
operation
is
IBlockOperation
blockOperation
))
if
(!(
operation
is
IBlockOperation
blockOperation
))
{
return
default
;
return
default
;
}
// Owning symbol has to be an override of Object.GetHashCode.
// Owning symbol has to be an override of Object.GetHashCode.
if
(!(
owningSymbol
is
IMethodSymbol
{
Name
:
nameof
(
GetHashCode
)
}
method
))
if
(!(
owningSymbol
is
IMethodSymbol
{
Name
:
nameof
(
GetHashCode
)
}
method
))
{
return
default
;
return
default
;
}
if
(
method
.
Locations
.
Length
!=
1
||
if
(
method
.
Locations
.
Length
!=
1
||
method
.
DeclaringSyntaxReferences
.
Length
!=
1
)
method
.
DeclaringSyntaxReferences
.
Length
!=
1
)
{
return
default
;
return
default
;
}
if
(!
method
.
Locations
[
0
].
IsInSource
)
if
(!
method
.
Locations
[
0
].
IsInSource
)
{
return
default
;
return
default
;
}
if
(!
OverridesSystemObject
(
method
))
if
(!
OverridesSystemObject
(
method
))
{
return
default
;
return
default
;
}
// Unwind through nested blocks. This also handles if we're in an 'unchecked' block in C#
// Unwind through nested blocks. This also handles if we're in an 'unchecked' block in C#
while
(
blockOperation
.
Operations
.
Length
==
1
&&
while
(
blockOperation
.
Operations
.
Length
==
1
&&
...
@@ -95,9 +84,12 @@ public static bool TryGetAnalyzer(Compilation compilation, [NotNullWhen(true)] o
...
@@ -95,9 +84,12 @@ public static bool TryGetAnalyzer(Compilation compilation, [NotNullWhen(true)] o
}
}
var
statements
=
blockOperation
.
Operations
.
WhereAsArray
(
o
=>
!
o
.
IsImplicit
);
var
statements
=
blockOperation
.
Operations
.
WhereAsArray
(
o
=>
!
o
.
IsImplicit
);
return
MatchAccumulatorPattern
(
method
,
statements
)
??
var
(
accessesBase
,
members
)
=
MatchTuplePattern
(
method
,
statements
)
??
MatchAccumulatorPattern
(
method
,
statements
)
??
default
;
MatchTuplePattern
(
method
,
statements
)
??
default
;
return
(
accessesBase
,
members
,
statements
);
}
}
private
(
bool
accessesBase
,
ImmutableArray
<
ISymbol
>
members
)?
MatchTuplePattern
(
private
(
bool
accessesBase
,
ImmutableArray
<
ISymbol
>
members
)?
MatchTuplePattern
(
...
...
src/Analyzers/Core/Analyzers/UseSystemHashCode/UseSystemHashCodeDiagnosticAnalyzer.cs
浏览文件 @
04f88d26
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
#
nullable
enable
#
nullable
enable
using
System.Collections.Immutable
;
using
System.Collections.Immutable
;
using
System.Diagnostics
;
using
Microsoft.CodeAnalysis.CodeStyle
;
using
Microsoft.CodeAnalysis.CodeStyle
;
using
Microsoft.CodeAnalysis.Diagnostics
;
using
Microsoft.CodeAnalysis.Diagnostics
;
...
@@ -39,26 +40,37 @@ protected override void InitializeWorker(AnalysisContext context)
...
@@ -39,26 +40,37 @@ protected override void InitializeWorker(AnalysisContext context)
private
void
AnalyzeOperationBlock
(
Analyzer
analyzer
,
OperationBlockAnalysisContext
context
)
private
void
AnalyzeOperationBlock
(
Analyzer
analyzer
,
OperationBlockAnalysisContext
context
)
{
{
if
(
context
.
OperationBlocks
.
Length
!=
1
)
if
(
context
.
OperationBlocks
.
Length
!=
1
)
{
return
;
return
;
}
var
owningSymbol
=
context
.
OwningSymbol
;
var
owningSymbol
=
context
.
OwningSymbol
;
var
operation
=
context
.
OperationBlocks
[
0
];
var
operation
=
context
.
OperationBlocks
[
0
];
var
(
accessesBase
,
hashedMembers
)
=
analyzer
.
GetHashedMembers
(
owningSymbol
,
operation
);
var
(
accessesBase
,
hashedMembers
,
statements
)
=
analyzer
.
GetHashedMembers
(
owningSymbol
,
operation
);
if
(!
accessesBase
&&
hashedMembers
.
IsDefaultOrEmpty
)
var
elementCount
=
(
accessesBase
?
1
:
0
)
+
(
hashedMembers
.
IsDefaultOrEmpty
?
0
:
hashedMembers
.
Length
);
{
// No members to call into HashCode.Combine with. Don't offer anything here.
if
(
elementCount
==
0
)
return
;
return
;
}
// Just one member to call into HashCode.Combine. Only offer this if we have multiple statements that we can
// reduce to a single statement. It's not worth it to offer to replace:
//
// `return x.GetHashCode();` with `return HashCode.Combine(x);`
//
// But it is work it to offer to replace:
//
// `return (a, b).GetHashCode();` with `return HashCode.Combine(a, b);`
if
(
elementCount
==
1
&&
statements
.
Length
<
2
)
return
;
// We've got multiple members to hash, or multiple statements that can be reduced at this point.
Debug
.
Assert
(
elementCount
>=
2
||
statements
.
Length
>=
2
);
var
syntaxTree
=
operation
.
Syntax
.
SyntaxTree
;
var
syntaxTree
=
operation
.
Syntax
.
SyntaxTree
;
var
cancellationToken
=
context
.
CancellationToken
;
var
cancellationToken
=
context
.
CancellationToken
;
var
option
=
context
.
Options
.
GetOption
(
CodeStyleOptions2
.
PreferSystemHashCode
,
operation
.
Language
,
syntaxTree
,
cancellationToken
);
var
option
=
context
.
Options
.
GetOption
(
CodeStyleOptions2
.
PreferSystemHashCode
,
operation
.
Language
,
syntaxTree
,
cancellationToken
);
if
(
option
?.
Value
!=
true
)
if
(
option
?.
Value
!=
true
)
{
return
;
return
;
}
var
operationLocation
=
operation
.
Syntax
.
GetLocation
();
var
operationLocation
=
operation
.
Syntax
.
GetLocation
();
var
declarationLocation
=
context
.
OwningSymbol
.
DeclaringSyntaxReferences
[
0
].
GetSyntax
(
cancellationToken
).
GetLocation
();
var
declarationLocation
=
context
.
OwningSymbol
.
DeclaringSyntaxReferences
[
0
].
GetSyntax
(
cancellationToken
).
GetLocation
();
...
...
src/Analyzers/Core/CodeFixes/UseSystemHashCode/UseSystemHashCodeCodeFixProvider.cs
浏览文件 @
04f88d26
...
@@ -74,7 +74,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
...
@@ -74,7 +74,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
var
method
=
semanticModel
.
GetDeclaredSymbol
(
methodDecl
,
cancellationToken
);
var
method
=
semanticModel
.
GetDeclaredSymbol
(
methodDecl
,
cancellationToken
);
var
methodBlock
=
declarationService
.
GetDeclarations
(
method
)[
0
].
GetSyntax
(
cancellationToken
);
var
methodBlock
=
declarationService
.
GetDeclarations
(
method
)[
0
].
GetSyntax
(
cancellationToken
);
var
(
accessesBase
,
members
)
=
analyzer
.
GetHashedMembers
(
method
,
operation
);
var
(
accessesBase
,
members
,
_
)
=
analyzer
.
GetHashedMembers
(
method
,
operation
);
if
(
accessesBase
||
!
members
.
IsDefaultOrEmpty
)
if
(
accessesBase
||
!
members
.
IsDefaultOrEmpty
)
{
{
// Produce the new statements for the GetHashCode method and replace the
// Produce the new statements for the GetHashCode method and replace the
...
...
src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Utilities/SpeculationAnalyzer.cs
浏览文件 @
04f88d26
...
@@ -426,6 +426,11 @@ protected override bool ReplacementChangesSemanticsForNodeLanguageSpecific(Synta
...
@@ -426,6 +426,11 @@ protected override bool ReplacementChangesSemanticsForNodeLanguageSpecific(Synta
// expression type are not broken.
// expression type are not broken.
var
newSwitchStatement
=
(
SwitchStatementSyntax
)
currentReplacedNode
;
var
newSwitchStatement
=
(
SwitchStatementSyntax
)
currentReplacedNode
;
var
previousReplacedExpression
=
(
ExpressionSyntax
)
previousReplacedNode
;
// it is never legal to use `default/null` in a switch statement's expression.
if
(
previousReplacedExpression
.
WalkDownParentheses
().
IsKind
(
SyntaxKind
.
NullLiteralExpression
,
SyntaxKind
.
DefaultLiteralExpression
))
return
true
;
var
originalSwitchLabels
=
originalSwitchStatement
.
Sections
.
SelectMany
(
section
=>
section
.
Labels
).
ToArray
();
var
originalSwitchLabels
=
originalSwitchStatement
.
Sections
.
SelectMany
(
section
=>
section
.
Labels
).
ToArray
();
var
newSwitchLabels
=
newSwitchStatement
.
Sections
.
SelectMany
(
section
=>
section
.
Labels
).
ToArray
();
var
newSwitchLabels
=
newSwitchStatement
.
Sections
.
SelectMany
(
section
=>
section
.
Labels
).
ToArray
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录