dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.89k stars 4.01k forks source link

GetDocumentationCommentId crashes with ArgumentNullException on VB qualified name in cref with generic parameter #19756

Open twsouthwick opened 7 years ago

twsouthwick commented 7 years ago

Version Used: v2.0

Steps to Reproduce:

[Fact]
public async Task DocumentationCommentIdOfGenericTypeInCref()
{
    var source = @"''' <see cref=""C(Of T).M()"" />
Module Module1
Sub Main()
End Sub
End Module

Class C(Of T)
Sub M()
End Sub
End Class";
    var ws = new AdhocWorkspace();
    var document = ws.CurrentSolution.AddProject("Test", "test", LanguageNames.VisualBasic)
        .AddDocument("doc", source);
    var project = document.Project
        .AddMetadataReference(MetadataReference.CreateFromFile(typeof(string).Assembly.Location))
        .AddMetadataReference(MetadataReference.CreateFromFile(typeof(Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute).Assembly.Location));

    var compilation = await project.GetCompilationAsync();
    var diagnostics = compilation.GetDiagnostics();

    Assert.Empty(diagnostics);

    var tree = await project.GetDocument(document.Id).GetSyntaxTreeAsync();
    var root = await tree.GetRootAsync();
    var semantic = compilation.GetSemanticModel(tree);

    var generic = root.DescendantNodes(t => true, descendIntoTrivia: true)
        .OfType<GenericNameSyntax>()
        .Single();

    var symbol = semantic.GetSymbolInfo(generic).Symbol;
    Assert.NotNull(symbol);

    var docId = symbol.GetDocumentationCommentId();
    Assert.NotNull(docId);
}

Expected Behavior: Retrieve a valid documentation comment

Actual Behavior:

Result StackTrace:  
at Microsoft.CodeAnalysis.VisualBasic.DocumentationCommentIdVisitor.PartVisitor.VisitTypeParameter(TypeParameterSymbol symbol, StringBuilder builder)
   at Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeParameterSymbol.Accept[TArgument,TResult](VisualBasicSymbolVisitor`2 visitor, TArgument arg)
   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSymbolVisitor`2.Visit(Symbol symbol, TArgument arg)
   at Microsoft.CodeAnalysis.VisualBasic.DocumentationCommentIdVisitor.PartVisitor.VisitNamedType(NamedTypeSymbol symbol, StringBuilder builder)
   at Microsoft.CodeAnalysis.VisualBasic.Symbols.NamedTypeSymbol.Accept[TArgument,TResult](VisualBasicSymbolVisitor`2 visitor, TArgument arg)
   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSymbolVisitor`2.Visit(Symbol symbol, TArgument arg)
   at Microsoft.CodeAnalysis.VisualBasic.DocumentationCommentIdVisitor.VisitNamedType(NamedTypeSymbol symbol, StringBuilder builder)
   at Microsoft.CodeAnalysis.VisualBasic.Symbols.NamedTypeSymbol.Accept[TArgument,TResult](VisualBasicSymbolVisitor`2 visitor, TArgument arg)
   at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSymbolVisitor`2.Visit(Symbol symbol, TArgument arg)
   at Microsoft.CodeAnalysis.VisualBasic.Symbol.GetDocumentationCommentId()
jcouv commented 6 years ago

@twsouthwick Thanks for the detailed bug report. I'm able to repro and have a fix pending review.

        <Fact>
        <WorkItem(19756, "https://github.com/dotnet/roslyn/issues/19756")>
        Public Sub Bug()

            Dim comp = CreateCompilationWithMscorlib(
                <compilation name="TypeDocumentationCommentTests">
                    <file name="a.vb"><![CDATA[
''' <see cref="C(Of T).M()" />
Module Module1
End Module

Class C(Of T)
    Sub M()
    End Sub
End Class
                    ]]></file>
                </compilation>)

            Dim tree = comp.SyntaxTrees.Single()
            Dim model = comp.GetSemanticModel(tree)

            Dim generic = tree.GetRoot().
                DescendantNodes(descendIntoChildren:=Function(t) True, descendIntoTrivia:=True).
                OfType(Of GenericNameSyntax)().Single()

            Assert.Equal("C(Of T)", generic.ToString())

            Dim symbol = model.GetSymbolInfo(generic).Symbol
            Dim docId = symbol.GetDocumentationCommentId()
            Assert.NotNull(docId)
        End Sub