/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/EditorFeatures/CSharpTest/Debugging/ProximityExpressionsGetterTests.cs
817 строк
26 KB
Cyrus Najmabadi
Use raw strings in tests
09 июл 2025, 08:52
09 июл 2025, 08:52
f265dce
Код
Авторство
О чём код?
// 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.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CSharp.Debugging; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Debugging; [UseExportProvider] [Trait(Traits.Feature, Traits.Features.DebuggingProximityExpressions)] public sealed partial class ProximityExpressionsGetterTests { private static string s_lazyTestFileContent; private static string GetTestFileContent() { if (s_lazyTestFileContent == null) { using var stream = typeof(ProximityExpressionsGetterTests).Assembly.GetManifestResourceStream("Debugging/ProximityExpressionsGetterTestFile.cs"); using var reader = new StreamReader(stream, Encoding.UTF8); s_lazyTestFileContent = reader.ReadToEnd(); } return s_lazyTestFileContent; } private static SyntaxTree GetTree() => SyntaxFactory.ParseSyntaxTree(GetTestFileContent()); private static SyntaxTree GetTreeFromCode(string code) => SyntaxFactory.ParseSyntaxTree(code); [Fact] public void TestWithinStatement_1() { var tree = GetTreeFromCode(""" using System; using System.Collections.Generic; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var xx = true; var yy = new List<bool>(); yy.Add(xx?true:false); } } } """); var terms = CSharpProximityExpressionsService.GetProximityExpressions(tree, 245, cancellationToken: default); Assert.NotNull(terms); AssertEx.Equal((string[])["yy", "xx"], terms); } private static async Task TestProximityExpressionGetterAsync( string markup, Func<CSharpProximityExpressionsService, Document, int, Task> continuation) { using var workspace = EditorTestWorkspace.CreateCSharp(markup); var testDocument = workspace.Documents.Single(); var caretPosition = testDocument.CursorPosition.Value; var snapshot = testDocument.GetTextBuffer().CurrentSnapshot; var languageDebugInfo = new CSharpLanguageDebugInfoService(); var document = workspace.CurrentSolution.GetDocument(testDocument.Id); var proximityExpressionsGetter = new CSharpProximityExpressionsService(); await continuation(proximityExpressionsGetter, document, caretPosition); } private static async Task TestTryDoInMainAsync(string body, bool topLevelStatement, params string[] expectedTerms) { string input; if (topLevelStatement) { input = body; } else { input = $$""" class Program { static void Main(string[] args) { {{string.Join(Environment.NewLine, body.ReplaceLineEndings("\n").Split('\n').Select(line => line == "" ? line : $" {line}"))}} } } """; } await TestTryDoAsync(input, expectedTerms); } private static Task TestTryDoAsync(string input, params string[] expectedTerms) => TestProximityExpressionGetterAsync(input, async (getter, document, position) => { var actualTerms = await getter.GetProximityExpressionsAsync(document, position, CancellationToken.None); Assert.True(actualTerms is null or { Count: > 0 }); AssertEx.Equal(expectedTerms, actualTerms ?? Array.Empty<string>()); }); private static Task TestIsValidAsync(string input, string expression, bool expectedValid) => TestProximityExpressionGetterAsync(input, async (getter, semanticSnapshot, position) => { var actualValid = await getter.IsValidAsync(semanticSnapshot, position, expression, CancellationToken.None); Assert.Equal(expectedValid, actualValid); }); [Fact] public async Task TestTryDo1() => await TestTryDoAsync("class Class { void Method() { string local;$$ } }", "local", "this"); [Fact] public async Task TestNoParentToken() => await TestTryDoAsync("$$"); [Fact] public async Task TestIsValid1() => await TestIsValidAsync("class Class { void Method() { string local;$$ } }", "local", true); [Fact] public Task TestIsValidWithDiagnostics() => TestIsValidAsync("class Class { void Method() { string local; } $$}", "local", false); [Fact] public async Task TestIsValidReferencingLocalBeforeDeclaration() => await TestIsValidAsync("class Class { void Method() { $$int i; int j; } }", "j", false); [Fact] public async Task TestIsValidReferencingUndefinedVariable() => await TestIsValidAsync("class Class { void Method() { $$int i; int j; } }", "k", false); [Fact] public async Task TestIsValidNoTypeSymbol() => await TestIsValidAsync("namespace Namespace$$ { }", "goo", false); [Fact] public async Task TestIsValidLocalAfterPosition() => await TestIsValidAsync("class Class { void Method() { $$ int i; string local; } }", "local", false); [Fact] public Task TestThis() => TestTryDoAsync(""" class Class { public Class() : this(true) { base.ToString(); this.ToString()$$; } } """, "this"); [Theory, CombinatorialData] public async Task TestArrayCreationExpression(bool topLevelStatement) { if (!topLevelStatement) { await TestTryDoAsync(""" class Class { void Method() { int[] i = new int[] { 3 }$$; } } """, "i", "this"); } await TestTryDoInMainAsync(""" int[] i = new int[] { 3 }$$; """, topLevelStatement, "i", "args"); } [Theory, CombinatorialData] public async Task TestPostfixUnaryExpressionSyntax(bool topLevelStatement) { if (!topLevelStatement) { await TestTryDoAsync(""" class Class { void Method() { int i = 3; i++$$; } } """, "i", "this"); } await TestTryDoInMainAsync(""" int i = 3; i++$$; """, topLevelStatement, "i"); } [Theory, CombinatorialData] public async Task TestLabeledStatement(bool topLevelStatement) { if (!topLevelStatement) { await TestTryDoAsync(""" class Class { void Method() { label: int i = 3; label2$$: i++; } } """, "i", "this"); } await TestTryDoInMainAsync(""" label: int i = 3; label2$$: i++; """, topLevelStatement, "i"); } [Theory, CombinatorialData] public Task TestThrowStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" e = new Exception(); thr$$ow e; """, topLevelStatement, "e"); [Theory, CombinatorialData] public Task TestDoStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" do$$ { } while (true); """, topLevelStatement, "args"); [Theory, CombinatorialData] public Task TestLockStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" lock(typeof(Cl$$ass)) { }; """, topLevelStatement, "args"); [Theory, CombinatorialData] public Task TestWhileStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" while(DateTime.Now <$$ DateTime.Now) { }; """, topLevelStatement, "DateTime", "DateTime.Now", "args"); [Theory, CombinatorialData] public Task TestForStatementWithDeclarators(bool topLevelStatement) => TestTryDoInMainAsync(""" for(int i = 0; i < 10; i$$++) { } """, topLevelStatement, "i", "args"); [Theory, CombinatorialData] public Task TestForStatementWithInitializers(bool topLevelStatement) => TestTryDoInMainAsync(""" int i = 0; for(i = 1; i < 10; i$$++) { } """, topLevelStatement, "i"); [Theory, CombinatorialData] public async Task TestUsingStatement(bool topLevelStatement) { if (!topLevelStatement) { await TestTryDoAsync(""" class Class { void Method() { using (FileStream fs = new FileStream($$)) { } } } """, "this"); } await TestTryDoInMainAsync(""" using (FileStream fs = new FileStream($$)) { } """, topLevelStatement, "args"); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538879")] public Task TestValueInPropertySetter() => TestTryDoAsync(""" class Class { string Name { get { return ""; } set { $$ } } } """, "this", "value"); [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/48504")] public Task TestValueInPropertyInit() => TestTryDoAsync(""" class Class { string Name { get { return ""; } init { $$ } } } """, "this", "value"); [Fact] public Task TestValueInEventAdd() => TestTryDoAsync(""" class Class { event Action Event { add { $$ } set { } } } """, "this", "value"); [Fact] public Task TestValueInEventRemove() => TestTryDoAsync(""" class Class { event Action Event { add { } remove { $$ } } } """, "this", "value"); [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538880")] public Task TestValueInIndexerSetter() => TestTryDoAsync(""" class Class { string this[int index] { get { return ""; } set { $$ } } } """, "index", "this", "value"); [Theory, CombinatorialData] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538881")] public async Task TestCatchBlock(bool topLevelStatement) { if (!topLevelStatement) { await TestTryDoAsync(""" class Class { void Method() { try { } catch(Exception ex) { int $$ } } } """, "ex", "this"); } await TestTryDoInMainAsync(""" try { } catch(Exception ex) { int $$ } """, topLevelStatement, "ex"); } [Theory, CombinatorialData] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538881")] public async Task TestCatchBlockEmpty_OpenBrace(bool topLevelStatement) { if (!topLevelStatement) { await TestTryDoAsync(""" class Class { void Method() { try { } catch(Exception ex) { $$ } } } """, "ex", "this"); } await TestTryDoInMainAsync(""" try { } catch(Exception ex) { $$ } """, topLevelStatement, "ex"); } [Theory, CombinatorialData] public async Task TestCatchBlockEmpty_CloseBrace(bool topLevelStatement) { if (!topLevelStatement) { await TestTryDoAsync(""" class Class { void Method() { try { } catch(Exception ex) { } $$ } } """, "this"); } await TestTryDoInMainAsync(""" try { } catch(Exception ex) { } $$ """, topLevelStatement); } [Theory, CombinatorialData] [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538874")] public async Task TestObjectCreation(bool topLevelStatement) { if (!topLevelStatement) { await TestTryDoAsync(""" class Class { void Method() { $$Goo(new Bar(a).Baz); } } """, "a", "new Bar(a).Baz", "Goo", "this"); } await TestTryDoInMainAsync(""" $$Goo(new Bar(a).Baz); """, topLevelStatement, "a", "new Bar(a).Baz", "Goo", "args"); } [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538874")] public Task Test2() => TestIsValidAsync(""" class D { private static int x; } class Class { void Method() { $$Goo(D.x); } } """, "D.x", false); [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538890")] public Task TestArrayCreation() => TestTryDoAsync(""" class Class { int a; void Method() { $$new int[] { a }; } } """, "this"); [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/751141")] public Task Bug751141() => TestTryDoAsync(""" class Program { double m_double = 1.1; static void Main(string[] args) { new Program().M(); } void M() { int local_int = (int)m_double; $$System.Diagnostics.Debugger.Break(); } } """, "System.Diagnostics.Debugger", "local_int", "m_double", "(int)m_double", "this"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ForLoopExpressionsInFirstStatementOfLoop1(bool topLevelStatement) => TestTryDoInMainAsync(""" for(int i = 0; i < 5; i++) { $$var x = 8; } """, topLevelStatement, "i", "x"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ForLoopExpressionsInFirstStatementOfLoop2(bool topLevelStatement) => TestTryDoInMainAsync(""" int i = 0, j = 0, k = 0, m = 0, n = 0; for(i = 0; j < 5; k++) { $$m = 8; n = 7; } """, topLevelStatement, "m", "i", "j", "k"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ForLoopExpressionsInFirstStatementOfLoop3(bool topLevelStatement) => TestTryDoInMainAsync(""" int i = 0, j = 0, k = 0, m = 0; for(i = 0; j < 5; k++) { var m = 8; $$var n = 7; } """, topLevelStatement, "m", "n"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ForLoopExpressionsInFirstStatementOfLoop4(bool topLevelStatement) => TestTryDoInMainAsync(""" int i = 0, j = 0, k = 0, m = 0; for(i = 0; j < 5; k++) $$m = 8; """, topLevelStatement, "m", "i", "j", "k"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ForEachLoopExpressionsInFirstStatementOfLoop1(bool topLevelStatement) => TestTryDoInMainAsync(""" foreach (var x in new int[] { 1, 2, 3 }) { $$var z = 0; } """, topLevelStatement, "x", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ForEachLoopExpressionsInFirstStatementOfLoop2(bool topLevelStatement) => TestTryDoInMainAsync(""" foreach (var x in new int[] { 1, 2, 3 }) $$var z = 0; """, topLevelStatement, "x", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterForLoop1(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0; for (a = 5; b < 1; b++) { c = 8; d = 9; // included } $$var z = 0; """, topLevelStatement, "a", "b", "d", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterForLoop2(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0; for (a = 5; b < 1; b++) { c = 8; int d = 9; // not included } $$var z = 0; """, topLevelStatement, "a", "b", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterForEachLoop(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0; foreach (var q in new int[] {1, 2, 3}) { c = 8; d = 9; // included } $$var z = 0; """, topLevelStatement, "q", "d", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterNestedForLoop(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; for (a = 5; b < 1; b++) { c = 8; d = 9; for (a = 7; b < 9; b--) { e = 8; f = 10; // included } } $$var z = 0; """, topLevelStatement, "a", "b", "f", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterCheckedStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; checked { a = 7; b = 0; // included } $$var z = 0; """, topLevelStatement, "b", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterUncheckedStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; unchecked { a = 7; b = 0; // included } $$var z = 0; """, topLevelStatement, "b", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterIfStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; if (a == 0) { c = 8; d = 9; // included } $$var z = 0; """, topLevelStatement, "a", "d", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterIfStatementWithElse(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; if (a == 0) { c = 8; d = 9; // included } else { e = 1; f = 2; // included } $$var z = 0; """, topLevelStatement, "a", "d", "f", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterLockStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; lock (new object()) { a = 2; b = 3; // included } $$var z = 0; """, topLevelStatement, "b", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterSwitchStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0; switch(a) { case 1: b = 7; c = 8; // included break; case 2: d = 9; e = 10; // included break; default: f = 1; g = 2; // included break; } $$var z = 0; """, topLevelStatement, "a", "c", "e", "g", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterTryStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0; try { a = 2; b = 3; // included } catch (System.DivideByZeroException) { c = 2; d = 5; // included } catch (System.EntryPointNotFoundException) { e = 8; f = 9; // included } $$var z = 0; """, topLevelStatement, "b", "d", "f", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterTryStatementWithFinally(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0; try { a = 2; b = 3; } catch (System.DivideByZeroException) { c = 2; d = 5; } catch (System.EntryPointNotFoundException) { e = 8; f = 9; } finally { g = 2; // included } $$var z = 0; """, topLevelStatement, "g", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterUsingStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0; using (null as System.IDisposable) { a = 4; b = 8; // Included } $$var z = 0; """, topLevelStatement, "b", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData] public Task ExpressionsAfterWhileStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0; while (a < 5) { a++; b = 8; // Included } $$var z = 0; """, topLevelStatement, "a", "b", "z"); [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/778215"), CombinatorialData] public Task ExpressionsInParenthesizedExpressions(bool topLevelStatement) => TestTryDoInMainAsync(""" int i = 0, j = 0, k = 0, m = 0; int flags = 7; if((flags & i) == k) { $$ m = 8; } """, topLevelStatement, "m", "flags", "i", "k"); [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/58337"), CombinatorialData] public Task ExpressionsInTopLevelStatement(bool topLevelStatement) => TestTryDoInMainAsync(""" int a = 1; int b = 2; $$ Console.WriteLine("Hello, World!"); """, topLevelStatement, "Console", "b"); }