|
// 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.
#nullable disable
using System;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders;
[Trait(Traits.Feature, Traits.Features.Completion)]
public class ObjectCreationCompletionProviderTests : AbstractCSharpCompletionProviderTests
{
internal override Type GetCompletionProviderType()
=> typeof(ObjectCreationCompletionProvider);
[Fact]
public async Task InObjectCreation()
{
var markup = @"
class MyGeneric<T> { }
void goo()
{
MyGeneric<string> goo = new $$
}";
await VerifyItemExistsAsync(markup, "MyGeneric<string>");
}
[Fact]
public async Task NotInAnonymousTypeObjectCreation1()
{
var markup = @"
class C
{
void M()
{
var x = new[] { new { Goo = ""asdf"", Bar = 1 }, new $$
}
}";
await VerifyItemIsAbsentAsync(markup, "<anonymous type: string Goo, int Bar>");
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/854497")]
public async Task NotVoid()
{
var markup = @"
class C
{
void M()
{
var x = new $$
}
}";
await VerifyItemIsAbsentAsync(markup, "void");
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/827897")]
public async Task InYieldReturn()
{
var markup =
@"using System;
using System.Collections.Generic;
class Program
{
IEnumerable<FieldAccessException> M()
{
yield return new $$
}
}";
await VerifyItemExistsAsync(markup, "FieldAccessException");
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/827897")]
public async Task InAsyncMethodReturnStatement()
{
var markup =
@"using System;
using System.Threading.Tasks;
class Program
{
async Task<FieldAccessException> M()
{
await Task.Delay(1);
return new $$
}
}";
await VerifyItemExistsAsync(markup, "FieldAccessException");
}
[Fact]
public async Task InAsyncMethodReturnValueTask()
{
var markup =
@"using System;
using System.Threading.Tasks;
class Program
{
async ValueTask<string> M2Async()
{
return new $$;
}
}";
await VerifyItemExistsAsync(MakeMarkup(markup), "string");
}
[Fact]
public async Task IsCommitCharacterTest()
{
const string markup = @"
using D = System.Globalization.DigitShapes;
class Program
{
static void Main(string[] args)
{
D d = new $$
}
}";
await VerifyCommitCharactersAsync(markup, textTypedSoFar: "",
validChars: [' ', '(', '{', '['],
invalidChars: ['x', ',', '#']);
}
[Fact]
public void IsTextualTriggerCharacterTest()
{
VerifyTextualTriggerCharacter("Abc$$ ", shouldTriggerWithTriggerOnLettersEnabled: true, shouldTriggerWithTriggerOnLettersDisabled: true);
VerifyTextualTriggerCharacter("Abc $$X", shouldTriggerWithTriggerOnLettersEnabled: true, shouldTriggerWithTriggerOnLettersDisabled: false);
VerifyTextualTriggerCharacter("Abc $$@", shouldTriggerWithTriggerOnLettersEnabled: false, shouldTriggerWithTriggerOnLettersDisabled: false);
VerifyTextualTriggerCharacter("Abc$$@", shouldTriggerWithTriggerOnLettersEnabled: false, shouldTriggerWithTriggerOnLettersDisabled: false);
VerifyTextualTriggerCharacter("Abc$$.", shouldTriggerWithTriggerOnLettersEnabled: false, shouldTriggerWithTriggerOnLettersDisabled: false);
}
[Fact]
public async Task SendEnterThroughToEditorTest()
{
const string markup = @"
using D = System.Globalization.DigitShapes;
class Program
{
static void Main(string[] args)
{
D d = new $$
}
}";
await VerifySendEnterThroughToEnterAsync(markup, "D", sendThroughEnterOption: EnterKeyRule.Never, expected: false);
await VerifySendEnterThroughToEnterAsync(markup, "D", sendThroughEnterOption: EnterKeyRule.AfterFullyTypedWord, expected: true);
await VerifySendEnterThroughToEnterAsync(markup, "D", sendThroughEnterOption: EnterKeyRule.Always, expected: true);
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/828196")]
public async Task SuggestAlias()
{
var markup = @"
using D = System.Globalization.DigitShapes;
class Program
{
static void Main(string[] args)
{
D d= new $$
}
}";
await VerifyItemExistsAsync(markup, "D");
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/828196")]
public async Task SuggestAlias2()
{
var markup = @"
namespace N
{
using D = System.Globalization.DigitShapes;
class Program
{
static void Main(string[] args)
{
D d= new $$
}
}
}
";
await VerifyItemExistsAsync(markup, "D");
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1075275")]
public async Task CommitAlias()
{
var markup = @"
using D = System.Globalization.DigitShapes;
class Program
{
static void Main(string[] args)
{
D d= new $$
}
}";
var expected = @"
using D = System.Globalization.DigitShapes;
class Program
{
static void Main(string[] args)
{
D d= new D(
}
}";
await VerifyProviderCommitAsync(markup, "D", expected, '(');
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1090377")]
public async Task AfterNewFollowedByAssignment()
{
var markup = @"
class Location {}
enum EAB { A, B }
class Goo
{
Location Loc {get; set;}
EAB E {get; set;}
void stuff()
{
var x = new Goo
{
Loc = new $$
E = EAB.A
};
}
}
";
await VerifyItemExistsAsync(markup, "Location");
}
[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1090377")]
public async Task AfterNewFollowedByAssignment_GrandParentIsSimpleAssignment()
{
var markup = @"
class Program
{
static void Main(string[] args)
{
Program p = new $$
bool b = false;
}
}";
await VerifyItemExistsAsync(markup, "Program");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2836")]
public async Task AfterNewFollowedBySimpleAssignment_GrandParentIsEqualsValueClause()
{
var markup = @"
class Program
{
static void Main(string[] args)
{
bool b;
Program p = new $$
b = false;
}
}";
await VerifyItemExistsAsync(markup, "Program");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2836")]
public async Task AfterNewFollowedByCompoundAssignment_GrandParentIsEqualsValueClause()
{
var markup = @"
class Program
{
static void Main(string[] args)
{
int i;
Program p = new $$
i += 5;
}
}";
await VerifyItemExistsAsync(markup, "Program");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2836")]
public async Task AfterNewFollowedByCompoundAssignment_GrandParentIsEqualsValueClause2()
{
var markup = @"
class Program
{
static void Main(string[] args)
{
int i = 1000;
Program p = new $$
i <<= 4;
}
}";
await VerifyItemExistsAsync(markup, "Program");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/4115")]
public async Task CommitObjectWithParenthesis1()
{
var markup = @"
class C
{
void M1()
{
object o = new $$
}
}";
var expected = @"
class C
{
void M1()
{
object o = new object(
}
}";
await VerifyProviderCommitAsync(markup, "object", expected, '(');
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/4115")]
public async Task CommitObjectWithParenthesis2()
{
var markup = @"
class C
{
void M1()
{
M2(new $$
}
void M2(object o) { }
}";
var expected = @"
class C
{
void M1()
{
M2(new object(
}
void M2(object o) { }
}";
await VerifyProviderCommitAsync(markup, "object", expected, '(');
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/4115")]
public async Task DoNotCommitObjectWithOpenBrace1()
{
var markup = @"
class C
{
void M1()
{
object o = new $$
}
}";
var expected = @"
class C
{
void M1()
{
object o = new {
}
}";
await VerifyProviderCommitAsync(markup, "object", expected, '{');
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/4115")]
public async Task DoNotCommitObjectWithOpenBrace2()
{
var markup = @"
class C
{
void M1()
{
M2(new $$
}
void M2(object o) { }
}";
var expected = @"
class C
{
void M1()
{
M2(new {
}
void M2(object o) { }
}";
await VerifyProviderCommitAsync(markup, "object", expected, '{');
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/4310")]
public async Task InExpressionBodiedProperty()
{
var markup =
@"class C
{
object Object => new $$
}
";
await VerifyItemExistsAsync(markup, "object");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/4310")]
public async Task InExpressionBodiedMethod()
{
var markup =
@"class C
{
object GetObject() => new $$
}
";
await VerifyItemExistsAsync(markup, "object");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/15804")]
public async Task BeforeAttributeParsedAsImplicitArray()
{
var markup =
@"class Program
{
Program p = new $$
[STAThread]
static void Main() { }
}
";
await VerifyItemExistsAsync(markup, "Program");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/14084")]
public async Task InMethodCallBeforeAssignment1()
{
var markup =
@"namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
object o;
string s;
Test(new $$
o = s;
}
static void Test(TimeSpan t, TimeSpan t2) { }
}
}
";
await VerifyItemExistsAsync(markup, "TimeSpan");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/14084")]
public async Task InMethodCallBeforeAssignment2()
{
var markup =
@"namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
object o;
string s;
Test(new TimeSpan(), new $$
o = s;
}
static void Test(TimeSpan t, TimeSpan t2) { }
}
}
";
await VerifyItemExistsAsync(markup, "TimeSpan");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2644")]
public async Task InPropertyWithSameNameAsGenericTypeArgument1()
{
var markup =
@"namespace ConsoleApplication1
{
class Program
{
public static List<Bar> Bar { get; set; }
static void Main(string[] args)
{
Bar = new $$
}
}
class Bar
{
}
}
";
await VerifyItemExistsAsync(markup, "List<Bar>");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2644")]
public async Task InPropertyWithSameNameAsGenericTypeArgument2()
{
var markup =
@"namespace ConsoleApplication1
{
class Program
{
public static List<Bar> Bar { get; set; } = new $$
}
class Bar
{
}
}
";
await VerifyItemExistsAsync(markup, "List<Bar>");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2644")]
public async Task InPropertyWithSameNameAsGenericTypeArgument3()
{
var markup =
@"namespace ConsoleApplication1
{
class Program
{
public static List<Bar> Bar { get; set; } => new $$
}
class Bar
{
}
}
";
await VerifyItemExistsAsync(markup, "List<Bar>");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/2644")]
public async Task InPropertyWithSameNameAsGenericTypeArgument4()
{
var markup =
@"namespace ConsoleApplication1
{
class Program
{
static C<A> B { get; set; }
static C<B> A { get; set; }
static void Main(string[] args)
{
B = new $$
}
}
class A { }
class B { }
class C<T> { }
}
";
await VerifyItemExistsAsync(markup, "C<A>");
}
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/21674")]
public async Task PropertyWithSameNameAsOtherType()
{
var markup =
@"namespace ConsoleApplication1
{
class Program
{
static A B { get; set; }
static B A { get; set; }
static void Main()
{
B = new $$
}
}
class A { }
class B { }
}
";
await VerifyItemExistsAsync(markup, "A");
}
[Fact]
public async Task NullableTypeCreation()
{
var markup =
@"#nullable enable
namespace ConsoleApplication1
{
class Program
{
void M()
{
object? o;
o = new $$
}
}
}
";
await VerifyItemExistsAsync(markup, "object");
}
[Fact]
public async Task NullableTypeCreation_AssignedNull()
{
var markup =
@"#nullable enable
namespace ConsoleApplication1
{
class Program
{
void M()
{
object? o = null;
o = new $$
}
}
}
";
await VerifyItemExistsAsync(markup, "object");
}
[Fact]
public async Task NullableTypeCreation_NestedNull()
{
var markup =
@"#nullable enable
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
void M()
{
List<object?> l;
l = new $$
}
}
}
";
await VerifyItemExistsAsync(markup, "List<object?>");
}
[Theory]
[InlineData('.')]
[InlineData(';')]
public async Task CreateObjectAndCommitWithCustomizedCommitChar(char commitChar)
{
var markup = @"
class Program
{
void Bar()
{
object o = new $$
}
}";
var expectedMark = $@"
class Program
{{
void Bar()
{{
object o = new object(){commitChar}
}}
}}";
await VerifyProviderCommitAsync(markup, "object", expectedMark, commitChar: commitChar);
}
[Theory]
[InlineData('.')]
[InlineData(';')]
public async Task CreateNullableObjectAndCommitWithCustomizedCommitChar(char commitChar)
{
var markup = @"
class Program
{
void Bar()
{
object? o = new $$
}
}";
var expectedMark = $@"
class Program
{{
void Bar()
{{
object? o = new object(){commitChar}
}}
}}";
await VerifyProviderCommitAsync(markup, "object", expectedMark, commitChar: commitChar);
}
[Theory]
[InlineData('.')]
[InlineData(';')]
public async Task CreateStringAsLocalAndCommitWithCustomizedCommitChar(char commitChar)
{
var markup = @"
class Program
{
void Bar()
{
string o = new $$
}
}";
var expectedMark = $@"
class Program
{{
void Bar()
{{
string o = new string(){commitChar}
}}
}}";
await VerifyProviderCommitAsync(markup, "string", expectedMark, commitChar: commitChar);
}
[Theory]
[InlineData('.')]
[InlineData(';')]
public async Task CreateGenericListAsLocalAndCommitWithCustomizedChar(char commitChar)
{
var markup = @"
using System.Collections.Generic;
class Program
{
void Bar()
{
List<int> o = new $$
}
}";
var expectedMark = $@"
using System.Collections.Generic;
class Program
{{
void Bar()
{{
List<int> o = new List<int>(){commitChar}
}}
}}";
await VerifyProviderCommitAsync(markup, "List<int>", expectedMark, commitChar: commitChar);
}
[Fact]
public async Task CreateGenericListAsFieldAndCommitWithSemicolon()
{
var markup = @"
using System.Collections.Generic;
class Program
{
private List<int> o = new $$
}";
var expectedMark = @"
using System.Collections.Generic;
class Program
{
private List<int> o = new List<int>();
}";
await VerifyProviderCommitAsync(markup, "List<int>", expectedMark, commitChar: ';');
}
private static string MakeMarkup(string source, string languageVersion = "Preview")
{
return $$"""
<Workspace>
<Project Language="C#" AssemblyName="Assembly" CommonReferencesNet6="true" LanguageVersion="{{languageVersion}}">
<Document FilePath="Test.cs">
{{source}}
</Document>
</Project>
</Workspace>
""";
}
}
|