------------------------------------------------------------------------------
--                                  G P S                                   --
--                                                                          --
--                     Copyright (C) 2007-2016, AdaCore                     --
--                                                                          --
-- This is free software;  you can redistribute it  and/or modify it  under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion.  This software is distributed in the hope  that it will be useful, --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
-- License for  more details.  You should have  received  a copy of the GNU --
-- General  Public  License  distributed  with  this  software;   see  file --
-- COPYING3.  If not, go to http://www.gnu.org/licenses for a complete copy --
-- of the license.                                                          --
------------------------------------------------------------------------------

--  This package defines the format of the tree used to represent the sources
--  internally. Semantic information and documentation retrieved from sources
--  are combined in this tree. There is no separate symbol table structure.

--  Each tree nodes is composed of two parts:

--    * Low level: This part contains the information retrieved directly from
--      the Xref database. This information should be fully reliable since it
--      is the information in the Sqlite database which is composed of the
--      information directly retrieved from the LI files generated by the
--      compiler. By contrast in some cases this information may not be
--      complete enough to have the full context of a given entity. The
--      low level information of a node is available through the routines
--      of package LL.

--    * High Level: This part complements the low level information. It is
--      composed of information synthesized from combinations of low level
--      attributes and information synthesized using the context of an
--      entity by the frontend of GNATdoc. The high level information of a
--      node is directly available through the public routines of this
--      package (excluding the routines of package LL).

-----------------------
-- Entity Attributes --
-----------------------

--  This section contains a complete list of the attributes that are defined
--  on entities. Some attributes apply to all entities, others only to certain
--  kinds of entities. In the latter case the attribute should only be set or
--  accessed if the Kind field indicates an appropriate entity.

--  Attributes whose value is directly retrieved from the database are marked
--  "LL" (from low-level) in the table bellow.

--  There are two kinds of attributes that apply to entities, stored and
--  synthesized. Stored attributes correspond to a field or flag in the entity
--  itself. Synthesized attributes are not stored directly, but are rather
--  computed as needed from other attributes, or from information in the tree.
--  These are marked "synthesized" in the table below. The stored attributes
--  have both access functions and set procedures to set the corresponding
--  values, while synthesized attributes have only access functions.

--    Alias
--       Defined in renamings. References the renamed entity.
--       See also Is_Alias.

--    Array_Component_Type
--       Defined in array types. Represents the type of the array components,
--       which is itself another entity.

--    Array_Index_Type
--       Defined in array types. List of types of the indexes.

--    Child_Types (LL)
--       Defined in types. Contains all the derivations of a type

--    Comment
--       Defined in all entities. Stores the structured comment parsed by
--       the frontend.

--    Components (synthesized)
--       Defined in record types, concurrent types and concurrent objects.

--    Direct derivations
--       Defined in types. Direct_Derivations (E) contains all the entities
--       for which Parent (Value) = E. In combination with attribute "Parent"
--       this attribute allows to traverse up and down the tree of tagged type
--       derivations. If all the derivations of a type are needed (for example,
--       all the types which implement an interface type) then attribute
--       LL.Get_Child_Types must be used. For backward compatibility, for
--       private types the attribute provides the same results when applied
--       to the partial and full view (to be improved???)

--    Discriminants (synthesized)
--       Defined in incomplete types, private types, record types, concurrent
--       types and concurrent objects.

--    End_Of_Syntax_Scope_Loc
--       Defined in all entities. Points to the location of the semicolon
--       closing the declaration of the entity.

--    Entity (LL)
--       Currently used only by the simple backend to identify the instances
--       of a generic (to be improved???)

--    Entities
--       Available in entities defining scopes: E_Abstract_Procedure,
--       E_Entry, E_Function, E_Generic_Package, E_Package, E_Procedure,
--       E_Protected_Type, E_Record_Type, E_Single_Protected, E_Single_Task,
--       E_Tagged_Record_Type, E_Task_Type.

--    Entries (synthesized)
--       Defined in concurrent types and objects (that is, E_Single_Task,
--       E_Task_Type, E_Single_Protected, E_Protected_Type).

--    Error_Msg
--       Defined in all entities. If present it contains the text of the
--       error reported by the frontend on this entity.

--    Etype
--       Defined in all entities. Represents the type of the entity, which
--       is itself another entity.

--    First_Private_Entity_Loc
--       Location of the first private entity (if any). Internally we have two
--       values associated with this attribute: 1) the value available in the
--       Xref database (value computed by the compiler and stored in ALI files
--       by compilers built after 2013-11-09), and 2) the value computed by
--       the frontend of GNATdoc. If the two values are available then this
--       attribute has the value computed by the compiler; otherwise it has
--       the value computed by the GNATdoc frontend.

--    Full_Name (synthesized)
--       Defined in all entities.

--    Full_View
--       Defined in the partial view of incomplete types and private types.

--    Generic_Formals_Loc
--       Defined in generic packages and generic subprograms. Points to the
--       location of the reserved word "generic" (before the generic formals)

--    Generic_Formals
--       Defined in generic packages and generic subprograms. Contains the
--       list of formals.

--    Has_Formals (synthesized)
--       Defined in subprograms and entries.

--    Has_Methods (LL)
--       Value available in the database. For incomplete types this attribute
--       is not reliable since it returns True for types that have no methods;
--       similarly, for tagged limited records with primitives returns False.
--       Must be improved adding a high-level attribute providing this
--       functionality. To be improved???

--    Has_Parent_Type (synthesized)
--       Defined in types and subtypes. True if the entity has the given
--       entity as its parent type.

--    Has_Private_Parent
--       Defined in types and subtypes. Set in the partial view of private
--       types and incomplete types when the partial view has no parent
--       type and the full view has a parent type.

--    Has_Unknown_Discriminants
--       Defined in types and subtypes. Set in the partial view of private
--       types that has unknown discriminants.

