/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodBase.cs
206 строк
8 KB
Jason Malinowski
Switch code that was using Assert.True/False as a replacement for .Fail
21 апр 2026, 23:28
21 апр 2026, 23:28
3bf59ba
Код
Авторство
О чём код?
// 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.Diagnostics.CodeAnalysis; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeCleanup; using Microsoft.CodeAnalysis.CodeGeneration; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.ExtractMethod; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.ExtractMethod; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ExtractMethod; [UseExportProvider] public abstract class ExtractMethodBase { protected static async Task ExpectExtractMethodToFailAsync( [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string codeWithMarker, string[] features = null) { ParseOptions parseOptions = null; if (features != null) { var featuresMapped = features.Select(x => KeyValuePair.Create(x, string.Empty)); parseOptions = new CSharpParseOptions().WithFeatures(featuresMapped); } using var workspace = EditorTestWorkspace.CreateCSharp(codeWithMarker, parseOptions: parseOptions); var testDocument = workspace.Documents.First(); var textSpan = testDocument.SelectedSpans.Single(); var treeAfterExtractMethod = await ExtractMethodAsync(workspace, testDocument, succeed: false); } protected static async Task ExpectExtractMethodToFailAsync( [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string codeWithMarker, [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string expected, CSharpParseOptions parseOptions = null) { using var workspace = EditorTestWorkspace.CreateCSharp(codeWithMarker, parseOptions: parseOptions); var testDocument = workspace.Documents.Single(); var subjectBuffer = testDocument.GetTextBuffer(); var tree = await ExtractMethodAsync(workspace, testDocument, succeed: false); using (var edit = subjectBuffer.CreateEdit()) { edit.Replace(0, edit.Snapshot.Length, tree.ToFullString()); edit.Apply(); } if (expected == "") Assert.Fail(subjectBuffer.CurrentSnapshot.GetText()); Assert.Equal(expected, subjectBuffer.CurrentSnapshot.GetText()); } protected static async Task NotSupported_ExtractMethodAsync( [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string codeWithMarker) { using var workspace = EditorTestWorkspace.CreateCSharp(codeWithMarker); Assert.NotNull(await Record.ExceptionAsync(async () => { var testDocument = workspace.Documents.Single(); var tree = await ExtractMethodAsync(workspace, testDocument); })); } protected static async Task TestExtractMethodAsync( [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string codeWithMarker, [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string expected, bool temporaryFailing = false, CSharpParseOptions parseOptions = null, bool localFunction = false) { using var workspace = EditorTestWorkspace.CreateCSharp(codeWithMarker, parseOptions: parseOptions); var testDocument = workspace.Documents.Single(); var subjectBuffer = testDocument.GetTextBuffer(); var tree = await ExtractMethodAsync(workspace, testDocument, localFunction: localFunction); using (var edit = subjectBuffer.CreateEdit()) { edit.Replace(0, edit.Snapshot.Length, tree.ToFullString()); edit.Apply(); } var actual = subjectBuffer.CurrentSnapshot.GetText(); if (temporaryFailing) { Assert.NotEqual(expected, actual); } else { if (expected != "") { AssertEx.EqualOrDiff(expected, actual); } else { // print out the entire diff to make adding tests simpler. Assert.Equal((object)expected, actual); } } } protected static async Task<SyntaxNode> ExtractMethodAsync( EditorTestWorkspace workspace, EditorTestHostDocument testDocument, bool succeed = true, bool localFunction = false) { var document = workspace.CurrentSolution.GetDocument(testDocument.Id); Assert.NotNull(document); var options = new ExtractMethodGenerationOptions() { CodeGenerationOptions = CodeGenerationOptionsProviders.GetDefault(document.Project.Services), CodeCleanupOptions = await document.GetCodeCleanupOptionsAsync(CancellationToken.None), }; var result = await ExtractMethodService.ExtractMethodAsync( document, testDocument.SelectedSpans.Single(), localFunction, options, CancellationToken.None); // If the test expects us to succeed, validate that we did. If it expects us to fail, ensure we either // failed or produced a message the user will have to confirm to continue. if (succeed) { Assert.Equal(succeed, result.Succeeded); } else { Assert.True(!result.Succeeded || result.Reasons.Length > 0); if (!result.Succeeded) return null; } var (doc, _) = await result.GetDocumentAsync(CancellationToken.None); return doc == null ? null : await doc.GetSyntaxRootAsync(); } protected static async Task TestSelectionAsync( [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string codeWithMarker, bool expectedFail = false, CSharpParseOptions parseOptions = null, TextSpan? textSpanOverride = null) { using var workspace = EditorTestWorkspace.CreateCSharp(codeWithMarker, parseOptions: parseOptions); var testDocument = workspace.Documents.Single(); var namedSpans = testDocument.AnnotatedSpans; var document = workspace.CurrentSolution.GetDocument(testDocument.Id); Assert.NotNull(document); var semanticDocument = await SemanticDocument.CreateAsync(document, CancellationToken.None); var validator = new CSharpExtractMethodService.CSharpSelectionValidator(semanticDocument, textSpanOverride ?? namedSpans["b"].Single(), localFunction: false); var (result, status) = await validator.GetValidSelectionAsync(CancellationToken.None); if (expectedFail) { Assert.True(status.Failed || status.Reasons.Length > 0); } else { Assert.True(status.Succeeded); } if (status.Succeeded && namedSpans.TryGetValue("r", out var revisedSpans)) Assert.Equal(revisedSpans.Single(), result.FinalSpan); } protected static async Task IterateAllAsync( [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string code) { using var workspace = EditorTestWorkspace.CreateCSharp(code, CodeAnalysis.CSharp.Test.Utilities.TestOptions.Regular); var document = workspace.CurrentSolution.GetDocument(workspace.Documents.First().Id); Assert.NotNull(document); var semanticDocument = await SemanticDocument.CreateAsync(document, CancellationToken.None); var root = await document.GetSyntaxRootAsync(); var iterator = root.DescendantNodesAndSelf().Cast<SyntaxNode>(); foreach (var node in iterator) { var validator = new CSharpExtractMethodService.CSharpSelectionValidator(semanticDocument, node.Span, localFunction: false); var (_, status) = await validator.GetValidSelectionAsync(CancellationToken.None); // check the obvious case if (node is not ExpressionSyntax && !node.UnderValidContext()) Assert.True(status.Failed); } } }