/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/EditorFeatures/CSharpTest/LineSeparators/LineSeparatorTests.cs
524 строки
13 KB
Cyrus Najmabadi
Make tests synchronous
08 июл 2025, 22:11
08 июл 2025, 22:11
542bfda
Код
Авторство
О чём код?
// 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.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.LineSeparators; using Microsoft.CodeAnalysis.LineSeparators; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.LineSeparators; [UseExportProvider] [Trait(Traits.Feature, Traits.Features.LineSeparators)] public sealed class LineSeparatorTests { [Fact] public async Task TestEmptyFile() => await AssertTagsOnBracesOrSemicolonsAsync(contents: string.Empty); [Fact] public Task TestEmptyClass() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { } """, 0); [Fact] public Task TestClassWithOneMethod() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { void M() { } } """, 1); [Fact] public Task TestClassWithTwoMethods() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { void M() { } void N() { } } """, 0, 2); [Fact] public Task TestClassWithTwoNonEmptyMethods() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { void M() { N(); } void N() { M(); } } """, 1, 4); [Fact] public Task TestClassWithMethodAndField() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { void M() { } int field; } """, 0, 2); [Fact] public Task TestEmptyNamespace() => AssertTagsOnBracesOrSemicolonsAsync(""" namespace N { } """, 0); [Fact] public Task TestNamespaceAndClass() => AssertTagsOnBracesOrSemicolonsAsync(""" namespace N { class C { } } """, 1); [Fact] public Task TestNamespaceAndTwoClasses() => AssertTagsOnBracesOrSemicolonsAsync(""" namespace N { class C { } class D { } } """, 0, 2); [Fact] public Task TestNamespaceAndTwoClassesAndDelegate() => AssertTagsOnBracesOrSemicolonsAsync(""" namespace N { class C { } class D { } delegate void Del(); } """, 0, 1, 3); [Fact] public Task TestNestedClass() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { class N { } } """, 1); [Fact] public Task TestTwoNestedClasses() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { class N { } class N2 { } } """, 0, 2); [Fact] public Task TestStruct() => AssertTagsOnBracesOrSemicolonsAsync(""" struct S { } """, 0); [Fact] public Task TestInterface() => AssertTagsOnBracesOrSemicolonsAsync(""" interface I { } """, 0); [Fact] public Task TestEnum() => AssertTagsOnBracesOrSemicolonsAsync(""" enum E { } """, 0); [Fact] public Task TestProperty() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { int Prop { get { return 0; } set { } } } """, 4); [Fact] public Task TestPropertyAndField() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { int Prop { get { return 0; } set { } } int field; } """, 3, 5); [Fact] public Task TestClassWithFieldAndMethod() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { int field; void M() { } } """, 0, 2); [Fact] public Task UsingDirective() => AssertTagsOnBracesOrSemicolonsAsync(""" using System; class C { } """, 0, 1); [Fact] public Task UsingDirectiveInNamespace() => AssertTagsOnBracesOrSemicolonsAsync(""" namespace N { using System; class C { } } """, 0, 2); [Fact] public Task UsingDirectiveInFileScopedNamespace() => AssertTagsOnBracesOrSemicolonsAsync(""" namespace N; using System; class C { } """, 1); [Fact] public Task PropertyStyleEventDeclaration() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { event EventHandler E { add { } remove { } } int i; } """, 2, 4); [Fact] public Task IndexerDeclaration() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { int this[int i] { get { return i; } set { } } int i; } """, 3, 5); [Fact] public Task Constructor() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { C() { } int i; } """, 0, 2); [Fact] public Task Destructor() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { ~C() { } int i; } """, 0, 2); [Fact] public Task Operator() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { static C operator +(C lhs, C rhs) { } int i; } """, 0, 2); [Fact] public Task ConversionOperator() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { static implicit operator C(int i) { } int i; } """, 0, 2); [Fact] public Task Bug930292() => AssertTagsOnBracesOrSemicolonsAsync(""" class Program { void A() { } void B() { } void C() { } void D() { } } """, 4); [Fact] public Task Bug930289() => AssertTagsOnBracesOrSemicolonsAsync(""" namespace Roslyn.Compilers.CSharp { internal struct ArrayElement<T> { internal T Value; internal ArrayElement(T value) { this.Value = value; } public static implicit operator ArrayElement<T>(T value) { return new ArrayElement<T>(value); } } } """, 6); [Fact] public Task TestConsoleApp() => AssertTagsOnBracesOrSemicolonsAsync(""" using System; using System.Collections.Generic; using System.Linq; class Program { static void Main(string[] args) { } } """, 2, 4); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/1297")] public Task ExpressionBodiedProperty() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { int Prop => 3; void M() { } } """, 0, 2); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/1297")] public Task ExpressionBodiedIndexer() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { int this[int i] => 3; void M() { } } """, 0, 2); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/1297")] public Task ExpressionBodiedEvent() => AssertTagsOnBracesOrSemicolonsAsync(""" class C { event EventHandler MyEvent => 3; void M() { } } """, 3); #region Negative (incomplete) tests [Fact] public async Task IncompleteClass() { await AssertTagsOnBracesOrSemicolonsAsync(@"class C"); await AssertTagsOnBracesOrSemicolonsAsync(@"class C {"); } [Fact] public async Task IncompleteEnum() { await AssertTagsOnBracesOrSemicolonsAsync(@"enum E"); await AssertTagsOnBracesOrSemicolonsAsync(@"enum E {"); } [Fact] public async Task IncompleteMethod() => await AssertTagsOnBracesOrSemicolonsAsync(@"void goo() {"); [Fact] public async Task IncompleteProperty() => await AssertTagsOnBracesOrSemicolonsAsync(@"class C { int P { get; set; void"); [Fact] public async Task IncompleteEvent() { await AssertTagsOnBracesOrSemicolonsAsync(@"public event EventHandler"); await AssertTagsOnBracesOrSemicolonsAsync(@"public event EventHandler {"); } [Fact] public async Task IncompleteIndexer() { await AssertTagsOnBracesOrSemicolonsAsync(@"int this[int i]"); await AssertTagsOnBracesOrSemicolonsAsync(@"int this[int i] {"); } [Fact] public Task IncompleteOperator() => AssertTagsOnBracesOrSemicolonsTokensAsync(@"C operator +(C lhs, C rhs) {", [], Options.Regular); [Fact] public async Task IncompleteConversionOperator() => await AssertTagsOnBracesOrSemicolonsAsync(@"implicit operator C(int i) {"); [Fact] public async Task IncompleteMember() => await AssertTagsOnBracesOrSemicolonsAsync(@"class C { private !C("); #endregion private static async Task AssertTagsOnBracesOrSemicolonsAsync(string contents, params int[] tokenIndices) { await AssertTagsOnBracesOrSemicolonsTokensAsync(contents, tokenIndices); await AssertTagsOnBracesOrSemicolonsTokensAsync(contents, tokenIndices, Options.Script); } private static async Task AssertTagsOnBracesOrSemicolonsTokensAsync(string contents, int[] tokenIndices, CSharpParseOptions? options = null) { using var workspace = EditorTestWorkspace.CreateCSharp(contents, options); var document = workspace.CurrentSolution.GetRequiredDocument(workspace.Documents.First().Id); var root = await document.GetRequiredSyntaxRootAsync(default); var lineSeparatorService = Assert.IsType<CSharpLineSeparatorService>(workspace.Services.GetLanguageServices(LanguageNames.CSharp).GetRequiredService<ILineSeparatorService>()); var spans = await lineSeparatorService.GetLineSeparatorsAsync(document, root.FullSpan, CancellationToken.None); var tokens = root.DescendantTokens().Where(t => t.Kind() is SyntaxKind.CloseBraceToken or SyntaxKind.SemicolonToken); Assert.Equal(tokenIndices.Length, spans.Length); var i = 0; foreach (var span in spans.OrderBy(t => t.Start)) { var expectedToken = tokens.ElementAt(tokenIndices[i]); var expectedSpan = expectedToken.Span; var message = string.Format("Expected to match curly {0} at span {1}. Actual span {2}", tokenIndices[i], expectedSpan, span); Assert.True(expectedSpan == span, message); ++i; } } }