--    IDepth_Level
--       Defined in tagged types. Natural value with their inheritance depth
--       level. For private types this attribute is available in their partial
--       and full views; however it provides the same value when applied to the
--       partial and full view. As an enhancement these values could be
--       independent to improve the documentation when switch -p (process
--       private part) is used.

--    Inherited_Methods
--       Defined in types and subtypes. Set in tagged types. For private types
--       the list of inherited methods of the partial view contains the methods
--       inherited from the partial view of its parent; similarly the list of
--       inherited methods of the full view contains the methods inherited from
--       the full view of its parent.

--    Instance_Of (LL)
--       Defined in generics. Set in instances of generics.

--    In_Ada_Language (synthesized)
--       Defined in all entities.

--    In_C_Or_CPP_Language (synthesized)
--       Defined in all entities.

--    In_Private_Part
--       Defined in all entities. True for entities defined in the private
--       part of their enclosing scope (that is, the enclosing package,
--       concurrent type or concurrent object).

--    Is_Abstract (LL)
--       Defined in types and subprograms.

--    Is_Access (LL)
--       Defined in types and subtypes.

--    Is_Array (LL)
--       Defined in types and subtypes.

--    Is_Alias
--       Defined in subprogram renamings. This attribute is more reliable than
--       attribute Alias and must be used to check subprogram renamings because
--       it is set to True for renamings even when the renamed entity is not
--       available (if the entity associated with the renamed subprogram is
--       available then it is available through attribute Alias).

--    Is_Class_Or_Record_Type (synthesized)
--       Defined in types and subtypes. True for Ada record types (including
--       tagged types and interface types), C structs and C++ classes.

--    Is_Concurrent_Type_Or_Object (synthesized)
--       Defined in all entities. True for E_Single_Task, E_Task_Type,
--       E_Single_Protected and E_Protected_Type.

--    Is_Decorated
--       Defined in all entities. True for entities which have been fully
--       decorated by the GNATdoc frontend. For entities whose ALI file is
--       not available to GNATdoc this attribute returns False and their
--       scope is generally not available.

--    Is_Full_View (synthesized)
--       Defined in types and subtypes. True in the full view of private
--       types and incomplete types.

--    Is_Generic (synthesized)
--       Defined in all entities. True for generic packages and generic
--       subprograms.

--    Is_Generic_Formal
--      Defined in all entities. True for generic formals.

--    Is_Generic_Subprogram (synthesized)
--       Defined in all entities. True for generic subprograms.

--    Is_Incomplete
--       Defined in types and subtypes. True for incomplete type declarations.

--    Is_Internal
--       Defined in all entities. True for entities internally built by the
--       frontend of GNATdoc.

--    Is_Package (synthesized)
--       Defined in all entities. True for packages and generic package.

--    Is_Partial_View (synthesized)
--       Defined in types and subtypes. True in the partial view of private
--       types and incomplete types.

--    Is_Primitive (LL)
--       Defined in subprograms. True for primitives of tagged types.

--    Is_Record_Type (synthesized)
--       Defined in all entities. True for record types and interface types.

--    Is_Type (LL)
--       Defined in all entities. True for types and subtypes.

--    Is_Standard_Entity
--       Defined in all entities. True if the entity represents the Standard
--       scope (ie. the outermost entity)

--    Is_Subprogram (synthesized)
--       Defined in all entities. True for procedures and functions.

--    Is_Subprogram_Or_Entry (synthesized)
--       Defined in all entities. True for subprograms and entries.

--    Is_Subtype
--       Defined in all entities. True for subtypes.

--    Is_Tagged
--       Defined in all entities. True for tagged types.

--    Kind
--       Defined in all entities. Entity kind.

--    Language
--       Defined in all entities. Language in which the entiy is defined.

--    Location (LL)
--       Defined in all entities.

--    Methods
--       Defined in types and subtypes. Set in tagged types. List of methods.

--    Parent
--       Defined in tagged types and subtypes.

--    Parent_Package
--       Defined in E_Package entities. Set in child packages.

--    Parent_Types (LL)
--       Defined in types and subtypes. List containing the parent and
--       progenitors of a derived type.

--    Partial_View
--       Defined in types and subtypes. Set in the full view of incomplete
--       and private types.

--    Progenitors
--       Defined in types and subtypes. Set in tagged types containing the
--       list of interfaces covered by a tagged type.

--    Scope
--       Defined in all entities.

--    Short_Name
--       Defined in all entities.

--    Subprograms (synthesized)
--       Defined in record types, concurrent types and concurrent objects.
--       For tagged types this attribute contains its list of primitives;
--       for concurrent types and objects contains their list of subprograms.

--    Short_Name
--       Defined in all entities.

--    Src
--       Defined in all entities. Contains the retrieved sources of the entity
--       declaration (empty lines located at the beginning and end of the
--       sources have been previously removed).

--  -------------------
--  Frontend attributes
--  -------------------

--  These attributes must not be used by the backends since they are not
--  fully reliable or else they are used by the frontend to temporarily
--  store information on entities.

--    Alias (LL)
--       Defined in renamings. References the Xref entity associated with
--       the renamed entity (if available).

--    Body_Loc (LL)
--       Defined in all entities. Set on the following kind of entities:
--         E_Discriminant
--           In discriminants of private or incomplete types
--         E_Package, E_Generic_Package,
--         E_Function, E_Procedure, E_Entry, E_Formal
--         E_Protected_Type, E_Single_Protected
--         E_Record_Type, E_Tagged_Record_Type
--           In the partial and full view of private types
--         E_Task_Type, E_Single_Task
--         E_Variable
--           On the partial and full view of incomplete declarations

--    Doc
--       Defined in all entities. Block of comments associated with an
--       entity. Depending on switch -l (leading documentation) the
--       frontend stores in this attribute the value of attribute
--       Doc_After or Doc_Before.

