提交 41a1d643 编写于 作者: C CyrusNajmabadi

Fix inference in awaits.

上级 91cad676
......@@ -2757,7 +2757,15 @@ public async Task TestGenerateMethodWithConfigureAwaitFalse()
public async Task TestGenerateMethodWithMethodChaining()
{
await TestAsync(
@"using System ; using System . Collections . Generic ; using System . Linq ; using System . Threading . Tasks ; class Program { static void Main ( string [ ] args ) { bool x = await [|Foo|] ( ) . ConfigureAwait ( false ) ; } } ",
@"using System ;
using System . Collections . Generic ;
using System . Linq ;
using System . Threading . Tasks ;
class Program {
static void Main ( string [ ] args ) {
bool x = await [|Foo|] ( ) . ConfigureAwait ( false ) ;
}
}",
@"using System ; using System . Collections . Generic ; using System . Linq ; using System . Threading . Tasks ; class Program { static void Main ( string [ ] args ) { bool x = await Foo ( ) . ConfigureAwait ( false ) ; } private static Task < bool > Foo ( ) { throw new NotImplementedException ( ) ; } } ");
}
......@@ -2766,8 +2774,14 @@ public async Task TestGenerateMethodWithMethodChaining()
public async Task TestGenerateMethodWithMethodChaining2()
{
await TestAsync(
@"using System ; using System . Threading . Tasks ; class C { static async void T ( ) { bool x = await [|M|] ( ) . ContinueWith ( a => { return true ; } ) . ContinueWith ( a => { return false ; } ) ; } } ",
@"using System ; using System . Threading . Tasks ; class C { static async void T ( ) { bool x = await M ( ) . ContinueWith ( a => { return true ; } ) . ContinueWith ( a => { return false ; } ) ; } private static Task < bool > M ( ) { throw new NotImplementedException ( ) ; } } ");
@"using System ;
using System . Threading . Tasks ;
class C {
static async void T ( ) {
bool x = await [|M|] ( ) . ContinueWith ( a => { return true ; } ) . ContinueWith ( a => { return false ; } ) ;
}
} ",
@"using System ; using System . Threading . Tasks ; class C { static async void T ( ) { bool x = await M ( ) . ContinueWith ( a => { return true ; } ) . ContinueWith ( a => { return false ; } ) ; } private static object M ( ) { throw new NotImplementedException ( ) ; } } ");
}
[WorkItem(529480, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529480")]
......
......@@ -1591,7 +1591,7 @@ static async void T()
bool x = await [|M()|].ConfigureAwait(false);
}
}";
await TestAsync(text, "global::System.Threading.Tasks.Task<System.Boolean>");
await TestAsync(text, "global::System.Threading.Tasks.Task<System.Boolean>", testPosition: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
......@@ -1609,7 +1609,7 @@ static async void T()
bool x = await [|M|].ContinueWith(a => { return true; }).ContinueWith(a => { return false; });
}
}";
await TestAsync(text, "global::System.Threading.Tasks.Task<System.Boolean>");
await TestAsync(text, "System.Object", testPosition: false);
}
[Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)]
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Option Strict Off
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.GenerateMethod
Imports Microsoft.CodeAnalysis.Diagnostics
Imports System.Threading.Tasks
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.GenerateMethod
Public Class GenerateMethodTests
......@@ -2190,17 +2188,24 @@ index:=1)
<Fact(), Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)>
Public Async Function TestGenerateMethodWithMethodChaining() As Task
Await TestAsync(
NewLines("Imports System \n Imports System.Linq \n Module M \n Async Sub T() \n Dim x As Boolean = Await [|F|]().ContinueWith(Function(a) True).ContinueWith(Function(a) False) \n End Sub \n End Module"),
NewLines("Imports System\nImports System.Linq\nImports System.Threading.Tasks\n\nModule M\n Async Sub T()\n Dim x As Boolean = Await F().ContinueWith(Function(a) True).ContinueWith(Function(a) False)\n End Sub\n\n Private Function F() As Task(Of Boolean)\n Throw New NotImplementedException()\n End Function\nEnd Module"))
End Function
<WorkItem(643, "https://github.com/dotnet/roslyn/issues/643")>
<Fact(), Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)>
Public Async Function TestGenerateMethodWithMethodChaining2() As Task
Await TestAsync(
NewLines("Imports System \n Imports System.Linq \n Module M \n Async Sub T() \n Dim x As Boolean = Await [|F|]().ContinueWith(Function(a) True).ContinueWith(Function(a) False) \n End Sub \n End Module"),
NewLines("Imports System\nImports System.Linq\nImports System.Threading.Tasks\n\nModule M\n Async Sub T()\n Dim x As Boolean = Await F().ContinueWith(Function(a) True).ContinueWith(Function(a) False)\n End Sub\n\n Private ReadOnly Property F As Task(Of Boolean)\n Get\n Throw New NotImplementedException()\n End Get\n End Property\nEnd Module"),
index:=1)
"Imports System
Imports System.Linq
Module M
Async Sub T()
Dim x As Boolean = Await [|F|]().ConfigureAwait(False)
End Sub
End Module",
"Imports System
Imports System.Linq
Imports System.Threading.Tasks
Module M
Async Sub T()
Dim x As Boolean = Await F().ConfigureAwait(False)
End Sub
Private Function F() As Task(Of Boolean)
Throw New NotImplementedException()
End Function
End Module")
End Function
<WorkItem(1130960, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1130960")>
......
......@@ -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, "Global.System.Threading.Tasks.Task(Of System.Boolean)", testPosition:=True)
Await TestAsync(text, "System.Object", testPosition:=False)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)>
......@@ -719,7 +719,7 @@ Module M
Dim x As Boolean = Await [|F|].ConfigureAwait(False)
End Sub
End Module"
Await TestAsync(text, "Global.System.Threading.Tasks.Task(Of System.Boolean)", testPosition:=True)
Await TestAsync(text, "Global.System.Threading.Tasks.Task(Of System.Boolean)", testPosition:=False)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.TypeInferenceService)>
......
......@@ -6,6 +6,7 @@
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Shared.Extensions;
......@@ -1446,22 +1447,37 @@ private IEnumerable<ITypeSymbol> InferTypeInNameColon(NameColonSyntax nameColon,
return SpecializedCollections.EmptyEnumerable<ITypeSymbol>();
}
// fall through
// 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);
}
else
{
Debug.Assert(expressionOpt != null);
if (expressionOpt != memberAccessExpression.Name)
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.
if (memberAccessExpression.Name.Identifier.Value.Equals(nameof(Task<int>.ConfigureAwait)) &&
memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) &&
memberAccessExpression.Parent.IsParentKind(SyntaxKind.AwaitExpression))
{
return InferTypes((ExpressionSyntax)memberAccessExpression.Parent);
}
return SpecializedCollections.EmptyEnumerable<ITypeSymbol>();
}
// fall through
// 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);
}
// 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> InferTypeInNameEquals(NameEqualsSyntax nameEquals, SyntaxToken? previousToken = null)
......
......@@ -2,6 +2,7 @@
Imports System.Collections.Immutable
Imports System.Threading
Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
......@@ -816,15 +817,28 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If previousToken.Value <> memberAccessExpression.OperatorToken Then
Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)
End If
' fall through
Return InferTypes(memberAccessExpression)
Else
If expressionOpt IsNot memberAccessExpression.Name Then
Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)
' 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.
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))
End If
Return SpecializedCollections.EmptyEnumerable(Of ITypeSymbol)()
End If
' fall through
End If
Return InferTypes(memberAccessExpression)
Return InferTypes(memberAccessExpression)
End If
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.
先完成此消息的编辑!
想要评论请 注册