diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.FieldSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.FieldSymbols.vb index f80052cf14c7726bdc15341a9173ed227c1a528f..bf782721c94e4aa8abdc8893467350f4c3d8020f 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.FieldSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.FieldSymbols.vb @@ -411,6 +411,41 @@ class Definition:Program ]]> + + Await TestAPIAndFeature(input, kind, host) + End Function + + + Public Async Function TestField_ValueUsageInfo(kind As TestKind, host As TestHost) As Task + Dim input = + + + + class C + { + int {|Definition:$$i|}; + + void Goo() + { + Console.WriteLine({|ValueUsageInfo.Read:[|i|]|}); + {|ValueUsageInfo.Write:[|i|]|} = 0; + {|ValueUsageInfo.ReadWrite:[|i|]|}++; + Goo2(in {|ValueUsageInfo.ReadableReference:[|i|]|}, ref {|ValueUsageInfo.ReadableWritableReference:[|i|]|}); + Goo3(out {|ValueUsageInfo.WritableReference:[|i|]|}); + Console.WriteLine(nameof({|ValueUsageInfo.Name:[|i|]|})); + } + + void Goo2(in int j, ref int k) + { + } + + void Goo3(out int i) + { + i = 0; + } + } + + Await TestAPIAndFeature(input, kind, host) End Function diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.LocalSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.LocalSymbols.vb index cab80c23850902fe2ad2ff8a4fe917da402a5854..23e88a1541035c33066ffadeeeea28166e809622 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.LocalSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.LocalSymbols.vb @@ -541,5 +541,38 @@ End Module Await TestAPIAndFeature(input, kind, host) End Function + + Public Async Function TestLocal_ValueUsageInfo(kind As TestKind, host As TestHost) As Task + Dim input = + + + + class C + { + void Goo() + { + int {|Definition:$$i|} = 0; + Console.WriteLine({|ValueUsageInfo.Read:[|i|]|}); + {|ValueUsageInfo.Write:[|i|]|} = 0; + {|ValueUsageInfo.ReadWrite:[|i|]|}++; + Goo2(in {|ValueUsageInfo.ReadableReference:[|i|]|}, ref {|ValueUsageInfo.ReadableWritableReference:[|i|]|}); + Goo3(out {|ValueUsageInfo.WritableReference:[|i|]|}); + Console.WriteLine(nameof({|ValueUsageInfo.Name:[|i|]|})); + } + + void Goo2(in int j, ref int k) + { + } + + void Goo3(out int i) + { + i = 0; + } + } + + + + Await TestAPIAndFeature(input, kind, host) + End Function End Class End Namespace diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb index c8f33244ab7ae542863ad59b93f5cb173532cd08..904212a4dcbd545e6fa984ce012518d35d2a3427 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb @@ -2189,5 +2189,48 @@ public class D { } End Function + + + + Public Async Function TestNamedType_TypeOrNamespaceUsageInfo(kind As TestKind, host As TestHost) As Task + Dim input = + + + { } + + public class {|Definition:$$Class1|} + { + public static int Field; + public class Nested { } + } + + public class Class2 : {|TypeOrNamespaceUsageInfo.Base:[|Class1|]|}, I<{|TypeOrNamespaceUsageInfo.TypeArgument:[|Class1|]|}> + { + public static int M() => {|TypeOrNamespaceUsageInfo.Qualified:[|Class1|]|}.Field; + } + } + + namespace N2.N3 + { + using Alias2 = N2.{|TypeOrNamespaceUsageInfo.Qualified,Import:[|Class1|]|}.Nested; + + public class Class3: {|TypeOrNamespaceUsageInfo.Qualified,Base:[|Class1|]|}.Nested, I<{|TypeOrNamespaceUsageInfo.Qualified,TypeArgument:[|Class1|]|}.Nested> + { + public static [|Class1|] M2() => new {|TypeOrNamespaceUsageInfo.ObjectCreation:[|Class1|]|}(); + } + }]]> + + + + Await TestAPIAndFeature(input, kind, host) + End Function End Class End Namespace diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamespaceSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamespaceSymbols.vb index 5ef025dfd4f2a1b4fdd47b6f36501a6613d59ae8..429976af4b872536c3da725e0ca07b84006fed84 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamespaceSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamespaceSymbols.vb @@ -372,5 +372,35 @@ namespace var { } Await TestAPIAndFeature(input, kind, host) End Function + + + Public Async Function TestNamespace_TypeOrNamespaceUsageInfo(host As TestHost) As Task + Dim input = + + + + using {|TypeOrNamespaceUsageInfo.Import:[|N1|]|}; + using {|TypeOrNamespaceUsageInfo.Qualified,Import:[|N1|]|}.N2; + + namespace {|Definition:{|TypeOrNamespaceUsageInfo.NamespaceDeclaration:[|$$N1|]|}|} + { + public class Class1 + { + public static int Field; + } + } + + namespace {|TypeOrNamespaceUsageInfo.Qualified,NamespaceDeclaration:[|N1|]|}.N2 + { + public class Class2 + { + public static int M() => {|TypeOrNamespaceUsageInfo.Qualified:[|N1|]|}.Class1.Field; + } + } + + + + Await TestAPI(input, host) + End Function End Class End Namespace diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.ParameterSymbol.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.ParameterSymbol.vb index 07df3ba4e69235081544807a1423f2dd98673632..6cf0778b80dd921e0f922afae6074d2f6a0410d6 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.ParameterSymbol.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.ParameterSymbol.vb @@ -635,6 +635,39 @@ end class } + + Await TestAPIAndFeature(input, kind, host) + End Function + + + Public Async Function TestParameter_ValueUsageInfo(kind As TestKind, host As TestHost) As Task + Dim input = + + + + class C + { + void Goo(int {|Definition:$$i|}) + { + Console.WriteLine({|ValueUsageInfo.Read:[|i|]|}); + {|ValueUsageInfo.Write:[|i|]|} = 0; + {|ValueUsageInfo.ReadWrite:[|i|]|}++; + Goo2(in {|ValueUsageInfo.ReadableReference:[|i|]|}, ref {|ValueUsageInfo.ReadableWritableReference:[|i|]|}); + Goo3(out {|ValueUsageInfo.WritableReference:[|i|]|}); + Console.WriteLine(nameof({|ValueUsageInfo.Name:[|i|]|})); + } + + void Goo2(in int j, ref int k) + { + } + + void Goo3(out int i) + { + i = 0; + } + } + + Await TestAPIAndFeature(input, kind, host) End Function diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb index 2e5a2e4ab3fa142c5b48609251e6042d3a062444..456173ab2826b85bfc6464a6aecf6d8299daab17 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb @@ -912,5 +912,41 @@ interface IC Await TestStreamingFeature(input, host) End Function + + + + Public Async Function TestProperty_ValueUsageInfo(kind As TestKind, host As TestHost) As Task + Dim input = + + + +using System; +namespace ConsoleApplication22 +{ + class Program + { + static public int {|Definition:G$$oo|} + { + get + { + return 1; + } + set + { + } + } + static void Main(string[] args) + { + Console.WriteLine(Program.{|ValueUsageInfo.Read:[|Goo|]|}); + Program.{|ValueUsageInfo.Write:[|Goo|]|} = 0; + Program.{|ValueUsageInfo.ReadWrite:[|Goo|]|} += 1; + } + } +} + + + + Await TestAPIAndFeature(input, kind, host) + End Function End Class End Namespace diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb index d653e02af81823eec008b54b43c6ba348b7922db..2f3ba45357655a7b05cbe985311e5f0e4c8724f2 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb @@ -19,6 +19,8 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences <[UseExportProvider]> Partial Public Class FindReferencesTests Private Const DefinitionKey As String = "Definition" + Private Const ValueUsageInfoKey As String = "ValueUsageInfo." + Private Const TypeOrNamespaceUsageInfoKey As String = "TypeOrNamespaceUsageInfo." Private ReadOnly _outputHelper As ITestOutputHelper @@ -96,6 +98,37 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences context.References.Select(Function(r) r.SourceSpan)) Assert.Equal(expectedReferences, actualReferences) + + Dim valueUsageInfoKeys = workspace.Documents.SelectMany(Function(d) d.AnnotatedSpans.Keys.Where(Function(key) key.StartsWith(ValueUsageInfoKey))) + For Each key In valueUsageInfoKeys + Dim expected = + workspace.Documents.Where(Function(d) d.AnnotatedSpans.ContainsKey(key) AndAlso d.AnnotatedSpans(key).Any()). + OrderBy(Function(d) d.Name). + Select(Function(d) New FileNameAndSpans( + d.Name, d.AnnotatedSpans(key).ToList())).ToList() + Dim valueUsageInfoField = key.Substring(ValueUsageInfoKey.Length) + Dim actual = GetFileNamesAndSpans( + context.References.Where(Function(r) r.SymbolUsageInfo.ValueUsageInfoOpt?.ToString() = valueUsageInfoField).Select(Function(r) r.SourceSpan)) + + Assert.Equal(expected, actual) + Next + + Dim typeOrNamespaceUsageInfoKeys = workspace.Documents.SelectMany(Function(d) d.AnnotatedSpans.Keys.Where(Function(key) key.StartsWith(TypeOrNamespaceUsageInfoKey))) + For Each key In typeOrNamespaceUsageInfoKeys + Dim expected = + workspace.Documents.Where(Function(d) d.AnnotatedSpans.ContainsKey(key) AndAlso d.AnnotatedSpans(key).Any()). + OrderBy(Function(d) d.Name). + Select(Function(d) New FileNameAndSpans( + d.Name, d.AnnotatedSpans(key).ToList())).ToList() + Dim typeOrNamespaceUsageInfoFieldNames = key.Substring(TypeOrNamespaceUsageInfoKey.Length).Split(","c).Select(Function(s) s.Trim) + Dim actual = GetFileNamesAndSpans( + context.References.Where(Function(r) + Return r.SymbolUsageInfo.TypeOrNamespaceUsageInfoOpt IsNot Nothing AndAlso + r.SymbolUsageInfo.TypeOrNamespaceUsageInfoOpt.ToString().Split(","c).Select(Function(s) s.Trim).SetEquals(typeOrNamespaceUsageInfoFieldNames) + End Function).Select(Function(r) r.SourceSpan)) + + Assert.Equal(expected, actual) + Next Next End Using End Function @@ -226,7 +259,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences Assert.Equal(Of String)(documentsWithAnnotatedSpans.Select(Function(d) GetFilePathAndProjectLabel(workspace, d)).Order(), actualDefinitions.Keys.Order()) For Each doc In documentsWithAnnotatedSpans - Dim expected = doc.AnnotatedSpans(DefinitionKey).Order() + Dim expected = If(doc.AnnotatedSpans.ContainsKey(DefinitionKey), doc.AnnotatedSpans(DefinitionKey), ImmutableArray(Of TextSpan).Empty).Order() Dim actual = actualDefinitions(GetFilePathAndProjectLabel(workspace, doc)).Order() If Not TextSpansMatch(expected, actual) Then @@ -234,15 +267,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences End If Next - Dim actualReferences = - result.FilterToItemsToShow(options). - SelectMany(Function(r) r.Locations.Select(Function(loc) loc.Location)). - Where(Function(loc) IsInSource(workspace, loc, uiVisibleOnly)). - Distinct(). - GroupBy(Function(loc) loc.SourceTree). - ToDictionary( - Function(g) GetFilePathAndProjectLabel(document.Project.Solution, g.Key), - Function(g) g.Select(Function(loc) loc.SourceSpan).Distinct().ToList()) + Dim actualReferences = GetActualReferences(result, uiVisibleOnly, options, document, workspace) Dim expectedDocuments = workspace.Documents.Where(Function(d) d.SelectedSpans.Any()) Assert.Equal(expectedDocuments.Select(Function(d) GetFilePathAndProjectLabel(workspace, d)).Order(), actualReferences.Keys.Order()) @@ -254,10 +279,66 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences AssertEx.Equal(expectedSpans, actualSpans, message:=PrintSpans(expectedSpans, actualSpans, workspace.CurrentSolution.GetDocument(doc.Id), "[|", "|]", messageOnly:=True)) Next + + Dim valueUsageInfoKeys = workspace.Documents.SelectMany(Function(d) d.AnnotatedSpans.Keys.Where(Function(key) key.StartsWith(ValueUsageInfoKey))) + For Each key In valueUsageInfoKeys + For Each doc In documentsWithAnnotatedSpans.Where(Function(d) d.AnnotatedSpans.ContainsKey(key)) + + Dim expectedSpans = doc.AnnotatedSpans(key).Order() + + Dim valueUsageInfoField = key.Substring(ValueUsageInfoKey.Length) + actualReferences = GetActualReferences(result, uiVisibleOnly, options, document, workspace, Function(r) r.SymbolUsageInfo.ValueUsageInfoOpt?.ToString() = valueUsageInfoField) + Dim actualSpans = actualReferences(GetFilePathAndProjectLabel(workspace, doc)).Order() + + If Not TextSpansMatch(expectedSpans, actualSpans) Then + Assert.True(False, PrintSpans(expectedSpans, actualSpans, workspace.CurrentSolution.GetDocument(doc.Id), $"{{|{key}:", "|}")) + End If + Next + Next + + Dim typeOrNamespaceUsageInfoKeys = workspace.Documents.SelectMany(Function(d) d.AnnotatedSpans.Keys.Where(Function(key) key.StartsWith(TypeOrNamespaceUsageInfoKey))) + For Each key In typeOrNamespaceUsageInfoKeys + For Each doc In documentsWithAnnotatedSpans.Where(Function(d) d.AnnotatedSpans.ContainsKey(key)) + + Dim expectedSpans = doc.AnnotatedSpans(key).Order() + + Dim typeOrNamespaceUsageInfoFieldNames = key.Substring(TypeOrNamespaceUsageInfoKey.Length).Split(","c).Select(Function(s) s.Trim) + actualReferences = GetActualReferences(result, uiVisibleOnly, options, document, workspace, Function(r) + Return r.SymbolUsageInfo.TypeOrNamespaceUsageInfoOpt IsNot Nothing AndAlso + r.SymbolUsageInfo.TypeOrNamespaceUsageInfoOpt.ToString().Split(","c).Select(Function(s) s.Trim).SetEquals(typeOrNamespaceUsageInfoFieldNames) + End Function) + Dim actualSpans = actualReferences(GetFilePathAndProjectLabel(workspace, doc)).Order() + + If Not TextSpansMatch(expectedSpans, actualSpans) Then + Assert.True(False, PrintSpans(expectedSpans, actualSpans, workspace.CurrentSolution.GetDocument(doc.Id), $"{{|{key}:", "|}")) + End If + Next + Next Next End Using End Function + Private Shared Function GetActualReferences(result As IEnumerable(Of ReferencedSymbol), + uiVisibleOnly As Boolean, + options As FindReferencesSearchOptions, + document As Document, + workspace As TestWorkspace, + Optional locationFilterOpt As Func(Of ReferenceLocation, Boolean) = Nothing) As Dictionary(Of String, List(Of TextSpan)) + Dim referenceLocations = result.FilterToItemsToShow(options).SelectMany(Function(r) r.Locations) + If locationFilterOpt IsNot Nothing Then + referenceLocations = referenceLocations.Where(locationFilterOpt) + End If + + Return referenceLocations. + Select(Function(loc) loc.Location). + Where(Function(loc) IsInSource(workspace, loc, uiVisibleOnly)). + Distinct(). + GroupBy(Function(loc) loc.SourceTree). + ToDictionary( + Function(g) GetFilePathAndProjectLabel(document.Project.Solution, g.Key), + Function(g) g.Select(Function(loc) loc.SourceSpan).Distinct().ToList()) + End Function + Private Shared Function PrintSpans(expected As IOrderedEnumerable(Of TextSpan), actual As IOrderedEnumerable(Of TextSpan), doc As Document, prefix As String, suffix As String, Optional messageOnly As Boolean = False) As String Debug.Assert(expected IsNot Nothing) Debug.Assert(actual IsNot Nothing)