--    Doc_After
--       Defined in all entities. Block of comments found after the
--       declaration of an entity.

--    Doc_Before
--       Defined in all entities. Block of comments found before the
--       declaration of an entity.

--    EKind (LL)
--       Defined in all entities. Kind of an entity returned by Xref.

--    End_Of_Profile_Location
--       Defined in subprograms and entries. Points to the location of the
--       semicolon closing the declaration of the entity. This attribute is
--       just a renaming of attribute End_Of_Syntax_Scope_Loc provided to
--       improve the readability of the sources.

--    End_Of_Profile_Location_In_Body
--       Defined in subprograms and entries. Points to the location of the
--       keyword "is" after the profile of the entity.

--    First_Private_Entity_Loc (LL)
--       Location of the first private entity (if provided by the compiler).

--    Full_Name (LL)
--       Qualified name of the entity (if available)

--    Is_Compilation_Unit
--       Defined in packages and subprograms.

--    Is_Self_Referenced_Type (LL)
--       Defined in C/C++ types and subtypes. Used to identify self referenced
--       types.

--    Is_Global (LL)
--       Value provided by Xref. Used by the frontend to identify library
--       level declarations.

--    Is_Predefined_Entity (LL)
--       Value provided by Xref. It can be used by the backend to avoid
--       generating cross references to predefined types.

--    Kind (LL)
--       Value provided by Xref. Not reliable. Used as the initial value of
--       attribute Kind.

--    Parent_Package (LL)
--       Parent of a package but not available in all the expected entities.

--    Pointed_Type (LL)
--       Value provided by Xref. Currently unused???

--    Scope (LL)
--       Value provided by Xref.

--    Subprograms_And_Entries (synthesized)
--       Defined in record types, concurrent types and concurrent objects.

--    Type (LL)
--       Value provided by Xref.

--    Unique_Id
--       Defined in all entities. Internal unique identifier associated with
--       each entity. Given that GNATdoc routines are currently executed by
--       a single thread, and given that their behavior is deterministic,
--       this unique identifier facilitates setting breakpoints in the
--       debugger using this Id. In addition, using this value entity
--       can be shown in the debugger session (cf. upnid)

--  Utility subprograms
--  -------------------

--    Append_Unique_Elmt
--       Append an entity to a list

--    Delete_Entity
--       Remove an entity from a list

--    Find_Entity
--       Search for an entity in a given list

--    For_All
--       Execute a procedure with all the elements of a given list

--    Has_Duplicated_Entities
--       Return True if the given list has duplicated entities

--    New_Entity / New_Internal_Entity
--       Entity constructors

--    In_Same_File
--       Return True if E1 and E2 are defined in the same file

--    No / Present
--       Used to check if an entity is available

--    Kind_In
--       Check if a given kind is one of the expected kinds

--    Remove_Full_View
--       Remove the full view of an entity (if available)

--    Remove_From_List
--       Remove an entity from a given list.

--    Remove_From_Scope
--       Remove an entity from its current scope list.

--    Traverse_Tree
--       Traverse all the entities of a subtree calling a given function on
--       each node.

with Ada.Containers.Vectors;
with GNATCOLL.Symbols;        use GNATCOLL.Symbols;
with Language;                use Language;
with GNATdoc.Comment;         use GNATdoc.Comment;
with Xref.Docgen;             use Xref.Docgen;

