VB SymbolDisplay.ToDisplayString doesn't use `Optional` keyword when `IncludeDefaultValue` and not `IncludeOptionalBrackets`
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
I use `Microsoft.CodeAnalysis.VisualBasic.SymbolDisplay.ToDisplayString` to generate VB declarations from dll files and xml files in my API docs. I found that the `Optional` keyword is missing when generating optional parameters in method declarations when the `SymbolDisplayParameterOptions.IncludeDefaultValue` flag is set and `SymbolDisplayParameterOptions.IncludeOptionalBrackets` is not set.
I need to display VB declarations with the exactly the same format as Microsoft Learn. To work around this bug, I have to use `ToDisplayParts` and adjust the return value, which is very inconvenient.
**Version Used**:
4.13.0
**Steps to Reproduce**:
Create a VB console project
**VbSymbolDisplayCsOptional.vbproj**
```xml
Exe
VbSymbolDisplayCsOptional
net9.0
```
Edit `Program.vb`
**Program.vb**
```vbnet
Imports System.IO
Imports Microsoft.CodeAnalysis
Imports CS = Microsoft.CodeAnalysis.CSharp
Imports VB = Microsoft.CodeAnalysis.VisualBasic
Module Program
Sub Main()
' Create C# code with optional parameter
Dim csharpCode As String = "
using System;
public class Example
{
public void MethodWithOptional(string required, string str1 = ""default"", int number = 42)
{
Console.WriteLine($""{required}, {str1}, {number}"");
}
}"
' Compile the C# code
Dim compilation = CreateCompilationFromCSharpCode(csharpCode, "OptionalParamExample")
' Get the symbol for the method with optional parameters
Dim exampleClass = compilation.GetTypeByMetadataName("Example")
Dim methodSymbol = exampleClass.GetMembers().OfType(Of IMethodSymbol)().First(Function(m) m.Name = "MethodWithOptional")
' Create a VB symbol display format
Dim format = SymbolDisplayFormat.FullyQualifiedFormat.
WithMemberOptions(
SymbolDisplayMemberOptions.IncludeParameters).
WithParameterOptions(
SymbolDisplayParameterOptions.IncludeName Or
SymbolDisplayParameterOptions.IncludeType Or
SymbolDisplayParameterOptions.IncludeDefaultValue Or
SymbolDisplayParameterOptions.IncludeModifiers)
' Display the symbol using VB SymbolDisplay
Dim formattedSymbol = VB.SymbolDisplay.ToDisplayString(methodSymbol, format)
Console.WriteLine("Method signature in VB format:")
Console.WriteLine(formattedSymbol)
' Also display the parameter info separately for clarity
Console.WriteLine("Parameters:")
For Each parameter In methodSymbol.Parameters
Dim paramStr = VB.SymbolDisplay.ToDisplayString(parameter, format)
Dim hasDefaultValue = parameter.HasExplicitDefaultValue
Console.WriteLine($"- {paramStr} (Optional: {parameter.IsOptional}, Has Default: {hasDefaultValue})")
Next
End Sub
Public Function CreateCompilationFromCSharpCode(
code As String,
name As String,
ParamArray references As MetadataReference()) As Compilation
Dim parserOption As New CS.CSharpParseOptions
Dim syntaxTree = CS.CSharpSyntaxTree.ParseText(code, parserOption)
Return CS.CSharpCompilation.Create(
name,
options:=New CS.CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary,
xmlReferenceResolver:=XmlFileResolver.Default),
syntaxTrees:={syntaxTree},
references:=GetDefaultMetadataReferences().
Concat(If(references, Array.Empty(Of MetadataReference))))
End Function
Private Function GetDefaultMetadataReferences() As IEnumerable(Of MetadataReference)
Dim dirPath = Path.GetDirectoryName(GetType(Object).Assembly.Location)
Return From dll In Directory.EnumerateFiles(dirPath, "*.dll", SearchOption.TopDirectoryOnly)
Select MetadataReference.CreateFromFile(dll)
End Function
End Module
```
Run the project.
**Diagnostic Id**:
N/A
**Expected Behavior**:
The program produces the following output:
```console
Method signature in VB format:
MethodWithOptional(required As String, Optional str1 As String = "default", Optional number As Integer = 42)
Parameters:
- required As String (Optional: False, Has Default: False)
- Optional str1 As String = "default" (Optional: True, Has Default: True)
- Optional number As Integer = 42 (Optional: True, Has Default: True)
```
**Actual Behavior**:
The program produces the following output:
```console
Method signature in VB format:
MethodWithOptional(required As String, str1 As String = "default", number As Integer = 42)
Parameters:
- required As String (Optional: False, Has Default: False)
- str1 As String = "default" (Optional: True, Has Default: True)
- number As Integer = 42 (Optional: True, Has Default: True)
```
Contributor guide
Assessment
This issue has not been assessed yet.