Doxygen 源码分析: Definition类

在这里插入图片描述

2023-05-21 13:05:28
ChrisZZ imzhuo@foxmailcom
Hompage https://github.com/zchrissirhcz
Blog https://blog.csdn.net/baiyu33

1. Doxygen 版本

本次使用的 doxygen 版本如下, 是 1.9.8 正式发布版本对应的 commit

$ git log
commit 5fded4215d4f9271fe92c940fc4532d4704f5be1 (HEAD -> master, upstream/master)
Author: Dimitri van Heesch <doxygen@gmail.com>
Date:   Thu May 18 22:14:30 2023 +0200
evelopment
bump version to 1.9.8 for d

2. Definition 类和它的8个子类

在这里插入图片描述

Defition 类是抽象基类, 提供了一系列的纯虚函数,并给出了9个 DefType, 其中 TypePackage 没有对应的子类, 其他 DefType 则分别对应一个子类:

DefType 取值解释
TypeClass对应到 ClassDef
TypeFile对应到 FileDef
TypeNamespace对应到 NamespaceDef
TypeMember对应到 MemberDef
TypeGroup对应到 GroupDef
TypePackage没有对应的子类
TypePage对应到 PageDef
TypeDir对应到 DirDef
TypeConcept对应到 ConceptDef
/** The common base class of all entity definitions found in the sources.
 *
 *  This can be a class or a member function, or a file, or a namespace, etc.
 *  Use definitionType() to find which type of definition this is.
 */
class Definition
{
  public:
    /*! Types of derived classes */
    enum DefType
    {
      TypeClass      = 0, // 对应到 ClassDef 类
      TypeFile       = 1, // 对应到 FileDef 类
      TypeNamespace  = 2, // 对应到 NamespaceDef 类
      TypeMember     = 3, // 对应到 MemberDef 类
      TypeGroup      = 4, // 对应到 GroupDef 类
      TypePackage    = 5, // 没有对应的子类
      TypePage       = 6, // 对应到 PageDef 类
      TypeDir        = 7, // 对应到 DirDef 类
      TypeConcept    = 8 // 对应到 ConceptDef 类
    };
    ...
}

而对于每个子类, 仍然是不是最终的实现类, 仍然包含了继承或组合的层次关系:

在这里插入图片描述

  • 红色: 代表 C++ 代码中确实存在的实体,是具备 semantic 的主体
  • 绿色: 代表文件、文件夹、页面这些偏“没有什么semantic信息”的实体
  • 橙色: 是红色的进一步细化, 是人为构建的 group, 更加虚拟抽象的概念

忽略 ConceptDef 类, 原因是暂时没接触过 c++ 的 concept。

3. Definition 类的 Private 成员

Definition 类使用了友元, 并且提供了:

  • 转换为可修改的(mutable)的 Defnition 指针对象的函数
  • 转换为 DefinitionImpl 指针对象的函数

这些都是 Private 方式提供的,意味着子类并不能访问到这些成员, 换言之这些成员都是通过父类 Definition 对象进行调用的。

class Definition
{
  ...
  private:
    friend class DefinitionImpl; // 友元
    friend DefinitionMutable* toDefinitionMutable(Definition *);
    friend DefinitionMutable* toDefinitionMutable(const Definition *);
    virtual DefinitionMutable *toDefinitionMutable_() = 0;
    virtual const DefinitionImpl *toDefinitionImpl_() const = 0;
};

具体实现:

Definition *toDefinition(DefinitionMutable *dm)
{
  if (dm==0) return 0;
  return dm->toDefinition_();
}

DefinitionMutable *toDefinitionMutable(Definition *d)
{
  if (d==0) return 0;
  return d->toDefinitionMutable_();
}

这里值得注意的C++ trick是, private 方式的纯虚函数,需要被子类实现; 子类本来无法访问父类的 private 方法, 但是经过 pure virtual 的修饰, 子类被动的知道了父类的 private 成员函数(编译器告诉你的):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sBLKKeWE-1684651643844)(private_pure_virutal_function.png)]

4. Definition 类的 Public 成员

这里简要过一遍 Public 成员, 大概留个印象, 具体到 Definition 的子类如 ClassDef 的分析时, 承上启下方式的查看, 可能更清晰一些。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tkA9c0Z4-1684651643845)(definition_public_members.png)]

4.1 特殊成员函数

    virtual ~Definition() = default;

4.2 获取 definition 类型

    /*! Use this for dynamic inspection of the type of the derived class */
    virtual DefType definitionType() const = 0;

4.3 获取代码符号 (symbol) 类型

    /*! Used for syntax highlighting symbol class */
    virtual CodeSymbolType codeSymbolType() const = 0;