private package GNATdoc.Atree is
   Std_Entity_Name : constant String := "Standard";

   type Entity_Info_Record is private;
   type Entity_Id is access all Entity_Info_Record;
   No_Entity : constant Entity_Id := null;

   procedure Initialize;
   --  Initialize internal state used to associate unique identifiers to all
   --  the tree nodes.

   function No (E : Entity_Id) return Boolean;
   --  Return true if E is null

   function Present (E : Entity_Id) return Boolean;
   --  Return true if E is not null

   -----------------
   -- Entity_Info --
   -----------------

   type Entity_Kind is
     (E_Unknown,
      E_Abstract_Function,
      E_Abstract_Procedure,
      E_Abstract_Record_Type,
      E_Access_Type,
      E_Array_Type,
      E_Boolean_Type,
      E_Class_Wide_Type,
      E_Decimal_Fixed_Point_Type,
      E_Entry,
      E_Enumeration_Type,
      E_Enumeration_Literal,
      E_Exception,
      E_Fixed_Point_Type,
      E_Floating_Point_Type,
      E_Function,
      E_Generic_Function,
      E_Generic_Package,
      E_Generic_Procedure,
      E_Interface,
      E_Integer_Type,
      E_Named_Number,
      E_Package,
      E_Private_Object,
      E_Procedure,
      E_Protected_Type,
      E_Record_Type,
      E_Single_Protected,
      E_Single_Task,
      E_String_Type,
      E_Task_Type,
      E_Variable,

      --  Synthesized Ada values

      E_Access_Subprogram_Type,
      E_Discriminant,
      E_Component,
      E_Formal,

      E_Generic_Formal,
        --  This value is used only to provide a minimum decoration to
        --  undecorated generic formals. To safely identify generic
        --  formals use Is_Generic_Formal

      E_Tagged_Record_Type,

      --  C/C++
      E_Macro,
      E_Function_Macro,
      E_Class,
      E_Class_Instance,
      E_Include_File,

      --  Synthesized C++ values

      E_Attribute);

   ----------------
   -- EInfo_List --
   ----------------

   package EInfo_List is new Ada.Containers.Vectors
     (Index_Type => Natural, Element_Type => Entity_Id);
   procedure Free (List : in out EInfo_List.Vector);

   function Present (List : access EInfo_List.Vector) return Boolean;
   --  Return true if List has entities

   function Less_Than_Loc (Left, Right : Entity_Id) return Boolean;
   --  Compare by location. When two entities are defined in different files
   --  instead of returning False we extend the meaning of the comparison and
   --  compare them using the base name of their files. Done to avoid spurious
   --  output differences between continuous builders.

   function Less_Than_Body_Loc (Left, Right : Entity_Id) return Boolean;
   --  Similar to the prevous one but using location of the body. Attribute
   --  Body_Loc must be present in all the entities.

   package EInfo_Vector_Sort_Loc is new EInfo_List.Generic_Sorting
     ("<" => Less_Than_Loc);

   package EInfo_Vector_Sort_Body_Loc is new EInfo_List.Generic_Sorting
     ("<" => Less_Than_Body_Loc);

   function Less_Than_Short_Name (Left, Right : Entity_Id) return Boolean;
   --  Compare by name. When two entities have the same name (for example,
   --  overloaded subprograms) instead of returning False we extend the
   --  meaning of the comparison and compare them using their location.
   --  Done to avoid spurious output differences between continuous builders.

   package EInfo_Vector_Sort_Short is new EInfo_List.Generic_Sorting
     ("<" => Less_Than_Short_Name);

   function Less_Than_Full_Name (Left, Right : Entity_Id) return Boolean;
   package EInfo_Vector_Sort_Full is new EInfo_List.Generic_Sorting
     ("<" => Less_Than_Full_Name);

   procedure Append_Unique_Elmt
     (Container : in out EInfo_List.Vector;
      Entity    : Entity_Id);
   --  Append Entity to the Container only if the container has no entity
   --  whose location matches the location of Entity.

   procedure Delete_Entity
     (List   : in out EInfo_List.Vector;
      Entity : Root_Entity'Class);
   procedure Delete_Entity
     (List   : in out EInfo_List.Vector;
      Entity : Entity_Id);
   --  Raise Not_Found if Entity is not found in List

   function Find_Entity
     (List   : EInfo_List.Vector;
      Entity : Root_Entity'Class) return Entity_Id;
   function Find_Entity
     (List : EInfo_List.Vector;
      Name : String) return Entity_Id;
   --  Find the entity with Name in List. Name may be a short name or an
   --  expanded name. If not found then return No_Entity.

   function Find_Entity
     (Location : General_Location) return Entity_Id;
   --  Find the entity reference from this location. If not found then
   --  return No_Entity.

   procedure For_All
     (Vector  : in out EInfo_List.Vector;
      Process : access procedure (E_Info : Entity_Id));
   --  Call subprogram Process for all the elements of Vector

   function Has_Duplicated_Entities
     (List : EInfo_List.Vector) return Boolean;
   --  Return True if List has duplicated entities. Used in assertions.

   Not_Found : exception;

   ---------------------------
   -- Entity_Id subprograms --
   ---------------------------

   function New_Entity
     (Context  : access constant Docgen_Context;
      Language : Language_Access;
      E        : Root_Entity'Class;
      Loc      : General_Location) return Entity_Id;
   function New_Internal_Entity
     (Context  : access constant Docgen_Context;
      Language : Language_Access;
      Name     : String) return Entity_Id;
   --  Tree node constructors. New_Internal_Entity is used only to build the
   --  entity associated with the Standard scope, the full-view of private
   --  and incomplete types, and the entity associated with unknown
   --  discriminants of private types.

   procedure Free (E : in out Entity_Id);
   --  Tree node destructor

   procedure Append_Generic_Formal
     (E : Entity_Id; Value : Entity_Id);
   procedure Append_Array_Index_Type
     (E : Entity_Id; Value : Entity_Id);
   procedure Append_Inherited_Method
     (E : Entity_Id; Value : Entity_Id);
   procedure Append_Method
     (E : Entity_Id; Value : Entity_Id);
   procedure Append_Progenitor
     (E : Entity_Id; Value : Entity_Id);
   procedure Append_To_Scope
     (E : Entity_Id; Value : Entity_Id);
   --  Append Value to the list of entities in the scope of E

   function Get_Alias
     (E : Entity_Id) return Entity_Id;
   function Get_Comment
     (E : Entity_Id) return Structured_Comment;

   function Get_Array_Component_Type
     (E : Entity_Id) return Entity_Id;

   function Get_Components
     (E : Entity_Id) return EInfo_List.Vector;
   --  Applicable to record types, concurrent types and concurrent objects

   function Get_Direct_Derivations
     (E : Entity_Id) return access EInfo_List.Vector;

   function Get_Discriminants
     (E : Entity_Id) return EInfo_List.Vector;
   --  Applicable to record types, concurrent types and concurrent objects

   function Get_Doc
     (E : Entity_Id) return Comment_Result;
   function Get_Doc_After
     (E : Entity_Id) return Comment_Result;
   function Get_Doc_Before
     (E : Entity_Id) return Comment_Result;

   function Get_End_Of_Profile_Location_In_Body
     (E : Entity_Id) return General_Location;
   --  This attribute is set only for subprograms

   function Get_End_Of_Syntax_Scope_Loc
     (E : Entity_Id) return General_Location;
   --  At current stage this attribute is set only for E_Package,
   --  E_Generic_Package entities, and concurrent types and objects.

   function Get_End_Of_Profile_Location
     (E : Entity_Id) return General_Location
      renames Get_End_Of_Syntax_Scope_Loc;

   function Get_Entities
     (E : Entity_Id) return access EInfo_List.Vector;
   function Get_Error_Msg
     (E : Entity_Id) return Unbounded_String;
   function Get_Etype
     (E : Entity_Id) return Entity_Id;
   function Get_First_Private_Entity_Loc
     (E : Entity_Id) return General_Location;
   function Get_Full_Name
     (E : Entity_Id) return String;
   function Get_Full_View
     (E : Entity_Id) return Entity_Id;

   function Get_Generic_Formals_Loc
     (E : Entity_Id) return General_Location;

   function Get_Generic_Formals
     (E : Entity_Id) return access EInfo_List.Vector;
   function Get_Array_Index_Type
     (E : Entity_Id) return access EInfo_List.Vector;
   function Get_Inherited_Methods
     (E : Entity_Id) return access EInfo_List.Vector;
   function Get_IDepth_Level
     (E : Entity_Id) return Natural;
   function Get_Kind
     (E : Entity_Id) return Entity_Kind;
   function Get_Language
     (E : Entity_Id) return Language_Access;

   function Get_Methods
     (E : Entity_Id) return access EInfo_List.Vector;
   function Get_Parent
     (E : Entity_Id) return Entity_Id;
   function Get_Parent_Package
     (E : Entity_Id) return Entity_Id;
   function Get_Partial_View
     (E : Entity_Id) return Entity_Id;
   function Get_Progenitors
     (E : Entity_Id) return access EInfo_List.Vector;
   function Get_Scope
     (E : Entity_Id) return Entity_Id;
   function Get_Short_Name
     (E : Entity_Id) return String;

   function Get_Entries
     (E : Entity_Id) return EInfo_List.Vector;
   --  Applicable to concurrent types and concurrent objects
   function Get_Subprograms
     (E : Entity_Id) return EInfo_List.Vector;
   --  Applicable to record types, concurrent types and concurrent objects

   function Get_Src
     (E : Entity_Id) return Unbounded_String;
   function Get_Unique_Id
     (E : Entity_Id) return Natural;

   function Has_Formals
     (E : Entity_Id) return Boolean;

   function Has_Parent_Type
     (E : Entity_Id; Parent : Entity_Id) return Boolean;

   function Has_Private_Parent
     (E : Entity_Id) return Boolean;
   --  True if E has a parent which is visible only in its full view

   function Has_Unknown_Discriminants
     (E : Entity_Id) return Boolean;

   function In_Ada_Language
     (E : Entity_Id) return Boolean;
   function In_C_Or_CPP_Language
     (E : Entity_Id) return Boolean;
   function In_Private_Part
     (E : Entity_Id) return Boolean;

   function In_Same_File (E1, E2 : Entity_Id) return Boolean;
   --  Return true if E1 and E2 are defined in the same file

   function Is_Alias
     (E : Entity_Id) return Boolean;

   function Is_Compilation_Unit
     (E : Entity_Id) return Boolean;

   function Is_Class_Or_Record_Type
     (E : Entity_Id) return Boolean;
   --  Return True for Ada record types (including tagged types and interface
   --  types), C structs and C++ classes
   function Is_Record_Type
     (E : Entity_Id) return Boolean;

   function Is_Concurrent_Type_Or_Object
     (E : Entity_Id) return Boolean;
   function Is_Decorated
     (E : Entity_Id) return Boolean;

   function Is_Full_View
     (E : Entity_Id) return Boolean;
   --  Return true if E is the full view of a private or incomplete type

   function Is_Excluded
     (E : Entity_Id) return Boolean;
   --  Return True when entity is excluded from generated documentation

   function Is_Generic
     (E : Entity_Id) return Boolean;
   function Is_Generic_Formal
     (E : Entity_Id) return Boolean;
   function Is_Generic_Subprogram
     (E : Entity_Id) return Boolean;
   function Is_Incomplete
     (E : Entity_Id) return Boolean;
   function Is_Internal
     (E : Entity_Id) return Boolean;
   function Is_Package
     (E : Entity_Id) return Boolean;

   function Is_Partial_View
     (E : Entity_Id) return Boolean;
   --  Return true if E is the partial view of a private or incomplete type

   function Is_Private
     (E : Entity_Id) return Boolean;
   function Is_Standard_Entity
     (E : Entity_Id) return Boolean;
   --  Return true if E represents the Standard scope (the outermost entity)
   function Is_Subprogram
     (E : Entity_Id) return Boolean;
   function Is_Subprogram_Or_Entry
     (E : Entity_Id) return Boolean;
   function Is_Subtype
     (E : Entity_Id) return Boolean;
   function Is_Tagged
     (E : Entity_Id) return Boolean;

   function Kind_In
     (K  : Entity_Kind;
      V1 : Entity_Kind;
      V2 : Entity_Kind) return Boolean;
   function Kind_In
     (K  : Entity_Kind;
      V1 : Entity_Kind;
      V2 : Entity_Kind;
      V3 : Entity_Kind) return Boolean;
   function Kind_In
     (K  : Entity_Kind;
      V1 : Entity_Kind;
      V2 : Entity_Kind;
      V3 : Entity_Kind;
      V4 : Entity_Kind) return Boolean;

   procedure Remove_Full_View
     (E : Entity_Id);
   procedure Remove_From_List
     (List : access EInfo_List.Vector;
      E : Entity_Id);
   procedure Remove_From_Scope
     (E : Entity_Id);

   procedure Set_Alias
     (E : Entity_Id; Value : Entity_Id);
   procedure Set_Comment
     (E : Entity_Id; Value : Structured_Comment);

   procedure Set_Doc
     (E : Entity_Id; Value : Comment_Result);
   procedure Set_Doc_After
     (E : Entity_Id; Value : Comment_Result);
   procedure Set_Doc_Before
     (E : Entity_Id; Value : Comment_Result);

   procedure Set_End_Of_Profile_Location_In_Body
     (E : Entity_Id; Loc : General_Location);
   procedure Set_End_Of_Syntax_Scope_Loc
     (E : Entity_Id; Loc : General_Location);

   procedure Set_Error_Msg
     (E : Entity_Id; Value : Unbounded_String);

   procedure Set_First_Private_Entity_Loc
     (E : Entity_Id; Value : General_Location);

   procedure Set_Full_View
     (E : Entity_Id; Value : Entity_Id);

   procedure Set_Generic_Formals_Loc
     (E : Entity_Id; Value : General_Location);

   procedure Set_Has_Incomplete_Decoration
     (E : Entity_Id);

   procedure Set_Has_Private_Parent
     (E : Entity_Id; Value : Boolean := True);
   procedure Set_Has_Unknown_Discriminants
     (E : Entity_Id);

   procedure Set_In_Private_Part
     (E : Entity_Id);
   procedure Set_IDepth_Level
     (E : Entity_Id);

   procedure Set_Is_Alias
     (E : Entity_Id);

   procedure Set_Is_Decorated
     (E : Entity_Id);

   procedure Set_Is_Excluded (E : Entity_Id);
   --  Mark entity as excluded from generated documentation

   procedure Set_Is_Generic_Formal
     (E : Entity_Id);
   procedure Set_Is_Incomplete
     (E : Entity_Id; Value : Boolean := True);
   procedure Set_Is_Private
     (E : Entity_Id);
   procedure Set_Is_Subtype
     (E : Entity_Id);
   procedure Set_Is_Tagged
     (E : Entity_Id);
   procedure Set_Kind
     (E : Entity_Id; Value : Entity_Kind);
   procedure Set_Parent
     (E : Entity_Id; Value : Entity_Id);
   procedure Set_Parent_Package
     (E : Entity_Id; Value : Entity_Id);
   procedure Set_Partial_View
     (E : Entity_Id; Value : Entity_Id);
   procedure Set_Scope
     (E : Entity_Id; Value : Entity_Id);

   procedure Set_Short_Name
     (Context : access constant Docgen_Context;
      E       : Entity_Id;
      Value   : String);

   procedure Set_Src
     (E : Entity_Id; Value : Unbounded_String);

   type Traverse_Result is (OK, Skip);

   procedure Traverse_Tree
     (Root    : Entity_Id;
      Process : access function
                         (Entity      : Entity_Id;
                          Scope_Level : Natural) return Traverse_Result);

   --  Given the parent node for a subtree, traverses all nodes of this tree,
   --  calling the given function Process on each one, in pre order (i.e.
   --  top-down). The order of traversing subtrees follows their order in the
   --  attribute Entities. The traversal is controlled as follows by the result
   --  returned by Process:

   --    OK       The traversal continues normally with the children of the
   --             node just processed.

   --    Skip     The children of the node just processed are skipped and
   --             excluded from the traversal, but otherwise processing
   --             continues elsewhere in the tree.

   -----------------------------------
   -- Low-Level abstraction package --
   -----------------------------------

   --  This local package provides the information retrieved directly from the
   --  Xref database when the entity is created. It is named LL (Low Level)
   --  instead of Xref to avoid having a third package in the GPS project
   --  named Xref (the other packages are Xref and GNATCOLL.Xref).

   package LL is
      procedure Append_Child_Type
        (E : Entity_Id; Value : Entity_Id);
      procedure Append_Parent_Type
        (E : Entity_Id; Value : Entity_Id);

      function Get_Alias
        (E : Entity_Id) return Root_Entity'Class;
      function Get_Body_Loc
        (E : Entity_Id) return General_Location;
      function Get_Child_Types
        (E : Entity_Id) return access EInfo_List.Vector;
      function Get_End_Of_Scope_Loc
        (E : Entity_Id) return General_Location;
      function Get_Entity
        (E : Entity_Id) return Root_Entity'Class;
      function Get_Instance_Of
        (E : Entity_Id) return Root_Entity'Class;
      function Get_Location
        (E : Entity_Id) return General_Location;
      function Get_Parent_Package
        (E : Entity_Id) return Root_Entity'Class;
      function Get_Parent_Types
        (E : Entity_Id) return access EInfo_List.Vector;
      function Get_Pointed_Type
        (E : Entity_Id) return Root_Entity'Class;
      function Get_Scope
        (E : Entity_Id) return Root_Entity'Class;

      function Get_Ekind
        (E           : Root_Entity'Class;
         In_Ada_Lang : Boolean) return Entity_Kind;
      --  In_Ada_Lang is used to enable an assertion since in Ada we are not
      --  processing bodies yet???

      function Has_Methods
        (E : Entity_Id) return Boolean;
      function Is_Abstract
        (E : Entity_Id) return Boolean;
      function Is_Access
        (E : Entity_Id) return Boolean;
      function Is_Array
        (E : Entity_Id) return Boolean;
      function Is_Global
        (E : Entity_Id) return Boolean;
      function Is_Predefined_Entity
        (E : Entity_Id) return Boolean;
      function Is_Primitive
        (E : Entity_Id) return Boolean;
      function Is_Type
        (E : Entity_Id) return Boolean;

      function Is_Self_Referenced_Type
        (E    : Root_Entity'Class;
         Lang : Language_Access) return Boolean;
      --  Return true if Lang is C or C++ and the scope of E is itself. Used to
      --  identify the second second entity generated by the C/C++ compiler for
      --  named typedef structs (the compiler generates two entites in the LI
      --  file with the same name).

      procedure Set_Location
        (E : Entity_Id; Value : General_Location);

   private
      pragma Inline (Append_Child_Type);
      pragma Inline (Append_Parent_Type);

      pragma Inline (Get_Alias);
      pragma Inline (Get_Body_Loc);
      pragma Inline (Get_Child_Types);
      pragma Inline (Get_End_Of_Scope_Loc);
      pragma Inline (Get_Entity);
      pragma Inline (Get_Location);
      pragma Inline (Get_Parent_Package);
      pragma Inline (Get_Parent_Types);
      pragma Inline (Get_Pointed_Type);
      pragma Inline (Get_Scope);

      pragma Inline (Is_Abstract);
      pragma Inline (Is_Access);
      pragma Inline (Is_Array);
      pragma Inline (Is_Global);
      pragma Inline (Is_Predefined_Entity);
      pragma Inline (Is_Primitive);
      pragma Inline (Is_Type);

      pragma Inline (Set_Location);
   end LL;

   ------------------------------------------
   --  Debugging routines (for use in gdb) --
   ------------------------------------------

   procedure Register_Database (Database : General_Xref_Database);
   --  Routine called by gnatdoc.adb to register in this package the database
   --  and thus simplify the use of subprogram "pn" from gdb.

   function name
     (E  : Root_Entity'Class) return String;
   --  (gdb) Returns the short name of E

   procedure pl (E : Entity_Id);
   --  (gdb) Prints the list of entities defined in the scope of E

   procedure pn (E : Entity_Id);
   --  (gdb) Prints a single tree node (full output), without printing
   --  descendants.

   procedure ploc (E : Entity_Id);
   --  (gdb) Prints the location of E

   procedure pns (E : Entity_Id);
   procedure pns (E : Root_Entity'Class);
   --  (gdb) Print a single tree node (short output), without printing
   --  descendants.

   procedure pnsb (E : Entity_Id);
   --  (gdb) Print a single tree node (short output), without printing
   --  descendants displaying its value of LL.Body_Loc()

   procedure pv (V : EInfo_List.Vector);
   procedure pv (V : Xref.Entity_Array);
   --  (gdb) Using pns print all the elements of V

   procedure pvb (V : EInfo_List.Vector);
   --  (gdb) Using pnsb print all the elements of V

   function To_String
     (E              : Entity_Id;
      Prefix         : String := "";
      With_Full_Loc  : Boolean := False;
      With_Src       : Boolean := False;
      With_Doc       : Boolean := False;
      With_Errors    : Boolean := False;
      With_Unique_Id : Boolean := False;
      Reliable_Mode  : Boolean := True) return String;
   --  Returns a string containing all the information associated with E.
   --  Prefix is used by routines of package GNATdoc.Treepr to generate the
   --  bar which represents the enclosing scopes. If With_Full_Loc is true then
   --  the full path of the location of the file is added to the output; if
   --  With_Src is true then the source retrieved from the sources is added to
   --  the output; if With_Doc is true then the documentation retrieved from
   --  sources is added to the output; if With_Errors is true then the errors
   --  reported on the node are added to the output; if With_Unique_Id is true
   --  then the unique identifier of E as well as the unique identifier of all
   --  the entities associated with E (ie. Parent, Scope, etc.) is added to
   --  the output. If Reliable_Mode is True then Xref information which is not
   --  fully reliable and can vary between platforms is not added to the output

private
   type Ref_Info is record
      Entity : Entity_Id;
      Ref    : Root_Entity_Reference_Ref;
      Loc    : General_Location;
   end record;

   package Ref_List is new Ada.Containers.Vectors
     (Index_Type => Natural, Element_Type => Ref_Info);

   type Xref_Info is
      record
         Alias            : Root_Entity_Ref;
         Body_Loc         : General_Location;
         Ekind            : Entity_Kind;
         End_Of_Scope_Loc : General_Location;
         Entity           : Root_Entity_Ref;
         Etype            : Root_Entity_Ref;
         Etype_Loc        : General_Location;
         Instance_Of      : Root_Entity_Ref;
         Loc              : General_Location;

         Array_Component_Type : Root_Entity_Ref;

         Pointed_Type     : Root_Entity_Ref;

         Scope_E          : Root_Entity_Ref;
         Parent_Package   : Root_Entity_Ref;
         --  Present in packages

         First_Private_Entity_Loc : General_Location;

         Parent_Types  : aliased EInfo_List.Vector;
         --  Parent types of tagged types (or base classes of C++ classes)

         Child_Types   : aliased EInfo_List.Vector;
         --  Derivations of tagged types (or C++ classes)

         References    : aliased Ref_List.Vector;

         Has_Methods   : Boolean;

         Is_Abstract   : Boolean;
         Is_Access     : Boolean;
         Is_Array      : Boolean;
         Is_Container  : Boolean;
         Is_Global     : Boolean;
         Is_Predef     : Boolean;
         Is_Type       : Boolean;
         Is_Subprogram : Boolean;
         Is_Primitive  : Boolean;
         Is_Generic    : Boolean;
      end record;

   type Entity_Info_Record is
      record
         Id : Natural;
         --  Unique identifier

         Language : Language_Access;
         --  Language associated with the entity. It can be used by the backend
         --  to generate full or short names depending on the language. For
         --  examples see Backend.Simple.

         Kind            : Entity_Kind;
         --  When the entity is created the fields Kind and Xref.Ekind are
         --  initialized with the same values. However, Kind may be decorated
         --  with other values by the frontend at later stages based on the
         --  context (for example, an E_Variable entity may be redecorated
         --  as E_Formal (see gnatdoc-frontend.adb)

         Etype           : Entity_Id;
         Alias           : Entity_Id;
         Scope           : Entity_Id;
         Parent_Package  : Entity_Id;
         --  Present in packages

         End_Of_Syntax_Scope_Loc         : General_Location;
         End_Of_Profile_Location_In_Body : General_Location;
         Generic_Formals_Loc             : General_Location;
         First_Private_Entity_Loc        : General_Location;

         Full_Name       : GNATCOLL.Symbols.Symbol;
         Short_Name      : GNATCOLL.Symbols.Symbol;

         Has_Private_Parent : Boolean;
         --  True if the parent type is only visible in the full view

         Has_Unknown_Discriminants : Boolean;

         Has_Incomplete_Decoration : Boolean;
         Is_Decorated              : Boolean;

         In_Private_Part   : Boolean;
         --  True if the entity is defined in the private part of a package

         Is_Alias          : Boolean;
         Is_Generic_Formal : Boolean;
         Is_Internal       : Boolean;
         Is_Incomplete     : Boolean;
         Is_Private        : Boolean;

         Is_Subtype        : Boolean;
         Is_Tagged_Type    : Boolean;
         Idepth_Level      : Natural;
         --  Inheritance depth level of a tagged type

         Doc               : Comment_Result;
         Doc_After         : Comment_Result;
         Doc_Before        : Comment_Result;
         Src               : Unbounded_String;
         Comment           : aliased Structured_Comment;
         --  Doc is a temporary buffer used to store the block of comments
         --  retrieved from the source file. After processed, it is cleaned and
         --  its contents is stored in the structured comment, which identifies
         --  tags and attributes.

         Full_View         : Entity_Id;
         Partial_View      : Entity_Id;

         Array_Component_Type : Entity_Id;
         Array_Index_Type     : aliased EInfo_List.Vector;
         --  Present in array types

         Entities          : aliased EInfo_List.Vector;
         --  Entities defined in the scope of this entity. For example, all
         --  the entities defined in the scope of a package, all the components
         --  of a record, etc.

         Generic_Formals   : aliased EInfo_List.Vector;
         Methods           : aliased EInfo_List.Vector;
         Inherited_Methods : aliased EInfo_List.Vector;
         --  Primitives of tagged types (or methods of C++ classes)

         Parent             : Entity_Id;
         Progenitors        : aliased EInfo_List.Vector;
         Direct_Derivations : aliased EInfo_List.Vector;

         Error_Msg       : Unbounded_String;
         --  Errors reported on this entity

         Xref            : Xref_Info;
         --  Information retrieved directly from the Xref database.

         Is_Excluded : Boolean;
         --  Mark entity as excluded from documentation generation.
      end record;

   pragma Inline (Append_Array_Index_Type);
   pragma Inline (Append_Generic_Formal);
   pragma Inline (Append_Inherited_Method);
   pragma Inline (Append_Method);
   pragma Inline (Append_Progenitor);
   pragma Inline (Append_To_Scope);

   pragma Inline (Get_Alias);
   pragma Inline (Get_Comment);
   pragma Inline (Get_Array_Component_Type);
   pragma Inline (Get_Array_Index_Type);
   pragma Inline (Get_Direct_Derivations);
   pragma Inline (Get_Doc);
   pragma Inline (Get_Doc_After);
   pragma Inline (Get_Doc_Before);
   pragma Inline (Get_End_Of_Profile_Location_In_Body);
   pragma Inline (Get_End_Of_Syntax_Scope_Loc);
   pragma Inline (Get_Entities);
   pragma Inline (Get_Error_Msg);
   pragma Inline (Get_Etype);
   pragma Inline (Get_Full_Name);
   pragma Inline (Get_Full_View);
   pragma Inline (Get_Generic_Formals_Loc);
   pragma Inline (Get_Generic_Formals);
   pragma Inline (Get_Inherited_Methods);
   pragma Inline (Get_IDepth_Level);
   pragma Inline (Get_Kind);
   pragma Inline (Get_Language);
   pragma Inline (Get_Methods);
   pragma Inline (Get_Parent);
   pragma Inline (Get_Parent_Package);
   pragma Inline (Get_Partial_View);
   pragma Inline (Get_First_Private_Entity_Loc);
   pragma Inline (Get_Progenitors);
   pragma Inline (Get_Scope);
   pragma Inline (Get_Short_Name);
   pragma Inline (Get_Src);
   pragma Inline (Get_Unique_Id);
   pragma Inline (Has_Formals);
   pragma Inline (Has_Parent_Type);
   pragma Inline (Has_Private_Parent);
   pragma Inline (Has_Unknown_Discriminants);
   pragma Inline (In_Ada_Language);
   pragma Inline (In_C_Or_CPP_Language);
   pragma Inline (In_Private_Part);
   pragma Inline (In_Same_File);
   pragma Inline (Is_Alias);
   pragma Inline (Is_Compilation_Unit);
   pragma Inline (Is_Class_Or_Record_Type);
   pragma Inline (Is_Concurrent_Type_Or_Object);
   pragma Inline (Is_Decorated);
   pragma Inline (Is_Full_View);
   pragma Inline (Is_Generic);
   pragma Inline (Is_Generic_Formal);
   pragma Inline (Is_Incomplete);
   pragma Inline (Is_Package);
   pragma Inline (Is_Partial_View);
   pragma Inline (Is_Private);
   pragma Inline (Is_Record_Type);
   pragma Inline (Is_Subprogram);
   pragma Inline (Is_Subprogram_Or_Entry);
   pragma Inline (Is_Subtype);
   pragma Inline (Is_Tagged);
   pragma Inline (Kind_In);
   pragma Inline (No);
   pragma Inline (Present);
   pragma Inline (Set_Alias);
   pragma Inline (Set_Comment);
   pragma Inline (Set_In_Private_Part);
   pragma Inline (Set_IDepth_Level);
   pragma Inline (Set_Doc);
   pragma Inline (Set_Doc_After);
   pragma Inline (Set_Doc_Before);
   pragma Inline (Set_End_Of_Profile_Location_In_Body);
   pragma Inline (Set_End_Of_Syntax_Scope_Loc);
   pragma Inline (Set_Error_Msg);
   pragma Inline (Set_Full_View);
   pragma Inline (Set_Generic_Formals_Loc);
   pragma Inline (Set_Has_Incomplete_Decoration);
   pragma Inline (Set_Has_Private_Parent);
   pragma Inline (Set_Has_Unknown_Discriminants);
   pragma Inline (Set_Is_Alias);
   pragma Inline (Set_Is_Decorated);
   pragma Inline (Set_Is_Excluded);
   pragma Inline (Set_Is_Generic_Formal);
   pragma Inline (Set_Is_Incomplete);
   pragma Inline (Set_Is_Private);
   pragma Inline (Set_Is_Subtype);
   pragma Inline (Set_Is_Tagged);
   pragma Inline (Set_Kind);
   pragma Inline (Set_Parent);
   pragma Inline (Set_Parent_Package);
   pragma Inline (Set_Partial_View);
   pragma Inline (Set_First_Private_Entity_Loc);
   pragma Inline (Set_Scope);
   pragma Inline (Set_Short_Name);
   pragma Inline (Set_Src);
end GNATdoc.Atree;
