|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Completion.KeywordRecommenders;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Recommendations
{
[Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public class VarKeywordRecommenderTests : RecommenderTests
{
protected override string KeywordText => "var";
private readonly VarKeywordRecommender _recommender = new();
public VarKeywordRecommenderTests()
{
this.RecommendKeywordsAsync = (position, context) => Task.FromResult(_recommender.RecommendKeywords(position, context, CancellationToken.None));
}
[Fact]
public async Task TestAtRoot_Interactive()
{
await VerifyKeywordAsync(SourceCodeKind.Script,
@"$$");
}
[Fact]
public async Task TestAfterClass_Interactive()
{
await VerifyKeywordAsync(SourceCodeKind.Script,
"""
class C { }
$$
""");
}
[Fact]
public async Task TestAfterGlobalStatement_Interactive()
{
await VerifyKeywordAsync(SourceCodeKind.Script,
"""
System.Console.WriteLine();
$$
""");
}
[Fact]
public async Task TestAfterGlobalVariableDeclaration_Interactive()
{
await VerifyKeywordAsync(SourceCodeKind.Script,
"""
int i = 0;
$$
""");
}
[Fact]
public async Task TestNotInUsingAlias()
{
await VerifyAbsenceAsync(
@"using Goo = $$");
}
[Fact]
public async Task TestNotInGlobalUsingAlias()
{
await VerifyAbsenceAsync(
@"global using Goo = $$");
}
[Fact]
public async Task TestNotAfterStackAlloc()
{
await VerifyAbsenceAsync(
"""
class C {
int* goo = stackalloc $$
""");
}
[Fact]
public async Task TestNotInFixedStatement()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"fixed ($$"));
}
[Fact]
public async Task TestNotInDelegateReturnType()
{
await VerifyAbsenceAsync(
@"public delegate $$");
}
[Fact]
public async Task TestInCastType()
{
// Could be a deconstruction
await VerifyKeywordAsync(AddInsideMethod(
@"var str = (($$"));
}
[Fact]
public async Task TestInCastType2()
{
// Could be a deconstruction
await VerifyKeywordAsync(AddInsideMethod(
@"var str = (($$)items) as string;"));
}
[Fact]
public async Task TestEmptyStatement()
{
await VerifyKeywordAsync(AddInsideMethod(
@"$$"));
}
[Fact]
public async Task TestBeforeStatement()
{
await VerifyKeywordAsync(AddInsideMethod(
"""
$$
return true;
"""));
}
[Fact]
public async Task TestAfterStatement()
{
await VerifyKeywordAsync(AddInsideMethod(
"""
return true;
$$
"""));
}
[Fact]
public async Task TestAfterBlock()
{
await VerifyKeywordAsync(AddInsideMethod(
"""
if (true) {
}
$$
"""));
}
[Fact]
public async Task TestNotAfterLock()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"lock $$"));
}
[Fact]
public async Task TestNotAfterLock2()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"lock ($$"));
}
[Fact]
public async Task TestNotAfterLock3()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"lock (l$$"));
}
[Fact]
public async Task TestNotInClass()
{
await VerifyAbsenceAsync("""
class C
{
$$
}
""");
}
[Fact]
public async Task TestInFor()
{
await VerifyKeywordAsync(AddInsideMethod(
@"for ($$"));
}
[Fact]
public async Task TestNotInFor()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"for (var $$"));
}
[Fact]
public async Task TestInFor2()
{
await VerifyKeywordAsync(AddInsideMethod(
@"for ($$;"));
}
[Fact]
public async Task TestInFor3()
{
await VerifyKeywordAsync(AddInsideMethod(
@"for ($$;;"));
}
[Fact]
public async Task TestNotAfterVar()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"var $$"));
}
[Fact]
public async Task TestInForEach()
{
await VerifyKeywordAsync(AddInsideMethod(
@"foreach ($$"));
}
[Fact]
public async Task TestNotInForEach()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"foreach (var $$"));
}
[Fact]
public async Task TestInAwaitForEach()
{
await VerifyKeywordAsync(AddInsideMethod(
@"await foreach ($$"));
}
[Fact]
public async Task TestNotInAwaitForEach()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"await foreach (var $$"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37223")]
public async Task TestInForEachRefLoop0()
{
await VerifyKeywordAsync(AddInsideMethod(
@"foreach (ref $$"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37223")]
public async Task TestInForEachRefLoop1()
{
await VerifyKeywordAsync(AddInsideMethod(
@"foreach (ref $$ x"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37223")]
public async Task TestInForEachRefLoop2()
{
await VerifyKeywordAsync(AddInsideMethod(
@"foreach (ref v$$ x"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37223")]
public async Task TestInForEachRefReadonlyLoop0()
{
await VerifyKeywordAsync(AddInsideMethod(
@"foreach (ref readonly $$ x"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37223")]
public async Task TestInForRefLoop0()
{
await VerifyKeywordAsync(AddInsideMethod(
@"for (ref $$"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37223")]
public async Task TestInForRefLoop1()
{
await VerifyKeywordAsync(AddInsideMethod(
@"for (ref v$$"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37223")]
public async Task TestInForRefReadonlyLoop0()
{
await VerifyKeywordAsync(AddInsideMethod(
@"for (ref readonly $$"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37223")]
public async Task TestInForRefReadonlyLoop1()
{
await VerifyKeywordAsync(AddInsideMethod(
@"for (ref readonly v$$"));
}
[Fact]
public async Task TestInUsing()
{
await VerifyKeywordAsync(AddInsideMethod(
@"using ($$"));
}
[Fact]
public async Task TestNotInUsing()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"using (var $$"));
}
[Fact]
public async Task TestInAwaitUsing()
{
await VerifyKeywordAsync(AddInsideMethod(
@"await using ($$"));
}
[Fact]
public async Task TestNotInAwaitUsing()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"await using (var $$"));
}
[Fact]
public async Task TestAfterConstLocal()
{
await VerifyKeywordAsync(AddInsideMethod(
@"const $$"));
}
[Fact]
public async Task TestNotAfterConstField()
{
await VerifyAbsenceAsync(
"""
class C {
const $$
""");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/12121")]
public async Task TestAfterOutKeywordInArgument()
{
await VerifyKeywordAsync(AddInsideMethod(
@"M(out $$"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/12121")]
public async Task TestAfterOutKeywordInParameter()
{
await VerifyAbsenceAsync(
"""
class C {
void M1(out $$
""");
}
[Fact]
public async Task TestVarPatternInSwitch()
{
await VerifyKeywordAsync(AddInsideMethod(
"""
switch(o)
{
case $$
}
"""));
}
[Fact]
public async Task TestVarPatternInIs()
=> await VerifyKeywordAsync(AddInsideMethod("var b = o is $$ "));
[Fact]
public async Task TestNotAfterRefInMemberContext()
{
await VerifyAbsenceAsync(
"""
class C {
ref $$
""");
}
[Fact]
public async Task TestNotAfterRefReadonlyInMemberContext()
{
await VerifyAbsenceAsync(
"""
class C {
ref readonly $$
""");
}
[Fact]
public async Task TestAfterRefInStatementContext()
{
await VerifyKeywordAsync(AddInsideMethod(
@"ref $$"));
}
[Fact]
public async Task TestAfterRefReadonlyInStatementContext()
{
await VerifyKeywordAsync(AddInsideMethod(
@"ref readonly $$"));
}
[Fact]
public async Task TestAfterRefLocalDeclaration()
{
await VerifyKeywordAsync(AddInsideMethod(
@"ref $$ int local;"));
}
[Fact]
public async Task TestAfterRefReadonlyLocalDeclaration()
{
await VerifyKeywordAsync(AddInsideMethod(
@"ref readonly $$ int local;"));
}
// For a local function, we can't add any tests - sometimes the keyword is offered and sometimes it's not,
// depending on whether the keyword is partially written or not. This is because a partially written keyword
// causes this to be parsed as a local declaration instead. We can't add either test because
// VerifyKeywordAsync & VerifyAbsenceAsync check for both cases - with the keyword partially written and without.
[Fact]
public async Task TestNotAfterRefExpression()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"ref int x = ref $$"));
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/10170")]
public async Task TestInPropertyPattern()
{
await VerifyKeywordAsync(
"""
using System;
class Person { public string Name; }
class Program
{
void Goo(object o)
{
if (o is Person { Name: $$ })
{
Console.WriteLine(n);
}
}
}
""");
}
[Fact]
public async Task TestNotInDeclarationDeconstruction()
{
await VerifyAbsenceAsync(AddInsideMethod(
@"var (x, $$) = (0, 0);"));
}
[Fact]
public async Task TestInMixedDeclarationAndAssignmentInDeconstruction()
{
await VerifyKeywordAsync(AddInsideMethod(
@"(x, $$) = (0, 0);"));
}
[Fact]
public async Task TestAfterScoped()
{
await VerifyKeywordAsync(AddInsideMethod("scoped $$"));
await VerifyKeywordAsync("scoped $$");
}
}
}
|