Skip to content

Commit 5213c18

Browse files
Property update return type when updating method. (#76157)
Fixes #55975
2 parents f9f45b9 + 0c56aa2 commit 5213c18

File tree

7 files changed

+600
-171
lines changed

7 files changed

+600
-171
lines changed

src/EditorFeatures/CSharpTest/Completion/CompletionProviders/AwaitCompletionProviderTests.cs

Lines changed: 126 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using System.Diagnostics.CodeAnalysis;
67
using System.Threading.Tasks;
78
using Microsoft.CodeAnalysis.CSharp;
89
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
@@ -14,32 +15,33 @@
1415
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations;
1516

1617
/// <summary>
17-
/// The <see cref="AwaitCompletionProvider"/> adds async modifier if the return type is Task or ValueTask.
18-
/// The tests here are only checking whether the completion item is provided or not.
19-
/// Tests for checking adding async modifier are in:
20-
/// src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_AwaitCompletion.vb
18+
/// The <see cref="AwaitCompletionProvider"/> adds async modifier if the return type is Task or ValueTask. The tests
19+
/// here are only checking whether the completion item is provided or not. Tests for checking adding async modifier are
20+
/// in: src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests_AwaitCompletion.vb
2121
/// </summary>
2222
[Trait(Traits.Feature, Traits.Features.Completion)]
23-
public class AwaitCompletionProviderTests : AbstractCSharpCompletionProviderTests
23+
public sealed class AwaitCompletionProviderTests : AbstractCSharpCompletionProviderTests
2424
{
2525
internal override Type GetCompletionProviderType() => typeof(AwaitCompletionProvider);
2626

2727
private const string CompletionDisplayTextAwait = "await";
2828
private const string CompletionDisplayTextAwaitAndConfigureAwait = "awaitf";
2929

30-
private async Task VerifyAbsenceAsync(string code)
30+
private async Task VerifyAbsenceAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string code)
3131
{
3232
await VerifyItemIsAbsentAsync(code, CompletionDisplayTextAwait);
3333
await VerifyItemIsAbsentAsync(code, CompletionDisplayTextAwaitAndConfigureAwait);
3434
}
3535

36-
private async Task VerifyAbsenceAsync(string code, LanguageVersion languageVersion = LanguageVersion.Default)
36+
private async Task VerifyAbsenceAsync(
37+
[StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string code, LanguageVersion languageVersion = LanguageVersion.Default)
3738
{
3839
await VerifyItemIsAbsentAsync(GetMarkup(code, languageVersion), CompletionDisplayTextAwait);
3940
await VerifyItemIsAbsentAsync(GetMarkup(code, languageVersion), CompletionDisplayTextAwaitAndConfigureAwait);
4041
}
4142

42-
private async Task VerifyKeywordAsync(string code, LanguageVersion languageVersion = LanguageVersion.Default, string? inlineDescription = null, bool dotAwait = false, bool dotAwaitf = false)
43+
private async Task VerifyKeywordAsync(
44+
[StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string code, LanguageVersion languageVersion = LanguageVersion.Default, string? inlineDescription = null, bool dotAwait = false, bool dotAwaitf = false)
4345
{
4446
var expectedDescription = dotAwait
4547
? GetDescription(CompletionDisplayTextAwait, FeaturesResources.Await_the_preceding_expression)
@@ -351,24 +353,24 @@ async Task F(Task<int> someTask)
351353
public async Task TestDotAwaitSuggestAfterDotOnValueTask()
352354
{
353355
var valueTaskAssembly = typeof(ValueTask).Assembly.Location;
354-
var markup = @$"
355-
<Workspace>
356-
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true"">
357-
<MetadataReference>{valueTaskAssembly}</MetadataReference>
358-
<Document FilePath=""Test2.cs"">
359-
using System.Threading.Tasks;
356+
var markup = $$"""
357+
<Workspace>
358+
<Project Language="C#" AssemblyName="Assembly1" CommonReferences="true">
359+
<MetadataReference>{{valueTaskAssembly}}</MetadataReference>
360+
<Document FilePath="Test2.cs">
361+
using System.Threading.Tasks;
360362
361-
class C
362-
{{
363-
async Task F(ValueTask someTask)
364-
{{
365-
someTask.$$
366-
}}
367-
}}
368-
</Document>
369-
</Project>
370-
</Workspace>
371-
";
363+
class C
364+
{
365+
async Task F(ValueTask someTask)
366+
{
367+
someTask.$$
368+
}
369+
}
370+
</Document>
371+
</Project>
372+
</Workspace>
373+
""";
372374
await VerifyItemExistsAsync(markup, "await");
373375
await VerifyItemExistsAsync(markup, "awaitf");
374376
}
@@ -499,18 +501,19 @@ async Task Test() { }
499501
[InlineData("async Task<System.Int32> Test() => await Task.FromResult(1);")]
500502
public async Task TestDotAwaitSuggestAfterDotBeforeDifferentStatements(string statement)
501503
{
502-
await VerifyKeywordAsync($@"
503-
using System;
504-
using System.Threading.Tasks;
504+
await VerifyKeywordAsync($$"""
505+
using System;
506+
using System.Threading.Tasks;
505507
506-
static class Program
507-
{{
508-
static async Task Main(Task someTask)
509-
{{
510-
someTask.$$
511-
{statement}
512-
}}
513-
}}", dotAwait: true, dotAwaitf: true);
508+
static class Program
509+
{
510+
static async Task Main(Task someTask)
511+
{
512+
someTask.$$
513+
{{statement}}
514+
}
515+
}
516+
""", dotAwait: true, dotAwaitf: true);
514517
}
515518

516519
[Theory]
@@ -546,38 +549,39 @@ static async Task Main(Task someTask)
546549
[InlineData("(null ?? Task.CompletedTask).$$")]
547550
public async Task TestDotAwaitSuggestAfterDifferentExpressions(string expression)
548551
{
549-
await VerifyKeywordAsync($@"
550-
using System;
551-
using System.Threading.Tasks;
552+
await VerifyKeywordAsync($$"""
553+
using System;
554+
using System.Threading.Tasks;
552555
553-
class C
554-
{{
555-
public C Self => this;
556-
public Task Field = Task.CompletedTask;
557-
public Task Method() => Task.CompletedTask;
558-
public Task Property => Task.CompletedTask;
559-
public Task this[int i] => Task.CompletedTask;
560-
public Func<Task> Function() => () => Task.CompletedTask;
561-
public static Task operator +(C left, C right) => Task.CompletedTask;
562-
public static explicit operator Task(C c) => Task.CompletedTask;
563-
}}
556+
class C
557+
{
558+
public C Self => this;
559+
public Task Field = Task.CompletedTask;
560+
public Task Method() => Task.CompletedTask;
561+
public Task Property => Task.CompletedTask;
562+
public Task this[int i] => Task.CompletedTask;
563+
public Func<Task> Function() => () => Task.CompletedTask;
564+
public static Task operator +(C left, C right) => Task.CompletedTask;
565+
public static explicit operator Task(C c) => Task.CompletedTask;
566+
}
564567
565-
static class Program
566-
{{
567-
static Task StaticField = Task.CompletedTask;
568-
static Task StaticProperty => Task.CompletedTask;
569-
static Task StaticMethod() => Task.CompletedTask;
568+
static class Program
569+
{
570+
static Task StaticField = Task.CompletedTask;
571+
static Task StaticProperty => Task.CompletedTask;
572+
static Task StaticMethod() => Task.CompletedTask;
570573
571-
static async Task Main(Task parameter)
572-
{{
573-
Task local = Task.CompletedTask;
574-
var c = new C();
574+
static async Task Main(Task parameter)
575+
{
576+
Task local = Task.CompletedTask;
577+
var c = new C();
575578
576-
{expression}
579+
{{expression}}
577580
578-
Task LocalFunction() => Task.CompletedTask;
579-
}}
580-
}}", dotAwait: true, dotAwaitf: true);
581+
Task LocalFunction() => Task.CompletedTask;
582+
}
583+
}
584+
""", dotAwait: true, dotAwaitf: true);
581585
}
582586

583587
[Fact(Skip = "Fails because speculative binding can't figure out that local is a Task.")]
@@ -618,17 +622,18 @@ static async Task Main()
618622
[InlineData("await Task.Run(() => someTask.$$")]
619623
public async Task TestDotAwaitSuggestInLambdas(string lambda)
620624
{
621-
await VerifyKeywordAsync($@"
622-
using System.Threading.Tasks;
625+
await VerifyKeywordAsync($$"""
626+
using System.Threading.Tasks;
623627
624-
static class Program
625-
{{
626-
static async Task Main()
627-
{{
628-
var someTask = Task.CompletedTask;
629-
{lambda}
630-
}}
631-
}}", dotAwait: true, dotAwaitf: true);
628+
static class Program
629+
{
630+
static async Task Main()
631+
{
632+
var someTask = Task.CompletedTask;
633+
{{lambda}}
634+
}
635+
}
636+
""", dotAwait: true, dotAwaitf: true);
632637
}
633638

634639
[Fact]
@@ -854,25 +859,25 @@ async Task F(Task someTask)
854859
[InlineData("new C().M()?.Pro.M()?.M().SomeTask.$$")]
855860
public async Task TestDotAwaitNotAfterDotInConditionalAccessChain(string conditionalAccess)
856861
{
857-
await VerifyAbsenceAsync($@"
858-
using System.Threading.Tasks;
859-
public class C
860-
{{
861-
public Task SomeTask => Task.CompletedTask;
862-
863-
public C Pro => this;
864-
public C M() => this;
865-
}}
866-
867-
static class Program
868-
{{
869-
public static async Task Main()
870-
{{
871-
var c = new C();
872-
{conditionalAccess}
873-
}}
874-
}}
875-
");
862+
await VerifyAbsenceAsync($$"""
863+
using System.Threading.Tasks;
864+
public class C
865+
{
866+
public Task SomeTask => Task.CompletedTask;
867+
868+
public C Pro => this;
869+
public C M() => this;
870+
}
871+
872+
static class Program
873+
{
874+
public static async Task Main()
875+
{
876+
var c = new C();
877+
{{conditionalAccess}}
878+
}
879+
}
880+
""");
876881
}
877882

878883
[Theory]
@@ -895,41 +900,42 @@ public static async Task Main()
895900
[InlineData("new C().M()!.Pro.M()!.M().SomeTask.$$")]
896901
public async Task TestDotAwaitAfterNullForgivingOperatorAccessChain(string nullForgivingAccess)
897902
{
898-
await VerifyKeywordAsync($@"
899-
#nullable enable
903+
await VerifyKeywordAsync($$"""
904+
#nullable enable
900905
901-
using System.Threading.Tasks;
902-
public class C
903-
{{
904-
public Task? SomeTask => Task.CompletedTask;
905-
906-
public C? Pro => this;
907-
public C? M() => this;
908-
}}
909-
910-
static class Program
911-
{{
912-
public static async Task Main(params string[] args)
913-
{{
914-
var c = args[1] == string.Empty ? new C() : null;
915-
{nullForgivingAccess}
916-
}}
917-
}}
918-
", dotAwait: true, dotAwaitf: true);
906+
using System.Threading.Tasks;
907+
public class C
908+
{
909+
public Task? SomeTask => Task.CompletedTask;
910+
911+
public C? Pro => this;
912+
public C? M() => this;
913+
}
914+
915+
static class Program
916+
{
917+
public static async Task Main(params string[] args)
918+
{
919+
var c = args[1] == string.Empty ? new C() : null;
920+
{{nullForgivingAccess}}
921+
}
922+
}
923+
""", dotAwait: true, dotAwaitf: true);
919924
}
920925

921926
[Theory, CombinatorialData]
922927
[WorkItem("https://github.com/dotnet/roslyn/issues/58921")]
923928
public async Task TestInCastExpressionThatMightBeParenthesizedExpression(bool hasNewline)
924929
{
925-
var code = $@"
926-
class C
927-
{{
928-
void M()
929-
{{
930-
var data = (n$$) {(hasNewline ? Environment.NewLine : string.Empty)} M();
931-
}}
932-
}}";
930+
var code = $$"""
931+
class C
932+
{
933+
void M()
934+
{
935+
var data = (n$$) {{(hasNewline ? Environment.NewLine : string.Empty)}} M();
936+
}
937+
}
938+
""";
933939
if (hasNewline)
934940
await VerifyKeywordAsync(code);
935941
else

0 commit comments

Comments
 (0)