From 52cae39b6b76afb5643d2a3ec6f47dda609f87e3 Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Mon, 13 Jun 2016 14:04:49 -0700 Subject: [PATCH] Move target typing implmentation onto public API --- ...ompletionListTagCompletionProviderTests.cs | 26 +++ .../SymbolCompletionProviderTests.cs | 87 ++++++++ .../BoolKeywordRecommenderTests.cs | 16 ++ .../ByteKeywordRecommenderTests.cs | 17 ++ .../CharKeywordRecommenderTests.cs | 19 +- .../DecimalKeywordRecommenderTests.cs | 16 ++ .../DoubleKeywordRecommenderTests.cs | 16 ++ .../FloatKeywordRecommenderTests.cs | 16 ++ .../IntKeywordRecommenderTests.cs | 16 ++ .../LongKeywordRecommenderTests.cs | 16 ++ .../ObjectKeywordRecommenderTests.cs | 16 ++ .../Recommendations/RecommenderTests.cs | 4 + .../SByteKeywordRecommenderTests.cs | 16 ++ .../ShortKeywordRecommenderTests.cs | 16 ++ .../ThisKeywordRecommenderTests.cs | 16 ++ .../UIntKeywordRecommenderTests.cs | 16 ++ .../ULongKeywordRecommenderTests.cs | 16 ++ .../UShortKeywordRecommenderTests.cs | 16 ++ .../Completion/CompletionHelper.cs | 5 + .../CSharpCompletionCommandHandlerTests.vb | 203 ++++++++++++++++++ ...isualBasicCompletionCommandHandlerTests.vb | 147 ++++++++++++- .../Expressions/MeKeywordRecommenderTests.vb | 20 ++ .../RecommendationTestHelpers.vb | 33 ++- .../BuiltInTypesKeywordRecommenderTests.vb | 19 ++ .../CSharp/Portable/CSharpFeatures.csproj | 1 + ...mAndCompletionListTagCompletionProvider.cs | 8 + .../KeywordCompletionProvider.cs | 3 +- .../NamedParameterCompletionProvider.cs | 3 +- .../SymbolCompletionProvider.cs | 10 +- ...ecialTypePreselectingKeywordRecommender.cs | 28 +++ ...stractSyntacticSingleKeywordRecommender.cs | 17 +- .../BoolKeywordRecommender.cs | 6 +- .../ByteKeywordRecommender.cs | 6 +- .../CharKeywordRecommender.cs | 5 +- .../DecimalKeywordRecommender.cs | 5 +- .../DoubleKeywordRecommender.cs | 6 +- .../FloatKeywordRecommender.cs | 5 +- .../IntKeywordRecommender.cs | 5 +- .../LongKeywordRecommender.cs | 5 +- .../ObjectKeywordRecommender.cs | 5 +- .../SByteKeywordRecommender.cs | 5 +- .../ShortKeywordRecommender.cs | 6 +- .../StringKeywordRecommender.cs | 6 +- .../ThisKeywordRecommender.cs | 6 + .../UIntKeywordRecommender.cs | 5 +- .../ULongKeywordRecommender.cs | 6 +- .../UShortKeywordRecommender.cs | 5 +- .../AbstractKeywordCompletionProvider.cs | 2 +- ...mendationServiceBasedCompletionProvider.cs | 97 +++++++++ .../Providers/RecommendedKeyword.cs | 10 +- .../Providers/SymbolMatchPriority.cs | 18 ++ src/Features/Core/Portable/Features.csproj | 2 + .../SymbolCompletionProvider.vb | 10 +- .../Expressions/MeKeywordRecommender.vb | 10 +- .../TrueFalseKeywordRecommender.vb | 7 +- .../Types/BuiltInTypesKeywordRecommender.vb | 7 +- .../VisualBasicCompletionService.vb | 4 +- .../ContextQuery/CSharpSyntaxContext.cs | 25 ++- .../Extensions/ITypeSymbolExtensions.cs | 25 +++ .../AbstractTypeInferenceService.cs | 17 ++ .../ContextQuery/AbstractSyntaxContext.cs | 18 +- .../ContextQuery/VisualBasicSyntaxContext.vb | 7 +- .../Extensions/ITypeSymbolExtensions.vb | 24 +++ 63 files changed, 1169 insertions(+), 59 deletions(-) create mode 100644 src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSpecialTypePreselectingKeywordRecommender.cs create mode 100644 src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs create mode 100644 src/Features/Core/Portable/Completion/Providers/SymbolMatchPriority.cs diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs index 84a76a3e30f..a460768ca1f 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProviderTests.cs @@ -465,5 +465,31 @@ enum Colors "; await VerifyItemExistsAsync(markup, "Colors"); } + + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task NotAfterDot() + { + var markup = +@"namespace ConsoleApplication253 +{ + class Program + { + static void Main(string[] args) + { + M(E.$$) + } + + static void M(E e) { } + } + + enum E + { + A, + B, + } +} +"; + await VerifyNoItemsExistAsync(markup); + } } } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs index 3c9be1f49c0..7928b47b0f1 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs @@ -8767,5 +8767,92 @@ public async Task NoCompletionInShebangComments() await VerifyNoItemsExistAsync("#!$$", sourceCodeKind: SourceCodeKind.Script); await VerifyNoItemsExistAsync("#! S$$", sourceCodeKind: SourceCodeKind.Script, usePreviousCharAsTrigger: true); } + + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task CompoundNameTargetTypePreselection() + { + var markup = @" +class Class1 +{ + void foo() + { + int x = 3; + string y = x.$$ + } +}"; + await VerifyItemExistsAsync(markup, "ToString", matchPriority: SymbolMatchPriority.PreferEventOrMethod); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task TargetTypeInCollectionInitializer1() + { + var markup = @" +using System.Collections.Generic; + +class Program +{ + static void Main(string[] args) + { + int z; + string q; + List x = new List() { $$ } + } +}"; + await VerifyItemExistsAsync(markup, "z", matchPriority: SymbolMatchPriority.PreferLocal); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task TargetTypeInCollectionInitializer2() + { + var markup = @" +using System.Collections.Generic; + +class Program +{ + static void Main(string[] args) + { + int z; + string q; + List x = new List() { 1, $$ } + } +}"; + await VerifyItemExistsAsync(markup, "z", matchPriority: SymbolMatchPriority.PreferLocal); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task TargeTypeInObjectInitializer1() + { + var markup = @" +class C +{ + public int X { get; set; } + public int Y { get; set; } + + void foo() + { + int i; + var c = new C() { X = $$ } + } +}"; + await VerifyItemExistsAsync(markup, "i", matchPriority: SymbolMatchPriority.PreferLocal); + } + + [Fact, Trait(Traits.Feature, Traits.Features.Completion)] + public async Task TargeTypeInObjectInitializer2() + { + var markup = @" +class C +{ + public int X { get; set; } + public int Y { get; set; } + + void foo() + { + int i; + var c = new C() { X = 1, Y = $$ } + } +}"; + await VerifyItemExistsAsync(markup, "i", matchPriority: SymbolMatchPriority.PreferLocal); + } } } \ No newline at end of file diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs index c0d62b5ead6..0677f24db65 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/BoolKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -607,5 +608,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(bool x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs index c8f5bf97af8..21bafb96ac3 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ByteKeywordRecommenderTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -607,5 +609,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(byte x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/CharKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/CharKeywordRecommenderTests.cs index 208f6f55ba9..f61a933c1fc 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/CharKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/CharKeywordRecommenderTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Completion; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -659,5 +661,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [WpfFact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(char x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/DecimalKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/DecimalKeywordRecommenderTests.cs index 5f4de6b6581..79a9529065e 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/DecimalKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/DecimalKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -608,5 +609,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(decimal x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/DoubleKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/DoubleKeywordRecommenderTests.cs index 89debb6204d..2a7f56376fa 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/DoubleKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/DoubleKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -607,5 +608,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(double x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/FloatKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/FloatKeywordRecommenderTests.cs index dbba0de6566..33adae35ab1 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/FloatKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/FloatKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -580,5 +581,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(float x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/IntKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/IntKeywordRecommenderTests.cs index 08f611b73d3..bc32f0e6098 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/IntKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/IntKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -676,5 +677,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(int x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/LongKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/LongKeywordRecommenderTests.cs index cc3f04d7742..27b9b174bfc 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/LongKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/LongKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -607,5 +608,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(int x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ObjectKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ObjectKeywordRecommenderTests.cs index 5432f88baad..0fef71c5122 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ObjectKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ObjectKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -614,5 +615,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(object x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/RecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/RecommenderTests.cs index 2fd4cd36bfb..86a0cbe23f9 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/RecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/RecommenderTests.cs @@ -87,6 +87,10 @@ private async Task CheckResultAsync(bool absent, int position, CSharpSyntaxConte var result = (await RecommendKeywordsAsync(position, context)).Single(); Assert.NotNull(result); Assert.Equal(keywordText, result.Keyword); + if (matchPriority != null) + { + Assert.Equal(matchPriority.Value, result.MatchPriority); + } } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/SByteKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/SByteKeywordRecommenderTests.cs index 0d60dccdd6c..39b642f6028 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/SByteKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/SByteKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -607,5 +608,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(sbyte x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ShortKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ShortKeywordRecommenderTests.cs index 80f01f2594f..b8fabdb0d94 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ShortKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ShortKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -601,5 +602,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(short x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ThisKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ThisKeywordRecommenderTests.cs index eb5e599785d..21e6c1c8e3a 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ThisKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ThisKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -616,5 +617,20 @@ class C int p; }"); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + void Main(string[] args) + { + Helper($$) + } + void Helper(Program x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/UIntKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/UIntKeywordRecommenderTests.cs index 6dca6269013..aa9fcc99f62 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/UIntKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/UIntKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -607,5 +608,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(uint x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/ULongKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/ULongKeywordRecommenderTests.cs index 38a84e0267f..d36132d5602 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/ULongKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/ULongKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -607,5 +608,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(ulong x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/CSharpTest2/Recommendations/UShortKeywordRecommenderTests.cs b/src/EditorFeatures/CSharpTest2/Recommendations/UShortKeywordRecommenderTests.cs index 22fefe2f714..1fd36adc113 100644 --- a/src/EditorFeatures/CSharpTest2/Recommendations/UShortKeywordRecommenderTests.cs +++ b/src/EditorFeatures/CSharpTest2/Recommendations/UShortKeywordRecommenderTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Xunit; @@ -607,5 +608,20 @@ public async Task TestNotInCrefTypeParameter() class C { } "); } + + [Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)] + public async Task Preselection() + { + await VerifyKeywordAsync(@" +class Program +{ + static void Main(string[] args) + { + Helper($$) + } + static void Helper(ushort x) { } +} +", matchPriority: SymbolMatchPriority.Keyword); + } } } diff --git a/src/EditorFeatures/Core/Extensibility/Completion/CompletionHelper.cs b/src/EditorFeatures/Core/Extensibility/Completion/CompletionHelper.cs index e1a346b1fb3..7f43851f5e9 100644 --- a/src/EditorFeatures/Core/Extensibility/Completion/CompletionHelper.cs +++ b/src/EditorFeatures/Core/Extensibility/Completion/CompletionHelper.cs @@ -164,6 +164,11 @@ private PatternMatcher GetEnUSPatternMatcher(string value) /// text, or false if it is not better. /// public virtual bool IsBetterFilterMatch(CompletionItem item1, CompletionItem item2, string filterText, CompletionTrigger trigger, ImmutableArray recentItems) + { + return IsBetterFilterMatchWorker(item1, item2, filterText, recentItems); + } + + protected bool IsBetterFilterMatchWorker(CompletionItem item1, CompletionItem item2, string filterText, ImmutableArray recentItems) { var match1 = GetMatch(item1, filterText); var match2 = GetMatch(item2, filterText); diff --git a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb index e5302f1364b..32d34abb476 100644 --- a/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/CSharpCompletionCommandHandlerTests.vb @@ -1682,5 +1682,208 @@ class C End Using End Function + + + Public Async Function TargetTypePreselection1() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendInvokeCompletionList() + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("cancellationToken", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselection2() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendTypeChars("a") + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("args", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselection_DoesNotOverrideEnumPreselection() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendInvokeCompletionList() + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("E", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselection3() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendTypeChars("c") + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("cx", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselectionLocalsOverType() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendTypeChars("c") + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("cx", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselectionParameterOverMethod() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendInvokeCompletionList() + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("f", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselectionConvertibility1() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendTypeChars("c") + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("cx", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselectionParamsArray() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendInvokeCompletionList() + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("yx", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselectionLocalOverProperty() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendInvokeCompletionList() + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("aaq", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselectionSetterValuey() As Task + Using state = TestState.CreateCSharpTestState( + , extraExportedTypes:={GetType(CSharpEditorFormattingService)}.ToList()) + state.SendInvokeCompletionList() + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("value", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function End Class End Namespace diff --git a/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb b/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb index 407c37e1270..f3f701c5406 100644 --- a/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb +++ b/src/EditorFeatures/Test2/IntelliSense/VisualBasicCompletionCommandHandlerTests.vb @@ -980,13 +980,11 @@ Class Foo Bar(0$$ End Sub End Class -class Foo ) state.SendTypeChars(", ") Await state.WaitForAsynchronousOperationsAsync() - Await state.AssertSelectedCompletionItem(displayText:="Numeros", isSoftSelected:=True) - Assert.Equal(1, state.CurrentCompletionPresenterSession.PresentationItems.Where(Function(c) c.Item.DisplayText = "Numeros").Count()) + Await state.AssertSelectedCompletionItem(displayText:="Numeros.Dos", isSoftSelected:=True) End Using End Function @@ -2292,5 +2290,148 @@ End Module]]>) Await state.AssertSelectedCompletionItem("T") End Using End Function + + + Public Async Function TargetTypePreselection1() As Task + Using state = TestState.CreateVisualBasicTestState( + ) + state.SendInvokeCompletionList() + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("cancellationToken").ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselection2() As Task + Using state = TestState.CreateVisualBasicTestState( + ) + state.SendTypeChars("a") + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("args").ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselection3() As Task + Using state = TestState.CreateVisualBasicTestState( + ) + state.SendTypeChars("c") + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("cx", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselectionLocalsOverType() As Task + Using state = TestState.CreateVisualBasicTestState( + ) + state.SendTypeChars("c") + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("cx", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselectionConvertibility1() As Task + Using state = TestState.CreateVisualBasicTestState( + ) + state.SendTypeChars("c") + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("cx", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + Public Async Function TargetTypePreselectionParamsArray() As Task + Using state = TestState.CreateVisualBasicTestState( + ) + state.SendInvokeCompletionList() + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("azc", isHardSelected:=True).ConfigureAwait(True) + End Using + End Function + + + + Public Async Function TargetTypePreselectionSetterValue() As Task + Using state = TestState.CreateVisualBasicTestState( + ) + state.SendInvokeCompletionList() + Await state.WaitForAsynchronousOperationsAsync().ConfigureAwait(True) + Await state.AssertSelectedCompletionItem("value", isHardSelected:=False).ConfigureAwait(True) + End Using + End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/Recommendations/Expressions/MeKeywordRecommenderTests.vb b/src/EditorFeatures/VisualBasicTest/Recommendations/Expressions/MeKeywordRecommenderTests.vb index 87290b8804d..d9873384e9f 100644 --- a/src/EditorFeatures/VisualBasicTest/Recommendations/Expressions/MeKeywordRecommenderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Recommendations/Expressions/MeKeywordRecommenderTests.vb @@ -1,5 +1,7 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +Imports Microsoft.CodeAnalysis.Completion.Providers + Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Recommendations.Expressions Public Class MeKeywordRecommenderTests @@ -197,5 +199,23 @@ End Class| Public Async Function MeInNameOf2Test() As Task Await VerifyRecommendationsMissingAsync(Dim s = NameOf(System.|, "Me") End Function + + + Public Async Function Preselection() As Task + Dim code = + +Class Program + Sub Main(args As String()) + Foo(|) + End Sub + + Sub Foo(x As Program) + + End Sub +End Class + + + Await VerifyRecommendationsWithPriority(code, SymbolMatchPriority.Keyword, "Me") + End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/Recommendations/RecommendationTestHelpers.vb b/src/EditorFeatures/VisualBasicTest/Recommendations/RecommendationTestHelpers.vb index cb03ebe347b..201ac45e5cd 100644 --- a/src/EditorFeatures/VisualBasicTest/Recommendations/RecommendationTestHelpers.vb +++ b/src/EditorFeatures/VisualBasicTest/Recommendations/RecommendationTestHelpers.vb @@ -2,6 +2,7 @@ Imports System.Threading Imports System.Xml.Linq +Imports Microsoft.CodeAnalysis.Completion Imports Microsoft.CodeAnalysis.Completion.Providers Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders @@ -50,16 +51,25 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Recommendations Assert.Equal(expectedText, recommendedKeyword.DescriptionFactory(CancellationToken.None).GetFullText()) End Function + Friend Async Function VerifyRecommendationsWithPriority(testSource As XElement, priority As Integer, ParamArray recommendations As String()) As Task + Assert.NotEmpty(recommendations) + + Dim source = ConvertTestSourceTag(testSource) + + Await VerifyRecommendationsContainNothingTypedAsync(source, priority, recommendations).ConfigureAwait(False) + Await VerifyRecommendationsContainPartiallyTypedAsync(source, priority, recommendations).ConfigureAwait(False) + End Function + Friend Async Function VerifyRecommendationsContainAsync(testSource As XElement, ParamArray recommendations As String()) As Task Assert.NotEmpty(recommendations) Dim source = ConvertTestSourceTag(testSource) - Await VerifyRecommendationsContainNothingTypedAsync(source, recommendations) - Await VerifyRecommendationsContainPartiallyTypedAsync(source, recommendations) + Await VerifyRecommendationsContainNothingTypedAsync(source, Nothing, recommendations) + Await VerifyRecommendationsContainPartiallyTypedAsync(source, Nothing, recommendations) End Function - Private Async Function VerifyRecommendationsContainNothingTypedAsync(source As String, ParamArray recommendations As String()) As Task + Private Async Function VerifyRecommendationsContainNothingTypedAsync(source As String, priority As Integer?, ParamArray recommendations As String()) As Task ' Test with the | removed Dim recommendedKeywords = Await GetRecommendedKeywordsAsync(source.Replace("|", ""), source.IndexOf("|"c)) @@ -68,6 +78,10 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Recommendations Assert.Contains(recommendation, recommendedKeywordStrings) Next + If priority.HasValue Then + Assert.All(recommendedKeywords.Where(Function(k) recommendations.Contains(k.Keyword)), Sub(k) Assert.Equal(k.MatchPriority, priority.Value)) + End If + VerifyRecommendationsHaveDescriptionText(recommendedKeywords.Where(Function(k) recommendations.Contains(k.Keyword))) End Function @@ -77,14 +91,21 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Recommendations Next End Sub - Private Async Function VerifyRecommendationsContainPartiallyTypedAsync(source As String, ParamArray recommendations As String()) As Task + Private Async Function VerifyRecommendationsContainPartiallyTypedAsync(source As String, priority As Integer?, ParamArray recommendations As String()) As Task ' Test with the | replaced with the first character of the keywords we expect For Each partiallyTypedRecommendation In recommendations.Select(Function(recommendation) recommendation(0)).Distinct() - Dim recommendedKeywords = (Await GetRecommendedKeywordStringsAsync(source.Replace("|"c, partiallyTypedRecommendation), source.IndexOf("|"c) + 1)).ToArray() + Dim recommendedKeywords = (Await GetRecommendedKeywordsAsync(source.Replace("|"c, partiallyTypedRecommendation), source.IndexOf("|"c) + 1)).ToArray() + Dim recommendedKeywordStrings = recommendedKeywords.Select(Function(k) k.Keyword) For Each recommendation In recommendations - Assert.Contains(recommendation, recommendedKeywords) + Assert.Contains(recommendation, recommendedKeywordStrings) Next + + If priority.HasValue Then + Assert.All(recommendedKeywords.Where(Function(k) recommendations.Contains(k.Keyword)), Sub(k) Assert.Equal(k.MatchPriority, priority.Value)) + End If + + VerifyRecommendationsHaveDescriptionText(recommendedKeywords.Where(Function(k) recommendations.Contains(k.Keyword))) Next End Function diff --git a/src/EditorFeatures/VisualBasicTest/Recommendations/Types/BuiltInTypesKeywordRecommenderTests.vb b/src/EditorFeatures/VisualBasicTest/Recommendations/Types/BuiltInTypesKeywordRecommenderTests.vb index b9014f4d764..29415a9cf90 100644 --- a/src/EditorFeatures/VisualBasicTest/Recommendations/Types/BuiltInTypesKeywordRecommenderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Recommendations/Types/BuiltInTypesKeywordRecommenderTests.vb @@ -1,5 +1,7 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +Imports Microsoft.CodeAnalysis.Completion.Providers + Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Recommendations.Types Public Class BuiltInTypesKeywordRecommenderTests Private ReadOnly _keywordList As String() = { @@ -93,5 +95,22 @@ End Class Await VerifyRecommendationsMissingAsync(code, _keywordList) End Function + + Public Async Function Preselection() As Task + Dim code = + +Class Program + Sub Main(args As String()) + Foo(|) + End Sub + + Sub Foo(x As Integer) + + End Sub +End Class + + + Await VerifyRecommendationsWithPriority(code, SymbolMatchPriority.Keyword, "Integer") + End Function End Class End Namespace diff --git a/src/Features/CSharp/Portable/CSharpFeatures.csproj b/src/Features/CSharp/Portable/CSharpFeatures.csproj index 679c728392f..a23775fc4dd 100644 --- a/src/Features/CSharp/Portable/CSharpFeatures.csproj +++ b/src/Features/CSharp/Portable/CSharpFeatures.csproj @@ -125,6 +125,7 @@ + diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs index 7201017cb68..79af297f7c6 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/EnumAndCompletionListTagCompletionProvider.cs @@ -58,6 +58,14 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) return; } + // Don't show up within member access + // This previously worked because the type inferrer didn't work + // in member access expressions. + if (token.IsKind(SyntaxKind.DotToken)) + { + return; + } + var typeInferenceService = document.GetLanguageService(); Contract.ThrowIfNull(typeInferenceService, nameof(typeInferenceService)); diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs index 7cbb5f12254..85c538643cf 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/KeywordCompletionProvider.cs @@ -175,7 +175,8 @@ protected override CompletionItem CreateItem(RecommendedKeyword keyword, TextSpa span: span, description: keyword.DescriptionFactory(CancellationToken.None), glyph: Glyph.Keyword, - shouldFormatOnCommit: keyword.ShouldFormatOnCommit); + shouldFormatOnCommit: keyword.ShouldFormatOnCommit, + matchPriority: keyword.MatchPriority); } internal override TextSpan GetCurrentSpan(TextSpan span, SourceText text) diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs index 9fd21a85440..44bd63b8bc1 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs @@ -97,7 +97,8 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) symbol: parameter, descriptionPosition: token.SpanStart, filterText: escapedName, - rules: CompletionItemRules.Default)); + rules: CompletionItemRules.Default, + matchPriority: SymbolMatchPriority.PreferNamedArgument)); } } diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs index 147eccec45d..9d7d769e209 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/SymbolCompletionProvider.cs @@ -16,16 +16,24 @@ using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; using Microsoft.CodeAnalysis.LanguageServices; +using System.Linq; +using Microsoft.CodeAnalysis.Shared.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers { - internal partial class SymbolCompletionProvider : AbstractSymbolCompletionProvider + internal partial class SymbolCompletionProvider : AbstractRecommendationServiceBasedCompletionProvider { protected override Task> GetSymbolsWorker(AbstractSyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) { return Recommender.GetRecommendedSymbolsAtPositionAsync(context.SemanticModel, position, context.Workspace, options, cancellationToken); } + protected override bool IsInstrinsic(ISymbol s) + { + var ts = s as ITypeSymbol; + return ts != null && ts.IsIntrinsicType(); + } + protected override string GetInsertionText(ISymbol symbol, AbstractSyntaxContext context, char ch) { return GetInsertionText(symbol, context); diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSpecialTypePreselectingKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSpecialTypePreselectingKeywordRecommender.cs new file mode 100644 index 00000000000..487c4666b90 --- /dev/null +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSpecialTypePreselectingKeywordRecommender.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; + +namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders +{ + internal abstract class AbstractSpecialTypePreselectingKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + { + public AbstractSpecialTypePreselectingKeywordRecommender( + SyntaxKind keywordKind, + bool isValidInPreprocessorContext = false, + bool shouldFormatOnCommit = false) + : base(keywordKind, isValidInPreprocessorContext, shouldFormatOnCommit) + { + } + + protected abstract SpecialType SpecialType { get; } + + protected override bool ShouldPreselect(CSharpSyntaxContext context, CancellationToken cancellationToken) + { + return context.InferredTypes.Any(t => t.SpecialType == this.SpecialType); + } + } +} diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSyntacticSingleKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSyntacticSingleKeywordRecommender.cs index 4f36ba2dc93..61e77b1a3dd 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSyntacticSingleKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/AbstractSyntacticSingleKeywordRecommender.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Completion.Providers; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Roslyn.Utilities; @@ -33,10 +34,7 @@ protected virtual Task IsValidContextAsync(int position, CSharpSyntaxConte return Task.FromResult(IsValidContext(position, context, cancellationToken)); } - protected virtual bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) - { - return false; - } + protected virtual bool IsValidContext(int position, CSharpSyntaxContext context, CancellationToken cancellationToken) => false; public async Task> RecommendKeywordsAsync( int position, @@ -47,19 +45,24 @@ protected virtual bool IsValidContext(int position, CSharpSyntaxContext context, if (syntaxKind.HasValue) { return SpecializedCollections.SingletonEnumerable( - new RecommendedKeyword(SyntaxFacts.GetText(syntaxKind.Value), shouldFormatOnCommit: this.ShouldFormatOnCommit)); + new RecommendedKeyword(SyntaxFacts.GetText(syntaxKind.Value), + shouldFormatOnCommit: this.ShouldFormatOnCommit, + matchPriority: ShouldPreselect(context, cancellationToken) ? SymbolMatchPriority.Keyword : MatchPriority.Default)); } return null; } + protected virtual bool ShouldPreselect(CSharpSyntaxContext context, CancellationToken cancellationToken) => false; + internal async Task> RecommendKeywordsAsync_Test(int position, CSharpSyntaxContext context) - { + { var syntaxKind = await this.RecommendKeywordAsync(position, context, CancellationToken.None).ConfigureAwait(false); if (syntaxKind.HasValue) { + var matchPriority = ShouldPreselect(context, CancellationToken.None) ? SymbolMatchPriority.Keyword : MatchPriority.Default; return SpecializedCollections.SingletonEnumerable( - new RecommendedKeyword(SyntaxFacts.GetText(syntaxKind.Value))); + new RecommendedKeyword(SyntaxFacts.GetText(syntaxKind.Value), matchPriority: matchPriority)); } return null; diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/BoolKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/BoolKeywordRecommender.cs index c75e637e49a..4dd6815891d 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/BoolKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/BoolKeywordRecommender.cs @@ -1,5 +1,7 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; +using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; @@ -9,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class BoolKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class BoolKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public BoolKeywordRecommender() : base(SyntaxKind.BoolKeyword) @@ -44,5 +46,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Boolean; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ByteKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ByteKeywordRecommender.cs index 0c713a763b4..925a05df657 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ByteKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ByteKeywordRecommender.cs @@ -6,10 +6,12 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; +using System; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class ByteKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class ByteKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public ByteKeywordRecommender() : base(SyntaxKind.ByteKeyword) @@ -46,5 +48,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Byte; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/CharKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/CharKeywordRecommender.cs index d548494affd..a32184f2557 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/CharKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/CharKeywordRecommender.cs @@ -6,10 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class CharKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class CharKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public CharKeywordRecommender() : base(SyntaxKind.CharKeyword) @@ -44,5 +45,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Char; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DecimalKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DecimalKeywordRecommender.cs index e0f5ed2da4f..f6a07b487bc 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DecimalKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DecimalKeywordRecommender.cs @@ -6,10 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class DecimalKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class DecimalKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public DecimalKeywordRecommender() : base(SyntaxKind.DecimalKeyword) @@ -44,5 +45,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Decimal; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DoubleKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DoubleKeywordRecommender.cs index 00c32c1a50b..c489daf2e77 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DoubleKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/DoubleKeywordRecommender.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Linq; using System.Threading; +using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -9,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class DoubleKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class DoubleKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public DoubleKeywordRecommender() : base(SyntaxKind.DoubleKeyword) @@ -44,5 +46,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Double; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/FloatKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/FloatKeywordRecommender.cs index a159e6ec832..c0ce761b1dd 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/FloatKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/FloatKeywordRecommender.cs @@ -6,10 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class FloatKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class FloatKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public FloatKeywordRecommender() : base(SyntaxKind.FloatKeyword) @@ -44,5 +45,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Single; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/IntKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/IntKeywordRecommender.cs index b853d3de58f..cc1c7cfa4f1 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/IntKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/IntKeywordRecommender.cs @@ -6,10 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class IntKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class IntKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public IntKeywordRecommender() : base(SyntaxKind.IntKeyword) @@ -45,5 +46,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Int32; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/LongKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/LongKeywordRecommender.cs index cace23400a0..7d506478d2b 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/LongKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/LongKeywordRecommender.cs @@ -6,10 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class LongKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class LongKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public LongKeywordRecommender() : base(SyntaxKind.LongKeyword) @@ -45,5 +46,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Int64; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ObjectKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ObjectKeywordRecommender.cs index 1f195349703..f8145d398f0 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ObjectKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ObjectKeywordRecommender.cs @@ -6,10 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class ObjectKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class ObjectKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public ObjectKeywordRecommender() : base(SyntaxKind.ObjectKeyword) @@ -43,5 +44,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Object; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/SByteKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/SByteKeywordRecommender.cs index 1b4b39b2ed1..1d04e00aaf1 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/SByteKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/SByteKeywordRecommender.cs @@ -6,10 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class SByteKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class SByteKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public SByteKeywordRecommender() : base(SyntaxKind.SByteKeyword) @@ -45,5 +46,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_SByte; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ShortKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ShortKeywordRecommender.cs index 257ccf8edcf..151350b755a 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ShortKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ShortKeywordRecommender.cs @@ -6,10 +6,12 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; +using System; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class ShortKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class ShortKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public ShortKeywordRecommender() : base(SyntaxKind.ShortKeyword) @@ -45,5 +47,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_Int16; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/StringKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/StringKeywordRecommender.cs index d7ed9f1c451..02cfbabfcbb 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/StringKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/StringKeywordRecommender.cs @@ -6,10 +6,12 @@ using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; +using System; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class StringKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class StringKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public StringKeywordRecommender() : base(SyntaxKind.StringKeyword) @@ -43,5 +45,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_String; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ThisKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ThisKeywordRecommender.cs index 30f42b8f658..3c1acc8a180 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ThisKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ThisKeywordRecommender.cs @@ -92,5 +92,11 @@ private static bool IsExtensionMethodParameterContext(CSharpSyntaxContext contex return true; } + + protected override bool ShouldPreselect(CSharpSyntaxContext context, CancellationToken cancellationToken) + { + var outerType = context.SemanticModel.GetEnclosingNamedType(context.Position, cancellationToken); + return context.InferredTypes.Any(t => t == outerType); + } } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UIntKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UIntKeywordRecommender.cs index 21a68127748..bdea5518161 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UIntKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UIntKeywordRecommender.cs @@ -6,10 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class UIntKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class UIntKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public UIntKeywordRecommender() : base(SyntaxKind.UIntKeyword) @@ -45,5 +46,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_UInt32; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ULongKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ULongKeywordRecommender.cs index b741704b37c..20ef57ed63d 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ULongKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/ULongKeywordRecommender.cs @@ -6,10 +6,12 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; +using System; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class ULongKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class ULongKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public ULongKeywordRecommender() : base(SyntaxKind.ULongKeyword) @@ -45,5 +47,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_UInt64; } } diff --git a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UShortKeywordRecommender.cs b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UShortKeywordRecommender.cs index a95d2c2f85c..66b5c43e4f9 100644 --- a/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UShortKeywordRecommender.cs +++ b/src/Features/CSharp/Portable/Completion/KeywordRecommenders/UShortKeywordRecommender.cs @@ -6,10 +6,11 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; +using System.Linq; namespace Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders { - internal class UShortKeywordRecommender : AbstractSyntacticSingleKeywordRecommender + internal class UShortKeywordRecommender : AbstractSpecialTypePreselectingKeywordRecommender { public UShortKeywordRecommender() : base(SyntaxKind.UShortKeyword) @@ -45,5 +46,7 @@ protected override bool IsValidContext(int position, CSharpSyntaxContext context canBePartial: false, cancellationToken: cancellationToken); } + + protected override SpecialType SpecialType => SpecialType.System_UInt16; } } diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs index ea574f8bd09..02974455960 100644 --- a/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs +++ b/src/Features/Core/Portable/Completion/Providers/AbstractKeywordCompletionProvider.cs @@ -73,7 +73,7 @@ protected virtual CompletionItem CreateItem(RecommendedKeyword keyword, TextSpan description: keyword.DescriptionFactory(CancellationToken.None), glyph: Glyph.Keyword, tags: s_Tags, - matchPriority: keyword.ShouldPreselect ? MatchPriority.Preselect : MatchPriority.Default); + matchPriority: keyword.MatchPriority); } protected virtual async Task> RecommendKeywordsAsync( diff --git a/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs b/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs new file mode 100644 index 00000000000..e1c07099e27 --- /dev/null +++ b/src/Features/Core/Portable/Completion/Providers/AbstractRecommendationServiceBasedCompletionProvider.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Recommendations; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; +using Microsoft.CodeAnalysis.Shared.Utilities; +using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Completion.Providers +{ + internal abstract class AbstractRecommendationServiceBasedCompletionProvider : AbstractSymbolCompletionProvider + { + protected override Task> GetSymbolsWorker(AbstractSyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) + { + var recommender = context.GetLanguageService(); + return recommender.GetRecommendedSymbolsAtPositionAsync(context.Workspace, context.SemanticModel, position, options, cancellationToken); + } + + protected override async Task> GetPreselectedSymbolsWorker(AbstractSyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken) + { + var recommender = context.GetLanguageService(); + var typeInferrer = context.GetLanguageService(); + + var inferredTypes = typeInferrer.InferTypes(context.SemanticModel, position, cancellationToken) + .Where(t => t.SpecialType != SpecialType.System_Void) + .ToSet(); + if (inferredTypes.Count == 0) + { + return SpecializedCollections.EmptyEnumerable(); + } + + var symbols = await recommender.GetRecommendedSymbolsAtPositionAsync( + context.Workspace, + context.SemanticModel, + position, + options, + cancellationToken).ConfigureAwait(false); + return symbols.Where(s => inferredTypes.Contains(GetSymbolType(s)) && !IsInstrinsic(s)); + } + + private ITypeSymbol GetSymbolType(ISymbol symbol) + { + if (symbol is IMethodSymbol) + { + return ((IMethodSymbol)symbol).ReturnType; + } + + return symbol.GetSymbolType(); + } + + protected override CompletionItem CreateItem(string displayText, string insertionText, int position, List symbols, AbstractSyntaxContext context, TextSpan span, bool preselect, SupportedPlatformData supportedPlatformData) + { + var matchPriority = preselect ? ComputeSymbolMatchPriority(symbols[0]) : MatchPriority.Default; + + return SymbolCompletionItem.Create( + displayText: displayText, + insertionText: insertionText, + filterText: GetFilterText(symbols[0], displayText, context), + span: span, + contextPosition: context.Position, + descriptionPosition: position, + symbols: symbols, + supportedPlatforms: supportedPlatformData, + matchPriority: matchPriority, + rules: GetCompletionItemRules(symbols, context)); + } + + protected abstract bool IsInstrinsic(ISymbol s); + + private static int ComputeSymbolMatchPriority(ISymbol symbol) + { + if (symbol.MatchesKind(SymbolKind.Local, SymbolKind.Parameter, SymbolKind.RangeVariable)) + { + return SymbolMatchPriority.PreferLocal; + } + + if (symbol.MatchesKind(SymbolKind.Field, SymbolKind.Property)) + { + return SymbolMatchPriority.PreferFieldOrProperty; + } + + if (symbol.MatchesKind(SymbolKind.Event, SymbolKind.Method)) + { + return SymbolMatchPriority.PreferEventOrMethod; + } + + return SymbolMatchPriority.PreferType; + } + } +} diff --git a/src/Features/Core/Portable/Completion/Providers/RecommendedKeyword.cs b/src/Features/Core/Portable/Completion/Providers/RecommendedKeyword.cs index bc58eb4fd05..39f0d6423c9 100644 --- a/src/Features/Core/Portable/Completion/Providers/RecommendedKeyword.cs +++ b/src/Features/Core/Portable/Completion/Providers/RecommendedKeyword.cs @@ -14,10 +14,10 @@ internal sealed class RecommendedKeyword public Func> DescriptionFactory { get; } public bool IsIntrinsic { get; } public bool ShouldFormatOnCommit { get; } - public bool ShouldPreselect { get; } + public int MatchPriority { get; } - public RecommendedKeyword(string keyword, string toolTip = "", Glyph glyph = Glyph.Keyword, bool isIntrinsic = false, bool shouldFormatOnCommit = false, bool shouldPreselect = false) - : this(keyword, glyph, _ => CreateDisplayParts(keyword, toolTip), isIntrinsic, shouldFormatOnCommit, shouldPreselect) + public RecommendedKeyword(string keyword, string toolTip = "", Glyph glyph = Glyph.Keyword, bool isIntrinsic = false, bool shouldFormatOnCommit = false, int? matchPriority = null) + : this(keyword, glyph, _ => CreateDisplayParts(keyword, toolTip), isIntrinsic, shouldFormatOnCommit, matchPriority) { } @@ -41,14 +41,14 @@ internal static ImmutableArray CreateDisplayParts(string keyw Func> descriptionFactory, bool isIntrinsic = false, bool shouldFormatOnCommit = false, - bool shouldPreselect = false) + int? matchPriority = null) { this.Keyword = keyword; this.Glyph = glyph; this.DescriptionFactory = descriptionFactory; this.IsIntrinsic = isIntrinsic; this.ShouldFormatOnCommit = shouldFormatOnCommit; - this.ShouldPreselect = shouldPreselect; + this.MatchPriority = matchPriority ?? Completion.MatchPriority.Default; } } } diff --git a/src/Features/Core/Portable/Completion/Providers/SymbolMatchPriority.cs b/src/Features/Core/Portable/Completion/Providers/SymbolMatchPriority.cs new file mode 100644 index 00000000000..3e6d234a7f5 --- /dev/null +++ b/src/Features/Core/Portable/Completion/Providers/SymbolMatchPriority.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.CodeAnalysis.Completion.Providers +{ + internal class SymbolMatchPriority + { + internal static int Keyword = 100; + internal static int PreferType = 200; + internal static int PreferNamedArgument = 300; + internal static int PreferEventOrMethod = 400; + internal static int PreferFieldOrProperty = 500; + internal static int PreferLocal = 600; + } +} diff --git a/src/Features/Core/Portable/Features.csproj b/src/Features/Core/Portable/Features.csproj index 0905ec3c1bb..2fc8095a71a 100644 --- a/src/Features/Core/Portable/Features.csproj +++ b/src/Features/Core/Portable/Features.csproj @@ -191,6 +191,8 @@ + + diff --git a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb index 0ace69a6325..894dff8e44b 100644 --- a/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb +++ b/src/Features/VisualBasic/Portable/Completion/CompletionProviders/SymbolCompletionProvider.vb @@ -15,11 +15,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers Partial Friend Class SymbolCompletionProvider - Inherits AbstractSymbolCompletionProvider - - Protected Overrides Function GetSymbolsWorker(context As AbstractSyntaxContext, position As Integer, options As OptionSet, cancellationToken As CancellationToken) As Task(Of IEnumerable(Of ISymbol)) - Return Recommender.GetRecommendedSymbolsAtPositionAsync(context.SemanticModel, position, context.Workspace, options, cancellationToken) - End Function + Inherits AbstractRecommendationServiceBasedCompletionProvider Protected Overrides Function GetInsertionText(symbol As ISymbol, context As AbstractSyntaxContext, ch As Char) As String Return CompletionUtilities.GetInsertionTextAtInsertionTime(symbol, context, ch) @@ -96,5 +92,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.Providers End If End Function + Protected Overrides Function IsInstrinsic(s As ISymbol) As Boolean + Return If(TryCast(s, ITypeSymbol)?.IsIntrinsicType(), False) + End Function + End Class End Namespace diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MeKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MeKeywordRecommender.vb index 3054bd56d46..c32cc0731da 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MeKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/MeKeywordRecommender.vb @@ -1,6 +1,7 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports System.Threading +Imports Microsoft.CodeAnalysis.Completion Imports Microsoft.CodeAnalysis.Completion.Providers Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Imports Microsoft.CodeAnalysis.VisualBasic.Syntax @@ -18,11 +19,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Expr If (context.IsAnyExpressionContext OrElse context.IsSingleLineStatementContext OrElse context.IsNameOfContext) AndAlso targetToken.GetInnermostDeclarationContext().IsKind(SyntaxKind.ClassBlock, SyntaxKind.StructureBlock) Then + Dim priority = MatchPriority.Default + Dim enclosingType = context.SemanticModel.GetEnclosingNamedType(context.Position, cancellationToken) + If enclosingType IsNot Nothing AndAlso context.InferredTypes.Any(Function(t) t Is enclosingType) Then + priority = SymbolMatchPriority.Keyword + End If + If targetToken.GetContainingMemberBlockBegin().TypeSwitch( Function(methodBase As MethodBaseSyntax) Not methodBase.Modifiers.Any(SyntaxKind.SharedKeyword), Function(propertyStatement As PropertyStatementSyntax) Not propertyStatement.Modifiers.Any(SyntaxKind.SharedKeyword), Function(eventStatement As EventStatementSyntax) Not eventStatement.Modifiers.Any(SyntaxKind.SharedKeyword)) Then - Return SpecializedCollections.SingletonEnumerable(New RecommendedKeyword(SyntaxFacts.GetText(SyntaxKind.MeKeyword), VBFeaturesResources.MeKeywordToolTip)) + + Return SpecializedCollections.SingletonEnumerable(New RecommendedKeyword(SyntaxFacts.GetText(SyntaxKind.MeKeyword), VBFeaturesResources.MeKeywordToolTip, matchPriority:=priority)) End If If targetToken.GetContainingMember().TypeSwitch(Function(fieldInitializer As FieldDeclarationSyntax) Not fieldInitializer.Modifiers.Any(SyntaxKind.SharedKeyword)) Then diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/TrueFalseKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/TrueFalseKeywordRecommender.vb index 7adb7e176be..a5f6304374d 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/TrueFalseKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Expressions/TrueFalseKeywordRecommender.vb @@ -1,6 +1,7 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports System.Threading +Imports Microsoft.CodeAnalysis.Completion Imports Microsoft.CodeAnalysis.Completion.Providers Imports Microsoft.CodeAnalysis.LanguageServices Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery @@ -13,11 +14,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Expr Inherits AbstractKeywordRecommender Protected Overrides Function RecommendKeywords(context As VisualBasicSyntaxContext, cancellationToken As CancellationToken) As IEnumerable(Of RecommendedKeyword) - Dim preselect As Boolean = ShouldPreselect(context, cancellationToken) + Dim matchPriority = If(ShouldPreselect(context, cancellationToken), CodeAnalysis.Completion.MatchPriority.Preselect, CodeAnalysis.Completion.MatchPriority.Default) If context.IsAnyExpressionContext Then - Return {New RecommendedKeyword("True", VBFeaturesResources.TrueKeywordToolTip, shouldPreselect:=preselect), - New RecommendedKeyword("False", VBFeaturesResources.FalseKeywordToolTip, shouldPreselect:=preselect)} + Return {New RecommendedKeyword("True", VBFeaturesResources.TrueKeywordToolTip, matchPriority:=matchPriority), + New RecommendedKeyword("False", VBFeaturesResources.FalseKeywordToolTip, matchPriority:=matchPriority)} End If Return SpecializedCollections.EmptyEnumerable(Of RecommendedKeyword)() diff --git a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Types/BuiltInTypesKeywordRecommender.vb b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Types/BuiltInTypesKeywordRecommender.vb index 4e8463d5a84..9e774f8ab42 100644 --- a/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Types/BuiltInTypesKeywordRecommender.vb +++ b/src/Features/VisualBasic/Portable/Completion/KeywordRecommenders/Types/BuiltInTypesKeywordRecommender.vb @@ -1,6 +1,7 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports System.Threading +Imports Microsoft.CodeAnalysis.Completion Imports Microsoft.CodeAnalysis.Completion.Providers Imports Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Imports Microsoft.CodeAnalysis.VisualBasic.Syntax @@ -97,16 +98,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Type Private Function GetIntrinsicTypeKeywords(context As VisualBasicSyntaxContext) As IEnumerable(Of RecommendedKeyword) Debug.Assert(s_intrinsicKeywordNames.Length = s_intrinsicSpecialTypes.Length) + Dim inferredSpecialTypes = context.InferredTypes.Select(Function(t) t.SpecialType).ToSet() + Dim recommendedKeywords(s_intrinsicKeywordNames.Length - 1) As RecommendedKeyword For i = 0 To s_intrinsicKeywordNames.Length - 1 Dim keyword As String = s_intrinsicKeywordNames(i) Dim specialType As SpecialType = DirectCast(s_intrinsicSpecialTypes(i), SpecialType) + Dim priority = If(inferredSpecialTypes.Contains(specialType), SymbolMatchPriority.Keyword, MatchPriority.Default) + recommendedKeywords(i) = New RecommendedKeyword(s_intrinsicKeywordNames(i), Glyph.Keyword, Function(cancellationToken) Dim tooltip = GetDocumentationCommentText(context, specialType, cancellationToken) Return RecommendedKeyword.CreateDisplayParts(keyword, tooltip) - End Function, isIntrinsic:=True) + End Function, isIntrinsic:=True, matchPriority:=priority) Next Return recommendedKeywords diff --git a/src/Features/VisualBasic/Portable/Completion/VisualBasicCompletionService.vb b/src/Features/VisualBasic/Portable/Completion/VisualBasicCompletionService.vb index de97e9392f6..265dc2c3d39 100644 --- a/src/Features/VisualBasic/Portable/Completion/VisualBasicCompletionService.vb +++ b/src/Features/VisualBasic/Portable/Completion/VisualBasicCompletionService.vb @@ -92,8 +92,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion Protected Overrides Function GetBetterItem(item As CompletionItem, existingItem As CompletionItem) As CompletionItem ' If one Is a keyword, And the other Is some other item that inserts the same text as the keyword, - ' keep the keyword (VB only) - If IsKeywordItem(existingItem) Then + ' keep the keyword (VB only), unless the other item is preselected + If IsKeywordItem(existingItem) AndAlso existingItem.Rules.MatchPriority >= item.Rules.MatchPriority Then Return existingItem End If diff --git a/src/Workspaces/CSharp/Portable/Extensions/ContextQuery/CSharpSyntaxContext.cs b/src/Workspaces/CSharp/Portable/Extensions/ContextQuery/CSharpSyntaxContext.cs index e755c06ca85..e8b91dea4a6 100644 --- a/src/Workspaces/CSharp/Portable/Extensions/ContextQuery/CSharpSyntaxContext.cs +++ b/src/Workspaces/CSharp/Portable/Extensions/ContextQuery/CSharpSyntaxContext.cs @@ -6,6 +6,8 @@ using Microsoft.CodeAnalysis.CSharp.Utilities; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; +using System; +using Microsoft.CodeAnalysis.LanguageServices; namespace Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery { @@ -48,6 +50,7 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext public readonly bool IsCatchFilterContext; public readonly bool IsDestructorTypeContext; + private CSharpSyntaxContext( Workspace workspace, SemanticModel semanticModel, @@ -95,13 +98,14 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext bool isInstanceContext, bool isCrefContext, bool isCatchFilterContext, - bool isDestructorTypeContext) + bool isDestructorTypeContext, + CancellationToken cancellationToken) : base(workspace, semanticModel, position, leftToken, targetToken, isTypeContext, isNamespaceContext, isNamespaceDeclarationNameContext, isPreProcessorDirectiveContext, isRightOfDotOrArrowOrColonColon, isStatementContext, isAnyExpressionContext, isAttributeNameContext, isEnumTypeMemberAccessContext, isNameOfContext, - isInQuery, isInImportsDirective) + isInQuery, isInImportsDirective, cancellationToken) { this.ContainingTypeDeclaration = containingTypeDeclaration; this.ContainingTypeOrEnumDeclaration = containingTypeOrEnumDeclaration; @@ -136,6 +140,11 @@ internal sealed class CSharpSyntaxContext : AbstractSyntaxContext } public static CSharpSyntaxContext CreateContext(Workspace workspace, SemanticModel semanticModel, int position, CancellationToken cancellationToken) + { + return CreateContextWorker(workspace, semanticModel, position, cancellationToken); + } + + private static CSharpSyntaxContext CreateContextWorker(Workspace workspace, SemanticModel semanticModel, int position, CancellationToken cancellationToken) { var syntaxTree = semanticModel.SyntaxTree; @@ -232,12 +241,15 @@ public static CSharpSyntaxContext CreateContext(Workspace workspace, SemanticMod syntaxTree.IsInstanceContext(position, leftToken, cancellationToken), syntaxTree.IsCrefContext(position, cancellationToken) && !leftToken.IsKind(SyntaxKind.DotToken), syntaxTree.IsCatchFilterContext(position, leftToken), - isDestructorTypeContext); + isDestructorTypeContext, + cancellationToken); } public static CSharpSyntaxContext CreateContext_Test(SemanticModel semanticModel, int position, CancellationToken cancellationToken) { - return CreateContext(/*workspace*/null, semanticModel, position, cancellationToken); + var inferenceService = new CSharpTypeInferenceService(); + var types = inferenceService.InferTypes(semanticModel, position, cancellationToken); + return CreateContextWorker(workspace: null, semanticModel: semanticModel, position: position, cancellationToken: cancellationToken); } public bool IsTypeAttributeContext(CancellationToken cancellationToken) @@ -313,5 +325,10 @@ private static bool IsLeftSideOfUsingAliasDirective(SyntaxToken leftToken, Cance return false; } + + internal override ITypeInferenceService GetTypeInferenceServiceWithoutWorkspace() + { + return new CSharpTypeInferenceService(); + } } } diff --git a/src/Workspaces/CSharp/Portable/Extensions/ITypeSymbolExtensions.cs b/src/Workspaces/CSharp/Portable/Extensions/ITypeSymbolExtensions.cs index a1cd9ee1d16..a48dac6f62a 100644 --- a/src/Workspaces/CSharp/Portable/Extensions/ITypeSymbolExtensions.cs +++ b/src/Workspaces/CSharp/Portable/Extensions/ITypeSymbolExtensions.cs @@ -98,5 +98,30 @@ private static IEnumerable GetApplicableUsings(int positio : namespaceUsings; return allUsings.Where(u => u.Alias != null); } + + public static bool IsIntrinsicType(this ITypeSymbol typeSymbol) + { + switch (typeSymbol.SpecialType) + { + case SpecialType.System_Boolean: + case SpecialType.System_Char: + case SpecialType.System_SByte: + case SpecialType.System_Int16: + case SpecialType.System_Int32: + case SpecialType.System_Int64: + case SpecialType.System_Byte: + case SpecialType.System_UInt16: + case SpecialType.System_UInt32: + case SpecialType.System_UInt64: + case SpecialType.System_Single: + case SpecialType.System_Double: + // NOTE: VB treats System.DateTime as an intrinsic, while C# does not, see "predeftype.h" + //case SpecialType.System_DateTime: + case SpecialType.System_Decimal: + return true; + default: + return false; + } + } } } diff --git a/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/AbstractTypeInferenceService.cs b/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/AbstractTypeInferenceService.cs index 4d11b580879..0dc59d99197 100644 --- a/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/AbstractTypeInferenceService.cs +++ b/src/Workspaces/Core/Portable/LanguageServices/TypeInferenceService/AbstractTypeInferenceService.cs @@ -74,6 +74,23 @@ private IEnumerable Filter(IEnumerable types, bool fil .Distinct() .ToImmutableReadOnlyListOrEmpty(); } + + protected IEnumerable ExpandParamsParameter(IParameterSymbol parameterSymbol) + { + var result = new List(); + result.Add(parameterSymbol.Type); + + if (parameterSymbol.IsParams) + { + var arrayTypeSymbol = parameterSymbol.Type as IArrayTypeSymbol; + if (arrayTypeSymbol != null) + { + result.Add(arrayTypeSymbol.ElementType); + } + } + + return result; + } } protected abstract AbstractTypeInferrer CreateTypeInferrer(SemanticModel semanticModel, CancellationToken cancellationToken); diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/ContextQuery/AbstractSyntaxContext.cs b/src/Workspaces/Core/Portable/Shared/Extensions/ContextQuery/AbstractSyntaxContext.cs index 8985329790a..62362177723 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/ContextQuery/AbstractSyntaxContext.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/ContextQuery/AbstractSyntaxContext.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading; using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.LanguageServices; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery @@ -28,7 +29,8 @@ internal abstract class AbstractSyntaxContext bool isEnumTypeMemberAccessContext, bool isNameOfContext, bool isInQuery, - bool isInImportsDirective) + bool isInImportsDirective, + CancellationToken cancellationToken) { this.Workspace = workspace; this.SemanticModel = semanticModel; @@ -48,6 +50,7 @@ internal abstract class AbstractSyntaxContext this.IsNameOfContext = isNameOfContext; this.IsInQuery = isInQuery; this.IsInImportsDirective = isInImportsDirective; + this.InferredTypes = ComputeInferredTypes(workspace, semanticModel, position, cancellationToken); } public Workspace Workspace { get; } @@ -74,6 +77,7 @@ internal abstract class AbstractSyntaxContext public bool IsInQuery { get; } public bool IsInImportsDirective { get; } + public IEnumerable InferredTypes { get; private set; } private ISet ComputeOuterTypes(CancellationToken cancellationToken) { @@ -90,6 +94,18 @@ private ISet ComputeOuterTypes(CancellationToken cancellationT return SpecializedCollections.EmptySet(); } + protected IEnumerable ComputeInferredTypes(Workspace workspace, + SemanticModel semanticModel, + int position, + CancellationToken cancellationToken) + { + var typeInferenceService = workspace?.Services.GetLanguageServices(semanticModel.Language).GetService() + ?? GetTypeInferenceServiceWithoutWorkspace(); + return typeInferenceService.InferTypes(semanticModel, position, cancellationToken); + } + + internal abstract ITypeInferenceService GetTypeInferenceServiceWithoutWorkspace(); + public ISet GetOuterTypes(CancellationToken cancellationToken) { if (_outerTypes == null) diff --git a/src/Workspaces/VisualBasic/Portable/Extensions/ContextQuery/VisualBasicSyntaxContext.vb b/src/Workspaces/VisualBasic/Portable/Extensions/ContextQuery/VisualBasicSyntaxContext.vb index 6acb504895b..d955364771b 100644 --- a/src/Workspaces/VisualBasic/Portable/Extensions/ContextQuery/VisualBasicSyntaxContext.vb +++ b/src/Workspaces/VisualBasic/Portable/Extensions/ContextQuery/VisualBasicSyntaxContext.vb @@ -1,6 +1,7 @@ ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. Imports System.Threading +Imports Microsoft.CodeAnalysis.LanguageServices Imports Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports Microsoft.CodeAnalysis.VisualBasic.Utilities @@ -93,7 +94,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery isEnumTypeMemberAccessContext:=isEnumTypeMemberAccessContext, isNameOfContext:=isNameOfContext, isInQuery:=isInQuery, - isInImportsDirective:=isInImportsDirective) + isInImportsDirective:=isInImportsDirective, + cancellationToken:=cancellationToken) Dim syntaxTree = semanticModel.SyntaxTree @@ -270,6 +272,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions.ContextQuery Position, TargetToken, Function(joinOperator) joinOperator.JoinedVariables.LastCollectionExpression(), cancellationToken) End Function + Friend Overrides Function GetTypeInferenceServiceWithoutWorkspace() As ITypeInferenceService + Return New VisualBasicTypeInferenceService() + End Function End Class End Namespace diff --git a/src/Workspaces/VisualBasic/Portable/Extensions/ITypeSymbolExtensions.vb b/src/Workspaces/VisualBasic/Portable/Extensions/ITypeSymbolExtensions.vb index 5c069f726b0..ca60d8c5ae5 100644 --- a/src/Workspaces/VisualBasic/Portable/Extensions/ITypeSymbolExtensions.vb +++ b/src/Workspaces/VisualBasic/Portable/Extensions/ITypeSymbolExtensions.vb @@ -97,5 +97,29 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions Return compilation.GetSpecialType(specialType) End Function + + + Public Function IsIntrinsicType(this As ITypeSymbol) As Boolean + Select Case this.SpecialType + Case SpecialType.System_Boolean, + SpecialType.System_Byte, + SpecialType.System_SByte, + SpecialType.System_Int16, + SpecialType.System_UInt16, + SpecialType.System_Int32, + SpecialType.System_UInt32, + SpecialType.System_Int64, + SpecialType.System_UInt64, + SpecialType.System_Single, + SpecialType.System_Double, + SpecialType.System_Decimal, + SpecialType.System_DateTime, + SpecialType.System_Char, + SpecialType.System_String + Return True + Case Else + Return False + End Select + End Function End Module End Namespace -- GitLab