From d86866cc7d92696720456be7b075aab309699faa Mon Sep 17 00:00:00 2001 From: Charles Stoner <chucks@microsoft.com> Date: Thu, 20 Oct 2016 10:42:02 -0700 Subject: [PATCH] Add SymbolDisplayMemberOptions.IncludeRef option to include `ref` keyword for ref-returning members --- .../SymbolDisplayVisitor.Members.cs | 19 +- .../SymbolDisplayVisitor.Types.cs | 5 +- .../SymbolDisplay/SymbolDisplayTests.cs | 230 +++++++++++++++++- .../Core/Portable/PublicAPI.Unshipped.txt | 1 + .../SymbolDisplay/SymbolDisplayFormat.cs | 3 +- .../SymbolDisplayMemberOptions.cs | 5 + .../SymbolDisplay/SymbolDisplayTests.vb | 196 ++++++++++++++- 7 files changed, 436 insertions(+), 23 deletions(-) diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs index e24c737043a7c..a68c0f89c6215 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Members.cs @@ -60,10 +60,9 @@ public override void VisitProperty(IPropertySymbol symbol) if (format.MemberOptions.IncludesOption(SymbolDisplayMemberOptions.IncludeType)) { - var property = symbol as PropertySymbol; - if (property != null) + if (symbol.ReturnsByRef) { - AddRefKindIfRequired(property.RefKind); + AddRefIfRequired(); } symbol.Type.Accept(this.NotFirstVisitor); @@ -232,10 +231,9 @@ public override void VisitMethod(IMethodSymbol symbol) // to visualize a symbol *during its construction*, the parameters and return type might // still be null. - var method = symbol as MethodSymbol; - if (method != null) + if (symbol.ReturnsByRef) { - AddRefKindIfRequired(method.RefKind); + AddRefIfRequired(); } if (symbol.ReturnsVoid) @@ -718,6 +716,15 @@ private void AddCustomModifiersIfRequired(ImmutableArray<CustomModifier> customM } } + private void AddRefIfRequired() + { + if (format.MemberOptions.IncludesOption(SymbolDisplayMemberOptions.IncludeRef)) + { + AddKeyword(SyntaxKind.RefKeyword); + AddSpace(); + } + } + private void AddRefKindIfRequired(RefKind refKind) { if (format.ParameterOptions.IncludesOption(SymbolDisplayParameterOptions.IncludeParamsRefOut)) diff --git a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs index 3fcf374e7402b..c1901b84b019e 100644 --- a/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs +++ b/src/Compilers/CSharp/Portable/SymbolDisplay/SymbolDisplayVisitor.Types.cs @@ -178,10 +178,9 @@ public override void VisitNamedType(INamedTypeSymbol symbol) if (format.DelegateStyle == SymbolDisplayDelegateStyle.NameAndSignature) { var invokeMethod = symbol.DelegateInvokeMethod; - var invokeMethodSymbol = invokeMethod as MethodSymbol; - if (invokeMethodSymbol != null) + if (invokeMethod.ReturnsByRef) { - AddRefKindIfRequired(invokeMethodSymbol.RefKind); + AddRefIfRequired(); } if (invokeMethod.ReturnsVoid) diff --git a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs index 68daf63c361e2..e297472439a4d 100644 --- a/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/SymbolDisplay/SymbolDisplayTests.cs @@ -2115,6 +2115,49 @@ void M(ref short s, int i, params string[] args) { } } SymbolDisplayPartKind.Space, SymbolDisplayPartKind.ParameterName, //args SymbolDisplayPartKind.Punctuation); + + // Without SymbolDisplayParameterOptions.IncludeParamsRefOut. + TestSymbolDescription( + text, + findSymbol, + format.WithParameterOptions(SymbolDisplayParameterOptions.IncludeType | SymbolDisplayParameterOptions.IncludeName), + "M(Int16 s, Int32 i, String[] args)", + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.StructName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.StructName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation); + + // Without SymbolDisplayParameterOptions.IncludeType, drops + // ref/out/params modifiers. (VB retains ByRef/ParamArray.) + TestSymbolDescription( + text, + findSymbol, + format.WithParameterOptions(SymbolDisplayParameterOptions.IncludeParamsRefOut | SymbolDisplayParameterOptions.IncludeName), + "M(s, i, args)", + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation); } [Fact()] @@ -2887,12 +2930,7 @@ private static void Verify(ImmutableArray<SymbolDisplayPart> actualParts, string Assert.Equal(expectedText, actualParts.ToDisplayString()); if (expectedKinds.Length > 0) { - for (int i = 0; i < Math.Min(expectedKinds.Length, actualParts.Length); i++) - { - Assert.Equal(expectedKinds[i], actualParts[i].Kind); - } - - Assert.Equal(expectedKinds.Length, actualParts.Length); + AssertEx.Equal(expectedKinds, actualParts.Select(p => p.Kind), itemInspector: p => $"SymbolDisplayPartKind.{p}"); } } @@ -4157,7 +4195,6 @@ class C SymbolDisplayPartKind.EventName); } - [WorkItem(765287, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/765287")] [Fact] public void TestVbSymbols() @@ -5184,6 +5221,185 @@ public void DisplayFakeTupleTypeSymbol() SymbolDisplayPartKind.Punctuation); } + [WorkItem(11356, "https://github.com/dotnet/roslyn/issues/11356")] + [Fact] + public void RefReturn() + { + var sourceA = +@"public delegate ref int D(); +public class C +{ + public ref int F(ref int i) => ref i; + int _p; + public ref int P => ref _p; + public ref int this[int i] => ref _p; +}"; + var compA = CreateCompilationWithMscorlib(sourceA); + compA.VerifyDiagnostics(); + var refA = compA.EmitToImageReference(); + // From C# symbols. + RefReturnInternal(compA); + + var compB = CreateVisualBasicCompilation(GetUniqueName(), "", referencedAssemblies: new[] { MscorlibRef, refA }); + compB.VerifyDiagnostics(); + // From VB symbols. + RefReturnInternal(compB); + } + + private static void RefReturnInternal(Compilation comp) + { + var formatBase = new SymbolDisplayFormat( + memberOptions: SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeType, + parameterOptions: SymbolDisplayParameterOptions.IncludeType | SymbolDisplayParameterOptions.IncludeParamsRefOut, + propertyStyle: SymbolDisplayPropertyStyle.ShowReadWriteDescriptor, + delegateStyle: SymbolDisplayDelegateStyle.NameAndSignature, + miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes); + var formatWithoutRef = formatBase.WithMemberOptions( + SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeType); + var formatWithRef = formatBase.WithMemberOptions( + SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeType | SymbolDisplayMemberOptions.IncludeRef); + var formatWithoutTypeWithRef = formatBase.WithMemberOptions( + SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeRef); + + var global = comp.GlobalNamespace; + var type = global.GetTypeMembers("C").Single(); + var method = type.GetMembers("F").Single(); + var property = type.GetMembers("P").Single(); + var indexer = type.GetMembers().Where(m => m.Kind == SymbolKind.Property && ((IPropertySymbol)m).IsIndexer).Single(); + var @delegate = global.GetTypeMembers("D").Single(); + + // Method without IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts(method, formatWithoutRef), + "int F(ref int)", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation); + + // Property without IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts(property, formatWithoutRef), + "int P { get; }", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.PropertyName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation); + + // Indexer without IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts(indexer, formatWithoutRef), + "int this[int] { get; }", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation); + + // Delegate without IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts(@delegate, formatWithoutRef), + "int D()", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.DelegateName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Punctuation); + + // Method with IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts(method, formatWithRef), + "ref int F(ref int)", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation); + + // Property with IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts(property, formatWithRef), + "ref int P { get; }", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.PropertyName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation); + + // Indexer with IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts(indexer, formatWithRef), + "ref int this[int] { get; }", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Punctuation); + + // Delegate with IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts(@delegate, formatWithRef), + "ref int D()", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.DelegateName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Punctuation); + + // Method without IncludeType, with IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts(method, formatWithoutTypeWithRef), + "F(ref int)", + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation); + } + [WorkItem(5002, "https://github.com/dotnet/roslyn/issues/5002")] [Fact] public void AliasInSpeculativeSemanticModel() diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 7a613be26136a..27ec7f201e4a8 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -710,6 +710,7 @@ Microsoft.CodeAnalysis.Semantics.UnaryOperationKind.UnsignedPrefixIncrement = 77 Microsoft.CodeAnalysis.SymbolDisplayFormat.RemoveGenericsOptions(Microsoft.CodeAnalysis.SymbolDisplayGenericsOptions options) -> Microsoft.CodeAnalysis.SymbolDisplayFormat Microsoft.CodeAnalysis.SymbolDisplayFormat.RemoveLocalOptions(Microsoft.CodeAnalysis.SymbolDisplayLocalOptions options) -> Microsoft.CodeAnalysis.SymbolDisplayFormat Microsoft.CodeAnalysis.SymbolDisplayFormat.RemoveMiscellaneousOptions(Microsoft.CodeAnalysis.SymbolDisplayMiscellaneousOptions options) -> Microsoft.CodeAnalysis.SymbolDisplayFormat +Microsoft.CodeAnalysis.SymbolDisplayMemberOptions.IncludeRef = 128 -> Microsoft.CodeAnalysis.SymbolDisplayMemberOptions Microsoft.CodeAnalysis.Text.SourceText.CanBeEmbedded.get -> bool Microsoft.CodeAnalysis.Text.SourceText.GetChecksum() -> System.Collections.Immutable.ImmutableArray<byte> abstract Microsoft.CodeAnalysis.CompilationOptions.Language.get -> string diff --git a/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayFormat.cs b/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayFormat.cs index 5244ef770c356..983677590b321 100644 --- a/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayFormat.cs +++ b/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayFormat.cs @@ -168,6 +168,7 @@ public class SymbolDisplayFormat SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeContainingType | SymbolDisplayMemberOptions.IncludeType | + SymbolDisplayMemberOptions.IncludeRef | SymbolDisplayMemberOptions.IncludeExplicitInterface, kindOptions: SymbolDisplayKindOptions.IncludeMemberKeyword, @@ -224,7 +225,7 @@ public class SymbolDisplayFormat new SymbolDisplayFormat( globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted, typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, - memberOptions: SymbolDisplayMemberOptions.IncludeContainingType | SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeType, + memberOptions: SymbolDisplayMemberOptions.IncludeContainingType | SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeType | SymbolDisplayMemberOptions.IncludeRef, kindOptions: SymbolDisplayKindOptions.IncludeMemberKeyword, genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters, parameterOptions: SymbolDisplayParameterOptions.IncludeParamsRefOut | SymbolDisplayParameterOptions.IncludeType, diff --git a/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayMemberOptions.cs b/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayMemberOptions.cs index 6843a4f112d98..176567a0b864d 100644 --- a/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayMemberOptions.cs +++ b/src/Compilers/Core/Portable/SymbolDisplay/SymbolDisplayMemberOptions.cs @@ -65,5 +65,10 @@ public enum SymbolDisplayMemberOptions /// Includes the value of the member if is a constant. /// </summary> IncludeConstantValue = 1 << 6, + + /// <summary> + /// Includes the <c>ref</c> keyword for ref-returning methods and properties/indexers. C# only. + /// </summary> + IncludeRef = 1 << 7, } } diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolDisplay/SymbolDisplayTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolDisplay/SymbolDisplayTests.vb index 0b455250baf65..be29af2bb8e63 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolDisplay/SymbolDisplayTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolDisplay/SymbolDisplayTests.vb @@ -6,7 +6,6 @@ Imports System.Threading Imports System.Xml.Linq Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis.Test.Utilities -Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax @@ -3092,7 +3091,6 @@ End Class findSymbol, format, "M(ByRef s As Int16, i As Int32, ParamArray args As String())", - { SymbolDisplayPartKind.MethodName, SymbolDisplayPartKind.Punctuation, SymbolDisplayPartKind.Keyword, @@ -3120,7 +3118,59 @@ End Class SymbolDisplayPartKind.ClassName, SymbolDisplayPartKind.Punctuation, SymbolDisplayPartKind.Punctuation, - SymbolDisplayPartKind.Punctuation}) + SymbolDisplayPartKind.Punctuation) + + ' Without SymbolDisplayParameterOptions.IncludeParamsRefOut. + TestSymbolDescription( + text, + findSymbol, + format.WithParameterOptions(SymbolDisplayParameterOptions.IncludeType Or SymbolDisplayParameterOptions.IncludeName), + "M(s As Int16, i As Int32, args As String())", + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.StructName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.StructName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ClassName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Punctuation) + + ' Without SymbolDisplayParameterOptions.IncludeType. + TestSymbolDescription( + text, + findSymbol, + format.WithParameterOptions(SymbolDisplayParameterOptions.IncludeParamsRefOut Or SymbolDisplayParameterOptions.IncludeName), + "M(ByRef s, i, ParamArray args)", + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.ParameterName, + SymbolDisplayPartKind.Punctuation) End Sub ' "Public" and "MustOverride" should not be included for interface members. @@ -4603,6 +4653,140 @@ class Outer Assert.Equal(Nothing, SymbolDisplay.FormatPrimitive(New Object(), quoteStrings:=False, useHexadecimalNumbers:=False)) End Sub + ' SymbolDisplayMemberOptions.IncludeRef is ignored in VB. + <WorkItem(11356, "https://github.com/dotnet/roslyn/issues/11356")> + <Fact()> + Public Sub RefReturn() + Dim sourceA = +"public delegate ref int D(); +public class C +{ + public ref int F(ref int i) => ref i; + int _p; + public ref int P => ref _p; + public ref int this[int i] => ref _p; +}" + Dim compA = CreateCSharpCompilation(GetUniqueName(), sourceA) + compA.VerifyDiagnostics() + Dim refA = compA.EmitToImageReference() + ' From C# symbols. + RefReturnInternal(compA) + + Dim sourceB = + <compilation> + <file name="b.vb"> + </file> + </compilation> + Dim compB = CompilationUtils.CreateCompilationWithMscorlib(sourceB, references:={refA}) + compB.VerifyDiagnostics() + ' From VB symbols. + RefReturnInternal(compB) + End Sub + + Private Shared Sub RefReturnInternal(comp As Compilation) + Dim formatWithRef = New SymbolDisplayFormat( + memberOptions:=SymbolDisplayMemberOptions.IncludeParameters Or SymbolDisplayMemberOptions.IncludeType Or SymbolDisplayMemberOptions.IncludeRef, + parameterOptions:=SymbolDisplayParameterOptions.IncludeType Or SymbolDisplayParameterOptions.IncludeParamsRefOut, + propertyStyle:=SymbolDisplayPropertyStyle.ShowReadWriteDescriptor, + delegateStyle:=SymbolDisplayDelegateStyle.NameAndSignature, + miscellaneousOptions:=SymbolDisplayMiscellaneousOptions.UseSpecialTypes) + + Dim [global] = comp.GlobalNamespace + Dim type = [global].GetTypeMembers("C").Single() + Dim method = type.GetMembers("F").Single() + Dim [property] = type.GetMembers("P").Single() + Dim indexer = type.GetMembers().Where(Function(m) m.Kind = SymbolKind.Property AndAlso DirectCast(m, IPropertySymbol).IsIndexer).Single() + Dim [delegate] = [global].GetTypeMembers("D").Single() + + ' Method with IncludeRef. + ' https://github.com/dotnet/roslyn/issues/14683: missing ByRef for C# parameters. + If comp.Language = "C#" Then + Verify( + SymbolDisplay.ToDisplayParts(method, formatWithRef), + "F(Integer) As Integer", + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword) + Else + Verify( + SymbolDisplay.ToDisplayParts(method, formatWithRef), + "F(ByRef Integer) As Integer", + SymbolDisplayPartKind.MethodName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword) + End If + + ' Property with IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts([property], formatWithRef), + "ReadOnly P As Integer", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.PropertyName, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword) + + ' Indexer with IncludeRef. + ' https://github.com/dotnet/roslyn/issues/14684: "this[]" for C# indexer. + If comp.Language = "C#" Then + Verify( + SymbolDisplay.ToDisplayParts(indexer, formatWithRef), + "ReadOnly this[](Integer) As Integer", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.PropertyName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword) + Else + Verify( + SymbolDisplay.ToDisplayParts(indexer, formatWithRef), + "ReadOnly Item(Integer) As Integer", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.PropertyName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword) + End If + + ' Delegate with IncludeRef. + Verify( + SymbolDisplay.ToDisplayParts([delegate], formatWithRef), + "Function D() As Integer", + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.DelegateName, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Punctuation, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword, + SymbolDisplayPartKind.Space, + SymbolDisplayPartKind.Keyword) + End Sub + <Fact> Public Sub AliasInSpeculativeSemanticModel() Dim text = @@ -4641,7 +4825,7 @@ End Class") #Region "Helpers" - Private Sub TestSymbolDescription( + Private Shared Sub TestSymbolDescription( text As XElement, findSymbol As Func(Of NamespaceSymbol, Symbol), format As SymbolDisplayFormat, @@ -4685,7 +4869,7 @@ End Class") Verify(description, expectedText, kinds) End Sub - Private Sub TestSymbolDescription( + Private Shared Sub TestSymbolDescription( text As XElement, findSymbol As Func(Of NamespaceSymbol, Symbol), format As SymbolDisplayFormat, @@ -4712,7 +4896,7 @@ End Class") Assert.Equal(expectedText, parts.ToDisplayString()) If (kinds.Length > 0) Then - AssertEx.Equal(kinds, parts.Select(Function(d) d.Kind)) + AssertEx.Equal(kinds, parts.Select(Function(p) p.Kind), itemInspector:=Function(p) $"SymbolDisplayPartKind.{p}") End If Return parts