其中 CodeSymbolType 是枚举类, 具体取值包括:

xClass typesother container typeMember type
DefaultClassConceptDefine
StructNamespaceFunction
UnionPackageVariable
InterfaceTypedef
ProtocolEnumValue
CategoryEnumeration
ExceptionSignal
ServiceSlot
SingletonFriend
DCOP
Property
Event
Sequence
Dictionar

4.4 判断是否为别名

    /*! Returns TRUE if this is an alias of another definition */
    virtual bool isAlias() const = 0;

4.5 获取名字

  • name(): 符号名字
  • isAnonymous(): 是否为形如 @) 的人工名字
  • displayName(): 输出显示时的名字
  • localName(): 不带任何域限定符的名字,例如去掉 namespace
  • qualifiedName(): 返回此定义的完全限定名称
  • symbolName(): 返回符号表中的名字
  • getOutputFileBase(): 文件名字去掉后缀后剩余的部分
  • getSourceFileBase(): 返回“列出了当前定义的那个源文件”的名字,不带扩展部分
    /*! Returns the name of the definition */
    virtual const QCString &name() const = 0;

    /*! Returns TRUE iff this definition has an artificially generated name
     * (typically starting with a @) that is used for nameless definitions
     */
    virtual bool isAnonymous() const = 0;

    /*! Returns the name of the definition as it appears in the output */
    virtual QCString displayName(bool includeScope=TRUE) const = 0;

    /*! Returns the local name without any scope qualifiers. */
    virtual const QCString &localName() const = 0;

    /*! Returns the fully qualified name of this definition
     */
    virtual QCString qualifiedName() const = 0;

    /*! Returns the name of this definition as it appears in the symbol map.
     */
    virtual QCString symbolName() const = 0;

    /*! Returns the base file name (without extension) of this definition.
     *  as it is referenced to/written to disk.
     */
    virtual QCString getOutputFileBase() const = 0;

    /*! Returns the name of the source listing of this definition. */
    virtual QCString getSourceFileBase() const = 0;

4.6 获取在页面中的位置

anchor 这里意思为位置

    /*! Returns the anchor within a page where this item can be found */
    virtual QCString anchor() const = 0;

    /*! Returns the anchor of the source listing of this definition. */
    virtual QCString getSourceAnchor() const = 0;

4.7 获取文档, 以及文档所处的位置等信息

详细文档:

  • documentation(): 当前 definition 的完整定义
  • docLine(): 当前 definition 的文档被发现的起始行
  • docFile(): 当前 definition 的文档所处的文件名字
    /*! Returns the detailed description of this definition */
    virtual QCString documentation() const = 0;

    /*! Returns the line number at which the detailed documentation was found. */
    virtual int docLine() const = 0;

    /*! Returns the file in which the detailed documentation block was found.
     *  This can differ from getDefFileName().
     */
    virtual QCString docFile() const = 0;

定义:

  • getDefFileName(): 当前definition 是在哪个文件被定义的
  • getDefFileExtension(): 发现当前 definition 定义的文件的扩展名字
  • getDefLine(): 定义当前 definition 的行号
  • getDefColumn(): 定义当前 definition 的列号
    /*! returns the file in which this definition was found */
    virtual QCString getDefFileName() const = 0;

    /*! returns the extension of the file in which this definition was found */
    virtual QCString getDefFileExtension() const = 0;

    /*! returns the line number at which the definition was found (can be the declaration) */
    virtual int getDefLine() const = 0;

    /*! returns the column number at which the definition was found */
    virtual int getDefColumn() const = 0;

概要文档:

  • briefDescription(): 当前 defintion 的文档描述中, 概要部分
  • briefDescriptionAsTooltip(): 返回纯文本表示的概要部分, 用于 tooltip
  • briefLine(): 详细文档的 brief 部分的起始行号
  • briefFile(): 文档的概要部分是在哪个文件被发现的
  • hasBriefDescription(): 是否有概要描述
    /*! Returns the brief description of this definition. This can include commands. */
    virtual QCString briefDescription(bool abbreviate=FALSE) const = 0;

    /*! Returns a plain text version of the brief description suitable for use
     *  as a tool tip.
     */
    virtual QCString briefDescriptionAsTooltip() const = 0;

    /*! Returns the line number at which the brief description was found. */
    virtual int briefLine() const = 0;

    /*! Returns the file in which the brief description was found.
     *  This can differ from getDefFileName().
     */
    virtual QCString briefFile() const = 0;

    /** returns TRUE if this class has a brief description */
    virtual bool hasBriefDescription() const = 0;

