dotnet / docfx

Static site generator for .NET API documentation.
https://dotnet.github.io/docfx/
MIT License
3.94k stars 839 forks source link

fix: `docfx metadata` command throw `ArgumentException` when referencing empty namespace by doc comment #10023

Closed filzrev closed 1 week ago

filzrev commented 1 week ago

This PR intended to fix issue reported at https://github.com/dotnet/docfx/issues/2532#issuecomment-2181542930

Details of problem

docfx metadata command failed with ArgumentException at this line

ArgumentException: An item with the same key has already been added. Key: Root.Datastore
  at bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
  at void Add(TKey key, TValue value)
  at MetadataItem GenerateNestedTocStructure(IEnumerable<KeyValuePair<string, MetadataItem>> namespaces,
     Dictionary<string, ReferenceItem> allReferences) in YamlMetadataResolver.cs:105

This problem is occurred when following conditions are met

  1. Referencing empty namespace with <see cref=""> tag.
  2. Using "namespaceLayout": "nested"
  3. Using "outputFormat": "mref"

What's changed in this PR

This PR changes allReferences.Add logic to allReferences.TryAdd method to skip when key already exists.

For example. When /// <see cref="Root.Datastore"/> comment exists. allReferences contains this information as ReferenceItem (N:Root.Datastore).

Additionally I've added post-process logics to overwrite empty namespace reference. It's required because Empty namespace don't generate HTML page. So <see cref=""/> link is not works for empty namespace.

Test I've manually tested following tests by using DocFxUndefinedReferenceBugDemo content.

  1. docfx metadata command successfully completed.
  2. <see cref="" link to empty namespace is rendered as plain text.
  3. <see cref="" link to other namespace is rendered as normal link.
scott-ainsworth commented 1 week ago

This branch correctly builds both the minimal sample I provided and the original 600+ *.cs files on which I first encountered the crash.

Thanks for the really fast resolution!

R/Scott Ainsworth