diff --git a/src/Features/CSharpTest/Snippets/AbstractCSharpConditionalBlockSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/AbstractCSharpConditionalBlockSnippetProviderTests.cs index 299468058da10..cc084154e6f48 100644 --- a/src/Features/CSharpTest/Snippets/AbstractCSharpConditionalBlockSnippetProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/AbstractCSharpConditionalBlockSnippetProviderTests.cs @@ -566,4 +566,21 @@ void M() } """); } + + [Fact] + public async Task NoInlineSnippetForTypeItselfTest_BeforeContextualKeyword() + { + await VerifySnippetIsAbsentAsync(""" + using System.Threading.Tasks; + + class C + { + async void M() + { + bool.$$ + await Task.Delay(10); + } + } + """); + } } diff --git a/src/Features/CSharpTest/Snippets/CSharpDoSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpDoSnippetProviderTests.cs index 01e86e3f3d04d..fe6ee4921126b 100644 --- a/src/Features/CSharpTest/Snippets/CSharpDoSnippetProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpDoSnippetProviderTests.cs @@ -582,4 +582,21 @@ void M() } """); } + + [Fact] + public async Task NoInlineDoSnippetForTypeItselfTest_BeforeContextualKeyword() + { + await VerifySnippetIsAbsentAsync(""" + using System.Threading.Tasks; + + class C + { + async void M() + { + bool.$$ + await Task.Delay(10); + } + } + """); + } } diff --git a/src/Features/CSharpTest/Snippets/CSharpForEachSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpForEachSnippetProviderTests.cs index 0108eeffc5074..ef08ca718abd8 100644 --- a/src/Features/CSharpTest/Snippets/CSharpForEachSnippetProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpForEachSnippetProviderTests.cs @@ -731,6 +731,24 @@ void M() """); } + [Theory] + [MemberData(nameof(CommonSnippetTestData.CommonEnumerableTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task NoInlineForEachSnippetForTypeItselfTest_BeforeContextualKeyword(string collectionType) + { + await VerifySnippetIsAbsentAsync($$""" + using System.Threading.Tasks; + + class C + { + async void M() + { + {{collectionType}}.$$ + await Task.Delay(10); + } + } + """); + } + [Theory] [InlineData("ArrayList")] [InlineData("IEnumerable")] diff --git a/src/Features/CSharpTest/Snippets/CSharpForSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpForSnippetProviderTests.cs index 0fa94d8d5c9c3..c6535a98cb8d4 100644 --- a/src/Features/CSharpTest/Snippets/CSharpForSnippetProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpForSnippetProviderTests.cs @@ -877,32 +877,68 @@ public class MyType } [Theory] + [InlineData("MyType")] [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] - public async Task NoInlineForSnippetForTypeItselfTest(string integerType) + public async Task NoInlineForSnippetForTypeItselfTest(string validTypes) { await VerifySnippetIsAbsentAsync($$""" class C { void M() { - {{integerType}}.$$ + {{validTypes}}.$$ } } + + class MyType + { + public int Count => 0; + } """); } [Theory] + [InlineData("MyType")] [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] - public async Task NoInlineForSnippetForTypeItselfTest_Parenthesized(string integerType) + public async Task NoInlineForSnippetForTypeItselfTest_Parenthesized(string validTypes) { await VerifySnippetIsAbsentAsync($$""" class C { void M() { - ({{integerType}}).$$ + ({{validTypes}}).$$ + } + } + + class MyType + { + public int Count => 0; + } + """); + } + + [Theory] + [InlineData("MyType")] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task NoInlineForSnippetForTypeItselfTest_BeforeContextualKeyword(string validTypes) + { + await VerifySnippetIsAbsentAsync($$""" + using System.Threading.Tasks; + + class C + { + async void M() + { + {{validTypes}}.$$ + await Task.Delay(10); } } + + class MyType + { + public int Count => 0; + } """); } diff --git a/src/Features/CSharpTest/Snippets/CSharpReversedForSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpReversedForSnippetProviderTests.cs index 3912eeb524458..88a56ffefd939 100644 --- a/src/Features/CSharpTest/Snippets/CSharpReversedForSnippetProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpReversedForSnippetProviderTests.cs @@ -879,32 +879,68 @@ public class MyType } [Theory] + [InlineData("MyType")] [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] - public async Task NoInlineReversedForSnippetForTypeItselfTest(string integerType) + public async Task NoInlineReversedForSnippetForTypeItselfTest(string validTypes) { await VerifySnippetIsAbsentAsync($$""" class C { void M() { - {{integerType}}.$$ + {{validTypes}}.$$ } } + + class MyType + { + public int Count => 0; + } """); } [Theory] + [InlineData("MyType")] [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] - public async Task NoInlineReversedForSnippetForTypeItselfTest_Parenthesized(string integerType) + public async Task NoInlineReversedForSnippetForTypeItselfTest_Parenthesized(string validTypes) { await VerifySnippetIsAbsentAsync($$""" class C { void M() { - ({{integerType}}).$$ + ({{validTypes}}).$$ + } + } + + class MyType + { + public int Count => 0; + } + """); + } + + [Theory] + [InlineData("MyType")] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task NoInlineReversedForSnippetForTypeItselfTest_BeforeContextualKeyword(string validTypes) + { + await VerifySnippetIsAbsentAsync($$""" + using System.Threading.Tasks; + + class C + { + async void M() + { + {{validTypes}}.$$ + await Task.Delay(10); } } + + class MyType + { + public int Count => 0; + } """); } diff --git a/src/Features/Core/Portable/Snippets/SnippetProviders/AbstractInlineStatementSnippetProvider.cs b/src/Features/Core/Portable/Snippets/SnippetProviders/AbstractInlineStatementSnippetProvider.cs index 07aea536e7e09..4234f497d0d3a 100644 --- a/src/Features/Core/Portable/Snippets/SnippetProviders/AbstractInlineStatementSnippetProvider.cs +++ b/src/Features/Core/Portable/Snippets/SnippetProviders/AbstractInlineStatementSnippetProvider.cs @@ -108,6 +108,16 @@ private static bool TryGetInlineExpressionInfo(SyntaxToken targetToken, ISyntaxF if (syntaxFacts.IsQualifiedName(parentNode)) { syntaxFacts.GetPartsOfQualifiedName(parentNode, out var expression, out _, out _); + var symbolInfo = semanticModel.GetSymbolInfo(expression, cancellationToken); + + // Forbid a case when we are dotting of a type, e.g. `string.$$`. + // Inline statement snippets are not valid in this context + if (symbolInfo.Symbol is ITypeSymbol) + { + expressionInfo = null; + return false; + } + var typeInfo = semanticModel.GetSpeculativeTypeInfo(expression.SpanStart, expression, SpeculativeBindingOption.BindAsExpression); expressionInfo = new(expression, typeInfo); return true;