Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
eb9cf11f
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,发现更多精彩内容 >>
提交
eb9cf11f
编写于
7月 01, 2019
作者:
C
Cyrus Najmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Require System.Index/Range to be present to offer to use the new language features.
上级
df15c64a
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
38 addition
and
52 deletion
+38
-52
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseIndexOperatorDiagnosticAnalyzer.InfoCache.cs
...tor/CSharpUseIndexOperatorDiagnosticAnalyzer.InfoCache.cs
+4
-4
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseIndexOperatorDiagnosticAnalyzer.cs
...RangeOperator/CSharpUseIndexOperatorDiagnosticAnalyzer.cs
+6
-0
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseRangeOperatorCodeFixProvider.cs
...xOrRangeOperator/CSharpUseRangeOperatorCodeFixProvider.cs
+16
-38
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseRangeOperatorDiagnosticAnalyzer.InfoCache.cs
...tor/CSharpUseRangeOperatorDiagnosticAnalyzer.InfoCache.cs
+4
-4
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseRangeOperatorDiagnosticAnalyzer.cs
...RangeOperator/CSharpUseRangeOperatorDiagnosticAnalyzer.cs
+8
-3
src/Features/CSharp/Portable/UseIndexOrRangeOperator/Helpers.cs
...atures/CSharp/Portable/UseIndexOrRangeOperator/Helpers.cs
+0
-3
未找到文件。
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseIndexOperatorDiagnosticAnalyzer.InfoCache.cs
浏览文件 @
eb9cf11f
...
...
@@ -19,7 +19,7 @@ private class InfoCache
/// The System.Index type. Needed so that we only fixup code if we see the type
/// we're using has an indexer that takes an Index.
/// </summary>
p
rivate
readonly
INamedTypeSymbol
_i
ndexType
;
p
ublic
readonly
INamedTypeSymbol
I
ndexType
;
/// <summary>
/// Mapping from a method like 'MyType.Get(int)' to the Length/Count property for
...
...
@@ -29,7 +29,7 @@ private class InfoCache
public
InfoCache
(
Compilation
compilation
)
{
_i
ndexType
=
compilation
.
GetTypeByMetadataName
(
"System.Index"
);
I
ndexType
=
compilation
.
GetTypeByMetadataName
(
"System.Index"
);
_methodToMemberInfo
=
new
ConcurrentDictionary
<
IMethodSymbol
,
MemberInfo
>();
...
...
@@ -85,7 +85,7 @@ private MemberInfo ComputeMemberInfo(IMethodSymbol method, bool requireIndexMemb
// this is the getter for an indexer. i.e. the user is calling something
// like s[...]. We need to see if there's an indexer that takes a System.Index
// value.
var
indexer
=
GetIndexer
(
containingType
,
_i
ndexType
,
method
.
ReturnType
);
var
indexer
=
GetIndexer
(
containingType
,
I
ndexType
,
method
.
ReturnType
);
if
(
indexer
!=
null
)
{
// Type had a matching indexer. We can convert calls to the int-indexer to
...
...
@@ -98,7 +98,7 @@ private MemberInfo ComputeMemberInfo(IMethodSymbol method, bool requireIndexMemb
Debug
.
Assert
(
method
.
MethodKind
==
MethodKind
.
Ordinary
);
// it's a method like: `SomeType MyType.Get(int index)`. Look
// for an overload like: `SomeType MyType.Get(Range)`
var
overloadedIndexMethod
=
GetOverload
(
method
,
_i
ndexType
);
var
overloadedIndexMethod
=
GetOverload
(
method
,
I
ndexType
);
if
(
overloadedIndexMethod
!=
null
)
{
return
new
MemberInfo
(
lengthLikeProperty
,
overloadedIndexMethod
);
...
...
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseIndexOperatorDiagnosticAnalyzer.cs
浏览文件 @
eb9cf11f
...
...
@@ -58,6 +58,12 @@ protected override void InitializeWorker(AnalysisContext context)
var
compilation
=
startContext
.
Compilation
;
var
infoCache
=
new
InfoCache
(
compilation
);
// The System.Index type is always required to offer this fix.
if
(
infoCache
.
IndexType
==
null
)
{
return
;
}
// Register to hear property references, so we can hear about calls to indexers
// like: s[s.Length - n]
context
.
RegisterOperationAction
(
...
...
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseRangeOperatorCodeFixProvider.cs
浏览文件 @
eb9cf11f
...
...
@@ -64,8 +64,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
InvocationExpressionSyntax
currentInvocation
,
CancellationToken
cancellationToken
)
{
var
invocation
=
semanticModel
.
GetOperation
(
currentInvocation
,
cancellationToken
)
as
IInvocationOperation
;
if
(
invocation
!=
null
)
if
(
semanticModel
.
GetOperation
(
currentInvocation
,
cancellationToken
)
is
IInvocationOperation
invocation
)
{
var
infoCache
=
new
InfoCache
(
semanticModel
.
Compilation
);
var
resultOpt
=
AnalyzeInvocation
(
...
...
@@ -74,7 +73,7 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
if
(
resultOpt
!=
null
)
{
var
result
=
resultOpt
.
Value
;
var
updatedNode
=
FixOne
(
semanticModel
,
result
,
cancellationToken
);
var
updatedNode
=
FixOne
(
result
,
cancellationToken
);
if
(
updatedNode
!=
null
)
{
return
currentRoot
.
ReplaceNode
(
result
.
Invocation
,
updatedNode
);
...
...
@@ -88,15 +87,14 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
private
static
InvocationExpressionSyntax
GetInvocationExpression
(
Diagnostic
d
,
CancellationToken
cancellationToken
)
=>
(
InvocationExpressionSyntax
)
d
.
AdditionalLocations
[
0
].
FindNode
(
getInnermostNodeForTie
:
true
,
cancellationToken
);
private
ExpressionSyntax
FixOne
(
SemanticModel
semanticModel
,
Result
result
,
CancellationToken
cancellationToken
)
private
ExpressionSyntax
FixOne
(
Result
result
,
CancellationToken
cancellationToken
)
{
var
invocation
=
result
.
Invocation
;
var
expression
=
invocation
.
Expression
is
MemberAccessExpressionSyntax
memberAccess
?
memberAccess
.
Expression
:
invocation
.
Expression
;
var
rangeExpression
=
CreateRangeExpression
(
semanticModel
,
result
,
cancellationToken
);
var
rangeExpression
=
CreateRangeExpression
(
result
);
var
argument
=
Argument
(
rangeExpression
).
WithAdditionalAnnotations
(
Formatter
.
Annotation
);
var
arguments
=
SingletonSeparatedList
(
argument
);
...
...
@@ -118,22 +116,15 @@ private static InvocationExpressionSyntax GetInvocationExpression(Diagnostic d,
}
}
private
RangeExpressionSyntax
CreateRangeExpression
(
SemanticModel
semanticModel
,
Result
result
,
CancellationToken
cancellationToken
)
{
switch
(
result
.
Kind
)
private
RangeExpressionSyntax
CreateRangeExpression
(
Result
result
)
=>
result
.
Kind
switch
{
case
ResultKind
.
Computed
:
return
CreateComputedRange
(
semanticModel
,
result
,
cancellationToken
);
case
ResultKind
.
Constant
:
return
CreateConstantRange
(
semanticModel
,
result
,
cancellationToken
);
default
:
throw
ExceptionUtilities
.
Unreachable
;
}
}
ResultKind
.
Computed
=>
CreateComputedRange
(
result
),
ResultKind
.
Constant
=>
CreateConstantRange
(
result
),
_
=>
throw
ExceptionUtilities
.
Unreachable
,
};
private
RangeExpressionSyntax
CreateComputedRange
(
SemanticModel
semanticModel
,
Result
result
,
CancellationToken
cancellationToken
)
private
RangeExpressionSyntax
CreateComputedRange
(
Result
result
)
{
// We have enough information now to generate `start..end`. However, this will often
// not be what the user wants. For example, generating `start..expr.Length` is not as
...
...
@@ -143,24 +134,18 @@ private static InvocationExpressionSyntax GetInvocationExpression(Diagnostic d,
var
startOperation
=
result
.
Op1
;
var
endOperation
=
result
.
Op2
;
var
startExpr
=
(
ExpressionSyntax
)
startOperation
.
Syntax
;
var
endExpr
=
(
ExpressionSyntax
)
endOperation
.
Syntax
;
var
startFromEnd
=
false
;
var
endFromEnd
=
false
;
var
lengthLikeProperty
=
result
.
MemberInfo
.
LengthLikeProperty
;
var
instance
=
result
.
InvocationOperation
.
Instance
;
// If our start-op is actually equivalent to `expr.Length - val`, then just change our
// start-op to be `val` and record that we should emit it as `^val`.
startFromEnd
=
IsFromEnd
(
lengthLikeProperty
,
instance
,
ref
startOperation
);
startExpr
=
(
ExpressionSyntax
)
startOperation
.
Syntax
;
var
startFromEnd
=
IsFromEnd
(
lengthLikeProperty
,
instance
,
ref
startOperation
);
var
startExpr
=
(
ExpressionSyntax
)
startOperation
.
Syntax
;
// Similarly, if our end-op is actually equivalent to `expr.Length - val`, then just
// change our end-op to be `val` and record that we should emit it as `^val`.
endFromEnd
=
IsFromEnd
(
lengthLikeProperty
,
instance
,
ref
endOperation
);
endExpr
=
(
ExpressionSyntax
)
endOperation
.
Syntax
;
var
endFromEnd
=
IsFromEnd
(
lengthLikeProperty
,
instance
,
ref
endOperation
);
var
endExpr
=
(
ExpressionSyntax
)
endOperation
.
Syntax
;
// If the range operation goes to 'expr.Length' then we can just leave off the end part
// of the range. i.e. `start..`
...
...
@@ -182,16 +167,9 @@ private static InvocationExpressionSyntax GetInvocationExpression(Diagnostic d,
endExpr
!=
null
&&
endFromEnd
?
IndexExpression
(
endExpr
)
:
endExpr
);
}
private
static
ExpressionSyntax
GetExpression
(
ImmutableDictionary
<
string
,
string
>
props
,
ExpressionSyntax
expr
,
string
omitKey
,
string
fromEndKey
)
=>
props
.
ContainsKey
(
omitKey
)
?
null
:
props
.
ContainsKey
(
fromEndKey
)
?
IndexExpression
(
expr
)
:
expr
;
private
static
RangeExpressionSyntax
CreateConstantRange
(
SemanticModel
semanticModel
,
Result
result
,
CancellationToken
cancellationToken
)
private
static
RangeExpressionSyntax
CreateConstantRange
(
Result
result
)
{
var
constant1Syntax
=
(
ExpressionSyntax
)
result
.
Op1
.
Syntax
;
var
constant2Syntax
=
(
ExpressionSyntax
)
result
.
Op2
.
Syntax
;
// the form is s.Slice(constant1, s.Length - constant2). Want to generate
// s[constant1..(constant2-constant1)]
...
...
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseRangeOperatorDiagnosticAnalyzer.InfoCache.cs
浏览文件 @
eb9cf11f
...
...
@@ -20,12 +20,12 @@ public class InfoCache
/// The System.Range type. Needed so that we only fixup code if we see the type
/// we're using has an indexer that takes a Range.
/// </summary>
p
rivate
readonly
INamedTypeSymbol
_r
angeType
;
p
ublic
readonly
INamedTypeSymbol
R
angeType
;
private
readonly
ConcurrentDictionary
<
IMethodSymbol
,
MemberInfo
>
_methodToMemberInfo
;
public
InfoCache
(
Compilation
compilation
)
{
_r
angeType
=
compilation
.
GetTypeByMetadataName
(
"System.Range"
);
R
angeType
=
compilation
.
GetTypeByMetadataName
(
"System.Range"
);
_methodToMemberInfo
=
new
ConcurrentDictionary
<
IMethodSymbol
,
MemberInfo
>();
...
...
@@ -89,7 +89,7 @@ private MemberInfo ComputeMemberInfo(IMethodSymbol sliceLikeMethod, bool require
// it's a method like: MyType MyType.Slice(int start, int length). Look for an
// indexer like `MyType MyType.this[Range range]`. If we can't find one return
// 'default' so we'll consider this named-type non-viable.
var
indexer
=
GetIndexer
(
containingType
,
_r
angeType
,
containingType
);
var
indexer
=
GetIndexer
(
containingType
,
R
angeType
,
containingType
);
if
(
indexer
!=
null
)
{
return
new
MemberInfo
(
lengthLikeProperty
,
overloadedMethodOpt
:
null
);
...
...
@@ -98,7 +98,7 @@ private MemberInfo ComputeMemberInfo(IMethodSymbol sliceLikeMethod, bool require
// it's a method like: `SomeType MyType.Slice(int start, int length)`. Look
// for an overload like: `SomeType MyType.Slice(Range)`
var
overloadedRangeMethod
=
GetOverload
(
sliceLikeMethod
,
_r
angeType
);
var
overloadedRangeMethod
=
GetOverload
(
sliceLikeMethod
,
R
angeType
);
if
(
overloadedRangeMethod
!=
null
)
{
return
new
MemberInfo
(
lengthLikeProperty
,
overloadedRangeMethod
);
...
...
src/Features/CSharp/Portable/UseIndexOrRangeOperator/CSharpUseRangeOperatorDiagnosticAnalyzer.cs
浏览文件 @
eb9cf11f
...
...
@@ -52,9 +52,14 @@ protected override void InitializeWorker(AnalysisContext context)
// We're going to be checking every invocation in the compilation. Cache information
// we compute in this object so we don't have to continually recompute it.
var
infoCache
=
new
InfoCache
(
compilationContext
.
Compilation
);
compilationContext
.
RegisterOperationAction
(
c
=>
AnalyzeInvocation
(
c
,
infoCache
),
OperationKind
.
Invocation
);
// The System.Range type is always required to offer this fix.
if
(
infoCache
.
RangeType
!=
null
)
{
compilationContext
.
RegisterOperationAction
(
c
=>
AnalyzeInvocation
(
c
,
infoCache
),
OperationKind
.
Invocation
);
}
});
}
...
...
src/Features/CSharp/Portable/UseIndexOrRangeOperator/Helpers.cs
浏览文件 @
eb9cf11f
...
...
@@ -67,9 +67,6 @@ public static bool IsSubtraction(IOperation operation, out IBinaryOperation subt
return
false
;
}
private
static
bool
IsConstantInt32
(
IOperation
operation
)
=>
operation
.
ConstantValue
.
HasValue
&&
operation
.
ConstantValue
.
Value
is
int
;
/// <summary>
/// Look for methods like "SomeType MyType.Get(int)". Also matches against the 'getter'
/// of an indexer like 'SomeType MyType.this[int]`
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录