diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs index 8a28773c4c0cb..c8077005d0dcc 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs @@ -792,6 +792,33 @@ readonly struct Colors await VerifyItemIsAbsentAsync(markup + colorsLike, "Colors"); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task NotAfterAsync1() + { + var markup = @" +class Test +{ + public async $$ +}"; + + await VerifyNoItemsExistAsync(markup); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task NotAfterAsync2() + { + var markup = @" +class Test +{ + public async $$ + public void M() {} +}"; + + await VerifyNoItemsExistAsync(markup); + } + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] public async Task NotAfterDot() { diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SpeculativeTCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SpeculativeTCompletionProviderTests.cs index 4ccee4bb71c37..621181b5a0f3e 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SpeculativeTCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SpeculativeTCompletionProviderTests.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.CSharp.Completion.Providers; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -864,7 +865,7 @@ async Task<$$ } [Fact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task OkAfterAsync() + public async Task NotOkAfterAsync() { var markup = @" using System.Threading.Tasks; @@ -873,7 +874,7 @@ class Program async $$ }"; - await VerifyItemExistsAsync(markup, "T"); + await VerifyItemIsAbsentAsync(markup, "T"); } [WorkItem(968256, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/968256")] diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs index 44a98dc4fc70a..ebd748860d147 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs @@ -2296,22 +2296,16 @@ void M(String parameter) await VerifyItemIsAbsentAsync(markup, "parameter"); } - [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.Completion)] + [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [InlineData("extern")] [InlineData("static extern")] [InlineData("extern static")] - [InlineData("async")] - [InlineData("static async")] - [InlineData("async static")] [InlineData("unsafe")] [InlineData("static unsafe")] [InlineData("unsafe static")] - [InlineData("async unsafe")] - [InlineData("unsafe async")] [InlineData("unsafe extern")] [InlineData("extern unsafe")] - [InlineData("extern unsafe async static")] public async Task AfterLocalFunction_TypeOnly(string keyword) { var markup = $@" @@ -2328,21 +2322,45 @@ void M(String parameter) await VerifyItemIsAbsentAsync(markup, "parameter"); } + [Theory, Trait(Traits.Feature, Traits.Features.Completion)] + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [InlineData("async")] + [InlineData("static async")] + [InlineData("async static")] + [InlineData("async unsafe")] + [InlineData("unsafe async")] + [InlineData("extern unsafe async static")] + public async Task AfterLocalFunction_TypeOnly_Async(string keyword) + { + var markup = $@" +using System; +class C +{{ + void M(String parameter) + {{ + {keyword} $$ + }} +}} +"; + await VerifyItemIsAbsentAsync(markup, "String"); + await VerifyItemIsAbsentAsync(markup, "parameter"); + } + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] - [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] public async Task AfterAsyncLocalFunctionWithTwoAsyncs() { var markup = @" using System; class C { - void M(String parameter) + void M(string parameter) { async async $$ } } "; - await VerifyItemExistsAsync(markup, "String"); + await VerifyItemIsAbsentAsync(markup, "String"); await VerifyItemIsAbsentAsync(markup, "parameter"); } @@ -7252,6 +7270,55 @@ public async T$$ await VerifyItemExistsAsync(markup, "Task"); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task AfterAsync3() + { + var markup = @" +using System.Threading.Tasks; +class Program +{ + public async $$ + + public void M() {} +}"; + + await VerifyItemExistsAsync(markup, "Task"); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task AfterAsync4() + { + var markup = @" +using System; +using System.Threading.Tasks; +class Program +{ + public async $$ +}"; + + await VerifyItemExistsAsync(markup, "Task"); + await VerifyItemIsAbsentAsync(markup, "Console"); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task AfterAsync5() + { + var markup = @" +using System.Threading.Tasks; +class Program +{ + public async $$ +} + +class Test {}"; + + await VerifyItemExistsAsync(markup, "Task"); + await VerifyItemIsAbsentAsync(markup, "Test"); + } + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] public async Task NotAfterAsyncInMethodBody() { diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs index 6c34c79dfe860..a06e89504d888 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs @@ -694,13 +694,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -786,10 +788,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs index 3ded8f7240961..96a2f3132964e 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs @@ -695,13 +695,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -787,10 +789,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/CharKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/CharKeywordRecommenderTests.cs index c3ecc55a8fd65..e32a115a46052 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/CharKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/CharKeywordRecommenderTests.cs @@ -667,13 +667,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(988025, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/988025")] [Fact, Trait(Traits.Feature, Traits.Features.Completion)] @@ -816,10 +818,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/DecimalKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/DecimalKeywordRecommenderTests.cs index 760ef8121886e..58a73cf27734f 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/DecimalKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/DecimalKeywordRecommenderTests.cs @@ -683,13 +683,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -780,10 +782,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/DoubleKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/DoubleKeywordRecommenderTests.cs index 91efa10815b10..48bbbde2190fc 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/DoubleKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/DoubleKeywordRecommenderTests.cs @@ -667,13 +667,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -764,10 +766,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/DynamicKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/DynamicKeywordRecommenderTests.cs index 3405e7a6f4a39..df84dc0948c13 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/DynamicKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/DynamicKeywordRecommenderTests.cs @@ -635,13 +635,15 @@ await VerifyAbsenceAsync( }"); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestInFunctionPointerType() diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/FloatKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/FloatKeywordRecommenderTests.cs index 38dbb6239f2f6..556867187624c 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/FloatKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/FloatKeywordRecommenderTests.cs @@ -640,13 +640,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -737,10 +739,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/IntKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/IntKeywordRecommenderTests.cs index c20bf02c4e756..c21791756a209 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/IntKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/IntKeywordRecommenderTests.cs @@ -740,13 +740,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -851,10 +853,19 @@ await VerifyKeywordAsync(AddInsideMethod( [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/LongKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/LongKeywordRecommenderTests.cs index 1c1a27b134961..32e1466f8551c 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/LongKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/LongKeywordRecommenderTests.cs @@ -667,13 +667,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -764,10 +766,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/NativeIntegerKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/NativeIntegerKeywordRecommenderTests.cs index 1a1a6cc3958e7..36547d810359b 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/NativeIntegerKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/NativeIntegerKeywordRecommenderTests.cs @@ -19,7 +19,7 @@ public class NativeIntegerKeywordRecommenderTests : RecommenderTests public NativeIntegerKeywordRecommenderTests() { - this.RecommendKeywordsAsync = (position, context) => Task.FromResult(_recommender.RecommendKeywords(position, context, CancellationToken.None)); + RecommendKeywordsAsync = (position, context) => Task.FromResult(_recommender.RecommendKeywords(position, context, CancellationToken.None)); } private async Task VerifyKeywordAsync(string text) @@ -292,6 +292,16 @@ class C delegate* await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -785,10 +787,19 @@ await VerifyKeywordAsync(AddInsideMethod( [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/SByteKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/SByteKeywordRecommenderTests.cs index 0c08b4471dcb9..3ba1762391601 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/SByteKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/SByteKeywordRecommenderTests.cs @@ -667,13 +667,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -764,10 +766,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ShortKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ShortKeywordRecommenderTests.cs index d3830ff09361c..4380b16ce7947 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ShortKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ShortKeywordRecommenderTests.cs @@ -667,9 +667,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -760,10 +766,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/StringKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/StringKeywordRecommenderTests.cs index 3d1b1ed2a07cb..1ef289d13266e 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/StringKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/StringKeywordRecommenderTests.cs @@ -176,13 +176,22 @@ await VerifyKeywordAsync(AddInsideMethod( [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" {keyword} $$")); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" +{keyword} $$")); + } + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] public async Task TestAfterRefExpression() { @@ -726,9 +735,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/TheoryDataKeywordsIndicatingLocalFunction.cs b/src/EditorFeatures/CSharpTest2/Recommendations/TheoryDataKeywordsIndicatingLocalFunction.cs index b2bac2fac98f5..fb7aa449a3062 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/TheoryDataKeywordsIndicatingLocalFunction.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/TheoryDataKeywordsIndicatingLocalFunction.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; using System.Collections; using System.Collections.Generic; @@ -30,4 +29,36 @@ public IEnumerator GetEnumerator() IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } + + internal class TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { "extern" }; + yield return new object[] { "static extern" }; + yield return new object[] { "extern static" }; + yield return new object[] { "unsafe" }; + yield return new object[] { "static unsafe" }; + yield return new object[] { "unsafe static" }; + yield return new object[] { "unsafe extern" }; + yield return new object[] { "extern unsafe" }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + internal class TheoryDataKeywordsIndicatingLocalFunctionWithAsync : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { "async" }; + yield return new object[] { "static async" }; + yield return new object[] { "async static" }; + yield return new object[] { "async unsafe" }; + yield return new object[] { "unsafe async" }; + yield return new object[] { "extern unsafe async static" }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/UIntKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/UIntKeywordRecommenderTests.cs index 7ea4e0cd064b2..a9c70a1c83c62 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/UIntKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/UIntKeywordRecommenderTests.cs @@ -667,13 +667,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -764,10 +766,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ULongKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ULongKeywordRecommenderTests.cs index 20f69728b3c8a..e2961a412a558 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ULongKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ULongKeywordRecommenderTests.cs @@ -667,13 +667,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -764,10 +766,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/UShortKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/UShortKeywordRecommenderTests.cs index a41f929c1fc4d..2a94e1f7005c3 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/UShortKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/UShortKeywordRecommenderTests.cs @@ -667,13 +667,15 @@ class C { } "); } + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsync() - => await VerifyKeywordAsync(@"class c { async $$ }"); + public async Task TestNotAfterAsync() + => await VerifyAbsenceAsync(@"class c { async $$ }"); + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - public async Task TestAfterAsyncAsType() - => await VerifyKeywordAsync(@"class c { async async $$ }"); + public async Task TestNotAfterAsyncAsType() + => await VerifyAbsenceAsync(@"class c { async async $$ }"); [WorkItem(1468, "https://github.com/dotnet/roslyn/issues/1468")] [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] @@ -764,10 +766,19 @@ class C [WorkItem(53585, "https://github.com/dotnet/roslyn/issues/53585")] [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] - [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunction))] - public async Task TestAfterKeywordIndicatingLocalFunction(string keyword) + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithoutAsync))] + public async Task TestAfterKeywordIndicatingLocalFunctionWithoutAsync(string keyword) { await VerifyKeywordAsync(AddInsideMethod($@" +{keyword} $$")); + } + + [WorkItem(60341, "https://github.com/dotnet/roslyn/issues/60341")] + [Theory, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + [ClassData(typeof(TheoryDataKeywordsIndicatingLocalFunctionWithAsync))] + public async Task TestNotAfterKeywordIndicatingLocalFunctionWithAsync(string keyword) + { + await VerifyAbsenceAsync(AddInsideMethod($@" {keyword} $$")); } } diff --git a/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb index 4b7634dfc4a2a..ded052db68087 100644 --- a/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb @@ -2659,7 +2659,7 @@ End Class New OptionKey(CompletionOptionsStorage.SnippetsBehavior, LanguageNames.VisualBasic), SnippetsRule.AlwaysInclude) state.SendTypeChars("Shortcu") - Await state.AssertSelectedCompletionItem(displayText:="Shortcut", isHardSelected:=True) + Await state.AssertNoCompletionSession() state.SendTypeChars(":") Assert.Contains("(Shortcu:", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) End Using @@ -2681,7 +2681,7 @@ End Class New OptionKey(CompletionOptionsStorage.SnippetsBehavior, LanguageNames.VisualBasic), SnippetsRule.AlwaysInclude) state.SendTypeChars("Shortcu") - Await state.AssertSelectedCompletionItem(displayText:="Shortcut", isHardSelected:=True) + Await state.AssertNoCompletionSession() state.SendTypeChars(":") Assert.Contains("(1, Shortcu:", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) End Using diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/KeywordCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/KeywordCompletionProviderTests.vb index 3596137b01918..c48eb0ac331db 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/KeywordCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/KeywordCompletionProviderTests.vb @@ -36,6 +36,34 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Completion.Complet Await VerifyAnyItemExistsAsync(markup) End Function + + Public Async Function TestNoTypeKeywordsInAsyncMemberDeclaration() As Task + Dim code = +Class C + Public Async Function Test() As $$ + + End Function +End Class +.Value + + Await VerifyItemIsAbsentAsync(code, "Boolean") + Await VerifyItemIsAbsentAsync(code, "Byte") + Await VerifyItemIsAbsentAsync(code, "Char") + Await VerifyItemIsAbsentAsync(code, "Date") + Await VerifyItemIsAbsentAsync(code, "Decimal") + Await VerifyItemIsAbsentAsync(code, "Double") + Await VerifyItemIsAbsentAsync(code, "Integer") + Await VerifyItemIsAbsentAsync(code, "Long") + Await VerifyItemIsAbsentAsync(code, "Object") + Await VerifyItemIsAbsentAsync(code, "SByte") + Await VerifyItemIsAbsentAsync(code, "Short") + Await VerifyItemIsAbsentAsync(code, "Single") + Await VerifyItemIsAbsentAsync(code, "String") + Await VerifyItemIsAbsentAsync(code, "UInteger") + Await VerifyItemIsAbsentAsync(code, "ULong") + Await VerifyItemIsAbsentAsync(code, "UShort") + End Function + Public Async Function TestNotInInactiveCode() As Task Dim code = diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs index 31178b7320210..d18b025f07732 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/DeclarationNameCompletionProvider.cs @@ -255,7 +255,7 @@ private static async Task GetRecommendedNamesAsync( { var rules = await document.GetNamingRulesAsync(FallbackNamingRules.CompletionFallbackRules, cancellationToken).ConfigureAwait(false); var supplementaryRules = FallbackNamingRules.CompletionSupplementaryRules; - var semanticFactsService = context.GetLanguageService(); + var semanticFactsService = context.GetRequiredLanguageService(); using var _1 = PooledHashSet.GetInstance(out var seenBaseNames); using var _2 = PooledHashSet.GetInstance(out var seenUniqueNames); diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs index a87623bd88cc2..35cd8755be451 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs @@ -69,9 +69,13 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) if (tree.IsInNonUserCode(position, cancellationToken)) return; - var token = tree.FindTokenOnLeftOfPosition(position, cancellationToken) - .GetPreviousTokenIfTouchingWord(position); + var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); + var syntaxContext = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); + + if (syntaxContext.IsInTaskLikeTypeContext) + return; + var token = syntaxContext.TargetToken; if (token.IsMandatoryNamedParameterPosition()) return; @@ -85,7 +89,6 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) var typeInferenceService = document.GetLanguageService(); Contract.ThrowIfNull(typeInferenceService, nameof(typeInferenceService)); - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); var types = typeInferenceService.InferTypes(semanticModel, position, cancellationToken); if (types.Length == 0) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs index 194784d9bffde..c7f4aa577c010 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/SnippetCompletionProvider.cs @@ -11,12 +11,12 @@ using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.ErrorReporting; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.LanguageServices; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Snippets; using Microsoft.CodeAnalysis.Text; @@ -87,12 +87,16 @@ private static async Task> GetSnippetsForDocument if (syntaxFacts.IsInNonUserCode(syntaxTree, position, cancellationToken) || syntaxTree.IsRightOfDotOrArrowOrColonColon(position, targetToken, cancellationToken) || - syntaxFacts.GetContainingTypeDeclaration(root, position) is EnumDeclarationSyntax) + syntaxFacts.GetContainingTypeDeclaration(root, position) is EnumDeclarationSyntax || + syntaxTree.IsPossibleTupleContext(leftToken, position)) { return ImmutableArray.Empty; } - var isPossibleTupleContext = syntaxFacts.IsPossibleTupleContext(syntaxTree, position, cancellationToken); + var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); + var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); + if (context.IsInTaskLikeTypeContext) + return ImmutableArray.Empty; if (syntaxFacts.IsPreProcessorDirectiveContext(syntaxTree, position, cancellationToken)) { @@ -112,16 +116,12 @@ private static async Task> GetSnippetsForDocument SyntaxKind.EndRegionKeyword, SyntaxKind.WarningKeyword)) { - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); return GetSnippetCompletionItems( - document.Project.Solution.Workspace, semanticModel, isPreProcessorContext: true, - isTupleContext: isPossibleTupleContext); + document.Project.Solution.Workspace, semanticModel, isPreProcessorContext: true); } } else { - var semanticModel = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false); - if (semanticFacts.IsGlobalStatementContext(semanticModel, position, cancellationToken) || semanticFacts.IsExpressionContext(semanticModel, position, cancellationToken) || semanticFacts.IsStatementContext(semanticModel, position, cancellationToken) || @@ -133,19 +133,15 @@ private static async Task> GetSnippetsForDocument semanticFacts.IsLabelContext(semanticModel, position, cancellationToken)) { return GetSnippetCompletionItems( - document.Project.Solution.Workspace, semanticModel, isPreProcessorContext: false, - isTupleContext: isPossibleTupleContext); + document.Project.Solution.Workspace, semanticModel, isPreProcessorContext: false); } } return ImmutableArray.Empty; } - private static readonly CompletionItemRules s_tupleRules = CompletionItemRules.Default. - WithCommitCharacterRule(CharacterSetModificationRule.Create(CharacterSetModificationKind.Remove, ':')); - private static ImmutableArray GetSnippetCompletionItems( - Workspace workspace, SemanticModel semanticModel, bool isPreProcessorContext, bool isTupleContext) + Workspace workspace, SemanticModel semanticModel, bool isPreProcessorContext) { var service = workspace.Services.GetLanguageServices(semanticModel.Language).GetService(); if (service == null) @@ -159,8 +155,7 @@ private static ImmutableArray GetSnippetCompletionItems( return snippets.SelectAsArray(snippet => { - var rules = isTupleContext ? s_tupleRules : CompletionItemRules.Default; - rules = rules.WithFormatOnCommit(service.ShouldFormatSnippet(snippet)); + var rules = CompletionItemRules.Default.WithFormatOnCommit(service.ShouldFormatSnippet(snippet)); return CommonCompletionItem.Create( displayText: isPreProcessorContext ? snippet.Shortcut[1..] : snippet.Shortcut, diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs index 9ce5cb6095dd6..6683678142149 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/SpeculativeTCompletionProvider.cs @@ -78,6 +78,10 @@ private static async Task ShouldShowSpeculativeTCompletionItemAsync(Docume var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); var semanticModel = await document.ReuseExistingSpeculativeModelAsync(token.Parent, cancellationToken).ConfigureAwait(false); + var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); + if (context.IsInTaskLikeTypeContext) + return false; + var spanStart = position; while (true) { diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs index 92d79003136e0..e5e6ec9536eb5 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs @@ -26,7 +26,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers [ExportCompletionProvider(nameof(SymbolCompletionProvider), LanguageNames.CSharp)] [ExtensionOrder(After = nameof(SpeculativeTCompletionProvider))] [Shared] - internal partial class SymbolCompletionProvider : AbstractRecommendationServiceBasedCompletionProvider + internal sealed class SymbolCompletionProvider : AbstractRecommendationServiceBasedCompletionProvider { private static readonly Dictionary<(bool importDirective, bool preselect, bool tupleLiteral), CompletionItemRules> s_cachedRules = new(); @@ -73,6 +73,8 @@ public SymbolCompletionProvider() { } + public override ImmutableHashSet TriggerCharacters { get; } = CompletionUtilities.CommonTriggerCharactersWithArgumentList; + internal override string Language => LanguageNames.CSharp; protected override CompletionItemSelectionBehavior PreselectedItemSelectionBehavior => CompletionItemSelectionBehavior.HardSelection; @@ -129,8 +131,6 @@ internal override async Task IsSyntacticTriggerCharacterAsync(Document doc return true; } - public override ImmutableHashSet TriggerCharacters { get; } = CompletionUtilities.CommonTriggerCharactersWithArgumentList; - protected override bool IsTriggerOnDot(SyntaxToken token, int characterPosition) { if (!CompletionUtilities.TreatAsDot(token, characterPosition)) diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractNativeIntegerKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractNativeIntegerKeywordRecommender.cs index 1b040fb509a1f..205174c1e9cee 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractNativeIntegerKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractNativeIntegerKeywordRecommender.cs @@ -15,6 +15,9 @@ internal abstract class AbstractNativeIntegerKeywordRecommender : IKeywordRecomm private static bool IsValidContext(CSharpSyntaxContext context) { + if (context.IsInTaskLikeTypeContext) + return false; + if (context.IsStatementContext || context.IsGlobalStatementContext || context.IsPossibleTupleContext || diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSpecialTypePreselectingKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSpecialTypePreselectingKeywordRecommender.cs index c9acbf783ed71..abc9fd36edf72 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSpecialTypePreselectingKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSpecialTypePreselectingKeywordRecommender.cs @@ -19,8 +19,18 @@ public AbstractSpecialTypePreselectingKeywordRecommender( } protected abstract SpecialType SpecialType { get; } + protected abstract bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken); protected override bool ShouldPreselect(CSharpSyntaxContext context, CancellationToken cancellationToken) => context.InferredTypes.Any(t => t.SpecialType == SpecialType); + + protected sealed override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + { + // Filter out all special-types from locations where we think we only want something task-like. + if (context.IsInTaskLikeTypeContext) + return false; + + return IsValidContextWorker(position, context, cancellationToken); + } } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/BoolKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/BoolKeywordRecommender.cs index 81b7436a6c8df..df0444e421816 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/BoolKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/BoolKeywordRecommender.cs @@ -20,7 +20,7 @@ public BoolKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ByteKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ByteKeywordRecommender.cs index 3a37ee8a9cc34..5db83842691a9 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ByteKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ByteKeywordRecommender.cs @@ -20,10 +20,9 @@ public ByteKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; - return context.IsAnyExpressionContext || context.IsDefiniteCastTypeContext || diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/CharKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/CharKeywordRecommender.cs index 315d31b52f2e8..f36bf57d3b181 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/CharKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/CharKeywordRecommender.cs @@ -20,7 +20,7 @@ public CharKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DecimalKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DecimalKeywordRecommender.cs index 9eea27ae2bc4d..ea0fe6999c515 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DecimalKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DecimalKeywordRecommender.cs @@ -20,7 +20,7 @@ public DecimalKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DoubleKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DoubleKeywordRecommender.cs index bf5a6113f5c1f..bc270126ab6bf 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DoubleKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DoubleKeywordRecommender.cs @@ -20,7 +20,7 @@ public DoubleKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DynamicKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DynamicKeywordRecommender.cs index b54cbee975e8e..8094431002ca7 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DynamicKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DynamicKeywordRecommender.cs @@ -18,7 +18,8 @@ internal class DynamicKeywordRecommender : IKeywordRecommender new RecommendedKeyword("nint"); + protected override RecommendedKeyword Keyword => new("nint"); } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/NuintKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/NuintKeywordRecommender.cs index f450f61e78ddf..8001e07ab8215 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/NuintKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/NuintKeywordRecommender.cs @@ -18,6 +18,6 @@ internal sealed class NuintKeywordRecommender : AbstractNativeIntegerKeywordReco /// strict adherence to our normal textual matching procedure. The user can always still get this item simply /// by typing one additional character and unambiguously referring to nui. /// - protected override RecommendedKeyword Keyword => new RecommendedKeyword("nuint", matchPriority: MatchPriority.Default - 1); + protected override RecommendedKeyword Keyword => new("nuint", matchPriority: MatchPriority.Default - 1); } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ObjectKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ObjectKeywordRecommender.cs index ac949e83c7b90..eac47043ba8f9 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ObjectKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ObjectKeywordRecommender.cs @@ -20,7 +20,7 @@ public ObjectKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/SByteKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/SByteKeywordRecommender.cs index ec0c59104ecac..291500e0fc34c 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/SByteKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/SByteKeywordRecommender.cs @@ -20,7 +20,7 @@ public SByteKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ShortKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ShortKeywordRecommender.cs index 6126c0e2cca2c..ff342caaa773b 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ShortKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ShortKeywordRecommender.cs @@ -20,7 +20,7 @@ public ShortKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/StringKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/StringKeywordRecommender.cs index c8796ceaea285..e4d18d82b50b3 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/StringKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/StringKeywordRecommender.cs @@ -20,7 +20,7 @@ public StringKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UIntKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UIntKeywordRecommender.cs index 74d17fdd359ee..656189dd315d4 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UIntKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UIntKeywordRecommender.cs @@ -20,7 +20,7 @@ public UIntKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ULongKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ULongKeywordRecommender.cs index 4ad9c223b7e06..e4b15fd0757da 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ULongKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ULongKeywordRecommender.cs @@ -20,7 +20,7 @@ public ULongKeywordRecommender() { } - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UShortKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UShortKeywordRecommender.cs index b5c57b9c6741e..45fbe5bff6c58 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UShortKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UShortKeywordRecommender.cs @@ -25,7 +25,7 @@ public UShortKeywordRecommender() /// protected override int DefaultMatchPriority => MatchPriority.Default - 1; - protected override bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) + protected override bool IsValidContextWorker(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) { var syntaxTree = context.SyntaxTree; return diff --git a/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs b/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs index 7d635d0151b59..33ef4c7c177e6 100644 --- a/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs +++ b/src/Features/Core/Portable/Completion/CommonCompletionUtilities.cs @@ -232,7 +232,7 @@ internal static bool IsTextualTriggerString(SourceText text, int characterPositi public static bool TryRemoveAttributeSuffix(ISymbol symbol, SyntaxContext context, [NotNullWhen(true)] out string? name) { var isAttributeNameContext = context.IsAttributeNameContext; - var syntaxFacts = context.GetLanguageService(); + var syntaxFacts = context.GetRequiredLanguageService(); if (!isAttributeNameContext) { diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractAwaitCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractAwaitCompletionProvider.cs index 72871e0ac265e..b80cd734385f5 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractAwaitCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractAwaitCompletionProvider.cs @@ -66,7 +66,7 @@ protected AbstractAwaitCompletionProvider(ISyntaxFacts syntaxFacts) protected abstract SyntaxToken? GetDotTokenLeftOfPosition(SyntaxTree syntaxTree, int position, CancellationToken cancellationToken); protected virtual bool IsAwaitKeywordContext(SyntaxContext syntaxContext) - => syntaxContext.IsAwaitKeywordContext(); + => syntaxContext.IsAwaitKeywordContext; private static bool IsConfigureAwaitable(Compilation compilation, ITypeSymbol symbol) { @@ -250,9 +250,9 @@ private DotAwaitContext GetDotAwaitKeywordContext(SyntaxContext syntaxContext, C { // We have a awaitable type left of the dot, that is not yet awaited. // We need to check if await is valid at the insertion position. - var syntaxContextAtInsertationPosition = syntaxContext.GetLanguageService().CreateContext( + var syntaxContextAtInsertationPosition = syntaxContext.GetRequiredLanguageService().CreateContext( document, syntaxContext.SemanticModel, potentialAwaitableExpression.SpanStart, cancellationToken); - if (syntaxContextAtInsertationPosition.IsAwaitKeywordContext()) + if (syntaxContextAtInsertationPosition.IsAwaitKeywordContext) { return IsConfigureAwaitable(syntaxContext.SemanticModel.Compilation, symbol) ? DotAwaitContext.AwaitAndConfigureAwait diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractObjectCreationCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractObjectCreationCompletionProvider.cs index a6b9ffbbf71d0..f6b9fa726161f 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractObjectCreationCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractObjectCreationCompletionProvider.cs @@ -53,7 +53,7 @@ protected override CompletionItem CreateItem( if (newExpression == null) return SpecializedTasks.EmptyImmutableArray<(ISymbol symbol, bool preselect)>(); - var typeInferenceService = context.GetLanguageService(); + var typeInferenceService = context.GetRequiredLanguageService(); var type = typeInferenceService.InferType( context.SemanticModel, position, objectAsDefault: false, cancellationToken: cancellationToken); diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs index 95b807a502fbc..9ead77fc94368 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs @@ -2,13 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.LanguageServices; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Recommendations; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -33,27 +33,63 @@ internal abstract class AbstractRecommendationServiceBasedCompletionProvider(); + var recommender = context.GetRequiredLanguageService(); var recommendedSymbols = recommender.GetRecommendedSymbolsAtPosition(context.Document, context.SemanticModel, position, recommendationOptions, cancellationToken); - var shouldPreselectInferredTypes = await ShouldPreselectInferredTypesAsync(completionContext, position, options, cancellationToken).ConfigureAwait(false); - if (!shouldPreselectInferredTypes) - return recommendedSymbols.NamedSymbols.SelectAsArray(s => (s, preselect: false)); + if (context.IsInTaskLikeTypeContext) + { + // If we get 'Task' back, attempt to preselect that as the most likely result. + var taskType = context.SemanticModel.Compilation.TaskType(); + return recommendedSymbols.NamedSymbols.SelectAsArray( + s => IsValidForTaskLikeTypeOnlyContext(s, context), + s => (s, preselect: s.OriginalDefinition.Equals(taskType))); + } + else + { + var shouldPreselectInferredTypes = await ShouldPreselectInferredTypesAsync(completionContext, position, options, cancellationToken).ConfigureAwait(false); + if (!shouldPreselectInferredTypes) + return recommendedSymbols.NamedSymbols.SelectAsArray(s => (s, preselect: false)); + + var inferredTypes = context.InferredTypes.Where(t => t.SpecialType != SpecialType.System_Void).ToSet(); + + using var _ = ArrayBuilder<(ISymbol symbol, bool preselect)>.GetInstance(out var result); + + foreach (var symbol in recommendedSymbols.NamedSymbols) + { + // Don't preselect intrinsic type symbols so we can preselect their keywords instead. We will also + // ignore nullability for purposes of preselection -- if a method is returning a string? but we've + // inferred we're assigning to a string or vice versa we'll still count those as the same. + var preselect = inferredTypes.Contains(GetSymbolType(symbol), SymbolEqualityComparer.Default) && !IsInstrinsic(symbol); + result.Add((symbol, preselect)); + } - var inferredTypes = context.InferredTypes.Where(t => t.SpecialType != SpecialType.System_Void).ToSet(); + return result.ToImmutable(); + } + } - using var _ = ArrayBuilder<(ISymbol symbol, bool preselect)>.GetInstance(out var result); + private static bool IsValidForTaskLikeTypeOnlyContext(ISymbol symbol, TSyntaxContext context) + { + // We want to allow all namespaces as the user may be typing a namespace name to get to a task-like type. + if (symbol.IsNamespace()) + return true; + + if (symbol is not INamedTypeSymbol namedType || + symbol.IsDelegateType() || + namedType.IsEnumType()) + { + return false; + } - foreach (var symbol in recommendedSymbols.NamedSymbols) + if (namedType.TypeKind == TypeKind.Interface) { - // Don't preselect intrinsic type symbols so we can preselect their keywords instead. We will also - // ignore nullability for purposes of preselection -- if a method is returning a string? but we've - // inferred we're assigning to a string or vice versa we'll still count those as the same. - var preselect = inferredTypes.Contains(GetSymbolType(symbol), SymbolEqualityComparer.Default) && !IsInstrinsic(symbol); - result.Add((symbol, preselect)); + // The only interfaces, that are valid in async context are IAsyncEnumerable and IAsyncEnumerator. + // So if we are validating an interface, then we can just check for 2 of this possible variants + var compilation = context.SemanticModel.Compilation; + return namedType.Equals(compilation.IAsyncEnumerableOfTType()) || + namedType.Equals(compilation.IAsyncEnumeratorOfTType()); } - return result.ToImmutable(); + return symbol.IsAwaitableNonDynamic(context.SemanticModel, context.Position); } private static ITypeSymbol? GetSymbolType(ISymbol symbol) diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractSymbolCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractSymbolCompletionProvider.cs index ba57111097f0a..7d057e0e16560 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractSymbolCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractSymbolCompletionProvider.cs @@ -364,7 +364,7 @@ protected virtual Task IsSemanticTriggerCharacterAsync(Document document, protected async Task> TryGetSymbolsForContextAsync( CompletionContext? completionContext, TSyntaxContext syntaxContext, CompletionOptions options, CancellationToken cancellationToken) { - var syntaxFacts = syntaxContext.GetLanguageService(); + var syntaxFacts = syntaxContext.GetRequiredLanguageService(); return syntaxFacts.IsInInactiveRegion(syntaxContext.SyntaxTree, syntaxContext.Position, cancellationToken) ? default : await GetSymbolsAsync(completionContext, syntaxContext, syntaxContext.Position, options, cancellationToken).ConfigureAwait(false); diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb index 822b4b4931dd8..e4edffdeee042 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers <[Shared]> - Partial Friend Class SymbolCompletionProvider + Friend NotInheritable Class SymbolCompletionProvider Inherits AbstractRecommendationServiceBasedCompletionProvider(Of VisualBasicSyntaxContext) Private Shared ReadOnly s_cachedRules As New Dictionary(Of (importDirective As Boolean, preselect As Boolean, tuple As Boolean), CompletionItemRules) diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/ArrayStatements/EraseKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/ArrayStatements/EraseKeywordRecommender.vb index 1d156e210ec53..b7397113e6a60 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/ArrayStatements/EraseKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/ArrayStatements/EraseKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Arra ImmutableArray.Create(New RecommendedKeyword("Erase", VBFeaturesResources.Used_to_release_array_variables_and_deallocate_the_memory_used_for_their_elements)) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) + Return If(context.IsStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/ArrayStatements/ReDimKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/ArrayStatements/ReDimKeywordRecommender.vb index 453937ac4c8b3..bfe4415e87544 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/ArrayStatements/ReDimKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/ArrayStatements/ReDimKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Arra ImmutableArray.Create(New RecommendedKeyword("ReDim", VBFeaturesResources.Reallocates_storage_space_for_an_array_variable)) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) + Return If(context.IsStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/AddHandlerKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/AddHandlerKeywordRecommender.vb index 2015eda2edc37..403e8a2116d68 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/AddHandlerKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/AddHandlerKeywordRecommender.vb @@ -20,7 +20,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Even SyntaxKind.AddHandlerKeyword, VBFeaturesResources.AddHandler_statement, Glyph.Keyword, New AddHandlerStatementDocumentation())) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext OrElse context.CanDeclareCustomEventAccessor(SyntaxKind.AddHandlerAccessorBlock), + Return If(context.IsStatementContext OrElse context.CanDeclareCustomEventAccessor(SyntaxKind.AddHandlerAccessorBlock), s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/RaiseEventKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/RaiseEventKeywordRecommender.vb index c7a838e31d3f4..99fecaeb21536 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/RaiseEventKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/RaiseEventKeywordRecommender.vb @@ -15,7 +15,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Even Inherits AbstractKeywordRecommender Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - If context.IsSingleLineStatementContext OrElse context.IsMultiLineStatementContext Then + If context.IsStatementContext OrElse context.IsMultiLineStatementContext Then Return ImmutableArray.Create(New RecommendedKeyword("RaiseEvent", VBFeaturesResources.Triggers_an_event_declared_at_module_level_within_a_class_form_or_document_RaiseEvent_eventName_bracket_argumentList_bracket)) ElseIf context.CanDeclareCustomEventAccessor(SyntaxKind.RaiseEventAccessorBlock) Then Return ImmutableArray.Create(New RecommendedKeyword("RaiseEvent", VBFeaturesResources.Specifies_the_statements_to_run_when_the_event_is_raised_by_the_RaiseEvent_statement_RaiseEvent_delegateSignature_End_RaiseEvent)) diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/RemoveHandlerKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/RemoveHandlerKeywordRecommender.vb index 4a3d5147e7478..1b851377edd71 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/RemoveHandlerKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/EventHandling/RemoveHandlerKeywordRecommender.vb @@ -22,7 +22,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Even New RemoveHandlerStatementDocumentation())) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext OrElse context.CanDeclareCustomEventAccessor(SyntaxKind.RemoveHandlerAccessorBlock), + Return If(context.IsStatementContext OrElse context.CanDeclareCustomEventAccessor(SyntaxKind.RemoveHandlerAccessorBlock), s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/CastOperatorsKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/CastOperatorsKeywordRecommender.vb index 0976c337e94ee..0816bb8b59296 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/CastOperatorsKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/CastOperatorsKeywordRecommender.vb @@ -32,7 +32,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Expr SyntaxKind.CUShortKeyword} Protected Overloads Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - If context.IsAnyExpressionContext OrElse context.IsSingleLineStatementContext Then + If context.IsAnyExpressionContext OrElse context.IsStatementContext Then Dim recommendedKeywords As New List(Of RecommendedKeyword) For Each keyword In PredefinedKeywordList diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/GetTypeKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/GetTypeKeywordRecommender.vb index b253a3345d807..186702b888ddf 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/GetTypeKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/GetTypeKeywordRecommender.vb @@ -16,7 +16,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Expr Inherits AbstractKeywordRecommender Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - If context.IsAnyExpressionContext OrElse context.IsSingleLineStatementContext Then + If context.IsAnyExpressionContext OrElse context.IsStatementContext Then Return ImmutableArray.Create(CreateRecommendedKeywordForIntrinsicOperator( SyntaxKind.GetTypeKeyword, VBFeaturesResources.GetType_function, Glyph.Keyword, New GetTypeExpressionDocumentation(), context.SemanticModel, context.Position)) End If diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MeKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MeKeywordRecommender.vb index 8901d7ceaeb7a..19a08944029d1 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MeKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MeKeywordRecommender.vb @@ -19,7 +19,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Expr Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) Dim targetToken = context.TargetToken - If (context.IsAnyExpressionContext OrElse context.IsSingleLineStatementContext OrElse context.IsNameOfContext) AndAlso + If (context.IsAnyExpressionContext OrElse context.IsStatementContext OrElse context.IsNameOfContext) AndAlso targetToken.GetInnermostDeclarationContext().IsKind(SyntaxKind.ClassBlock, SyntaxKind.StructureBlock) Then ' Preselect the Me keyword when the target type is the same @@ -48,7 +48,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Expr End If End If - If context.IsAccessibleEventContext(startAtEnclosingBaseType:=False, cancellationToken:=cancellationToken) Then + If context.IsAccessibleEventContext(startAtEnclosingBaseType:=False) Then Return ImmutableArray.Create(New RecommendedKeyword(SyntaxFacts.GetText(SyntaxKind.MeKeyword), VBFeaturesResources.Provides_a_way_to_refer_to_the_current_instance_of_a_class_or_structure_that_is_the_instance_in_which_the_code_is_running)) End If diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MyBaseKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MyBaseKeywordRecommender.vb index c43aa7d5082af..d19c354f5c8d4 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MyBaseKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MyBaseKeywordRecommender.vb @@ -20,12 +20,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Expr Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) Dim targetToken = context.TargetToken - If (context.IsAnyExpressionContext OrElse context.IsSingleLineStatementContext OrElse context.IsNameOfContext) AndAlso + If (context.IsAnyExpressionContext OrElse context.IsStatementContext OrElse context.IsNameOfContext) AndAlso targetToken.GetInnermostDeclarationContext().IsKind(SyntaxKind.ClassBlock) Then Return s_keywords End If - If context.IsAccessibleEventContext(startAtEnclosingBaseType:=True, cancellationToken:=cancellationToken) Then + If context.IsAccessibleEventContext(startAtEnclosingBaseType:=True) Then Return s_keywords End If diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MyClassKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MyClassKeywordRecommender.vb index 1083de291fbdf..4fb687559ef44 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MyClassKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MyClassKeywordRecommender.vb @@ -21,7 +21,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Expr Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) Dim targetToken = context.TargetToken - If (context.IsAnyExpressionContext OrElse context.IsSingleLineStatementContext OrElse context.IsNameOfContext) AndAlso + If (context.IsAnyExpressionContext OrElse context.IsStatementContext OrElse context.IsNameOfContext) AndAlso targetToken.GetInnermostDeclarationContext().IsKind(SyntaxKind.ClassBlock, SyntaxKind.StructureBlock) Then ' This isn't valid in shared methods Dim methodBlock = targetToken.GetAncestor(Of MethodBlockBaseSyntax)() @@ -33,7 +33,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Expr Return s_keywords End If - If context.IsAccessibleEventContext(startAtEnclosingBaseType:=False, cancellationToken:=cancellationToken) Then + If context.IsAccessibleEventContext(startAtEnclosingBaseType:=False) Then Return s_keywords End If diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/OnErrorStatements/ErrorKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/OnErrorStatements/ErrorKeywordRecommender.vb index ed19f8cea44cc..1c162776ca240 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/OnErrorStatements/ErrorKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/OnErrorStatements/ErrorKeywordRecommender.vb @@ -24,7 +24,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.OnEr End If ' The Error statement (i.e. "Error 11" to raise an error) - If context.IsMultiLineStatementContext OrElse context.IsSingleLineStatementContext Then + If context.IsMultiLineStatementContext OrElse context.IsStatementContext Then Return ImmutableArray.Create(New RecommendedKeyword("Error", VBFeaturesResources.Simulates_the_occurrence_of_an_error)) End If diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/CallKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/CallKeywordRecommender.vb index 20e50306a6f30..351dc45a9bbf6 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/CallKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/CallKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat ImmutableArray.Create(New RecommendedKeyword("Call", VBFeaturesResources.Transfers_execution_to_a_Function_Sub_or_dynamic_link_library_DLL_procedure_bracket_Call_bracket_procedureName_bracket_argumentList_bracket)) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) + Return If(context.IsStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ElseIfKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ElseIfKeywordRecommender.vb index df6fa18cfb831..cc583cba80dd0 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ElseIfKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ElseIfKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat ImmutableArray.Create(New RecommendedKeyword("ElseIf", VBFeaturesResources.Introduces_a_condition_in_an_If_statement_that_is_to_be_tested_if_the_previous_conditional_test_fails)) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - If context.IsSingleLineStatementContext AndAlso + If context.IsStatementContext AndAlso context.IsInStatementBlockOfKind(SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock) AndAlso Not context.IsInStatementBlockOfKind(SyntaxKind.ElseBlock) Then diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb index fae06d7d6847e..00d3e272a245f 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb @@ -25,7 +25,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat End If End If - If context.IsSingleLineStatementContext AndAlso + If context.IsStatementContext AndAlso IsDirectlyInIfOrElseIf(context) Then Return ImmutableArray.Create(New RecommendedKeyword("Else", VBFeaturesResources.Introduces_a_group_of_statements_in_an_If_statement_that_is_executed_if_no_previous_condition_evaluates_to_True)) diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/EndKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/EndKeywordRecommender.vb index e26d56f1a4329..fd16e11b53709 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/EndKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/EndKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat ImmutableArray.Create(New RecommendedKeyword("End", VBFeaturesResources.Stops_execution_immediately)) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) + Return If(context.IsStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ExitKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ExitKeywordRecommender.vb index 0f7a151ff1c9a..47a591267d90e 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ExitKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ExitKeywordRecommender.vb @@ -41,7 +41,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat ' We know that in any executable statement context, there always must be at least one thing we can exit: the ' function or sub itself (except for Finally blocks) - Return If(context.IsSingleLineStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) + Return If(context.IsStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function End Class diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/IfKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/IfKeywordRecommender.vb index b4bd957ca08b0..7a84c8c4a6238 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/IfKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/IfKeywordRecommender.vb @@ -16,7 +16,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat Inherits AbstractKeywordRecommender Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - If context.IsSingleLineStatementContext Then + If context.IsStatementContext Then Return ImmutableArray.Create(New RecommendedKeyword("If", VBFeaturesResources.Conditionally_executes_a_group_of_statements_depending_on_the_value_of_an_expression)) End If diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/LoopKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/LoopKeywordRecommender.vb index e7e66a52d1dc0..0b8c3e108f9d4 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/LoopKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/LoopKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) Dim targetToken = context.TargetToken - If context.IsSingleLineStatementContext Then + If context.IsStatementContext Then Dim doBlock = targetToken.GetAncestor(Of DoLoopBlockSyntax)() If doBlock Is Nothing OrElse Not doBlock.LoopStatement.IsMissing Then diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/MidKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/MidKeywordRecommender.vb index ca19d1327097d..f95aa879441dc 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/MidKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/MidKeywordRecommender.vb @@ -23,7 +23,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat New MidAssignmentDocumentation())) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) + Return If(context.IsStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/NextKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/NextKeywordRecommender.vb index e42ca92955b77..398bd8db08003 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/NextKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/NextKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat ImmutableArray.Create(New RecommendedKeyword("Next", VBFeaturesResources.Terminates_a_loop_that_iterates_through_the_values_of_a_loop_variable)) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, CancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext AndAlso context.IsInStatementBlockOfKind(SyntaxKind.ForBlock, SyntaxKind.ForEachBlock), + Return If(context.IsStatementContext AndAlso context.IsInStatementBlockOfKind(SyntaxKind.ForBlock, SyntaxKind.ForEachBlock), s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ReturnKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ReturnKeywordRecommender.vb index ef45710aa70c0..7a531692e02ea 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ReturnKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ReturnKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat ImmutableArray.Create(New RecommendedKeyword("Return", VBFeaturesResources.Returns_execution_to_the_code_that_called_the_Function_Sub_Get_Set_or_Operator_procedure_Return_or_Return_expression)) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext AndAlso Not context.IsInStatementBlockOfKind(SyntaxKind.FinallyBlock), + Return If(context.IsStatementContext AndAlso Not context.IsInStatementBlockOfKind(SyntaxKind.FinallyBlock), s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/StopKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/StopKeywordRecommender.vb index 8e16071b53b1b..264b5079a90a6 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/StopKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/StopKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat ImmutableArray.Create(New RecommendedKeyword("Stop", VBFeaturesResources.Suspends_program_execution)) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) + Return If(context.IsStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ThrowKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ThrowKeywordRecommender.vb index 1a5d9b9be207e..827ff54074b28 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ThrowKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Statements/ThrowKeywordRecommender.vb @@ -18,7 +18,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat ImmutableArray.Create(New RecommendedKeyword("Throw", VBFeaturesResources.Throws_an_exception_within_a_procedure_so_that_you_can_handle_it_with_structured_or_unstructured_exception_handling_code)) Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) - Return If(context.IsSingleLineStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) + Return If(context.IsStatementContext, s_keywords, ImmutableArray(Of RecommendedKeyword).Empty) End Function End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Types/BuiltInTypesKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Types/BuiltInTypesKeywordRecommender.vb index 7fa648ec5e403..ed1fdc7e708d6 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Types/BuiltInTypesKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Types/BuiltInTypesKeywordRecommender.vb @@ -17,6 +17,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Type Inherits AbstractKeywordRecommender Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As ImmutableArray(Of RecommendedKeyword) + If context.IsInTaskLikeTypeContext Then + Return ImmutableArray(Of RecommendedKeyword).Empty + End If + Dim targetToken = context.TargetToken ' Are we right after an As in an Enum declaration? diff --git a/src/VisualStudio/Core/Test/Completion/CSharpCompletionSnippetNoteTests.vb b/src/VisualStudio/Core/Test/Completion/CSharpCompletionSnippetNoteTests.vb index 23458b17b36b6..c67cb86f91aa1 100644 --- a/src/VisualStudio/Core/Test/Completion/CSharpCompletionSnippetNoteTests.vb +++ b/src/VisualStudio/Core/Test/Completion/CSharpCompletionSnippetNoteTests.vb @@ -36,23 +36,23 @@ class C Public Async Function ColonDoesntTriggerSnippetInTupleLiteral() As Task - Using state = CreateCSharpSnippetExpansionNoteTestState(_markup, "interface") - state.SendTypeChars("var t = (interfac") + Using state = CreateCSharpSnippetExpansionNoteTestState(_markup, "glob") + state.SendTypeChars("var t = (glob") Await state.AssertCompletionSession() - Await state.AssertSelectedCompletionItem(displayText:="interface", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="global", isHardSelected:=True) state.SendTypeChars(":") - Assert.Contains("(interfac:", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) + Assert.Contains("(glob:", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) End Using End Function Public Async Function ColonDoesntTriggerSnippetInTupleLiteralAfterComma() As Task - Using state = CreateCSharpSnippetExpansionNoteTestState(_markup, "interface") - state.SendTypeChars("var t = (1, interfac") + Using state = CreateCSharpSnippetExpansionNoteTestState(_markup, "glob") + state.SendTypeChars("var t = (1, glob") Await state.AssertCompletionSession() - Await state.AssertSelectedCompletionItem(displayText:="interface", isHardSelected:=True) + Await state.AssertSelectedCompletionItem(displayText:="global", isHardSelected:=True) state.SendTypeChars(":") - Assert.Contains("(1, interfac:", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) + Assert.Contains("(1, glob:", state.GetLineTextFromCaretPosition(), StringComparison.Ordinal) End Using End Function diff --git a/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb b/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb index bb74941b96bce..685882e3d63db 100644 --- a/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb +++ b/src/VisualStudio/VisualBasic/Impl/Snippets/SnippetCompletionProvider.vb @@ -7,6 +7,7 @@ Imports System.ComponentModel.Composition Imports System.Threading Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Completion +Imports Microsoft.CodeAnalysis.Completion.Providers Imports Microsoft.CodeAnalysis.Editor Imports Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.SignatureHelp Imports Microsoft.CodeAnalysis.Editor.Shared.Utilities @@ -18,6 +19,7 @@ Imports Microsoft.CodeAnalysis.Snippets Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.Text.Shared.Extensions Imports Microsoft.CodeAnalysis.VisualBasic.Extensions +Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Imports Microsoft.VisualStudio.Editor Imports Microsoft.VisualStudio.Text Imports Microsoft.VisualStudio.Text.Editor @@ -80,32 +82,40 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Snippets Dim snippets = snippetInfoService.GetSnippetsIfAvailable() Dim syntaxTree = Await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(False) - Dim syntaxFacts = document.GetLanguageService(Of ISyntaxFactsService)() - Dim isPossibleTupleContext = syntaxFacts.IsPossibleTupleContext(syntaxTree, position, cancellationToken) + Dim leftToken = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken) + Dim targetToken = leftToken.GetPreviousTokenIfTouchingWord(position) - If (IsInNonUserCode(syntaxTree, position, cancellationToken)) Then + If syntaxTree.IsPossibleTupleContext(leftToken, position) Then + Return + End If + + Dim semanticModel = Await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(False) + Dim syntaxContext = VisualBasicSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken) + If syntaxContext.IsInTaskLikeTypeContext Then + Return + End If + + Dim syntaxFacts = document.GetLanguageService(Of ISyntaxFactsService)() + If IsInNonUserCode(syntaxTree, position, cancellationToken) Then Return End If context.IsExclusive = context.CompletionOptions.SnippetsBehavior = SnippetsRule.IncludeAfterTypingIdentifierQuestionTab - context.AddItems(CreateCompletionItems(snippets, isPossibleTupleContext)) + context.AddItems(CreateCompletionItems(snippets)) End Function Private Shared ReadOnly s_commitChars As Char() = {" "c, ";"c, "("c, ")"c, "["c, "]"c, "{"c, "}"c, "."c, ","c, ":"c, "+"c, "-"c, "*"c, "/"c, "\"c, "^"c, "<"c, ">"c, "'"c, "="c} Private Shared ReadOnly s_rules As CompletionItemRules = CompletionItemRules.Create( commitCharacterRules:=ImmutableArray.Create(CharacterSetModificationRule.Create(CharacterSetModificationKind.Replace, s_commitChars))) - Private Shared ReadOnly s_tupleRules As CompletionItemRules = s_rules. - WithCommitCharacterRule(CharacterSetModificationRule.Create(CharacterSetModificationKind.Remove, ":"c)) - - Private Shared Function CreateCompletionItems(snippets As IEnumerable(Of SnippetInfo), isTupleContext As Boolean) As IEnumerable(Of CompletionItem) + Private Shared Function CreateCompletionItems(snippets As IEnumerable(Of SnippetInfo)) As IEnumerable(Of CompletionItem) Return snippets.Select(Function(s) CommonCompletionItem.Create( s.Shortcut, displayTextSuffix:="", description:=s.Description.ToSymbolDisplayParts(), glyph:=Glyph.Snippet, - rules:=If(isTupleContext, s_tupleRules, s_rules))) + rules:=s_rules)) End Function Public Overrides Function IsInsertionTrigger(text As SourceText, characterPosition As Integer, options As CompletionOptions) As Boolean diff --git a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationService.cs b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationService.cs index 5ae11cd5d0be0..031295d9d0434 100644 --- a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationService.cs +++ b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationService.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Recommendations { [ExportLanguageService(typeof(IRecommendationService), LanguageNames.CSharp), Shared] - internal class CSharpRecommendationService : AbstractRecommendationService + internal partial class CSharpRecommendationService : AbstractRecommendationService { [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] @@ -23,7 +23,7 @@ public CSharpRecommendationService() protected override CSharpSyntaxContext CreateContext(Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken) => CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken); - protected override AbstractRecommendationServiceRunner CreateRunner(CSharpSyntaxContext context, bool filterOutOfScopeLocals, CancellationToken cancellationToken) + protected override AbstractRecommendationServiceRunner CreateRunner(CSharpSyntaxContext context, bool filterOutOfScopeLocals, CancellationToken cancellationToken) => new CSharpRecommendationServiceRunner(context, filterOutOfScopeLocals, cancellationToken); } } diff --git a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs index b3a77993024a8..924314b2d5678 100644 --- a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs +++ b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner.cs @@ -17,9 +17,11 @@ using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; -namespace Microsoft.CodeAnalysis.CSharp.Recommendations +namespace Microsoft.CodeAnalysis.CSharp.Recommendations; + +internal partial class CSharpRecommendationService { - internal partial class CSharpRecommendationServiceRunner : AbstractRecommendationServiceRunner + private sealed partial class CSharpRecommendationServiceRunner : AbstractRecommendationServiceRunner { public CSharpRecommendationServiceRunner( CSharpSyntaxContext context, bool filterOutOfScopeLocals, CancellationToken cancellationToken) @@ -232,7 +234,7 @@ private ImmutableArray GetSymbolsForExpressionOrStatementContext() // Filter out any extension methods that might be imported by a using static directive. // But include extension methods declared in the context's type or it's parents - var contextOuterTypes = _context.GetOuterTypes(_cancellationToken); + var contextOuterTypes = ComputeOuterTypes(_context, _cancellationToken); var contextEnclosingNamedType = _context.SemanticModel.GetEnclosingNamedType(_context.Position, _cancellationToken); symbols = symbols.WhereAsArray(symbol => diff --git a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Conversions.cs b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Conversions.cs index e1b741e7936b1..6cd6464aaaa18 100644 --- a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Conversions.cs +++ b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Conversions.cs @@ -8,12 +8,14 @@ using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; -namespace Microsoft.CodeAnalysis.CSharp.Recommendations +namespace Microsoft.CodeAnalysis.CSharp.Recommendations; + +internal partial class CSharpRecommendationService { /// /// Adds user defined and predefined conversions to the unnamed recommendation set. /// - internal partial class CSharpRecommendationServiceRunner + private sealed partial class CSharpRecommendationServiceRunner { private static readonly ImmutableArray s_predefinedEnumConversionTargets = ImmutableArray.Create( SpecialType.System_Byte, diff --git a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Operators.cs b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Operators.cs index 125d13e82fd86..edc16ffbc1971 100644 --- a/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Operators.cs +++ b/src/Workspaces/CSharp/Portable/Recommendations/CSharpRecommendationServiceRunner_Operators.cs @@ -7,12 +7,14 @@ using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; -namespace Microsoft.CodeAnalysis.CSharp.Recommendations +namespace Microsoft.CodeAnalysis.CSharp.Recommendations; + +internal partial class CSharpRecommendationService { /// /// Adds user defined operators to the unnamed recommendation set. /// - internal partial class CSharpRecommendationServiceRunner + private sealed partial class CSharpRecommendationServiceRunner { private static void AddOperators(ITypeSymbol container, ArrayBuilder symbols) { diff --git a/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs b/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs index 5dede1880271c..8dea60dbbf689 100644 --- a/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs +++ b/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationService.cs @@ -4,25 +4,23 @@ #nullable disable -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Recommendations { - internal abstract class AbstractRecommendationService : IRecommendationService + internal abstract partial class AbstractRecommendationService : IRecommendationService where TSyntaxContext : SyntaxContext { protected abstract TSyntaxContext CreateContext( Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken); - protected abstract AbstractRecommendationServiceRunner CreateRunner( + protected abstract AbstractRecommendationServiceRunner CreateRunner( TSyntaxContext context, bool filterOutOfScopeLocals, CancellationToken cancellationToken); public RecommendedSymbols GetRecommendedSymbolsAtPosition(Document document, SemanticModel semanticModel, int position, RecommendationServiceOptions options, CancellationToken cancellationToken) @@ -43,12 +41,27 @@ public RecommendedSymbols GetRecommendedSymbolsAtPosition(Document document, Sem return new RecommendedSymbols(namedSymbols, unnamedSymbols); } + protected static ISet ComputeOuterTypes(SyntaxContext context, CancellationToken cancellationToken) + { + var enclosingSymbol = context.SemanticModel.GetEnclosingSymbol(context.LeftToken.SpanStart, cancellationToken); + if (enclosingSymbol != null) + { + var containingType = enclosingSymbol.GetContainingTypeOrThis(); + if (containingType != null) + { + return containingType.GetContainingTypes().ToSet(); + } + } + + return SpecializedCollections.EmptySet(); + } + private sealed class ShouldIncludeSymbolContext { private readonly SyntaxContext _context; private readonly CancellationToken _cancellationToken; - private IEnumerable _lazyOuterTypesAndBases; - private IEnumerable _lazyEnclosingTypeBases; + private ImmutableArray _lazyOuterTypesAndBases; + private ImmutableArray _lazyEnclosingTypeBases; internal ShouldIncludeSymbolContext(SyntaxContext context, CancellationToken cancellationToken) { @@ -127,24 +140,26 @@ internal bool ShouldIncludeSymbol(ISymbol symbol) return true; } - private IEnumerable GetOuterTypesAndBases() + private ImmutableArray GetOuterTypesAndBases() { - if (_lazyOuterTypesAndBases == null) + if (_lazyOuterTypesAndBases.IsDefault) { - _lazyOuterTypesAndBases = _context.GetOuterTypes(_cancellationToken).SelectMany(o => o.GetBaseTypesAndThis()).Select(t => t.OriginalDefinition); + _lazyOuterTypesAndBases = ComputeOuterTypes(_context, _cancellationToken) + .SelectMany(o => o.GetBaseTypesAndThis()) + .SelectAsArray(t => t.OriginalDefinition); } return _lazyOuterTypesAndBases; } - private IEnumerable GetEnclosingTypeBases() + private ImmutableArray GetEnclosingTypeBases() { - if (_lazyEnclosingTypeBases == null) + if (_lazyEnclosingTypeBases.IsDefault) { var enclosingType = _context.SemanticModel.GetEnclosingNamedType(_context.LeftToken.SpanStart, _cancellationToken); - _lazyEnclosingTypeBases = (enclosingType == null) ? - SpecializedCollections.EmptyEnumerable() : - enclosingType.GetBaseTypes().Select(b => b.OriginalDefinition); + _lazyEnclosingTypeBases = enclosingType == null + ? ImmutableArray.Empty + : enclosingType.GetBaseTypes().SelectAsArray(b => b.OriginalDefinition); } return _lazyEnclosingTypeBases; diff --git a/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationServiceRunner.cs b/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationServiceRunner.cs index 44de0a13263c6..61cd2534c553a 100644 --- a/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationServiceRunner.cs +++ b/src/Workspaces/Core/Portable/Recommendations/AbstractRecommendationServiceRunner.cs @@ -14,12 +14,12 @@ using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; -using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; -namespace Microsoft.CodeAnalysis.Recommendations +namespace Microsoft.CodeAnalysis.Recommendations; + +internal abstract partial class AbstractRecommendationService { - internal abstract class AbstractRecommendationServiceRunner - where TSyntaxContext : SyntaxContext + protected abstract class AbstractRecommendationServiceRunner { protected readonly TSyntaxContext _context; protected readonly bool _filterOutOfScopeLocals; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs index d90f5d03d5f67..a84f2be994f61 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs @@ -750,7 +750,7 @@ public static bool IsKind(this ISymbol symbol, SymbolKind kind, [NotNul /// public static bool IsSymbolWithSpecialDiscardName(this ISymbol symbol) => symbol.Name.StartsWith("_") && - (symbol.Name.Length == 1 || uint.TryParse(symbol.Name.Substring(1), out _)); + (symbol.Name.Length == 1 || uint.TryParse(symbol.Name[1..], out _)); /// /// Returns , if the symbol is marked with the . @@ -761,7 +761,7 @@ public static bool IsObsolete(this ISymbol symbol) => symbol.GetAttributes().Any(x => x.AttributeClass is { MetadataName: nameof(ObsoleteAttribute), - ContainingNamespace: { Name: nameof(System) }, + ContainingNamespace.Name: nameof(System), }); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/CSharpSyntaxContext.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/CSharpSyntaxContext.cs index 63323f064bd94..73db16bb1f032 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/CSharpSyntaxContext.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/ContextQuery/CSharpSyntaxContext.cs @@ -17,39 +17,36 @@ internal sealed class CSharpSyntaxContext : SyntaxContext public readonly TypeDeclarationSyntax? ContainingTypeDeclaration; public readonly BaseTypeDeclarationSyntax? ContainingTypeOrEnumDeclaration; - public readonly bool IsInNonUserCode; - - public readonly bool IsPreProcessorKeywordContext; - - public readonly bool IsNonAttributeExpressionContext; + public readonly bool IsCatchFilterContext; public readonly bool IsConstantExpressionContext; - - public readonly bool IsLabelContext; - public readonly bool IsTypeArgumentOfConstraintContext; - - public readonly bool IsIsOrAsOrSwitchOrWithExpressionContext; - public readonly bool IsObjectCreationTypeContext; + public readonly bool IsCrefContext; + public readonly bool IsDeclarationExpressionContext; public readonly bool IsDefiniteCastTypeContext; - public readonly bool IsGenericTypeArgumentContext; + public readonly bool IsDelegateReturnTypeContext; + public readonly bool IsDestructorTypeContext; public readonly bool IsEnumBaseListContext; + public readonly bool IsFixedVariableDeclarationContext; + public readonly bool IsFunctionPointerTypeArgumentContext; + public readonly bool IsGenericTypeArgumentContext; + public readonly bool IsImplicitOrExplicitOperatorTypeContext; + public readonly bool IsInNonUserCode; + public readonly bool IsInstanceContext; + public readonly bool IsIsOrAsOrSwitchOrWithExpressionContext; public readonly bool IsIsOrAsTypeContext; + public readonly bool IsLabelContext; + public readonly bool IsLeftSideOfImportAliasDirective; + public readonly bool IsLocalFunctionDeclarationContext; public readonly bool IsLocalVariableDeclarationContext; - public readonly bool IsDeclarationExpressionContext; - public readonly bool IsFixedVariableDeclarationContext; + public readonly bool IsNonAttributeExpressionContext; + public readonly bool IsObjectCreationTypeContext; public readonly bool IsParameterTypeContext; public readonly bool IsPossibleLambdaOrAnonymousMethodParameterTypeContext; - public readonly bool IsImplicitOrExplicitOperatorTypeContext; + public readonly bool IsPreProcessorKeywordContext; public readonly bool IsPrimaryFunctionExpressionContext; - public readonly bool IsDelegateReturnTypeContext; + public readonly bool IsTypeArgumentOfConstraintContext; public readonly bool IsTypeOfExpressionContext; + public readonly ISet PrecedingModifiers; - public readonly bool IsInstanceContext; - public readonly bool IsCrefContext; - public readonly bool IsCatchFilterContext; - public readonly bool IsDestructorTypeContext; - public readonly bool IsLeftSideOfImportAliasDirective; - public readonly bool IsFunctionPointerTypeArgumentContext; - public readonly bool IsLocalFunctionDeclarationContext; private CSharpSyntaxContext( Document document, @@ -59,95 +56,121 @@ private CSharpSyntaxContext( SyntaxToken targetToken, TypeDeclarationSyntax? containingTypeDeclaration, BaseTypeDeclarationSyntax? containingTypeOrEnumDeclaration, - bool isInNonUserCode, - bool isPreProcessorDirectiveContext, - bool isPreProcessorKeywordContext, - bool isPreProcessorExpressionContext, - bool isTypeContext, - bool isNamespaceContext, - bool isNamespaceDeclarationNameContext, - bool isStatementContext, - bool isGlobalStatementContext, bool isAnyExpressionContext, - bool isNonAttributeExpressionContext, - bool isConstantExpressionContext, + bool isAtEndOfPattern, + bool isAtStartOfPattern, bool isAttributeNameContext, + bool isAwaitKeywordContext, + bool isCatchFilterContext, + bool isConstantExpressionContext, + bool isCrefContext, + bool isDeclarationExpressionContext, + bool isDefiniteCastTypeContext, + bool isDelegateReturnTypeContext, + bool isDestructorTypeContext, + bool isEnumBaseListContext, bool isEnumTypeMemberAccessContext, - bool isNameOfContext, - bool isInQuery, + bool isFixedVariableDeclarationContext, + bool isFunctionPointerTypeArgumentContext, + bool isGenericTypeArgumentContext, + bool isGlobalStatementContext, + bool isImplicitOrExplicitOperatorTypeContext, bool isInImportsDirective, - bool isLeftSideOfImportAliasDirective, - bool isLabelContext, - bool isTypeArgumentOfConstraintContext, - bool isRightOfDotOrArrowOrColonColon, + bool isInNonUserCode, + bool isInQuery, + bool isInstanceContext, + bool isInTaskLikeTypeContext, bool isIsOrAsOrSwitchOrWithExpressionContext, - bool isObjectCreationTypeContext, - bool isDefiniteCastTypeContext, - bool isGenericTypeArgumentContext, - bool isEnumBaseListContext, bool isIsOrAsTypeContext, + bool isLabelContext, + bool isLeftSideOfImportAliasDirective, + bool isLocalFunctionDeclarationContext, bool isLocalVariableDeclarationContext, - bool isDeclarationExpressionContext, - bool isFixedVariableDeclarationContext, + bool isNameOfContext, + bool isNamespaceContext, + bool isNamespaceDeclarationNameContext, + bool isNonAttributeExpressionContext, + bool isObjectCreationTypeContext, + bool isOnArgumentListBracketOrComma, bool isParameterTypeContext, bool isPossibleLambdaOrAnonymousMethodParameterTypeContext, - bool isImplicitOrExplicitOperatorTypeContext, + bool isPossibleTupleContext, + bool isPreProcessorDirectiveContext, + bool isPreProcessorExpressionContext, + bool isPreProcessorKeywordContext, bool isPrimaryFunctionExpressionContext, - bool isDelegateReturnTypeContext, + bool isRightOfNameSeparator, + bool isRightSideOfNumericType, + bool isStatementContext, + bool isTypeArgumentOfConstraintContext, + bool isTypeContext, bool isTypeOfExpressionContext, + bool isWithinAsyncMethod, ISet precedingModifiers, - bool isInstanceContext, - bool isCrefContext, - bool isCatchFilterContext, - bool isDestructorTypeContext, - bool isPossibleTupleContext, - bool isStartPatternContext, - bool isAfterPatternContext, - bool isRightSideOfNumericType, - bool isInArgumentList, - bool isFunctionPointerTypeArgumentContext, - bool isLocalFunctionDeclarationContext, CancellationToken cancellationToken) - : base(document, semanticModel, position, leftToken, targetToken, - isTypeContext, isNamespaceContext, isNamespaceDeclarationNameContext, - isPreProcessorDirectiveContext, isPreProcessorExpressionContext, - isRightOfDotOrArrowOrColonColon, isStatementContext, isGlobalStatementContext, - isAnyExpressionContext, isAttributeNameContext, isEnumTypeMemberAccessContext, - isNameOfContext, isInQuery, isInImportsDirective, IsWithinAsyncMethod(), isPossibleTupleContext, - isStartPatternContext, isAfterPatternContext, isRightSideOfNumericType, isInArgumentList, - cancellationToken) + : base( + document, + semanticModel, + position, + leftToken, + targetToken, + isAnyExpressionContext: isAnyExpressionContext, + isAtEndOfPattern: isAtEndOfPattern, + isAtStartOfPattern: isAtStartOfPattern, + isAttributeNameContext: isAttributeNameContext, + isAwaitKeywordContext: isAwaitKeywordContext, + isEnumTypeMemberAccessContext: isEnumTypeMemberAccessContext, + isGlobalStatementContext: isGlobalStatementContext, + isInImportsDirective: isInImportsDirective, + isInQuery: isInQuery, + isInTaskLikeTypeContext: isInTaskLikeTypeContext, + isNameOfContext: isNameOfContext, + isNamespaceContext: isNamespaceContext, + isNamespaceDeclarationNameContext: isNamespaceDeclarationNameContext, + isOnArgumentListBracketOrComma: isOnArgumentListBracketOrComma, + isPossibleTupleContext: isPossibleTupleContext, + isPreProcessorDirectiveContext: isPreProcessorDirectiveContext, + isPreProcessorExpressionContext: isPreProcessorExpressionContext, + isRightOfNameSeparator: isRightOfNameSeparator, + isRightSideOfNumericType: isRightSideOfNumericType, + isStatementContext: isStatementContext, + isTypeContext: isTypeContext, + isWithinAsyncMethod: isWithinAsyncMethod, + cancellationToken) { this.ContainingTypeDeclaration = containingTypeDeclaration; this.ContainingTypeOrEnumDeclaration = containingTypeOrEnumDeclaration; - this.IsInNonUserCode = isInNonUserCode; - this.IsPreProcessorKeywordContext = isPreProcessorKeywordContext; - this.IsNonAttributeExpressionContext = isNonAttributeExpressionContext; + + this.IsCatchFilterContext = isCatchFilterContext; this.IsConstantExpressionContext = isConstantExpressionContext; - this.IsLabelContext = isLabelContext; - this.IsTypeArgumentOfConstraintContext = isTypeArgumentOfConstraintContext; - this.IsIsOrAsOrSwitchOrWithExpressionContext = isIsOrAsOrSwitchOrWithExpressionContext; - this.IsObjectCreationTypeContext = isObjectCreationTypeContext; + this.IsCrefContext = isCrefContext; + this.IsDeclarationExpressionContext = isDeclarationExpressionContext; this.IsDefiniteCastTypeContext = isDefiniteCastTypeContext; - this.IsGenericTypeArgumentContext = isGenericTypeArgumentContext; + this.IsDelegateReturnTypeContext = isDelegateReturnTypeContext; + this.IsDestructorTypeContext = isDestructorTypeContext; this.IsEnumBaseListContext = isEnumBaseListContext; + this.IsFixedVariableDeclarationContext = isFixedVariableDeclarationContext; + this.IsFunctionPointerTypeArgumentContext = isFunctionPointerTypeArgumentContext; + this.IsGenericTypeArgumentContext = isGenericTypeArgumentContext; + this.IsImplicitOrExplicitOperatorTypeContext = isImplicitOrExplicitOperatorTypeContext; + this.IsInNonUserCode = isInNonUserCode; + this.IsInstanceContext = isInstanceContext; + this.IsIsOrAsOrSwitchOrWithExpressionContext = isIsOrAsOrSwitchOrWithExpressionContext; this.IsIsOrAsTypeContext = isIsOrAsTypeContext; + this.IsLabelContext = isLabelContext; + this.IsLeftSideOfImportAliasDirective = isLeftSideOfImportAliasDirective; + this.IsLocalFunctionDeclarationContext = isLocalFunctionDeclarationContext; this.IsLocalVariableDeclarationContext = isLocalVariableDeclarationContext; - this.IsDeclarationExpressionContext = isDeclarationExpressionContext; - this.IsFixedVariableDeclarationContext = isFixedVariableDeclarationContext; + this.IsNonAttributeExpressionContext = isNonAttributeExpressionContext; + this.IsObjectCreationTypeContext = isObjectCreationTypeContext; this.IsParameterTypeContext = isParameterTypeContext; this.IsPossibleLambdaOrAnonymousMethodParameterTypeContext = isPossibleLambdaOrAnonymousMethodParameterTypeContext; - this.IsImplicitOrExplicitOperatorTypeContext = isImplicitOrExplicitOperatorTypeContext; + this.IsPreProcessorKeywordContext = isPreProcessorKeywordContext; this.IsPrimaryFunctionExpressionContext = isPrimaryFunctionExpressionContext; - this.IsDelegateReturnTypeContext = isDelegateReturnTypeContext; + this.IsTypeArgumentOfConstraintContext = isTypeArgumentOfConstraintContext; this.IsTypeOfExpressionContext = isTypeOfExpressionContext; + this.PrecedingModifiers = precedingModifiers; - this.IsInstanceContext = isInstanceContext; - this.IsCrefContext = isCrefContext; - this.IsCatchFilterContext = isCatchFilterContext; - this.IsDestructorTypeContext = isDestructorTypeContext; - this.IsLeftSideOfImportAliasDirective = isLeftSideOfImportAliasDirective; - this.IsFunctionPointerTypeArgumentContext = isFunctionPointerTypeArgumentContext; - this.IsLocalFunctionDeclarationContext = isLocalFunctionDeclarationContext; } public static CSharpSyntaxContext CreateContext(Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken) @@ -210,10 +233,12 @@ private static CSharpSyntaxContext CreateContextWorker(Document document, Semant // If the second dot was typed, we just insert two dots. var isRightSideOfNumericType = leftToken.IsNumericTypeContext(semanticModel, cancellationToken); - var isArgumentListToken = targetToken.Parent.IsKind(SyntaxKind.ArgumentList, SyntaxKind.AttributeArgumentList, SyntaxKind.ArrayRankSpecifier); + var isOnArgumentListBracketOrComma = targetToken.Parent.IsKind(SyntaxKind.ArgumentList, SyntaxKind.AttributeArgumentList, SyntaxKind.ArrayRankSpecifier); var isLocalFunctionDeclarationContext = syntaxTree.IsLocalFunctionDeclarationContext(position, cancellationToken); + var precedingModifiers = syntaxTree.GetPrecedingModifiers(position, cancellationToken); + return new CSharpSyntaxContext( document: document, semanticModel: semanticModel, @@ -222,58 +247,61 @@ private static CSharpSyntaxContext CreateContextWorker(Document document, Semant targetToken: targetToken, containingTypeDeclaration: containingTypeDeclaration, containingTypeOrEnumDeclaration: containingTypeOrEnumDeclaration, - isInNonUserCode: isInNonUserCode, - isPreProcessorDirectiveContext: isPreProcessorDirectiveContext, - isPreProcessorKeywordContext: isPreProcessorKeywordContext, - isPreProcessorExpressionContext: isPreProcessorExpressionContext, - isTypeContext: syntaxTree.IsTypeContext(position, cancellationToken, semanticModelOpt: semanticModel), - isNamespaceContext: syntaxTree.IsNamespaceContext(position, cancellationToken, semanticModelOpt: semanticModel), - isNamespaceDeclarationNameContext: syntaxTree.IsNamespaceDeclarationNameContext(position, cancellationToken), - isStatementContext: isStatementContext, - isGlobalStatementContext: isGlobalStatementContext, isAnyExpressionContext: isAnyExpressionContext, - isNonAttributeExpressionContext: isNonAttributeExpressionContext, - isConstantExpressionContext: isConstantExpressionContext, + isAtEndOfPattern: syntaxTree.IsAtEndOfPattern(leftToken, position), + isAtStartOfPattern: syntaxTree.IsAtStartOfPattern(leftToken, position), isAttributeNameContext: syntaxTree.IsAttributeNameContext(position, cancellationToken), + isAwaitKeywordContext: ComputeIsAwaitKeywordContext(position, leftToken, targetToken, isGlobalStatementContext, isAnyExpressionContext, isStatementContext), + isCatchFilterContext: syntaxTree.IsCatchFilterContext(position, leftToken), + isConstantExpressionContext: isConstantExpressionContext, + isCrefContext: syntaxTree.IsCrefContext(position, cancellationToken) && !leftToken.IsKind(SyntaxKind.DotToken), + isDeclarationExpressionContext: syntaxTree.IsDeclarationExpressionContext(position, leftToken), + isDefiniteCastTypeContext: syntaxTree.IsDefiniteCastTypeContext(position, leftToken), + isDelegateReturnTypeContext: syntaxTree.IsDelegateReturnTypeContext(position, leftToken), + isDestructorTypeContext: isDestructorTypeContext, + isEnumBaseListContext: syntaxTree.IsEnumBaseListContext(position, leftToken), isEnumTypeMemberAccessContext: syntaxTree.IsEnumTypeMemberAccessContext(semanticModel, position, cancellationToken), - isNameOfContext: syntaxTree.IsNameOfContext(position, semanticModel, cancellationToken), - isInQuery: leftToken.GetAncestor() != null, + isFixedVariableDeclarationContext: syntaxTree.IsFixedVariableDeclarationContext(position, leftToken), + isFunctionPointerTypeArgumentContext: syntaxTree.IsFunctionPointerTypeArgumentContext(position, leftToken, cancellationToken), + isGenericTypeArgumentContext: syntaxTree.IsGenericTypeArgumentContext(position, leftToken, cancellationToken), + isGlobalStatementContext: isGlobalStatementContext, + isImplicitOrExplicitOperatorTypeContext: syntaxTree.IsImplicitOrExplicitOperatorTypeContext(position, leftToken), + isOnArgumentListBracketOrComma: isOnArgumentListBracketOrComma, isInImportsDirective: leftToken.GetAncestor() != null, - isLeftSideOfImportAliasDirective: IsLeftSideOfUsingAliasDirective(leftToken), - isLabelContext: syntaxTree.IsLabelContext(position, cancellationToken), - isTypeArgumentOfConstraintContext: syntaxTree.IsTypeArgumentOfConstraintClause(position, cancellationToken), - isRightOfDotOrArrowOrColonColon: syntaxTree.IsRightOfDotOrArrowOrColonColon(position, targetToken, cancellationToken), + isInNonUserCode: isInNonUserCode, + isInQuery: leftToken.GetAncestor() != null, + isInstanceContext: syntaxTree.IsInstanceContext(targetToken, semanticModel, cancellationToken), + isInTaskLikeTypeContext: precedingModifiers.Contains(SyntaxKind.AsyncKeyword), isIsOrAsOrSwitchOrWithExpressionContext: syntaxTree.IsIsOrAsOrSwitchOrWithExpressionContext(semanticModel, position, leftToken, cancellationToken), - isObjectCreationTypeContext: syntaxTree.IsObjectCreationTypeContext(position, leftToken, cancellationToken), - isDefiniteCastTypeContext: syntaxTree.IsDefiniteCastTypeContext(position, leftToken), - isGenericTypeArgumentContext: syntaxTree.IsGenericTypeArgumentContext(position, leftToken, cancellationToken), - isEnumBaseListContext: syntaxTree.IsEnumBaseListContext(position, leftToken), isIsOrAsTypeContext: syntaxTree.IsIsOrAsTypeContext(position, leftToken), + isLabelContext: syntaxTree.IsLabelContext(position, cancellationToken), + isLeftSideOfImportAliasDirective: IsLeftSideOfUsingAliasDirective(leftToken), + isLocalFunctionDeclarationContext: isLocalFunctionDeclarationContext, isLocalVariableDeclarationContext: syntaxTree.IsLocalVariableDeclarationContext(position, leftToken, cancellationToken), - isDeclarationExpressionContext: syntaxTree.IsDeclarationExpressionContext(position, leftToken), - isFixedVariableDeclarationContext: syntaxTree.IsFixedVariableDeclarationContext(position, leftToken), + isNameOfContext: syntaxTree.IsNameOfContext(position, semanticModel, cancellationToken), + isNamespaceContext: syntaxTree.IsNamespaceContext(position, cancellationToken, semanticModelOpt: semanticModel), + isNamespaceDeclarationNameContext: syntaxTree.IsNamespaceDeclarationNameContext(position, cancellationToken), + isNonAttributeExpressionContext: isNonAttributeExpressionContext, + isObjectCreationTypeContext: syntaxTree.IsObjectCreationTypeContext(position, leftToken, cancellationToken), isParameterTypeContext: syntaxTree.IsParameterTypeContext(position, leftToken), isPossibleLambdaOrAnonymousMethodParameterTypeContext: syntaxTree.IsPossibleLambdaOrAnonymousMethodParameterTypeContext(position, leftToken, cancellationToken), - isImplicitOrExplicitOperatorTypeContext: syntaxTree.IsImplicitOrExplicitOperatorTypeContext(position, leftToken), - isPrimaryFunctionExpressionContext: syntaxTree.IsPrimaryFunctionExpressionContext(position, leftToken), - isDelegateReturnTypeContext: syntaxTree.IsDelegateReturnTypeContext(position, leftToken), - isTypeOfExpressionContext: syntaxTree.IsTypeOfExpressionContext(position, leftToken), - precedingModifiers: syntaxTree.GetPrecedingModifiers(position, cancellationToken), - isInstanceContext: syntaxTree.IsInstanceContext(targetToken, semanticModel, cancellationToken), - isCrefContext: syntaxTree.IsCrefContext(position, cancellationToken) && !leftToken.IsKind(SyntaxKind.DotToken), - isCatchFilterContext: syntaxTree.IsCatchFilterContext(position, leftToken), - isDestructorTypeContext: isDestructorTypeContext, isPossibleTupleContext: syntaxTree.IsPossibleTupleContext(leftToken, position), - isStartPatternContext: syntaxTree.IsAtStartOfPattern(leftToken, position), - isAfterPatternContext: syntaxTree.IsAtEndOfPattern(leftToken, position), + isPreProcessorDirectiveContext: isPreProcessorDirectiveContext, + isPreProcessorExpressionContext: isPreProcessorExpressionContext, + isPreProcessorKeywordContext: isPreProcessorKeywordContext, + isPrimaryFunctionExpressionContext: syntaxTree.IsPrimaryFunctionExpressionContext(position, leftToken), + isRightOfNameSeparator: syntaxTree.IsRightOfDotOrArrowOrColonColon(position, targetToken, cancellationToken), isRightSideOfNumericType: isRightSideOfNumericType, - isInArgumentList: isArgumentListToken, - isFunctionPointerTypeArgumentContext: syntaxTree.IsFunctionPointerTypeArgumentContext(position, leftToken, cancellationToken), - isLocalFunctionDeclarationContext: isLocalFunctionDeclarationContext, + isStatementContext: isStatementContext, + isTypeArgumentOfConstraintContext: syntaxTree.IsTypeArgumentOfConstraintClause(position, cancellationToken), + isTypeContext: syntaxTree.IsTypeContext(position, cancellationToken, semanticModelOpt: semanticModel), + isTypeOfExpressionContext: syntaxTree.IsTypeOfExpressionContext(position, leftToken), + isWithinAsyncMethod: ComputeIsWithinAsyncMethod(), + precedingModifiers: precedingModifiers, cancellationToken: cancellationToken); } - private static new bool IsWithinAsyncMethod() + private static bool ComputeIsWithinAsyncMethod() { // TODO: Implement this if any C# completion code needs to know if it is in an async // method or not. @@ -406,16 +434,22 @@ internal bool IsAwaitStatementContext(int position, CancellationToken cancellati /// /// Determines whether await should be suggested in a given position. /// - internal override bool IsAwaitKeywordContext() + private static bool ComputeIsAwaitKeywordContext( + int position, + SyntaxToken leftToken, + SyntaxToken targetToken, + bool isGlobalStatementContext, + bool isAnyExpressionContext, + bool isStatementContext) { - if (IsGlobalStatementContext) + if (isGlobalStatementContext) { return true; } - if (IsAnyExpressionContext || IsStatementContext) + if (isAnyExpressionContext || isStatementContext) { - foreach (var node in LeftToken.GetAncestors()) + foreach (var node in leftToken.GetAncestors()) { if (node.IsAnyLambdaOrAnonymousMethod()) { @@ -426,9 +460,9 @@ internal override bool IsAwaitKeywordContext() { // There are some cases where "await" is allowed in a query context. See error CS1995 for details: // error CS1995: The 'await' operator may only be used in a query expression within the first collection expression of the initial 'from' clause or within the collection expression of a 'join' clause - if (TargetToken.IsKind(SyntaxKind.InKeyword)) + if (targetToken.IsKind(SyntaxKind.InKeyword)) { - return TargetToken.Parent switch + return targetToken.Parent switch { FromClauseSyntax { Parent: QueryExpressionSyntax queryExpression } fromClause => queryExpression.FromClause == fromClause, JoinClauseSyntax => true, @@ -443,7 +477,7 @@ internal override bool IsAwaitKeywordContext() { if (lockStatement.Statement != null && !lockStatement.Statement.IsMissing && - lockStatement.Statement.Span.Contains(Position)) + lockStatement.Statement.Span.Contains(position)) { return false; } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxFactsService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxFactsService.cs index f2bd55d10c9c0..51d04a721d2ad 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxFactsService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/LanguageServices/CSharpSyntaxFactsService.cs @@ -45,12 +45,6 @@ public void AddFirstMissingCloseBrace( newContextNode = (TContextNode)newRoot.GetAnnotatedNodes(s_annotation).Single(); } - public bool IsPossibleTupleContext(SyntaxTree syntaxTree, int position, CancellationToken cancellationToken) - { - var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken); - return syntaxTree.IsPossibleTupleContext(token, position); - } - private class AddFirstMissingCloseBraceRewriter : CSharpSyntaxRewriter { private readonly SyntaxNode _contextNode; diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/ContextQuery/SyntaxContext.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/ContextQuery/SyntaxContext.cs index ad21845b57318..75c79ecf2114f 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/ContextQuery/SyntaxContext.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/ContextQuery/SyntaxContext.cs @@ -2,20 +2,55 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#nullable disable - -using System.Collections.Generic; using System.Collections.Immutable; using System.Threading; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.LanguageServices; -using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery { internal abstract class SyntaxContext { - private ISet _outerTypes; + public Document Document { get; } + public SemanticModel SemanticModel { get; } + public SyntaxTree SyntaxTree { get; } + public int Position { get; } + + /// + /// The token to the left of . This token may be touching the position. + /// + public SyntaxToken LeftToken { get; } + + /// + /// The first token to the left of that we're not touching. Equal to + /// if we aren't touching . + /// + public SyntaxToken TargetToken { get; } + + public bool IsAnyExpressionContext { get; } + public bool IsAtEndOfPattern { get; } + public bool IsAtStartOfPattern { get; } + public bool IsAttributeNameContext { get; } + public bool IsAwaitKeywordContext { get; } + public bool IsEnumTypeMemberAccessContext { get; } + public bool IsGlobalStatementContext { get; } + public bool IsInImportsDirective { get; } + public bool IsInQuery { get; } + public bool IsInTaskLikeTypeContext { get; } + public bool IsNameOfContext { get; } + public bool IsNamespaceContext { get; } + public bool IsNamespaceDeclarationNameContext { get; } + public bool IsOnArgumentListBracketOrComma { get; } + public bool IsPossibleTupleContext { get; } + public bool IsPreProcessorDirectiveContext { get; } + public bool IsPreProcessorExpressionContext { get; } + public bool IsRightOfNameSeparator { get; } + public bool IsRightSideOfNumericType { get; } + public bool IsStatementContext { get; } + public bool IsTypeContext { get; } + public bool IsWithinAsyncMethod { get; } + + public ImmutableArray InferredTypes { get; } protected SyntaxContext( Document document, @@ -23,26 +58,28 @@ protected SyntaxContext( int position, SyntaxToken leftToken, SyntaxToken targetToken, - bool isTypeContext, + bool isAnyExpressionContext, + bool isAtEndOfPattern, + bool isAtStartOfPattern, + bool isAttributeNameContext, + bool isAwaitKeywordContext, + bool isEnumTypeMemberAccessContext, + bool isGlobalStatementContext, + bool isInImportsDirective, + bool isInQuery, + bool isInTaskLikeTypeContext, + bool isNameOfContext, bool isNamespaceContext, bool isNamespaceDeclarationNameContext, + bool isOnArgumentListBracketOrComma, + bool isPossibleTupleContext, bool isPreProcessorDirectiveContext, bool isPreProcessorExpressionContext, bool isRightOfNameSeparator, + bool isRightSideOfNumericType, bool isStatementContext, - bool isGlobalStatementContext, - bool isAnyExpressionContext, - bool isAttributeNameContext, - bool isEnumTypeMemberAccessContext, - bool isNameOfContext, - bool isInQuery, - bool isInImportsDirective, + bool isTypeContext, bool isWithinAsyncMethod, - bool isPossibleTupleContext, - bool isAtStartOfPattern, - bool isAtEndOfPattern, - bool isRightSideOfNumericType, - bool isOnArgumentListBracketOrComma, CancellationToken cancellationToken) { this.Document = document; @@ -51,101 +88,37 @@ protected SyntaxContext( this.Position = position; this.LeftToken = leftToken; this.TargetToken = targetToken; - this.IsTypeContext = isTypeContext; + + this.IsAnyExpressionContext = isAnyExpressionContext; + this.IsAtEndOfPattern = isAtEndOfPattern; + this.IsAtStartOfPattern = isAtStartOfPattern; + this.IsAttributeNameContext = isAttributeNameContext; + this.IsAwaitKeywordContext = isAwaitKeywordContext; + this.IsEnumTypeMemberAccessContext = isEnumTypeMemberAccessContext; + this.IsGlobalStatementContext = isGlobalStatementContext; + this.IsInImportsDirective = isInImportsDirective; + this.IsInQuery = isInQuery; + this.IsInTaskLikeTypeContext = isInTaskLikeTypeContext; + this.IsNameOfContext = isNameOfContext; this.IsNamespaceContext = isNamespaceContext; this.IsNamespaceDeclarationNameContext = isNamespaceDeclarationNameContext; + this.IsOnArgumentListBracketOrComma = isOnArgumentListBracketOrComma; + this.IsPossibleTupleContext = isPossibleTupleContext; this.IsPreProcessorDirectiveContext = isPreProcessorDirectiveContext; this.IsPreProcessorExpressionContext = isPreProcessorExpressionContext; this.IsRightOfNameSeparator = isRightOfNameSeparator; + this.IsRightSideOfNumericType = isRightSideOfNumericType; this.IsStatementContext = isStatementContext; - this.IsGlobalStatementContext = isGlobalStatementContext; - this.IsAnyExpressionContext = isAnyExpressionContext; - this.IsAttributeNameContext = isAttributeNameContext; - this.IsEnumTypeMemberAccessContext = isEnumTypeMemberAccessContext; - this.IsNameOfContext = isNameOfContext; - this.IsInQuery = isInQuery; - this.IsInImportsDirective = isInImportsDirective; + this.IsTypeContext = isTypeContext; this.IsWithinAsyncMethod = isWithinAsyncMethod; - this.IsPossibleTupleContext = isPossibleTupleContext; - this.IsAtStartOfPattern = isAtStartOfPattern; - this.IsAtEndOfPattern = isAtEndOfPattern; - this.InferredTypes = document.GetRequiredLanguageService().InferTypes(semanticModel, position, cancellationToken); - this.IsRightSideOfNumericType = isRightSideOfNumericType; - this.IsOnArgumentListBracketOrComma = isOnArgumentListBracketOrComma; - } - - public Document Document { get; } - public SemanticModel SemanticModel { get; } - public SyntaxTree SyntaxTree { get; } - public int Position { get; } - - /// - /// The token to the left of . This token may be touching the position. - /// - public SyntaxToken LeftToken { get; } - /// - /// The first token to the left of that we're not touching. Equal to - /// if we aren't touching . - /// - public SyntaxToken TargetToken { get; } - - public bool IsTypeContext { get; } - public bool IsNamespaceContext { get; } - - public bool IsNamespaceDeclarationNameContext { get; } - - public bool IsPreProcessorDirectiveContext { get; } - public bool IsPreProcessorExpressionContext { get; } - - public bool IsRightOfNameSeparator { get; } - public bool IsStatementContext { get; } - public bool IsGlobalStatementContext { get; } - public bool IsAnyExpressionContext { get; } - public bool IsAttributeNameContext { get; } - public bool IsEnumTypeMemberAccessContext { get; } - public bool IsNameOfContext { get; } - - public bool IsInQuery { get; } - public bool IsInImportsDirective { get; } - public bool IsWithinAsyncMethod { get; } - public bool IsPossibleTupleContext { get; } - public bool IsAtStartOfPattern { get; } - public bool IsAtEndOfPattern { get; } - - public bool IsRightSideOfNumericType { get; } - public bool IsOnArgumentListBracketOrComma { get; } - - public ImmutableArray InferredTypes { get; } - - private ISet ComputeOuterTypes(CancellationToken cancellationToken) - { - var enclosingSymbol = this.SemanticModel.GetEnclosingSymbol(this.LeftToken.SpanStart, cancellationToken); - if (enclosingSymbol != null) - { - var containingType = enclosingSymbol.GetContainingTypeOrThis(); - if (containingType != null) - { - return containingType.GetContainingTypes().ToSet(); - } - } - - return SpecializedCollections.EmptySet(); - } - - internal abstract bool IsAwaitKeywordContext(); - - public ISet GetOuterTypes(CancellationToken cancellationToken) - { - if (_outerTypes == null) - { - Interlocked.CompareExchange(ref _outerTypes, ComputeOuterTypes(cancellationToken), null); - } - - return _outerTypes; + this.InferredTypes = document.GetRequiredLanguageService().InferTypes(semanticModel, position, cancellationToken); } - public TService GetLanguageService() where TService : class, ILanguageService + public TService? GetLanguageService() where TService : class, ILanguageService => Document.GetLanguageService(); + + public TService GetRequiredLanguageService() where TService : class, ILanguageService + => Document.GetRequiredLanguageService(); } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs index 07fa90679c793..b89aa886f5476 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs @@ -16,9 +16,6 @@ internal interface ISyntaxFactsService : ISyntaxFacts, ILanguageService { bool IsInNonUserCode(SyntaxTree syntaxTree, int position, CancellationToken cancellationToken); - // Violation. This is feature level code. - bool IsPossibleTupleContext(SyntaxTree syntaxTree, int position, CancellationToken cancellationToken); - // Violation. This is feature level code. Task> GetSelectedFieldsAndPropertiesAsync(SyntaxTree syntaxTree, TextSpan textSpan, bool allowPartialSelection, CancellationToken cancellationToken); diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/ContextQuery/VisualBasicSyntaxContext.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/ContextQuery/VisualBasicSyntaxContext.vb index fe6ff29927cd4..9775f822b5aba 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/ContextQuery/VisualBasicSyntaxContext.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/ContextQuery/VisualBasicSyntaxContext.vb @@ -34,22 +34,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery ''' Public ReadOnly MustBeginNewStatement As Boolean - Public ReadOnly IsSingleLineStatementContext As Boolean + Public ReadOnly IsCustomEventContext As Boolean + Public ReadOnly IsInLambda As Boolean + Public ReadOnly IsInterfaceMemberDeclarationKeywordContext As Boolean Public ReadOnly IsMultiLineStatementContext As Boolean - + Public ReadOnly IsPreprocessorEndDirectiveKeywordContext As Boolean + Public ReadOnly IsPreprocessorStartContext As Boolean + Public ReadOnly IsQueryOperatorContext As Boolean Public ReadOnly IsTypeDeclarationKeywordContext As Boolean Public ReadOnly IsTypeMemberDeclarationKeywordContext As Boolean - Public ReadOnly IsInterfaceMemberDeclarationKeywordContext As Boolean + Public ReadOnly IsWithinPreprocessorContext As Boolean Public ReadOnly ModifierCollectionFacts As ModifierCollectionFacts - Public ReadOnly IsPreprocessorStartContext As Boolean - Public ReadOnly IsInLambda As Boolean - Public ReadOnly IsQueryOperatorContext As Boolean - Public ReadOnly EnclosingNamedType As CancellableLazy(Of INamedTypeSymbol) - Public ReadOnly IsCustomEventContext As Boolean - Public ReadOnly IsPreprocessorEndDirectiveKeywordContext As Boolean - Public ReadOnly IsWithinPreprocessorContext As Boolean + Public ReadOnly EnclosingNamedType As INamedTypeSymbol Private Sub New( document As Document, @@ -57,53 +55,58 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery position As Integer, leftToken As SyntaxToken, targetToken As SyntaxToken, - isTypeContext As Boolean, - isNamespaceContext As Boolean, - isNamespaceDeclarationNameContext As Boolean, - isPreProcessorDirectiveContext As Boolean, - isPreProcessorExpressionContext As Boolean, - isRightOfNameSeparator As Boolean, - isSingleLineStatementContext As Boolean, - isGlobalStatementContext As Boolean, - isExpressionContext As Boolean, isAttributeNameContext As Boolean, + isAwaitKeywordContext As Boolean, + isCustomEventContext As Boolean, isEnumTypeMemberAccessContext As Boolean, - isNameOfContext As Boolean, + isAnyExpressionContext As Boolean, + isGlobalStatementContext As Boolean, + isOnArgumentListBracketOrComma As Boolean, + isInImportsDirective As Boolean, isInLambda As Boolean, isInQuery As Boolean, - isInImportsDirective As Boolean, - isCustomEventContext As Boolean, + isInTaskLikeTypeContext As Boolean, + isNameOfContext As Boolean, + isNamespaceContext As Boolean, + isNamespaceDeclarationNameContext As Boolean, isPossibleTupleContext As Boolean, - isInArgumentList As Boolean, + isPreProcessorDirectiveContext As Boolean, + isPreProcessorExpressionContext As Boolean, + isRightOfNameSeparator As Boolean, + isRightSideOfNumericType As Boolean, + isStatementContext As Boolean, + isTypeContext As Boolean, + isWithinAsyncMethod As Boolean, cancellationToken As CancellationToken ) - MyBase.New( document, semanticModel, position, leftToken, targetToken, - isTypeContext, - isNamespaceContext, - isNamespaceDeclarationNameContext, - isPreProcessorDirectiveContext, - isPreProcessorExpressionContext, - isRightOfNameSeparator, - isStatementContext:=isSingleLineStatementContext, - isGlobalStatementContext:=isGlobalStatementContext, - isAnyExpressionContext:=isExpressionContext, + isAnyExpressionContext:=isAnyExpressionContext, + isAtEndOfPattern:=False, + isAtStartOfPattern:=False, isAttributeNameContext:=isAttributeNameContext, + isAwaitKeywordContext:=isAwaitKeywordContext, isEnumTypeMemberAccessContext:=isEnumTypeMemberAccessContext, - isNameOfContext:=isNameOfContext, - isInQuery:=isInQuery, + isGlobalStatementContext:=isGlobalStatementContext, isInImportsDirective:=isInImportsDirective, - isWithinAsyncMethod:=IsWithinAsyncMethod(targetToken), + isInQuery:=isInQuery, + isInTaskLikeTypeContext:=isInTaskLikeTypeContext, + isNameOfContext:=isNameOfContext, + isNamespaceContext, + isNamespaceDeclarationNameContext, + isOnArgumentListBracketOrComma:=isOnArgumentListBracketOrComma, isPossibleTupleContext:=isPossibleTupleContext, - isAtStartOfPattern:=False, - isAtEndOfPattern:=False, - isRightSideOfNumericType:=False, - isOnArgumentListBracketOrComma:=isInArgumentList, + isPreProcessorDirectiveContext:=isPreProcessorDirectiveContext, + isPreProcessorExpressionContext:=isPreProcessorExpressionContext, + isRightOfNameSeparator:=isRightOfNameSeparator, + isRightSideOfNumericType:=isRightSideOfNumericType, + isStatementContext:=isStatementContext, + isTypeContext:=isTypeContext, + isWithinAsyncMethod:=isWithinAsyncMethod, cancellationToken:=cancellationToken) Dim syntaxTree = semanticModel.SyntaxTree @@ -111,7 +114,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Me.FollowsEndOfStatement = targetToken.FollowsEndOfStatement(position) Me.MustBeginNewStatement = targetToken.MustBeginNewStatement(position) - Me.IsSingleLineStatementContext = isSingleLineStatementContext Me.IsMultiLineStatementContext = syntaxTree.IsMultiLineStatementStartContext(position, targetToken, cancellationToken) Me.IsTypeDeclarationKeywordContext = syntaxTree.IsTypeDeclarationKeywordContext(position, targetToken, cancellationToken) @@ -124,13 +126,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Me.IsWithinPreprocessorContext = ComputeIsWithinPreprocessorContext(position, targetToken) Me.IsQueryOperatorContext = syntaxTree.IsFollowingCompleteExpression(Of QueryExpressionSyntax)(position, targetToken, Function(query) query, cancellationToken) - Me.EnclosingNamedType = CancellableLazy.Create(AddressOf ComputeEnclosingNamedType) + Me.EnclosingNamedType = ComputeEnclosingNamedType(cancellationToken) Me.IsCustomEventContext = isCustomEventContext Me.IsPreprocessorEndDirectiveKeywordContext = targetToken.FollowsBadEndDirective() End Sub - Private Shared Shadows Function IsWithinAsyncMethod(targetToken As SyntaxToken) As Boolean + Private Shared Function ComputeIsInTaskLikeTypeContext(targetToken As SyntaxToken) As Boolean + ' If we're after the 'as' in an async method declaration, then filter down to task-like types only. + If targetToken.Kind() = SyntaxKind.AsKeyword Then + Dim asClause = TryCast(targetToken.Parent, AsClauseSyntax) + Dim methodStatement = TryCast(asClause?.Parent, MethodBaseSyntax) + If methodStatement IsNot Nothing Then + Return methodStatement.Modifiers.Any(SyntaxKind.AsyncKeyword) + End If + End If + + Return False + End Function + + Private Shared Shadows Function ComputeIsWithinAsyncMethod(targetToken As SyntaxToken) As Boolean Dim enclosingMethod = targetToken.GetAncestor(Of MethodBlockBaseSyntax)() Return enclosingMethod IsNot Nothing AndAlso enclosingMethod.BlockStatement.Modifiers.Any(SyntaxKind.AsyncKeyword) End Function @@ -140,40 +155,52 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Dim leftToken = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken, includeDirectives:=True, includeDocumentationComments:=True) Dim targetToken = syntaxTree.GetTargetToken(position, cancellationToken) + Dim isAnyExpressionContext = syntaxTree.IsExpressionContext(position, targetToken, cancellationToken, semanticModel) + Dim isInQuery = leftToken.GetAncestor(Of QueryExpressionSyntax)() IsNot Nothing + Dim isStatementContext = syntaxTree.IsSingleLineStatementContext(position, targetToken, cancellationToken) + Return New VisualBasicSyntaxContext( document, semanticModel, position, leftToken, targetToken, - isTypeContext:=syntaxTree.IsTypeContext(position, targetToken, cancellationToken, semanticModel), + isAnyExpressionContext:=isAnyExpressionContext, + isAttributeNameContext:=syntaxTree.IsAttributeNameContext(position, targetToken, cancellationToken), + isAwaitKeywordContext:=ComputeIsAwaitKeywordContext(targetToken, isAnyExpressionContext, isInQuery, isStatementContext), + isCustomEventContext:=targetToken.GetAncestor(Of EventBlockSyntax)() IsNot Nothing, + isEnumTypeMemberAccessContext:=syntaxTree.IsEnumTypeMemberAccessContext(position, targetToken, semanticModel, cancellationToken), + isGlobalStatementContext:=syntaxTree.IsGlobalStatementContext(position, cancellationToken), + isInImportsDirective:=leftToken.GetAncestor(Of ImportsStatementSyntax)() IsNot Nothing, + isInLambda:=leftToken.GetAncestor(Of LambdaExpressionSyntax)() IsNot Nothing, + isInQuery:=isInQuery, + isInTaskLikeTypeContext:=ComputeIsInTaskLikeTypeContext(targetToken), + isNameOfContext:=syntaxTree.IsNameOfContext(position, cancellationToken), isNamespaceContext:=syntaxTree.IsNamespaceContext(position, targetToken, cancellationToken, semanticModel), isNamespaceDeclarationNameContext:=syntaxTree.IsNamespaceDeclarationNameContext(position, cancellationToken), + isOnArgumentListBracketOrComma:=targetToken.Parent.IsKind(SyntaxKind.ArgumentList), + isPossibleTupleContext:=syntaxTree.IsPossibleTupleContext(targetToken, position), isPreProcessorDirectiveContext:=syntaxTree.IsInPreprocessorDirectiveContext(position, cancellationToken), isPreProcessorExpressionContext:=syntaxTree.IsInPreprocessorExpressionContext(position, cancellationToken), isRightOfNameSeparator:=syntaxTree.IsRightOfDot(position, cancellationToken), - isSingleLineStatementContext:=syntaxTree.IsSingleLineStatementContext(position, targetToken, cancellationToken), - isGlobalStatementContext:=syntaxTree.IsGlobalStatementContext(position, cancellationToken), - isExpressionContext:=syntaxTree.IsExpressionContext(position, targetToken, cancellationToken, semanticModel), - isAttributeNameContext:=syntaxTree.IsAttributeNameContext(position, targetToken, cancellationToken), - isEnumTypeMemberAccessContext:=syntaxTree.IsEnumTypeMemberAccessContext(position, targetToken, semanticModel, cancellationToken), - isNameOfContext:=syntaxTree.IsNameOfContext(position, cancellationToken), - isInLambda:=leftToken.GetAncestor(Of LambdaExpressionSyntax)() IsNot Nothing, - isInQuery:=leftToken.GetAncestor(Of QueryExpressionSyntax)() IsNot Nothing, - isInImportsDirective:=leftToken.GetAncestor(Of ImportsStatementSyntax)() IsNot Nothing, - isCustomEventContext:=targetToken.GetAncestor(Of EventBlockSyntax)() IsNot Nothing, - isPossibleTupleContext:=syntaxTree.IsPossibleTupleContext(targetToken, position), - isInArgumentList:=targetToken.Parent.IsKind(SyntaxKind.ArgumentList), + isRightSideOfNumericType:=False, + isStatementContext:=isStatementContext, + isTypeContext:=syntaxTree.IsTypeContext(position, targetToken, cancellationToken, semanticModel), + isWithinAsyncMethod:=ComputeIsWithinAsyncMethod(targetToken), cancellationToken:=cancellationToken) End Function - Friend Overrides Function IsAwaitKeywordContext() As Boolean - If IsAnyExpressionContext OrElse IsSingleLineStatementContext Then - If IsInQuery Then + Private Shared Function ComputeIsAwaitKeywordContext( + targetToken As SyntaxToken, + isAnyExpressionContext As Boolean, + isInQuery As Boolean, + isSingleLineStatementContext As Boolean) As Boolean + If isAnyExpressionContext OrElse isSingleLineStatementContext Then + If isInQuery Then ' There are some places where Await is allowed: ' BC36929: 'Await' may only be used in a query expression within the first collection expression of the initial 'From' clause or within the collection expression of a 'Join' clause. - If TargetToken.Kind = SyntaxKind.InKeyword Then - Dim collectionRange = TryCast(TargetToken.Parent, CollectionRangeVariableSyntax) + If targetToken.Kind = SyntaxKind.InKeyword Then + Dim collectionRange = TryCast(targetToken.Parent, CollectionRangeVariableSyntax) If collectionRange IsNot Nothing Then If TypeOf collectionRange.Parent Is FromClauseSyntax AndAlso TypeOf collectionRange.Parent.Parent Is QueryExpressionSyntax Then Dim fromClause = DirectCast(collectionRange.Parent, FromClauseSyntax) @@ -193,7 +220,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Return False End If - For Each node In TargetToken.GetAncestors(Of SyntaxNode)() + For Each node In targetToken.GetAncestors(Of SyntaxNode)() If node.IsKind(SyntaxKind.SingleLineSubLambdaExpression, SyntaxKind.SingleLineFunctionLambdaExpression, SyntaxKind.MultiLineSubLambdaExpression, SyntaxKind.MultiLineFunctionLambdaExpression) Then Return True diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/ContextQuery/VisualBasicSyntaxContextExtensions.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/ContextQuery/VisualBasicSyntaxContextExtensions.vb index fd3e5e0dc90de..b928016845b83 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/ContextQuery/VisualBasicSyntaxContextExtensions.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/Extensions/ContextQuery/VisualBasicSyntaxContextExtensions.vb @@ -10,7 +10,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Friend Module VisualBasicSyntaxTreeExtensions - Friend Function IsAccessibleEventContext(context As VisualBasicSyntaxContext, startAtEnclosingBaseType As Boolean, cancellationToken As CancellationToken) As Boolean + Friend Function IsAccessibleEventContext(context As VisualBasicSyntaxContext, startAtEnclosingBaseType As Boolean) As Boolean If context.FollowsEndOfStatement Then Return False End If @@ -19,8 +19,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery If targetToken.IsChildToken(Of HandlesClauseSyntax)(Function(hc) hc.HandlesKeyword) OrElse targetToken.IsChildSeparatorToken(Function(hc As HandlesClauseSyntax) hc.Events) Then - Dim container = context.EnclosingNamedType.GetValue(cancellationToken) - + Dim container = context.EnclosingNamedType If container Is Nothing Then Return False End If diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxFactsService.vb b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxFactsService.vb index b600e5b9d7e1b..f797941a2eb47 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxFactsService.vb +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/VisualBasic/LanguageServices/VisualBasicSyntaxFactsService.vb @@ -28,15 +28,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return syntaxTree.IsInNonUserCode(position, cancellationToken) End Function - Public Function IsPossibleTupleContext( - syntaxTree As SyntaxTree, - position As Integer, - cancellationToken As CancellationToken) As Boolean Implements ISyntaxFactsService.IsPossibleTupleContext - - Dim token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken) - Return syntaxTree.IsPossibleTupleContext(token, position) - End Function - Public Sub AddFirstMissingCloseBrace(Of TContextNode As SyntaxNode)( root As SyntaxNode, contextNode As TContextNode, ByRef newRoot As SyntaxNode, ByRef newContextNode As TContextNode) Implements ISyntaxFactsService.AddFirstMissingCloseBrace diff --git a/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationService.vb b/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationService.vb index a23168fbc0441..4e8f0c5ebc35b 100644 --- a/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationService.vb +++ b/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationService.vb @@ -10,7 +10,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations - Friend Class VisualBasicRecommendationService + Partial Friend Class VisualBasicRecommendationService Inherits AbstractRecommendationService(Of VisualBasicSyntaxContext) @@ -22,7 +22,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations Return VisualBasicSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken) End Function - Protected Overrides Function CreateRunner(context As VisualBasicSyntaxContext, filterOutOfScopeLocals As Boolean, cancellationToken As CancellationToken) As AbstractRecommendationServiceRunner(Of VisualBasicSyntaxContext) + Protected Overrides Function CreateRunner(context As VisualBasicSyntaxContext, filterOutOfScopeLocals As Boolean, cancellationToken As CancellationToken) As AbstractRecommendationServiceRunner Return New VisualBasicRecommendationServiceRunner(context, filterOutOfScopeLocals, cancellationToken) End Function End Class diff --git a/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationServiceRunner.vb b/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationServiceRunner.vb index a285ef9b9f2b0..2371571c1fafc 100644 --- a/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationServiceRunner.vb +++ b/src/Workspaces/VisualBasic/Portable/Recommendations/VisualBasicRecommendationServiceRunner.vb @@ -11,507 +11,509 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations - Friend Class VisualBasicRecommendationServiceRunner - Inherits AbstractRecommendationServiceRunner(Of VisualBasicSyntaxContext) + Partial Friend Class VisualBasicRecommendationService + Private NotInheritable Class VisualBasicRecommendationServiceRunner + Inherits AbstractRecommendationServiceRunner - Public Sub New(context As VisualBasicSyntaxContext, filterOutOfScopeLocals As Boolean, cancellationToken As CancellationToken) - MyBase.New(context, filterOutOfScopeLocals, cancellationToken) - End Sub + Public Sub New(context As VisualBasicSyntaxContext, filterOutOfScopeLocals As Boolean, cancellationToken As CancellationToken) + MyBase.New(context, filterOutOfScopeLocals, cancellationToken) + End Sub - Public Overrides Function GetRecommendedSymbols() As RecommendedSymbols - Return New RecommendedSymbols(GetSymbols()) - End Function + Public Overrides Function GetRecommendedSymbols() As RecommendedSymbols + Return New RecommendedSymbols(GetSymbols()) + End Function - Private Overloads Function GetSymbols() As ImmutableArray(Of ISymbol) - If _context.SyntaxTree.IsInNonUserCode(_context.Position, _cancellationToken) OrElse + Private Overloads Function GetSymbols() As ImmutableArray(Of ISymbol) + If _context.SyntaxTree.IsInNonUserCode(_context.Position, _cancellationToken) OrElse _context.SyntaxTree.IsInSkippedText(_context.Position, _cancellationToken) Then - Return ImmutableArray(Of ISymbol).Empty - End If - - Dim node = _context.TargetToken.Parent - If _context.IsGlobalStatementContext Then - Return GetSymbolsForGlobalStatementContext() - ElseIf _context.IsRightOfNameSeparator Then - If node.Kind = SyntaxKind.SimpleMemberAccessExpression Then - Return GetSymbolsForMemberAccessExpression(DirectCast(node, MemberAccessExpressionSyntax)) - ElseIf node.Kind = SyntaxKind.QualifiedName Then - Return GetSymbolsForQualifiedNameSyntax(DirectCast(node, QualifiedNameSyntax)) - End If - ElseIf _context.SyntaxTree.IsQueryIntoClauseContext(_context.Position, _context.TargetToken, _cancellationToken) Then - Return GetUnqualifiedSymbolsForQueryIntoContext() - ElseIf _context.IsAnyExpressionContext OrElse - _context.IsSingleLineStatementContext OrElse + Return ImmutableArray(Of ISymbol).Empty + End If + + Dim node = _context.TargetToken.Parent + If _context.IsGlobalStatementContext Then + Return GetSymbolsForGlobalStatementContext() + ElseIf _context.IsRightOfNameSeparator Then + If node.Kind = SyntaxKind.SimpleMemberAccessExpression Then + Return GetSymbolsForMemberAccessExpression(DirectCast(node, MemberAccessExpressionSyntax)) + ElseIf node.Kind = SyntaxKind.QualifiedName Then + Return GetSymbolsForQualifiedNameSyntax(DirectCast(node, QualifiedNameSyntax)) + End If + ElseIf _context.SyntaxTree.IsQueryIntoClauseContext(_context.Position, _context.TargetToken, _cancellationToken) Then + Return GetUnqualifiedSymbolsForQueryIntoContext() + ElseIf _context.IsAnyExpressionContext OrElse + _context.IsStatementContext OrElse _context.IsNameOfContext Then - Return GetUnqualifiedSymbolsForExpressionOrStatementContext() - ElseIf _context.IsTypeContext OrElse _context.IsNamespaceContext Then - Return GetUnqualifiedSymbolsForType() - ElseIf _context.SyntaxTree.IsLabelContext(_context.Position, _context.TargetToken, _cancellationToken) Then - Return GetUnqualifiedSymbolsForLabelContext() - ElseIf _context.SyntaxTree.IsRaiseEventContext(_context.Position, _context.TargetToken, _cancellationToken) Then - Return GetUnqualifiedSymbolsForRaiseEvent() - ElseIf _context.TargetToken.IsKind(SyntaxKind.ForKeyword) Then - Dim symbols = GetUnqualifiedSymbolsForExpressionOrStatementContext().WhereAsArray(AddressOf IsWritableFieldOrLocal) - Return symbols - ElseIf _context.IsNamespaceDeclarationNameContext Then - Return GetSymbolsForNamespaceDeclarationNameContext(Of NamespaceBlockSyntax)() - End If - - Return ImmutableArray(Of ISymbol).Empty - End Function - - Public Overrides Function TryGetExplicitTypeOfLambdaParameter(lambdaSyntax As SyntaxNode, ordinalInLambda As Integer, ByRef explicitLambdaParameterType As ITypeSymbol) As Boolean - Dim lambdaExpressionSyntax = DirectCast(lambdaSyntax, LambdaExpressionSyntax) - Dim parameters = lambdaExpressionSyntax.SubOrFunctionHeader.ParameterList.Parameters - If parameters.Count > ordinalInLambda Then - Dim parameterSyntax = parameters(ordinalInLambda) - If parameterSyntax.AsClause IsNot Nothing Then - explicitLambdaParameterType = _context.SemanticModel.GetTypeInfo(parameterSyntax.AsClause.Type, _cancellationToken).Type - Return explicitLambdaParameterType IsNot Nothing - End If - End If - - Return False - End Function - - Private Function IsWritableFieldOrLocal(symbol As ISymbol) As Boolean - If symbol.Kind() = SymbolKind.Field Then - Dim field = DirectCast(symbol, IFieldSymbol) - Return Not field.IsReadOnly AndAlso Not field.IsConst - End If - - If symbol.Kind() = SymbolKind.Local Then - Dim local = DirectCast(symbol, ILocalSymbol) - Return Not local.IsConst - End If - - Return False - End Function - - Private Function GetSymbolsForGlobalStatementContext() As ImmutableArray(Of ISymbol) - Return _context.SemanticModel.LookupSymbols(_context.TargetToken.Span.End) - End Function - - Private Function GetUnqualifiedSymbolsForQueryIntoContext() As ImmutableArray(Of ISymbol) - Dim symbols = _context.SemanticModel _ + Return GetUnqualifiedSymbolsForExpressionOrStatementContext() + ElseIf _context.IsTypeContext OrElse _context.IsNamespaceContext Then + Return GetUnqualifiedSymbolsForType() + ElseIf _context.SyntaxTree.IsLabelContext(_context.Position, _context.TargetToken, _cancellationToken) Then + Return GetUnqualifiedSymbolsForLabelContext() + ElseIf _context.SyntaxTree.IsRaiseEventContext(_context.Position, _context.TargetToken, _cancellationToken) Then + Return GetUnqualifiedSymbolsForRaiseEvent() + ElseIf _context.TargetToken.IsKind(SyntaxKind.ForKeyword) Then + Dim symbols = GetUnqualifiedSymbolsForExpressionOrStatementContext().WhereAsArray(AddressOf IsWritableFieldOrLocal) + Return symbols + ElseIf _context.IsNamespaceDeclarationNameContext Then + Return GetSymbolsForNamespaceDeclarationNameContext(Of NamespaceBlockSyntax)() + End If + + Return ImmutableArray(Of ISymbol).Empty + End Function + + Public Overrides Function TryGetExplicitTypeOfLambdaParameter(lambdaSyntax As SyntaxNode, ordinalInLambda As Integer, ByRef explicitLambdaParameterType As ITypeSymbol) As Boolean + Dim lambdaExpressionSyntax = DirectCast(lambdaSyntax, LambdaExpressionSyntax) + Dim parameters = lambdaExpressionSyntax.SubOrFunctionHeader.ParameterList.Parameters + If parameters.Count > ordinalInLambda Then + Dim parameterSyntax = parameters(ordinalInLambda) + If parameterSyntax.AsClause IsNot Nothing Then + explicitLambdaParameterType = _context.SemanticModel.GetTypeInfo(parameterSyntax.AsClause.Type, _cancellationToken).Type + Return explicitLambdaParameterType IsNot Nothing + End If + End If + + Return False + End Function + + Private Function IsWritableFieldOrLocal(symbol As ISymbol) As Boolean + If symbol.Kind() = SymbolKind.Field Then + Dim field = DirectCast(symbol, IFieldSymbol) + Return Not field.IsReadOnly AndAlso Not field.IsConst + End If + + If symbol.Kind() = SymbolKind.Local Then + Dim local = DirectCast(symbol, ILocalSymbol) + Return Not local.IsConst + End If + + Return False + End Function + + Private Function GetSymbolsForGlobalStatementContext() As ImmutableArray(Of ISymbol) + Return _context.SemanticModel.LookupSymbols(_context.TargetToken.Span.End) + End Function + + Private Function GetUnqualifiedSymbolsForQueryIntoContext() As ImmutableArray(Of ISymbol) + Dim symbols = _context.SemanticModel _ .LookupSymbols(_context.TargetToken.SpanStart, includeReducedExtensionMethods:=True) - Return ImmutableArray(Of ISymbol).CastUp( + Return ImmutableArray(Of ISymbol).CastUp( symbols.OfType(Of IMethodSymbol)(). Where(Function(m) m.IsAggregateFunction()). ToImmutableArray()) - End Function + End Function - Private Function GetUnqualifiedSymbolsForLabelContext() As ImmutableArray(Of ISymbol) - Return _context.SemanticModel.LookupLabels(_context.TargetToken.SpanStart) - End Function + Private Function GetUnqualifiedSymbolsForLabelContext() As ImmutableArray(Of ISymbol) + Return _context.SemanticModel.LookupLabels(_context.TargetToken.SpanStart) + End Function - Private Function GetUnqualifiedSymbolsForRaiseEvent() As ImmutableArray(Of ISymbol) - Dim containingType = _context.SemanticModel.GetEnclosingSymbol(_context.Position, _cancellationToken).ContainingType + Private Function GetUnqualifiedSymbolsForRaiseEvent() As ImmutableArray(Of ISymbol) + Dim containingType = _context.SemanticModel.GetEnclosingSymbol(_context.Position, _cancellationToken).ContainingType - Return _context.SemanticModel _ + Return _context.SemanticModel _ .LookupSymbols(_context.Position, container:=containingType) _ .WhereAsArray(Function(s) s.Kind = SymbolKind.Event AndAlso Equals(s.ContainingType, containingType)) - End Function + End Function - Private Function GetUnqualifiedSymbolsForType() As ImmutableArray(Of ISymbol) - Dim symbols = _context.SemanticModel.LookupNamespacesAndTypes(_context.TargetToken.SpanStart) - Return FilterToValidAccessibleSymbols(symbols) - End Function + Private Function GetUnqualifiedSymbolsForType() As ImmutableArray(Of ISymbol) + Dim symbols = _context.SemanticModel.LookupNamespacesAndTypes(_context.TargetToken.SpanStart) + Return FilterToValidAccessibleSymbols(symbols) + End Function - Private Function GetUnqualifiedSymbolsForExpressionOrStatementContext() As ImmutableArray(Of ISymbol) - Dim lookupPosition = _context.TargetToken.SpanStart - If _context.FollowsEndOfStatement Then - lookupPosition = _context.Position - End If + Private Function GetUnqualifiedSymbolsForExpressionOrStatementContext() As ImmutableArray(Of ISymbol) + Dim lookupPosition = _context.TargetToken.SpanStart + If _context.FollowsEndOfStatement Then + lookupPosition = _context.Position + End If - Dim symbols = If( + Dim symbols = If( Not _context.IsNameOfContext AndAlso _context.TargetToken.Parent.IsInStaticContext(), _context.SemanticModel.LookupStaticMembers(lookupPosition), _context.SemanticModel.LookupSymbols(lookupPosition)) - If _filterOutOfScopeLocals Then - symbols = symbols.WhereAsArray(Function(symbol) Not symbol.IsInaccessibleLocal(_context.Position)) - End If + If _filterOutOfScopeLocals Then + symbols = symbols.WhereAsArray(Function(symbol) Not symbol.IsInaccessibleLocal(_context.Position)) + End If - ' GitHub #4428: When the user is typing a predicate (eg. "Enumerable.Range(0,10).Select($$") - ' "Func(Of" tends to get in the way of typing "Function". Exclude System.Func from expression - ' contexts, except within GetType - If Not _context.TargetToken.IsKind(SyntaxKind.OpenParenToken) OrElse + ' GitHub #4428: When the user is typing a predicate (eg. "Enumerable.Range(0,10).Select($$") + ' "Func(Of" tends to get in the way of typing "Function". Exclude System.Func from expression + ' contexts, except within GetType + If Not _context.TargetToken.IsKind(SyntaxKind.OpenParenToken) OrElse Not _context.TargetToken.Parent.IsKind(SyntaxKind.GetTypeExpression) Then - symbols = symbols.WhereAsArray(Function(s) Not IsInEligibleDelegate(s)) - End If - - ' Hide backing fields and events - Return symbols.WhereAsArray(Function(s) FilterEventsAndGeneratedSymbols(Nothing, s)) - End Function - - Private Shared Function IsInEligibleDelegate(s As ISymbol) As Boolean - If s.IsDelegateType() Then - Dim typeSymbol = DirectCast(s, ITypeSymbol) - Return typeSymbol.SpecialType <> SpecialType.System_Delegate - End If - - Return False - End Function - - Private Function GetSymbolsForQualifiedNameSyntax(node As QualifiedNameSyntax) As ImmutableArray(Of ISymbol) - ' We're in a name-only context, since if we were an expression we'd be a - ' MemberAccessExpressionSyntax. Thus, let's do other namespaces and types. - Dim leftHandSymbolInfo = _context.SemanticModel.GetSymbolInfo(node.Left, _cancellationToken) - Dim leftHandSymbol = TryCast(leftHandSymbolInfo.Symbol, INamespaceOrTypeSymbol) - Dim couldBeMergedNamespace = ContainsNamespaceCandidateSymbols(leftHandSymbolInfo) - - If leftHandSymbol Is Nothing AndAlso Not couldBeMergedNamespace Then - Return ImmutableArray(Of ISymbol).Empty - End If + symbols = symbols.WhereAsArray(Function(s) Not IsInEligibleDelegate(s)) + End If + + ' Hide backing fields and events + Return symbols.WhereAsArray(Function(s) FilterEventsAndGeneratedSymbols(Nothing, s)) + End Function + + Private Shared Function IsInEligibleDelegate(s As ISymbol) As Boolean + If s.IsDelegateType() Then + Dim typeSymbol = DirectCast(s, ITypeSymbol) + Return typeSymbol.SpecialType <> SpecialType.System_Delegate + End If + + Return False + End Function + + Private Function GetSymbolsForQualifiedNameSyntax(node As QualifiedNameSyntax) As ImmutableArray(Of ISymbol) + ' We're in a name-only context, since if we were an expression we'd be a + ' MemberAccessExpressionSyntax. Thus, let's do other namespaces and types. + Dim leftHandSymbolInfo = _context.SemanticModel.GetSymbolInfo(node.Left, _cancellationToken) + Dim leftHandSymbol = TryCast(leftHandSymbolInfo.Symbol, INamespaceOrTypeSymbol) + Dim couldBeMergedNamespace = ContainsNamespaceCandidateSymbols(leftHandSymbolInfo) - Dim symbols As ImmutableArray(Of ISymbol) - If couldBeMergedNamespace Then - symbols = leftHandSymbolInfo.CandidateSymbols.OfType(Of INamespaceSymbol)() _ + If leftHandSymbol Is Nothing AndAlso Not couldBeMergedNamespace Then + Return ImmutableArray(Of ISymbol).Empty + End If + + Dim symbols As ImmutableArray(Of ISymbol) + If couldBeMergedNamespace Then + symbols = leftHandSymbolInfo.CandidateSymbols.OfType(Of INamespaceSymbol)() _ .SelectMany(Function(n) _context.SemanticModel.LookupNamespacesAndTypes(node.SpanStart, n)) _ .ToImmutableArray() - Else - symbols = _context.SemanticModel _ + Else + symbols = _context.SemanticModel _ .LookupNamespacesAndTypes(position:=node.SpanStart, container:=leftHandSymbol) - If _context.IsNamespaceDeclarationNameContext Then - Dim declarationSyntax = node.GetAncestor(Of NamespaceBlockSyntax) - symbols = symbols.WhereAsArray(Function(symbol) IsNonIntersectingNamespace(symbol, declarationSyntax)) + If _context.IsNamespaceDeclarationNameContext Then + Dim declarationSyntax = node.GetAncestor(Of NamespaceBlockSyntax) + symbols = symbols.WhereAsArray(Function(symbol) IsNonIntersectingNamespace(symbol, declarationSyntax)) + End If End If - End If - Return FilterToValidAccessibleSymbols(symbols) - End Function + Return FilterToValidAccessibleSymbols(symbols) + End Function - Private Function GetSymbolsForMemberAccessExpression(node As MemberAccessExpressionSyntax) As ImmutableArray(Of ISymbol) - Dim leftExpression = node.GetExpressionOfMemberAccessExpression(allowImplicitTarget:=True) - If leftExpression Is Nothing Then - Return ImmutableArray(Of ISymbol).Empty - End If + Private Function GetSymbolsForMemberAccessExpression(node As MemberAccessExpressionSyntax) As ImmutableArray(Of ISymbol) + Dim leftExpression = node.GetExpressionOfMemberAccessExpression(allowImplicitTarget:=True) + If leftExpression Is Nothing Then + Return ImmutableArray(Of ISymbol).Empty + End If - Dim leftHandTypeInfo = _context.SemanticModel.GetTypeInfo(leftExpression, _cancellationToken) - Dim leftHandSymbolInfo = _context.SemanticModel.GetSymbolInfo(leftExpression, _cancellationToken) + Dim leftHandTypeInfo = _context.SemanticModel.GetTypeInfo(leftExpression, _cancellationToken) + Dim leftHandSymbolInfo = _context.SemanticModel.GetSymbolInfo(leftExpression, _cancellationToken) - ' https://github.com/dotnet/roslyn/issues/9087: Try to speculatively bind a type as an expression for My namespace - ' We'll get a type contained in the My Namespace if this is successful - If leftHandTypeInfo.Type IsNot Nothing AndAlso leftHandTypeInfo.Type.Equals(leftHandSymbolInfo.Symbol) Then - Dim leftHandSpeculativeBinding = _context.SemanticModel.GetSpeculativeSymbolInfo(_context.Position, leftExpression, SpeculativeBindingOption.BindAsExpression) - If leftHandSpeculativeBinding.Symbol IsNot Nothing AndAlso + ' https://github.com/dotnet/roslyn/issues/9087: Try to speculatively bind a type as an expression for My namespace + ' We'll get a type contained in the My Namespace if this is successful + If leftHandTypeInfo.Type IsNot Nothing AndAlso leftHandTypeInfo.Type.Equals(leftHandSymbolInfo.Symbol) Then + Dim leftHandSpeculativeBinding = _context.SemanticModel.GetSpeculativeSymbolInfo(_context.Position, leftExpression, SpeculativeBindingOption.BindAsExpression) + If leftHandSpeculativeBinding.Symbol IsNot Nothing AndAlso leftHandSpeculativeBinding.Symbol.ContainingNamespace?.IsMyNamespace(_context.SemanticModel.Compilation) Then - leftHandSymbolInfo = leftHandSpeculativeBinding + leftHandSymbolInfo = leftHandSpeculativeBinding + End If End If - End If - Dim excludeInstance = False - Dim excludeShared = True ' do not show shared members by default - Dim useBaseReferenceAccessibility = False - Dim inNameOfExpression = node.IsParentKind(SyntaxKind.NameOfExpression) + Dim excludeInstance = False + Dim excludeShared = True ' do not show shared members by default + Dim useBaseReferenceAccessibility = False + Dim inNameOfExpression = node.IsParentKind(SyntaxKind.NameOfExpression) - Dim container As ISymbol = leftHandTypeInfo.Type - If container Is Nothing AndAlso TypeOf (leftHandTypeInfo.ConvertedType) Is IArrayTypeSymbol Then - container = leftHandTypeInfo.ConvertedType - End If + Dim container As ISymbol = leftHandTypeInfo.Type + If container Is Nothing AndAlso TypeOf (leftHandTypeInfo.ConvertedType) Is IArrayTypeSymbol Then + container = leftHandTypeInfo.ConvertedType + End If - If container.IsErrorType() AndAlso leftHandSymbolInfo.Symbol IsNot Nothing Then - ' TODO remove this when 531549 which causes leftHandTypeInfo to be an error type is fixed - container = leftHandSymbolInfo.Symbol.GetSymbolType() - End If + If container.IsErrorType() AndAlso leftHandSymbolInfo.Symbol IsNot Nothing Then + ' TODO remove this when 531549 which causes leftHandTypeInfo to be an error type is fixed + container = leftHandSymbolInfo.Symbol.GetSymbolType() + End If - Dim couldBeMergedNamespace = False + Dim couldBeMergedNamespace = False - If leftHandSymbolInfo.Symbol IsNot Nothing Then - Dim firstSymbol = leftHandSymbolInfo.Symbol + If leftHandSymbolInfo.Symbol IsNot Nothing Then + Dim firstSymbol = leftHandSymbolInfo.Symbol - If firstSymbol.Kind = SymbolKind.Alias Then - firstSymbol = DirectCast(firstSymbol, IAliasSymbol).Target - End If + If firstSymbol.Kind = SymbolKind.Alias Then + firstSymbol = DirectCast(firstSymbol, IAliasSymbol).Target + End If - Select Case firstSymbol.Kind - Case SymbolKind.TypeParameter - ' 884060: We don't allow invocations off type parameters. - Return ImmutableArray(Of ISymbol).Empty - Case SymbolKind.NamedType, SymbolKind.Namespace - excludeInstance = True - excludeShared = False - container = DirectCast(firstSymbol, INamespaceOrTypeSymbol) - End Select + Select Case firstSymbol.Kind + Case SymbolKind.TypeParameter + ' 884060: We don't allow invocations off type parameters. + Return ImmutableArray(Of ISymbol).Empty + Case SymbolKind.NamedType, SymbolKind.Namespace + excludeInstance = True + excludeShared = False + container = DirectCast(firstSymbol, INamespaceOrTypeSymbol) + End Select + + If firstSymbol.Kind = SymbolKind.Parameter Then + Dim parameter = DirectCast(firstSymbol, IParameterSymbol) + + If parameter.IsMe Then + excludeShared = False + ' case: + ' MyBase. + useBaseReferenceAccessibility = Not parameter.Type.Equals(container) + End If - If firstSymbol.Kind = SymbolKind.Parameter Then - Dim parameter = DirectCast(firstSymbol, IParameterSymbol) + container = parameter + End If - If parameter.IsMe Then + ' Check for color color + Dim speculativeTypeBinding = _context.SemanticModel.GetSpeculativeTypeInfo(_context.Position, leftExpression, SpeculativeBindingOption.BindAsTypeOrNamespace) + Dim speculativeAliasBinding = _context.SemanticModel.GetSpeculativeAliasInfo(_context.Position, leftExpression, SpeculativeBindingOption.BindAsTypeOrNamespace) + If TypeOf leftHandSymbolInfo.Symbol IsNot INamespaceOrTypeSymbol AndAlso speculativeAliasBinding Is Nothing AndAlso Equals(firstSymbol.GetSymbolType(), speculativeTypeBinding.Type) Then excludeShared = False - ' case: - ' MyBase. - useBaseReferenceAccessibility = Not parameter.Type.Equals(container) + excludeInstance = False End If - container = parameter - End If - - ' Check for color color - Dim speculativeTypeBinding = _context.SemanticModel.GetSpeculativeTypeInfo(_context.Position, leftExpression, SpeculativeBindingOption.BindAsTypeOrNamespace) - Dim speculativeAliasBinding = _context.SemanticModel.GetSpeculativeAliasInfo(_context.Position, leftExpression, SpeculativeBindingOption.BindAsTypeOrNamespace) - If TypeOf leftHandSymbolInfo.Symbol IsNot INamespaceOrTypeSymbol AndAlso speculativeAliasBinding Is Nothing AndAlso Equals(firstSymbol.GetSymbolType(), speculativeTypeBinding.Type) Then - excludeShared = False - excludeInstance = False - End If + If inNameOfExpression Then + excludeInstance = False + End If - If inNameOfExpression Then - excludeInstance = False + If container Is Nothing OrElse TryCast(container, ITypeSymbol)?.TypeKind = TypeKind.Enum Then + excludeShared = False ' need to allow shared members for enums + End If + Else + couldBeMergedNamespace = ContainsNamespaceCandidateSymbols(leftHandSymbolInfo) End If - If container Is Nothing OrElse TryCast(container, ITypeSymbol)?.TypeKind = TypeKind.Enum Then - excludeShared = False ' need to allow shared members for enums + If container Is Nothing AndAlso Not couldBeMergedNamespace Then + Return ImmutableArray(Of ISymbol).Empty End If - Else - couldBeMergedNamespace = ContainsNamespaceCandidateSymbols(leftHandSymbolInfo) - End If - If container Is Nothing AndAlso Not couldBeMergedNamespace Then - Return ImmutableArray(Of ISymbol).Empty - End If - - Debug.Assert((Not excludeInstance OrElse Not excludeShared) OrElse + Debug.Assert((Not excludeInstance OrElse Not excludeShared) OrElse (inNameOfExpression AndAlso Not excludeInstance AndAlso Not excludeShared)) - Debug.Assert(Not excludeInstance OrElse Not useBaseReferenceAccessibility) + Debug.Assert(Not excludeInstance OrElse Not useBaseReferenceAccessibility) - ' On null conditional access, members of T for a Nullable(Of T) should be recommended - Dim unwrapNullable = _context.TargetToken.GetPreviousToken().IsKind(SyntaxKind.QuestionToken) + ' On null conditional access, members of T for a Nullable(Of T) should be recommended + Dim unwrapNullable = _context.TargetToken.GetPreviousToken().IsKind(SyntaxKind.QuestionToken) - ' No completion on types/namespace after conditional access - If leftExpression.Parent.IsKind(SyntaxKind.ConditionalAccessExpression) AndAlso + ' No completion on types/namespace after conditional access + If leftExpression.Parent.IsKind(SyntaxKind.ConditionalAccessExpression) AndAlso (couldBeMergedNamespace OrElse leftHandSymbolInfo.GetBestOrAllSymbols().FirstOrDefault().MatchesKind(SymbolKind.NamedType, SymbolKind.Namespace, SymbolKind.Alias)) Then - Return ImmutableArray(Of ISymbol).Empty - End If + Return ImmutableArray(Of ISymbol).Empty + End If - Dim position = node.SpanStart - Dim symbols As ImmutableArray(Of ISymbol) - If couldBeMergedNamespace Then - symbols = leftHandSymbolInfo.CandidateSymbols _ + Dim position = node.SpanStart + Dim symbols As ImmutableArray(Of ISymbol) + If couldBeMergedNamespace Then + symbols = leftHandSymbolInfo.CandidateSymbols _ .OfType(Of INamespaceSymbol) _ .SelectMany(Function(n) LookupSymbolsInContainer(n, position, excludeInstance)) _ .ToImmutableArray() - Else - symbols = GetMemberSymbols(container, position, excludeInstance, useBaseReferenceAccessibility, unwrapNullable, isForDereference:=False) - End If - - If excludeShared Then - symbols = symbols.WhereAsArray(Function(s) Not s.IsShared) - End If - - ' If the left expression is Me, MyBase or MyClass and we're the first statement of constructor, - ' we should filter out the parenting constructor. Otherwise, we should filter out all constructors. - If leftExpression.IsMeMyBaseOrMyClass() AndAlso node.IsFirstStatementInCtor() Then - Dim parentingCtor = GetEnclosingCtor(node) - Debug.Assert(parentingCtor IsNot Nothing) - - symbols = symbols.WhereAsArray(Function(s) Not s.Equals(parentingCtor)) - Else - symbols = symbols.WhereAsArray(Function(s) Not s.IsConstructor()) - End If - - ' If the left expression is My.MyForms, we should filter out all non-property symbols - If leftHandSymbolInfo.Symbol IsNot Nothing AndAlso - leftHandSymbolInfo.Symbol.IsMyFormsProperty(_context.SemanticModel.Compilation) Then - - symbols = symbols.WhereAsArray(Function(s) s.Kind = SymbolKind.Property) - End If - - ' Also filter out operators - symbols = symbols.WhereAsArray(Function(s) s.Kind <> SymbolKind.Method OrElse DirectCast(s, IMethodSymbol).MethodKind <> MethodKind.UserDefinedOperator) + Else + symbols = GetMemberSymbols(container, position, excludeInstance, useBaseReferenceAccessibility, unwrapNullable, isForDereference:=False) + End If - ' Filter events and generated members - symbols = symbols.WhereAsArray(Function(s) FilterEventsAndGeneratedSymbols(node, s)) + If excludeShared Then + symbols = symbols.WhereAsArray(Function(s) Not s.IsShared) + End If - ' Never show the enum backing field - symbols = symbols.WhereAsArray(Function(s) s.Kind <> SymbolKind.Field OrElse Not s.ContainingType.IsEnumType() OrElse s.Name <> WellKnownMemberNames.EnumBackingFieldName) + ' If the left expression is Me, MyBase or MyClass and we're the first statement of constructor, + ' we should filter out the parenting constructor. Otherwise, we should filter out all constructors. + If leftExpression.IsMeMyBaseOrMyClass() AndAlso node.IsFirstStatementInCtor() Then + Dim parentingCtor = GetEnclosingCtor(node) + Debug.Assert(parentingCtor IsNot Nothing) - Return symbols - End Function + symbols = symbols.WhereAsArray(Function(s) Not s.Equals(parentingCtor)) + Else + symbols = symbols.WhereAsArray(Function(s) Not s.IsConstructor()) + End If - Private Shared Function ContainsNamespaceCandidateSymbols(symbolInfo As SymbolInfo) As Boolean - Return symbolInfo.CandidateSymbols.Any() AndAlso symbolInfo.CandidateSymbols.All(Function(s) s.IsNamespace()) - End Function + ' If the left expression is My.MyForms, we should filter out all non-property symbols + If leftHandSymbolInfo.Symbol IsNot Nothing AndAlso + leftHandSymbolInfo.Symbol.IsMyFormsProperty(_context.SemanticModel.Compilation) Then - ''' - ''' In MemberAccessExpression Contexts, filter out event symbols (except for NameOf context), except inside AddRemoveHandler Statements - ''' Also, filter out any implicitly declared members generated by event declaration or property declaration - ''' - Private Function FilterEventsAndGeneratedSymbols(node As MemberAccessExpressionSyntax, s As ISymbol) As Boolean - If s.Kind = SymbolKind.Event AndAlso Not _context.IsNameOfContext Then - Return node IsNot Nothing AndAlso node.GetAncestor(Of AddRemoveHandlerStatementSyntax) IsNot Nothing - ElseIf s.Kind = SymbolKind.Field AndAlso s.IsImplicitlyDeclared Then - Dim associatedSymbol = DirectCast(s, IFieldSymbol).AssociatedSymbol - If associatedSymbol IsNot Nothing Then - Return associatedSymbol.Kind <> SymbolKind.Event AndAlso associatedSymbol.Kind <> SymbolKind.Property + symbols = symbols.WhereAsArray(Function(s) s.Kind = SymbolKind.Property) End If - ElseIf s.Kind = SymbolKind.NamedType AndAlso s.IsImplicitlyDeclared Then - Return Not TypeOf DirectCast(s, INamedTypeSymbol).AssociatedSymbol Is IEventSymbol - End If - Return True - End Function + ' Also filter out operators + symbols = symbols.WhereAsArray(Function(s) s.Kind <> SymbolKind.Method OrElse DirectCast(s, IMethodSymbol).MethodKind <> MethodKind.UserDefinedOperator) - Private Function GetEnclosingCtor(node As MemberAccessExpressionSyntax) As IMethodSymbol - Dim symbol = _context.SemanticModel.GetEnclosingSymbol(node.SpanStart, _cancellationToken) + ' Filter events and generated members + symbols = symbols.WhereAsArray(Function(s) FilterEventsAndGeneratedSymbols(node, s)) - While symbol IsNot Nothing - Dim method = TryCast(symbol, IMethodSymbol) - If method IsNot Nothing AndAlso method.MethodKind = MethodKind.Constructor Then - Return method - End If - End While + ' Never show the enum backing field + symbols = symbols.WhereAsArray(Function(s) s.Kind <> SymbolKind.Field OrElse Not s.ContainingType.IsEnumType() OrElse s.Name <> WellKnownMemberNames.EnumBackingFieldName) - Return Nothing - End Function + Return symbols + End Function + + Private Shared Function ContainsNamespaceCandidateSymbols(symbolInfo As SymbolInfo) As Boolean + Return symbolInfo.CandidateSymbols.Any() AndAlso symbolInfo.CandidateSymbols.All(Function(s) s.IsNamespace()) + End Function + + ''' + ''' In MemberAccessExpression Contexts, filter out event symbols (except for NameOf context), except inside AddRemoveHandler Statements + ''' Also, filter out any implicitly declared members generated by event declaration or property declaration + ''' + Private Function FilterEventsAndGeneratedSymbols(node As MemberAccessExpressionSyntax, s As ISymbol) As Boolean + If s.Kind = SymbolKind.Event AndAlso Not _context.IsNameOfContext Then + Return node IsNot Nothing AndAlso node.GetAncestor(Of AddRemoveHandlerStatementSyntax) IsNot Nothing + ElseIf s.Kind = SymbolKind.Field AndAlso s.IsImplicitlyDeclared Then + Dim associatedSymbol = DirectCast(s, IFieldSymbol).AssociatedSymbol + If associatedSymbol IsNot Nothing Then + Return associatedSymbol.Kind <> SymbolKind.Event AndAlso associatedSymbol.Kind <> SymbolKind.Property + End If + ElseIf s.Kind = SymbolKind.NamedType AndAlso s.IsImplicitlyDeclared Then + Return Not TypeOf DirectCast(s, INamedTypeSymbol).AssociatedSymbol Is IEventSymbol + End If - Private Function FilterToValidAccessibleSymbols(symbols As ImmutableArray(Of ISymbol)) As ImmutableArray(Of ISymbol) - ' If this is an Inherits or Implements statement, we filter out symbols which do not recursively contain accessible, valid types. - Dim inheritsContext = IsInheritsStatementContext(_context.TargetToken) - Dim implementsContext = IsImplementsStatementContext(_context.TargetToken) + Return True + End Function - If inheritsContext OrElse implementsContext Then + Private Function GetEnclosingCtor(node As MemberAccessExpressionSyntax) As IMethodSymbol + Dim symbol = _context.SemanticModel.GetEnclosingSymbol(node.SpanStart, _cancellationToken) - Dim typeBlock = _context.TargetToken.Parent?.FirstAncestorOrSelf(Of TypeBlockSyntax)() - If typeBlock IsNot Nothing Then - Dim typeOrAssemblySymbol As ISymbol = _context.SemanticModel.GetDeclaredSymbol(typeBlock, _cancellationToken) - If typeOrAssemblySymbol Is Nothing Then - typeOrAssemblySymbol = _context.SemanticModel.Compilation.Assembly + While symbol IsNot Nothing + Dim method = TryCast(symbol, IMethodSymbol) + If method IsNot Nothing AndAlso method.MethodKind = MethodKind.Constructor Then + Return method End If + End While - Dim isInterface = TryCast(typeOrAssemblySymbol, ITypeSymbol)?.TypeKind = TypeKind.Interface + Return Nothing + End Function - If inheritsContext Then + Private Function FilterToValidAccessibleSymbols(symbols As ImmutableArray(Of ISymbol)) As ImmutableArray(Of ISymbol) + ' If this is an Inherits or Implements statement, we filter out symbols which do not recursively contain accessible, valid types. + Dim inheritsContext = IsInheritsStatementContext(_context.TargetToken) + Dim implementsContext = IsImplementsStatementContext(_context.TargetToken) - ' In an interface's Inherits statement, only show interfaces. - If isInterface Then - Return symbols.WhereAsArray(Function(s) IsValidAccessibleInterfaceOrContainer(s, typeOrAssemblySymbol)) + If inheritsContext OrElse implementsContext Then + + Dim typeBlock = _context.TargetToken.Parent?.FirstAncestorOrSelf(Of TypeBlockSyntax)() + If typeBlock IsNot Nothing Then + Dim typeOrAssemblySymbol As ISymbol = _context.SemanticModel.GetDeclaredSymbol(typeBlock, _cancellationToken) + If typeOrAssemblySymbol Is Nothing Then + typeOrAssemblySymbol = _context.SemanticModel.Compilation.Assembly End If - Return symbols.WhereAsArray(Function(s) IsValidAccessibleClassOrContainer(s, typeOrAssemblySymbol)) + Dim isInterface = TryCast(typeOrAssemblySymbol, ITypeSymbol)?.TypeKind = TypeKind.Interface - Else ' implementsContext + If inheritsContext Then - ' In an interface's Implements statement, show nothing. - If isInterface Then - Return ImmutableArray(Of ISymbol).Empty - End If + ' In an interface's Inherits statement, only show interfaces. + If isInterface Then + Return symbols.WhereAsArray(Function(s) IsValidAccessibleInterfaceOrContainer(s, typeOrAssemblySymbol)) + End If + + Return symbols.WhereAsArray(Function(s) IsValidAccessibleClassOrContainer(s, typeOrAssemblySymbol)) + + Else ' implementsContext + + ' In an interface's Implements statement, show nothing. + If isInterface Then + Return ImmutableArray(Of ISymbol).Empty + End If - Return symbols.WhereAsArray(Function(s) IsValidAccessibleInterfaceOrContainer(s, typeOrAssemblySymbol)) + Return symbols.WhereAsArray(Function(s) IsValidAccessibleInterfaceOrContainer(s, typeOrAssemblySymbol)) + End If End If End If - End If - Return symbols - End Function + Return symbols + End Function - Private Shared Function IsInheritsStatementContext(token As SyntaxToken) As Boolean - If token.IsChildToken(Of InheritsStatementSyntax)(Function(n) n.InheritsKeyword) Then - Return True - End If + Private Shared Function IsInheritsStatementContext(token As SyntaxToken) As Boolean + If token.IsChildToken(Of InheritsStatementSyntax)(Function(n) n.InheritsKeyword) Then + Return True + End If - Return token.IsChildToken(Of QualifiedNameSyntax)(Function(n) n.DotToken) AndAlso + Return token.IsChildToken(Of QualifiedNameSyntax)(Function(n) n.DotToken) AndAlso token.Parent?.FirstAncestorOrSelf(Of InheritsStatementSyntax) IsNot Nothing - End Function + End Function - Private Shared Function IsImplementsStatementContext(token As SyntaxToken) As Boolean - If token.IsChildToken(Of ImplementsStatementSyntax)(Function(n) n.ImplementsKeyword) Then - Return True - End If + Private Shared Function IsImplementsStatementContext(token As SyntaxToken) As Boolean + If token.IsChildToken(Of ImplementsStatementSyntax)(Function(n) n.ImplementsKeyword) Then + Return True + End If - Return token.IsChildToken(Of QualifiedNameSyntax)(Function(n) n.DotToken) AndAlso + Return token.IsChildToken(Of QualifiedNameSyntax)(Function(n) n.DotToken) AndAlso token.Parent?.FirstAncestorOrSelf(Of ImplementsStatementSyntax) IsNot Nothing - End Function + End Function - Private Function IsValidAccessibleInterfaceOrContainer(symbol As ISymbol, within As ISymbol) As Boolean - If symbol.Kind = SymbolKind.Alias Then - symbol = DirectCast(symbol, IAliasSymbol).Target - End If + Private Function IsValidAccessibleInterfaceOrContainer(symbol As ISymbol, within As ISymbol) As Boolean + If symbol.Kind = SymbolKind.Alias Then + symbol = DirectCast(symbol, IAliasSymbol).Target + End If - Dim namespaceSymbol = TryCast(symbol, INamespaceSymbol) - If namespaceSymbol IsNot Nothing Then - Return namespaceSymbol.GetMembers().Any(Function(m) IsValidAccessibleInterfaceOrContainer(m, within)) - End If + Dim namespaceSymbol = TryCast(symbol, INamespaceSymbol) + If namespaceSymbol IsNot Nothing Then + Return namespaceSymbol.GetMembers().Any(Function(m) IsValidAccessibleInterfaceOrContainer(m, within)) + End If - Dim namedTypeSymbol = TryCast(symbol, INamedTypeSymbol) - If namedTypeSymbol Is Nothing Then - Return False - End If + Dim namedTypeSymbol = TryCast(symbol, INamedTypeSymbol) + If namedTypeSymbol Is Nothing Then + Return False + End If - Return namedTypeSymbol.TypeKind = TypeKind.Interface OrElse + Return namedTypeSymbol.TypeKind = TypeKind.Interface OrElse namedTypeSymbol _ .GetAccessibleMembersInThisAndBaseTypes(Of INamedTypeSymbol)(within) _ .Any(Function(m) IsOrContainsValidAccessibleInterface(m, within)) - End Function + End Function - Private Function IsOrContainsValidAccessibleInterface(namespaceOrTypeSymbol As INamespaceOrTypeSymbol, within As ISymbol) As Boolean - If namespaceOrTypeSymbol.Kind = SymbolKind.Namespace Then - Return IsValidAccessibleInterfaceOrContainer(namespaceOrTypeSymbol, within) - End If + Private Function IsOrContainsValidAccessibleInterface(namespaceOrTypeSymbol As INamespaceOrTypeSymbol, within As ISymbol) As Boolean + If namespaceOrTypeSymbol.Kind = SymbolKind.Namespace Then + Return IsValidAccessibleInterfaceOrContainer(namespaceOrTypeSymbol, within) + End If - Dim namedTypeSymbol = TryCast(namespaceOrTypeSymbol, INamedTypeSymbol) - If namedTypeSymbol Is Nothing Then - Return False - End If + Dim namedTypeSymbol = TryCast(namespaceOrTypeSymbol, INamedTypeSymbol) + If namedTypeSymbol Is Nothing Then + Return False + End If - If namedTypeSymbol.TypeKind = TypeKind.Interface Then - Return True - End If + If namedTypeSymbol.TypeKind = TypeKind.Interface Then + Return True + End If - Return namedTypeSymbol.GetMembers() _ + Return namedTypeSymbol.GetMembers() _ .OfType(Of INamedTypeSymbol)() _ .Where(Function(m) m.IsAccessibleWithin(within)) _ .Any(Function(m) IsOrContainsValidAccessibleInterface(m, within)) - End Function + End Function - Private Function IsValidAccessibleClassOrContainer(symbol As ISymbol, within As ISymbol) As Boolean - If symbol.Kind = SymbolKind.Alias Then - symbol = DirectCast(symbol, IAliasSymbol).Target - End If + Private Function IsValidAccessibleClassOrContainer(symbol As ISymbol, within As ISymbol) As Boolean + If symbol.Kind = SymbolKind.Alias Then + symbol = DirectCast(symbol, IAliasSymbol).Target + End If - Dim type = TryCast(symbol, ITypeSymbol) + Dim type = TryCast(symbol, ITypeSymbol) - If type IsNot Nothing Then - If type.TypeKind = TypeKind.Class AndAlso Not type.IsSealed AndAlso Not Equals(type, within) Then - Return True - End If + If type IsNot Nothing Then + If type.TypeKind = TypeKind.Class AndAlso Not type.IsSealed AndAlso Not Equals(type, within) Then + Return True + End If - If type.TypeKind = TypeKind.Class OrElse + If type.TypeKind = TypeKind.Class OrElse type.TypeKind = TypeKind.Module OrElse type.TypeKind = TypeKind.Struct Then - Return type.GetAccessibleMembersInThisAndBaseTypes(Of INamedTypeSymbol)(within).Any(Function(m) IsOrContainsValidAccessibleClass(m, within)) + Return type.GetAccessibleMembersInThisAndBaseTypes(Of INamedTypeSymbol)(within).Any(Function(m) IsOrContainsValidAccessibleClass(m, within)) + End If End If - End If - Dim namespaceSymbol = TryCast(symbol, INamespaceSymbol) - If namespaceSymbol IsNot Nothing Then - Return namespaceSymbol.GetMembers().Any(Function(m) IsValidAccessibleClassOrContainer(m, within)) - End If + Dim namespaceSymbol = TryCast(symbol, INamespaceSymbol) + If namespaceSymbol IsNot Nothing Then + Return namespaceSymbol.GetMembers().Any(Function(m) IsValidAccessibleClassOrContainer(m, within)) + End If - Return False - End Function + Return False + End Function - Private Function IsOrContainsValidAccessibleClass(namespaceOrTypeSymbol As INamespaceOrTypeSymbol, within As ISymbol) As Boolean - If namespaceOrTypeSymbol.Kind = SymbolKind.Namespace Then - Return IsValidAccessibleClassOrContainer(namespaceOrTypeSymbol, within) - End If + Private Function IsOrContainsValidAccessibleClass(namespaceOrTypeSymbol As INamespaceOrTypeSymbol, within As ISymbol) As Boolean + If namespaceOrTypeSymbol.Kind = SymbolKind.Namespace Then + Return IsValidAccessibleClassOrContainer(namespaceOrTypeSymbol, within) + End If - Dim namedTypeSymbol = TryCast(namespaceOrTypeSymbol, INamedTypeSymbol) - If namedTypeSymbol Is Nothing Then - Return False - End If + Dim namedTypeSymbol = TryCast(namespaceOrTypeSymbol, INamedTypeSymbol) + If namedTypeSymbol Is Nothing Then + Return False + End If - If namedTypeSymbol.TypeKind = TypeKind.Class AndAlso Not namedTypeSymbol.IsSealed AndAlso Not Equals(namedTypeSymbol, within) Then - Return True - End If + If namedTypeSymbol.TypeKind = TypeKind.Class AndAlso Not namedTypeSymbol.IsSealed AndAlso Not Equals(namedTypeSymbol, within) Then + Return True + End If - Return namedTypeSymbol.GetMembers() _ + Return namedTypeSymbol.GetMembers() _ .OfType(Of INamedTypeSymbol)() _ .Where(Function(m) m.IsAccessibleWithin(within)) _ .Any(Function(m) IsOrContainsValidAccessibleClass(m, within)) - End Function + End Function + End Class End Class End Namespace