body内文档:

  • inbodyDocumentation(): 成员函数的当前body内的文档
  • inbodyFile(): body内文档是在哪个文件被发现的
  • inbodyLine(): body内文档的起始行号
    /*! Returns the documentation found inside the body of a member */
    virtual QCString inbodyDocumentation() const = 0;

    /*! Returns the file in which the in body documentation was found */
    virtual QCString inbodyFile() const = 0;

    /*! Returns the line at which the first in body documentation
        part was found */
    virtual int inbodyLine() const = 0;

4.8 属性真假判断

  • hasDocumentation(): 是否有文档
  • hasUserDocumentation(): 是否有用户手写的文档
  • isLinkableInProject(): 是否可以在项目内链接
  • isLinkable(): 是否可以链接
  • isVisibleInProject(): 是否在项目中可见
  • isVisible(): 是否可见
  • isHidden(): 是否在 OUTPUT 中被隐藏
  • isArtificial(): 是否为人工引入
    /*! Returns TRUE iff the definition is documented
     *  (which could be generated documentation)
     *  @see hasUserDocumentation()
     */
    virtual bool hasDocumentation() const = 0;

    /*! Returns TRUE iff the definition is documented by the user. */
    virtual bool hasUserDocumentation() const = 0;

    /*! Returns TRUE iff it is possible to link to this item within this
     *  project.
     */
    virtual bool isLinkableInProject() const = 0;

    /*! Returns TRUE iff it is possible to link to this item. This can
     *  be a link to another project imported via a tag file.
     */
    virtual bool isLinkable() const = 0;

    /*! Returns TRUE iff the name is part of this project and
     *  may appear in the output
     */
    virtual bool isVisibleInProject() const = 0;

    /*! Returns TRUE iff the name may appear in the output */
    virtual bool isVisible() const = 0;

    /*! Returns TRUE iff this item is supposed to be hidden from the output. */
    virtual bool isHidden() const = 0;

    /*! returns TRUE if this entity was artificially introduced, for
     *  instance because it is used to show a template instantiation relation.
     */
    virtual bool isArtificial() const = 0;

4.9 Reference 相关

    /*! If this definition was imported via a tag file, this function
     *  returns the tagfile for the external project. This can be
     *  translated into an external link target via
     *  Doxygen::tagDestinationDict
     */
    virtual QCString getReference() const = 0;

    /*! Returns TRUE if this definition is imported via a tag file. */
    virtual bool isReference() const = 0;

    /*! Convenience method to return a resolved external link */
    virtual QCString externalReference(const QCString &relPath) const = 0;

4.10 获取位置

    /*! Returns the first line of the implementation of this item. See also getDefLine() */
    virtual int getStartDefLine() const = 0;

    /*! Returns the first line of the body of this item (applicable to classes and
     *  functions).
     */
    virtual int getStartBodyLine() const = 0;

    /*! Returns the last line of the body of this item (applicable to classes and
     *  functions).
     */
    virtual int getEndBodyLine() const = 0;

    /*! Returns the file in which the body of this item is located or 0 if no
     *  body is available.
     */
    virtual const FileDef *getBodyDef() const = 0;

4.11 细化类型和泛化类型

    virtual const Definition *findInnerCompound(const QCString &name) const = 0;
    virtual Definition *getOuterScope() const = 0;

4.12 导航路径

    virtual QCString navigationPathAsString() const = 0;
    virtual QCString pathFragment() const = 0;

4.13 设置和获取 symbol name

    //-----------------------------------------------------------------------------------
    // --- symbol name ----
    //-----------------------------------------------------------------------------------
    virtual void _setSymbolName(const QCString &name) = 0;
    virtual QCString _symbolName() const = 0;

4.14 杂项

  • getLanguage(): 获取对应的编程语言
  • 其他: 暂时不懂,忽略
    /** Returns the programming language this definition was written in. */
    virtual SrcLangExt getLanguage() const = 0;

    virtual const GroupList &partOfGroups() const = 0;
    virtual bool isLinkableViaGroup() const = 0;

    virtual const RefItemVector &xrefListItems() const = 0;

    virtual const MemberVector &getReferencesMembers() const = 0;
    virtual const MemberVector &getReferencedByMembers() const = 0;

    virtual bool hasSections() const = 0;
    virtual bool hasSources() const = 0;

    virtual QCString id() const = 0;

    /** returns the section dictionary, only of importance for pagedef */
    virtual const SectionRefs &getSectionRefs() const = 0;

5. 下一步

至此, 我们从 SymbolMap 入手, 对于 Definition 类及其子类有了进一步的认识, 而对于具体的 Definition 类别如 ClassDef, NamespaceDef, GroupDef 等, 又是一次 Hierarchical 的结构之旅, 需要具体带入分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值