Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc

Vlastní dokumentační pravidlo pro GhostDoc

 

Určitě nejsem sám, kdo používá tento prima add-in pro generování kostry dokumentace :-) V tomto příspěvku bych chtěl popsat svoje zkoumání tvorby vlastních “rules”. GhostDoc jako takový má sice “Custom match rules”, ale ty umožňují práci tak maximálně  na základě nějakého regulárního výrazu. Co když ale potřebuji něco mnohem sofistikovanějšího?

V současnosti pracuji na projektu, kde velká část dokumentace vypadá nějak takto (spousta tříd něco dědí nebo implementuje nějaký interface):

        #region IView Members

        /// <summary>

        /// See <see cref="IView.ViewClosing"/>.

        /// </summary>

        [MandatoryEvent]

        public event EventHandler<ViewClosingEventArgs> ViewClosing;

Pokud na to použiji GhostDoc, tak mi vyhledá komentář z interface. Ale to samozřejmě nechci. Absolutně nehodlám mít stejný komentář na více místech (údržba takových komentářů je horor). Obdobné je to s děděním, kdy se chci odkázat na předka a případně jen dopsat informace o tom, co metoda v override přidává nového. Jednou z možností je použít pragmu (abych obešel FxCop warningy) a očekávat, že bagr co bude vytvářet dokumentaci to schrastí z interface (stejně jako v Jave) nebo z předka. Alternativou je právě výše zmiňovaný odkaz z ukázky. Jak tohle naučit GhostDoc? Hned v této fázi přiznávám, že něco takového podle mě v současné verzi GhostDoc nejde, ale dá se tomu alespoň trochu přiblížit. A navíc tenhle článeček není o jednom use-case, ale o tom jak takové pravidlo udělat :-)

Prvním krokem samozřejmě bylo hledání na google. Neuspěl jsem. Další krok bylo studium v Reflectoru :-) a notepadu.

  • Bázová třída každého dokumentačního pravidla je třída Weigelt.GhostDoc.Rule (Weigelt.GhostDoc.Configuration.dll)
  • Seznam všech Rules, které se použijí je v konfiguraci add-inu ("c:\Documents and Settings\<USER>\Data aplikací\Weigelt\GhostDoc for VS2005\Configuration.gdc"). Tato konfigurace je celkem přehledné xml. Je vtipné, že ač se adresář jmenuje 2005, funguje i pro VS2008.
  • Konfigurace obsahuje vždy typ (System.Type) daného pravidla a pak jeho případné konfigurační parametry. To už je nadějné :-)

 

Vytvořil jsem si tedy dll s vlastním pravidlem, podepsal jí a umístil do GACu. Následovala úprava konfigurace – přidání dokumentačního pravidla (buď se dá použít import/export, nebo pro otestování stačí ruční modifikace výše uvedeného konfiguračního souboru).  Po asi 2 hodinách zjišťování, proč se pravidlo někdy načte a někdy ne mi došlo, že dll s definicí předka (Weigelt.GhostDoc.Configuration.dll) v GACu není. Takže šup tam s ní :-) A hotovo. Alpha proof je funkční. Důvod, proč to trvalo tak dlouho je ten, že po každé změně je potřeba restartovat VisualStudio.

Ukázka rozšíření konfigurace:

  <Methods>

    <Rule type="GhostDocRulesProof.TestInheritedMethodRule, GhostDocRulesProof, Version=1.0.0.0, Culture=neutral, PublicKeyToken=978adf348be73c64" id="0a18cd78-6e30-4a10-b044-afb3badb11a7" timestamp="633640841267256251" assembly="">

      <Settings>

        <Setting name="RuleDisplayText" default="CC542D08">

          <string>Inherited documentation (improoved)</string>

        </Setting>

      </Settings>

    </Rule>

  • type je celé jméno typu pravidla.
  • id je guid uvedený v attributu u třídy pravidla (viz níže).
  • timestamp – to netuším, ale okopíroval jsem to z jiného pravidla :-) a pro jistotu zvednul o jedničku (ale nenašel jsem, k čemu se to používá)
  • assembly – tady se jedná o vychytávku, kterou jsem objevil v při hledání reflectorem. Zjednodušeně umožňuje načíst pravidlo i z assembly, která není v GACu. Můžete se mrknout na třídu RuleConfiguration a její metodu Read(). Konkrétně na z ní volanou RuleCollection.Read(). Odsud se volá Rule.CreateInstance(XmlReader), kde se už s tímto attributem pracuje.  Z kódu Rule.CreateInstance(string, string) je jasné, že pokud je attribut uveden a obsahuje něco jiného než prázdný řetězec nebo “Weigelt.GhostDoc.Rules”, hledá se typ v dll s tímto jménem. Attribut by IMHO měl obsahovat relativní cestu od devenv.exe bez koncového “.dll”.
  • Settings pak obsahuje jednotlivé konfigurační parametry pravidla – ukázkové pravidlo má jen jméno, pod kterým se prezentuje v seznamu pravidel.

Ukázka vlastního pravidla:

namespace GhostDocRulesProof

{

    [Description("My describtion"), Rule(DisplayText = "Inherited documentation (improoved)"), SingleInstance("{0a18cd78-6e30-4a10-b044-afb3badb11a7}")]   

    public class TestInheritedMethodRule : MethodRule

    {

        public TestInheritedMethodRule()

        {           

        }

 

        protected override string DoGetSummaryTagText(MethodRuleArgs args)

        {           

            return "Test comment.";

        }

 

        protected override string OnGetParamTagText(MethodRuleArgs args, int index)

        {

            return string.Empty;

        }

 

        protected override string OnGetReturnsTagText(MethodRuleArgs args)

        {

            return string.Empty;

        }

 

        protected override string OnGetTypeParamTagText(MethodRuleArgs args, int index)

        {

            return string.Empty;

        }

 

        protected override bool DoMatch(MethodRuleArgs args)

        {

            if (args.InheritedDocumentation != null)

                return true;

            else

                return false;

        }

    }

  • Klíčový je attribut SingleInstance, kde je uveden GUID stejný jako v konfiguraci.
  • Ukázkové pravidlo je zděděno z MethodRule, ne z obecného Rule. Třída je definována v Weigelt.GhostDoc.Configuration.dll
  • Metoda DoMatch vrací true pokud má být pravidlo použito. Jinak je na řadě další pravidlo atd. Na konci každé řady je vždy Default pravidlo, které zabere na cokoli.

Závěrem

Z implementace plyne, že jsme velmi omezeni obsahem MethodModuleArgs. Neboli co nám GhostDoc nepošle, to nemáme. Informaci o typu bázové třídy nebo o typu implementovaného interface nemáme. A podle reakcí autora GhostDoc ve fóru mám obavu, že na další rozvoj tohoto add-inu budeme muset nějakou dobu čekat - škoda. Nicméně i vygenerování výstupu v následujícím tvaru může ušetřit trochu času (jméno interface se pak už doplní Ctrl+C, Ctrl+V). V souvislosti s tím je možná zajímavý tento link o podpoře <inheritdoc /> v SandCastle.

        /// <summary>

        /// See <see cref="ViewClosing"/>.

        /// </summary>

 

Závěrem2

 

Hmm… na začátek jsem chtěl nějaký článek o složitostech nějaké super moderní technologie, ale nepovedlo se ;-) Tak třeba příště.

Posted by danik | 1 Comments
Vedeno pod:
 
Vyvojar.cz na prodej!