------------------------------------------------------------------------------
--                                                                          --
--                            GNATPP COMPONENTS                             --
--                                                                          --
--                G N A T P P . A S I S _ U T I L I T I E S                 --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--                     Copyright (C) 2001-2013, AdaCore                     --
--                                                                          --
-- GNATPP 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 2,  or (at your option) any later ver- --
-- sion.  GNATPP is  distributed in the  hope that it will  be  useful, but --
-- WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABI- --
-- LITY 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 GNAT; see file COPYING. If not, --
-- write to the Free Software Foundation,  51 Franklin Street, Fifth Floor, --
-- Boston,                                                                  --
--                                                                          --
-- GNATPP is maintained by AdaCore (http://www.adacore.com)                 --
--                                                                          --
------------------------------------------------------------------------------

--  This package defines various ASIS utility programs. Some of them may
--  be moved to Asis.Extensions later

with Asis;                       use Asis;
with Asis.Extensions.Flat_Kinds; use Asis.Extensions.Flat_Kinds;

package GNATPP.Asis_Utilities is

   function Def_Name (Declaration_Element : Element) return Element;
   --  Supposing that Declaration_Element is a valid argument for the standard
   --  Asis query Asis.Declarations.Names and that it can define only one name,
   --  this query returns this single defining name

   function Unique_Name_Definition (An_Identifier :  Element) return Element;
   --  This is the modification of the standard ASIS query
   --  Corresponding_Name_Definition. Instead of raising
   --  ASIS_Inappropriate_Element in case when the argument Element does not
   --  have the definition or when it is not possible to determine the unique
   --  definition for it, this function returns Nil_Element

   function Name_Text_Image (El : Element) return Program_Text;
   --  Returns the string image of the name. This name can be a pragma name,
   --  a defining name or an identifier (a reference)

   function Is_Standard_Name (Defining_Name : Element) return Boolean;
   --  Checks if the argument is a defining name declared in a predefined Ada
   --  unit or in the unit belonging to a GNAT library

   procedure Detect_Possible_Layout
     (The_Element     : Element;
      Space_In_Output : out Natural;
      Comment_Inside  : out Boolean);
   --  For the argument Element, it detects the length of the text image of
   --  this Element in the output source provided that it is printed in
   --  one line, this is returned as the value of Space_In_Output parameter.
   --  If the code of the argument element contains comment(s), Comment_Inside
   --  parameter is set on, and Space_In_Output will contain the length of the
   --  pretty-printed image preceding this comment. If the value of
   --  Space_In_Output to return is for sure more than Max_Line_Length, then
   --  Space_In_Output is set to (Max_Line_Length + 1) instead of computing the
   --  exact value. If the argument Element is Nil_Element, Space_In_Output is
   --  set to 0, and Comment_Inside is set OFF.

   function Adds_Indentation (El : Flat_Element_Kinds) return Boolean;
   --  This function checks if El requires new indentation level

   function Declaration_Starts_From_Def_Name
     (El :   Flat_Element_Kinds)
      return Boolean;
   --  This function checks if El is A_Declaration element which starts from
   --  a defining name

   function In_Unconstrained_Array_Definition
     (El :   Element)
      return Boolean;
   --  Checks if the nearest non-expression enclosing element of the argument
   --  element is of An_Unconstrained_Array_Definition kind

   function In_Return_Statement
     (El :   Element)
      return Boolean;
   --  Checks if the nearest non-expression enclosing element of the argument
   --  element is of A_Return_Statement kind

   function Is_Function (El_Kind : Flat_Element_Kinds) return Boolean;
   --  Check if El_Kind is a (generic or formal) function (renaming or access
   --  to) or a function body (stub)

   function Is_Array_Definition
     (El_Kind : Flat_Element_Kinds)
      return    Boolean;
   --  Check if El_Kind is an array definition

   function Is_Unary (El_Kind : Flat_Element_Kinds) return Boolean;
   --  Check if El_Kind is an unary operator sign.
   --  to) or a function body (stub)

   function Has_Parameters (El_Kind : Flat_Element_Kinds) return Boolean;
   --  Check if El_Kind may have parameter specifications

   function Has_Choices (El_Kind : Flat_Element_Kinds) return Boolean;
   --  Check if El_Kind has choices. This test function gives the answer
   --  from the point of view of the current gnatpp implementation. That is,
   --  it says if the argument kind has choices which has to be formatted
   --  in some smart way

   function Contains_Declarations
     (El_Kind : Flat_Element_Kinds)
      return    Boolean;
   --  Check if El_Kind is a construct containing a declaration sequence

   function Contains_Statements
     (El_Kind : Flat_Element_Kinds)
      return    Boolean;
   --  Check if El_Kind is a construct containing a statement sequence

   function May_Have_Init_Expr
     (El_Kind : Flat_Element_Kinds)
      return    Boolean;
   --  Check if El_Kind is a declaration construct which may have an
   --  initialization expression

   function Is_Call (El : Element) return Boolean;
   --  Check if El is a procedure, an entry or a prefix function call or a
   --  pragma (we consider pragmas as calls because they from the syntactical
   --  point of view they are very similar to subprogram calls

   function Are_Of_Same_Priority
     (Op1, Op2 : Flat_Element_Kinds)
      return     Boolean;
   --  Check if Op1 and Op2 are of the same priority level (unary and binary
   --  adding operations are considered as being of different levels

   function Operator_Len (Op : Element) return Natural;
   --  Assuming that Op is an operator element, returns the length of the
   --  argument text image

   function Can_Be_Aligned (El : Element) return Boolean;
   --  Check if El is a construct for which component alignment does make
   --  sense.

   function Is_First_Association (El : Element) return Boolean;
   --  Check if El is the first association in the association list. Returns
   --  False for any non-association element.
   --  If the argument association is from a subprogram call, and if this
   --  call is given in Object.Operation notation, then this query returns
   --  True for the firts association that is given in brackets, that is,
   --  for the association that is not first, but SECOND in the association
   --  list!

   function Is_First_Prefix_Notation_Parameter (El : Element) return Boolean;
   --  Checks if El is a parameter association representing the first parameter
   --  in function or procedure call given in prafixed notation (that is,
   --  Object form Object.Opeartion (...))

   function Get_First_Par (El : Element) return Element;
   --  Returns the first actual parameter (not a parameter association!) from
   --  the argument function or procedure call. It is an error to call this
   --  function for an argument that is not of A_Function_Call or
   --  A_Procedure_Call_Statement kind.

   function Is_Part_Of_Generic_Formal_Part (El : Element) return Boolean;
   --  Check if El a part of the generic formal part (it may be a declaration
   --  of a generic formal parameter, a use clause or a pragma). This function
   --  assumes that the enclosing element of its argument is a generic
   --  declaration.

   function Is_Last_Pragma_In_Formal_Part (El : Element) return Boolean;
   --  Checks if El is a pragma element and it is a last element in a generic
   --  formal part

   function Is_Assignment_Expression (El : Element) return Boolean;
   --  Checks that the argument is the right-hand expression in an assignment
   --  statement.

   function First_Operand (El : Element) return Element;
   --  This function assumes that its argument is an infix call of a binary
   --  operation. It consider its argument as a sequence of operands and
   --  operators of the same priority (that is 'A + B + C + D' is considered as
   --  a sum of four items but not as '(A + B + C) + D'). It returns the first
   --  operand component of this sequence (that is, A in that example). In case
   --  if we have an unary adding operation in this sequence, this function
   --  returns a call to this unary operation (that is, in case of
   --  '- A + B - C + D' what is returned is '- A' but not just 'A')

   function Is_Terminal_Element (E : Element) return Boolean;
   --  Checks if the argument is a terminal Element (that is, an element with
   --  no components)

   function Split_Paragraph (E : Element) return Boolean;
   --  Checks if the given construct splits a sequense of "alignable" constucts
   --  into more than one paragraph

   function Decompose_Selected_Component (E : Element) return Element_List;
   --  If E is An_Identifier Element, returns a list consisting of this
   --  element, Otherwise, supposing that E represnts an expanded name,
   --  decomposes it as a sequence of names making up this name (that is, for
   --  A.B.C the list containing three elements A, B and C is returned).

   function Is_Huge_Aggregate  (E : Element) return Boolean;
   --  Checks if E is too big to be properly formatted

   function Starts_From_New_Line  (E : Element) return Boolean;
   --  Checks if in the argument source the argument element is startted from
   --  the new line
end GNATPP.Asis_Utilities;
