This project is read-only.
4
Vote

Spurious references to parametrized class with inner class

description

REPRODUCE

  1. Create a new Visual C# Console Application project for .NET 3.5 project and use the attached file (Program.cs) as the only code file. Enable doc building (of course) and build.
  2. Create a new Sandcastle Help File Builder 1.7.0.0 (SHFB) project from the above Visual C# project. I set FrameworkVersion="3.5", HelpFileFormat="Website", NamingMethod="MemberName" and left everything else at default.
  3. Build documentation using SHFB. I had sandcastle 2.4.10520 (with SandcastleStyles 2.4.10520 Patch Rev 1) installed.
     
    I realize this means it might be an SHFB bug instead of a sandcastle bug, but this does look like Sandcastle's area of responsibility... Apologies if I'm incorrect.
     
     

SYMPTOM with attached file as is

  • Open the Bar<TQux> class documentation (T_Experiments_Bar_1.htm).
  • Look at the Inheritance Hierarchy.
  • Below object, it says "BarBase<TBaz>".
  • For one, Bar<TQux> inherits BarBase<TQux>, not TBaz.
  • For another, "TBaz" incorrectly links to Foo<TBaz>. But "BarBase<TBaz>" entire should have been one link, the same as "BarBase" is now.
  • The same symptom appears in the Bar class' method summary if Bar overrides a BarBase method. But when it inherits a BarBase method, the link will be correct.
     
     

SYMPTOM when Foo<TBaz> is not included in the documentation (i.e. it is internal)

  • The Bar<TQux> class documentation inheritance list will still show TBaz (but not linked).
  • The log shows
    Warn: ResolveReferenceLinksComponent2: Unknown reference link target 'T:Experiments.Foo`1'.
  • A verbatim snippet from the log:
    Info: BuildAssembler: Building topic T:Experiments.Bar1
    Info: ShowMissingComponent: Auto-documenting constructor M:Experiments.Bar
    1.#ctor
    Warn: ResolveReferenceLinksComponent2: Unknown reference link target 'T:Experiments.Foo1'.
    Info: BuildAssembler: Building topic M:Experiments.Bar
    1.#ctor
     
    This symptom is the one we observed, because we grep for such warnings and break the build if they appear.
     
     

WORKAROUND

Move the inner class out. I.e. its visibility have to change from private to internal, something that isn't all that important, I guess, unless your assembly is big. But it was a fair pain to figure out this bug, so I would love to see it go away :)

file attachments

comments

hanscf wrote Oct 24, 2008 at 3:00 PM

Sorry, I attached that file a little too quick :)
Please reverse when the symptoms happens. I.e. the last symptom (log warning) occur when Program.cs is used as is and the first symptom (incorrect link) occur when you modify it so Foo<TBaz> is public (it was accidentally "internal" in the issue submission instead of "public" as intended).

hanscf wrote Nov 3, 2008 at 9:05 PM

ANOTHER WAY TO PROVOKE THIS BUG

Well, this code doesn't contain an inner class, as the issue title says, but it fair looks much like the same issue... So I'll just comment here instead of opening a new one.

REPRODUCE

As above, but with a Class Library project containing the following code:
namespace SandcastleBug2 {
/// <summary>
/// A parametrized, common base class.
/// </summary> <typeparam name="TBase">The type.</typeparam>
public abstract class Base<TBase> { }
}
namespace SandcastleBug2.Foo {
public class Foo<TFoo> : Base<TFoo> { }
}
namespace SandcastleBug2.Bar {
/// <summary>
/// Inheritance hierarchy will contain a spurious reference to <c>Foo{TFoo}</c>.
/// </summary> <typeparam name="TBar">The type.</typeparam>
public class Bar<TBar> : Base<TBar> { }
}

SYMPTOM with code as is

The Bar<TBar> class documentation's Inheritance Hierarchy has a link to Foo<TFoo> in place of Base's parameter.

SYMPTOM with Foo made internal

Verbatim from the log:
Info: BuildAssembler: Building topic T:SandcastleBug2.Bar.Bar1
Info: ShowMissingComponent: Auto-documenting constructor M:SandcastleBug2.Bar.Bar
1.#ctor
Warn: ResolveReferenceLinksComponent2: Unknown reference link target 'T:SandcastleBug2.Foo.Foo`1'.

WORKAROUND

Well, if you move Foo and Bar to the same namespace, the symptoms disappear. But that's hardly a workaround. You could always hope no one notices the erroneous link in the Inheritance Hierarchy (and overridden methods, if there are any of those), but if you don't want Foo to be public then that's not going to work.

So basically, we haven't found a workaround for this.

wrote Nov 4, 2008 at 3:55 AM

EWoodruff wrote Nov 4, 2008 at 8:19 PM

The problem appears to be in MRefBuilder. If you look at the reflection information file, it outputs the correct base type for the generic class as an ancestor but the specialization type listed within it is the wrong one.

pdohara wrote Jan 20, 2009 at 3:06 PM

Just to throw some more weight behind this, I am also seeing this problem. My case is similar to the second one reported. Hope this finds its way into the work flow.

wrote Jan 20, 2009 at 3:09 PM

wrote Jan 14, 2010 at 4:56 PM

wrote Feb 22, 2013 at 1:40 AM