Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
lwm1986
roslyn
提交
6bdb5a53
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,发现更多精彩内容 >>
提交
6bdb5a53
编写于
6月 20, 2016
作者:
C
CyrusNajmabadi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
VB side of type inference.
上级
f29a6cb0
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
189 addition
and
69 deletion
+189
-69
src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodePartials.vb
...mpilers/VisualBasic/Portable/Syntax/SyntaxNodePartials.vb
+1
-1
src/EditorFeatures/CSharpTest/TypeInferrer/TypeInferrerTests.cs
...itorFeatures/CSharpTest/TypeInferrer/TypeInferrerTests.cs
+0
-2
src/EditorFeatures/VisualBasicTest/TypeInferrer/TypeInferrerTests.vb
...eatures/VisualBasicTest/TypeInferrer/TypeInferrerTests.vb
+27
-1
src/Workspaces/CSharp/Portable/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs
...nguageServices/CSharpTypeInferenceService.TypeInferrer.cs
+65
-59
src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb
...eServices/VisualBasicTypeInferenceService.TypeInferrer.vb
+96
-6
未找到文件。
src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodePartials.vb
浏览文件 @
6bdb5a53
...
...
@@ -70,7 +70,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax
End
Function
End
Class
P
ublic
Partial
Class
SingleLineLambdaExpressionSyntax
P
artial
Public
Class
SingleLineLambdaExpressionSyntax
''' <summary>
''' Single line subs only have a single statement. However, when binding it is convenient to have a statement list. For example,
''' dim statements are not valid in a single line lambda. However, it is nice to be able to provide semantic info about the local.
...
...
src/EditorFeatures/CSharpTest/TypeInferrer/TypeInferrerTests.cs
浏览文件 @
6bdb5a53
...
...
@@ -1820,7 +1820,6 @@ static void Foo(System.ConsoleModifiers arg)
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
TypeInferenceService
)]
[
WorkItem
(
6765
,
"https://github.com/dotnet/roslyn/issues/6765"
)]
public
async
Task
TestWhereCall
()
{
var
text
=
...
...
@@ -1837,7 +1836,6 @@ void Foo()
}
[
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
TypeInferenceService
)]
[
WorkItem
(
6765
,
"https://github.com/dotnet/roslyn/issues/6765"
)]
public
async
Task
TestWhereCall2
()
{
var
text
=
...
...
src/EditorFeatures/VisualBasicTest/TypeInferrer/TypeInferrerTests.vb
浏览文件 @
6bdb5a53
...
...
@@ -705,7 +705,7 @@ Module M
Dim x As Boolean = Await [|F|].ContinueWith(Function(a) True).ContinueWith(Function(a) False)
End Sub
End Module"
Await
TestAsync
(
text
,
"
System.Object
"
,
testPosition
:
=
False
)
Await
TestAsync
(
text
,
"
Global.System.Threading.Tasks.Task(Of System.Object)
"
,
testPosition
:
=
False
)
End
Function
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
TypeInferenceService
)
>
...
...
@@ -736,5 +736,31 @@ End Module"
End Class"
Await
TestAsync
(
text
,
"System.Object"
,
testNode
:
=
False
,
testPosition
:
=
True
)
End
Function
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
TypeInferenceService
)
>
Public
Async
Function
TestWhereCall
()
As
Task
Dim
text
=
"imports System.Collections.Generic
class C
sub Foo()
[|ints|].Where(function(i) i > 10)
end sub
end class"
Await
TestAsync
(
text
,
"Global.System.Collections.Generic.IEnumerable(Of System.Int32)"
,
testPosition
:
=
False
)
End
Function
<
Fact
,
Trait
(
Traits
.
Feature
,
Traits
.
Features
.
TypeInferenceService
)
>
Public
Async
Function
TestWhereCall2
()
As
Task
Dim
text
=
"imports System.Collections.Generic
class C
sub Foo()
[|ints|].Where(function(i)
return i > 10
end function)
end sub
end class"
Await
TestAsync
(
text
,
"Global.System.Collections.Generic.IEnumerable(Of System.Int32)"
,
testPosition
:
=
False
)
End
Function
End
Class
End
Namespace
src/Workspaces/CSharp/Portable/LanguageServices/CSharpTypeInferenceService.TypeInferrer.cs
浏览文件 @
6bdb5a53
...
...
@@ -1457,72 +1457,78 @@ private IEnumerable<ITypeSymbol> InferTypeInNameColon(NameColonSyntax nameColon,
Debug
.
Assert
(
expressionOpt
!=
null
);
if
(
expressionOpt
==
memberAccessExpression
.
Expression
)
{
// If we're on the left side of a dot, it's possible in a few cases
// to figure out what type we should be. Specifically, if we have
//
// await foo.ConfigureAwait()
//
// then we can figure out what 'foo' should be based on teh await
// context.
var
name
=
memberAccessExpression
.
Name
.
Identifier
.
Value
;
if
(
name
.
Equals
(
nameof
(
Task
<
int
>.
ConfigureAwait
))
&&
memberAccessExpression
.
IsParentKind
(
SyntaxKind
.
InvocationExpression
)
&&
memberAccessExpression
.
Parent
.
IsParentKind
(
SyntaxKind
.
AwaitExpression
))
{
return
InferTypes
((
ExpressionSyntax
)
memberAccessExpression
.
Parent
);
}
else
if
(
name
.
Equals
(
nameof
(
Task
<
int
>.
ContinueWith
)))
return
InferTypeForExpressionOfMemberAccessExpression
(
memberAccessExpression
);
}
// We're right after the dot in "Foo.Bar". The type for "Bar" should be
// whatever type we'd infer for "Foo.Bar" itself.
return
InferTypes
(
memberAccessExpression
);
}
}
private
IEnumerable
<
ITypeSymbol
>
InferTypeForExpressionOfMemberAccessExpression
(
MemberAccessExpressionSyntax
memberAccessExpression
)
{
// If we're on the left side of a dot, it's possible in a few cases
// to figure out what type we should be. Specifically, if we have
//
// await foo.ConfigureAwait()
//
// then we can figure out what 'foo' should be based on teh await
// context.
var
name
=
memberAccessExpression
.
Name
.
Identifier
.
Value
;
if
(
name
.
Equals
(
nameof
(
Task
<
int
>.
ConfigureAwait
))
&&
memberAccessExpression
.
IsParentKind
(
SyntaxKind
.
InvocationExpression
)
&&
memberAccessExpression
.
Parent
.
IsParentKind
(
SyntaxKind
.
AwaitExpression
))
{
return
InferTypes
((
ExpressionSyntax
)
memberAccessExpression
.
Parent
);
}
else
if
(
name
.
Equals
(
nameof
(
Task
<
int
>.
ContinueWith
)))
{
// foo.ContinueWith(...)
// We want to infer Task<T>. For now, we'll just do Task<object>,
// in the future it would be nice to figure out the actual result
// type based on the argument to ContinueWith.
var
taskOfT
=
this
.
Compilation
.
TaskOfTType
();
if
(
taskOfT
!=
null
)
{
return
SpecializedCollections
.
SingletonEnumerable
(
taskOfT
.
Construct
(
this
.
Compilation
.
ObjectType
));
}
}
else
if
(
name
.
Equals
(
nameof
(
Enumerable
.
Select
))
||
name
.
Equals
(
nameof
(
Enumerable
.
Where
)))
{
var
ienumerableType
=
this
.
Compilation
.
IEnumerableOfTType
();
// foo.Select
// We want to infer IEnumerable<T>. We can try to figure out what
// T if we get a delegate as the first argument to Select/Where.
if
(
ienumerableType
!=
null
&&
memberAccessExpression
.
IsParentKind
(
SyntaxKind
.
InvocationExpression
))
{
var
invocation
=
(
InvocationExpressionSyntax
)
memberAccessExpression
.
Parent
;
if
(
invocation
.
ArgumentList
.
Arguments
.
Count
>
0
)
{
// foo.ContinueWith(...)
// We want to infer Task<T>. For now, we'll just do Task<object>,
// in the future it would be nice to figure out the actual result
// type based on the argument to ContinueWith.
var
taskOfT
=
this
.
Compilation
.
TaskOfTType
();
if
(
taskOfT
!=
null
)
var
argumentExpression
=
invocation
.
ArgumentList
.
Arguments
[
0
].
Expression
;
var
argumentTypes
=
GetTypes
(
argumentExpression
);
var
delegateType
=
argumentTypes
.
FirstOrDefault
().
GetDelegateType
(
this
.
Compilation
);
var
typeArg
=
delegateType
?.
TypeArguments
.
Length
>
0
?
delegateType
.
TypeArguments
[
0
]
:
this
.
Compilation
.
ObjectType
;
if
(
IsUnusableType
(
typeArg
)
&&
argumentExpression
is
LambdaExpressionSyntax
)
{
return
SpecializedCollections
.
SingletonEnumerable
(
t
askOfT
.
Construct
(
this
.
Compilation
.
ObjectType
))
;
typeArg
=
InferTypeForFirstParameterOfLambda
((
LambdaExpressionSyntax
)
argumentExpression
)
??
t
his
.
Compilation
.
ObjectType
;
}
}
else
if
(
name
.
Equals
(
nameof
(
Enumerable
.
Select
))
||
name
.
Equals
(
nameof
(
Enumerable
.
Where
)))
{
var
ienumerableType
=
this
.
Compilation
.
IEnumerableOfTType
();
// foo.Select
// We want to infer IEnumerable<T>. We can try to figure out what
// T if we get a delegate as the first argument to Select/Where.
if
(
ienumerableType
!=
null
&&
memberAccessExpression
.
IsParentKind
(
SyntaxKind
.
InvocationExpression
))
{
var
invocation
=
(
InvocationExpressionSyntax
)
memberAccessExpression
.
Parent
;
if
(
invocation
.
ArgumentList
.
Arguments
.
Count
>
0
)
{
var
argumentExpression
=
invocation
.
ArgumentList
.
Arguments
[
0
].
Expression
;
var
argumentTypes
=
GetTypes
(
argumentExpression
);
var
delegateType
=
argumentTypes
.
FirstOrDefault
().
GetDelegateType
(
this
.
Compilation
);
var
typeArg
=
delegateType
?.
TypeArguments
.
Length
>
0
?
delegateType
.
TypeArguments
[
0
]
:
this
.
Compilation
.
ObjectType
;
if
(
IsUnusableType
(
typeArg
)
&&
argumentExpression
is
LambdaExpressionSyntax
)
{
typeArg
=
InferTypeForFirstParameterOfLambda
((
LambdaExpressionSyntax
)
argumentExpression
)
??
this
.
Compilation
.
ObjectType
;
}
return
SpecializedCollections
.
SingletonEnumerable
(
ienumerableType
.
Construct
(
typeArg
));
}
}
return
SpecializedCollections
.
SingletonEnumerable
(
ienumerableType
.
Construct
(
typeArg
));
}
return
SpecializedCollections
.
EmptyEnumerable
<
ITypeSymbol
>();
}
// We're right after the dot in "Foo.Bar". The type for "Bar" should be
// whatever type we'd infer for "Foo.Bar" itself.
return
InferTypes
(
memberAccessExpression
);
}
return
SpecializedCollections
.
EmptyEnumerable
<
ITypeSymbol
>();
}
private
ITypeSymbol
InferTypeForFirstParameterOfLambda
(
...
...
src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicTypeInferenceService.TypeInferrer.vb
浏览文件 @
6bdb5a53
...
...
@@ -828,17 +828,107 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' then we can figure out what 'foo' should be based on teh await
' context.
If
expressionOpt
Is
memberAccessExpression
.
Expression
Then
If
memberAccessExpression
.
Name
.
Identifier
.
Value
.
Equals
(
NameOf
(
Task
(
Of
Integer
).
ConfigureAwait
))
AndAlso
memberAccessExpression
.
IsParentKind
(
SyntaxKind
.
InvocationExpression
)
AndAlso
memberAccessExpression
.
Parent
.
IsParentKind
(
SyntaxKind
.
AwaitExpression
)
Then
Return
InferTypes
(
DirectCast
(
memberAccessExpression
.
Parent
,
ExpressionSyntax
))
Return
InferTypeForExpressionOfMemberAccessExpression
(
memberAccessExpression
)
End
If
Return
InferTypes
(
memberAccessExpression
)
End
If
End
Function
Private
Function
InferTypeForExpressionOfMemberAccessExpression
(
memberAccessExpression
As
MemberAccessExpressionSyntax
)
As
IEnumerable
(
Of
ITypeSymbol
)
Dim
name
=
memberAccessExpression
.
Name
.
Identifier
.
Value
If
name
.
Equals
(
NameOf
(
Task
(
Of
Integer
).
ConfigureAwait
))
AndAlso
memberAccessExpression
.
IsParentKind
(
SyntaxKind
.
InvocationExpression
)
AndAlso
memberAccessExpression
.
Parent
.
IsParentKind
(
SyntaxKind
.
AwaitExpression
)
Then
Return
InferTypes
(
DirectCast
(
memberAccessExpression
.
Parent
,
ExpressionSyntax
))
ElseIf
name
.
Equals
(
NameOf
(
Task
(
Of
Integer
).
ContinueWith
))
Then
' foo.ContinueWith(...)
' We want to infer Task<T>. For now, we'll just do Task<object>,
' in the future it would be nice to figure out the actual result
' type based on the argument to ContinueWith.
Dim
taskOfT
=
Me
.
Compilation
.
TaskOfTType
()
If
taskOfT
IsNot
Nothing
Then
Return
SpecializedCollections
.
SingletonEnumerable
(
taskOfT
.
Construct
(
Me
.
Compilation
.
ObjectType
))
End
If
ElseIf
name
.
Equals
(
NameOf
(
Enumerable
.
Select
))
OrElse
name
.
Equals
(
NameOf
(
Enumerable
.
Where
))
Then
Dim
ienumerableType
=
Me
.
Compilation
.
IEnumerableOfTType
()
' foo.Select
' We want to infer IEnumerable<T>. We can try to figure out what
' T if we get a delegate as the first argument to Select/Where.
If
ienumerableType
IsNot
Nothing
AndAlso
memberAccessExpression
.
IsParentKind
(
SyntaxKind
.
InvocationExpression
)
Then
Dim
invocation
=
DirectCast
(
memberAccessExpression
.
Parent
,
InvocationExpressionSyntax
)
If
invocation
.
ArgumentList
.
Arguments
.
Count
>
0
AndAlso
TypeOf
invocation
.
ArgumentList
.
Arguments
(
0
)
Is
SimpleArgumentSyntax
Then
Dim
argumentExpression
=
DirectCast
(
invocation
.
ArgumentList
.
Arguments
(
0
),
SimpleArgumentSyntax
).
Expression
Dim
argumentTypes
=
GetTypes
(
argumentExpression
)
Dim
delegateType
=
argumentTypes
.
FirstOrDefault
().
GetDelegateType
(
Me
.
Compilation
)
Dim
typeArg
=
If
(
delegateType
?
.
TypeArguments
.
Length
>
0
,
delegateType
.
TypeArguments
(
0
),
Me
.
Compilation
.
ObjectType
)
If
delegateType
Is
Nothing
OrElse
IsUnusableType
(
typeArg
)
Then
If
TypeOf
argumentExpression
Is
LambdaExpressionSyntax
Then
typeArg
=
If
(
InferTypeForFirstParameterOfLambda
(
DirectCast
(
argumentExpression
,
LambdaExpressionSyntax
)),
Me
.
Compilation
.
ObjectType
)
End
If
End
If
Return
SpecializedCollections
.
SingletonEnumerable
(
ienumerableType
.
Construct
(
typeArg
))
End
If
End
If
End
If
Return
SpecializedCollections
.
EmptyEnumerable
(
Of
ITypeSymbol
)()
Return
SpecializedCollections
.
EmptyEnumerable
(
Of
ITypeSymbol
)()
End
Function
Private
Function
InferTypeForFirstParameterOfLambda
(
lambda
As
LambdaExpressionSyntax
)
As
ITypeSymbol
If
lambda
.
SubOrFunctionHeader
.
ParameterList
.
Parameters
.
Count
>
0
Then
Dim
parameter
=
lambda
.
SubOrFunctionHeader
.
ParameterList
.
Parameters
(
0
)
Dim
parameterName
=
parameter
.
Identifier
.
Identifier
.
ValueText
If
TypeOf
lambda
Is
SingleLineLambdaExpressionSyntax
Then
Dim
singleLine
=
DirectCast
(
lambda
,
SingleLineLambdaExpressionSyntax
)
Return
InferTypeForFirstParameterOfLambda
(
parameterName
,
singleLine
.
Body
)
ElseIf
TypeOf
lambda
Is
MultiLineLambdaExpressionSyntax
Then
Dim
multiLine
=
DirectCast
(
lambda
,
MultiLineLambdaExpressionSyntax
)
For
Each
statement
In
multiLine
.
Statements
Dim
type
=
InferTypeForFirstParameterOfLambda
(
parameterName
,
statement
)
If
type
IsNot
Nothing
Then
Return
type
End
If
Next
End
If
End
If
Return
InferTypes
(
memberAccessExpression
)
Return
Nothing
End
Function
Private
Function
InferTypeForFirstParameterOfLambda
(
parameterName
As
String
,
node
As
SyntaxNode
)
As
ITypeSymbol
If
node
.
IsKind
(
SyntaxKind
.
IdentifierName
)
Then
Dim
identifier
=
DirectCast
(
node
,
IdentifierNameSyntax
)
If
CaseInsensitiveComparison
.
Equals
(
parameterName
,
identifier
.
Identifier
.
ValueText
)
Then
Return
InferTypes
(
identifier
).
FirstOrDefault
()
End
If
Else
For
Each
child
In
node
.
ChildNodesAndTokens
()
If
child
.
IsNode
Then
Dim
type
=
InferTypeForFirstParameterOfLambda
(
parameterName
,
child
.
AsNode
)
If
type
IsNot
Nothing
Then
Return
type
End
If
End
If
Next
End
If
Return
Nothing
End
Function
Private
Function
InferTypeInNamedFieldInitializer
(
initializer
As
NamedFieldInitializerSyntax
,
Optional
previousToken
As
SyntaxToken
=
Nothing
)
As
IEnumerable
(
Of
ITypeSymbol
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录