File : asis-text.ads


------------------------------------------------------------------------------
--                                                                          --
--                 ASIS-for-GNAT IMPLEMENTATION COMPONENTS                  --
--                                                                          --
--                            A S I S . T E X T                             --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--                                                                          --
-- This   specification   is   adapted  from  the  Ada  Semantic  Interface --
-- Specification  (ASIS)  definition,  ISO/IEC  15291,  Working Draft.  In  --
-- accordance with the (expected) copyright of the ASIS definition, you can --
-- freely  copy  and  modify  this  specification,  provided  that  if  you --
-- redistribute  a  modified  version,  any  changes that you have made are --
-- clearly indicated.                                                       --
--                                                                          --
------------------------------------------------------------------------------

--  The content of this  specification is taken "as is" from ASIS 2.0.R,
--  except context clauses and the content of the private part.
--  The code is reformatted to follow the GNAT coding style rules

------------------------------------------------------------------------------
--  20 package Asis.Text
------------------------------------------------------------------------------
------------------------------------------------------------------------------
package Asis.Text is
------------------------------------------------------------------------------
------------------------------------------------------------------------------
--  Asis.Text
--
--  This package encapsulates a set of operations to access the text of ASIS
--  Elements.  It assumes no knowledge of the existence, location, or form of
--  the program text.
--
--  The text of a program consists of the texts of one or more compilations.
--  The text of each compilation is a sequence of separate lexical elements.
--  Each lexical element is either a delimiter, an identifier (which can be a
--  reserved word), a numeric literal, a character literal, a string literal,
--  blank space, or a comment.
--
--  Each ASIS Element has a text image whose value is the series of characters
--  contained by the text span of the Element.  The text span covers all the
--  characters from the first character of the Element through the last
--  character of the Element over some range of lines.
--
--  General Usage Rules:
--
--  Line lists can be indexed to obtain individual lines.  The bounds of each
--  list correspond to the lines with those same numbers from the compilation
--  text.
--
--  Any Asis.Text query may raise ASIS_Failed with a Status of Text_Error if
--  the program text cannot be located or retrieved for any reason such as
--  renaming, deletion, corruption, or moving of the text.
------------------------------------------------------------------------------
------------------------------------------------------------------------------
--  20.1  type Line
------------------------------------------------------------------------------
--  An Ada text line abstraction (a private type).
--
--  Used to represent text fragments from a compilation.
--  ASIS Lines are representations of the compilation text.
--  This shall be supported by all ASIS implementations.
------------------------------------------------------------------------------

   type Line is private;
   Nil_Line  : constant Line;

   function "=" (Left  : in Line; Right : in Line) return Boolean is abstract;

--  Nil_Line is the value of an uninitialized Line object.
--
------------------------------------------------------------------------------
--  20.2  type Line_Number
------------------------------------------------------------------------------
--  Line_Number
--
--  A numeric subtype that allows each ASIS implementation to place constraints
--  on the upper bound for Line_List elements and compilation unit size.
--
--  The upper bound of Line_Number (Maximum_Line_Number) is the only
--  allowed variation for these declarations.
--
--  Line_Number = 0 is reserved to act as an "invalid" Line_Number value.  No
--  unit text line will ever have a Line_Number of zero.
------------------------------------------------------------------------------
--  Line shall be an undiscriminated private type, or, shall be derived from an
--  undiscriminated private type.  It can be declared as a new type or as a
--  subtype of an existing type.
------------------------------------------------------------------------------

   Maximum_Line_Number : constant ASIS_Natural :=
      Implementation_Defined_Integer_Constant;

   subtype Line_Number is ASIS_Natural range 0 .. Maximum_Line_Number;

------------------------------------------------------------------------------
--  20.3  type Line_Number_Positive
------------------------------------------------------------------------------

   subtype Line_Number_Positive is Line_Number range 1 .. Maximum_Line_Number;

------------------------------------------------------------------------------
--  20.4  type Line_List
------------------------------------------------------------------------------

   type Line_List is array (Line_Number_Positive range <>) of Line;
   Nil_Line_List : constant Line_List;

------------------------------------------------------------------------------
--  20.5  type Character_Position
------------------------------------------------------------------------------
--  Character_Position
--
--  A numeric subtype that allows each ASIS implementation to place constraints
--  on the upper bound for Character_Position and for compilation unit line
--  lengths.
--
--  The upper bound of Character_Position (Maximum_Line_Length) is the
--  only allowed variation for these declarations.
--
--  Character_Position = 0 is reserved to act as an "invalid"
--  Character_Position value.  No unit text line will ever have a character in
--  position zero.
------------------------------------------------------------------------------

   Maximum_Line_Length : constant ASIS_Natural :=
      Implementation_Defined_Integer_Constant;

   subtype Character_Position is ASIS_Natural range 0 .. Maximum_Line_Length;

------------------------------------------------------------------------------
--  20.6  type Character_Position_Positive
------------------------------------------------------------------------------

   subtype Character_Position_Positive is
      Character_Position range 1 .. Maximum_Line_Length;

------------------------------------------------------------------------------
--  20.7  type Span
------------------------------------------------------------------------------
--  Span
--
--  A single text position is identified by a line number and a column number,
--  that represent the text's position within the compilation unit.
--
--  The text of an element can span one or more lines.  The textual Span of an
--  element identifies the lower and upper bound of a span of text positions.
--
--  Spans and positions give client tools the option of accessing compilation
--  unit text through the queries provided by this package, or, to access
--  the text directly through the original compilation unit text file. Type
--  span
--  facilitates the capture of comments before or after an element.
--
--  Note: The original compilation unit text may or may not have existed in a
--  "file", and any such file may or may not still exist. Reference Manual 10.1
--  specifies that the text of a compilation unit is submitted to a compiler.
--  It does not specify that the text is stored in a "file", nor does it
--  specify that the text of a compilation unit has any particular lifetime.
------------------------------------------------------------------------------

   type Span is                                       -- Default is Nil_Span
      record
         First_Line   : Line_Number_Positive        := 1; -- 1..0 - empty
         First_Column : Character_Position_Positive := 1; -- 1..0 - empty
         Last_Line    : Line_Number                 := 0;
         Last_Column  : Character_Position          := 0;
      end record;

   Nil_Span : constant Span := (First_Line   => 1,
                                First_Column => 1,
                                Last_Line    => 0,
                                Last_Column  => 0);

------------------------------------------------------------------------------
--  20.8  function First_Line_Number
------------------------------------------------------------------------------

   function First_Line_Number (Element : in Asis.Element) return Line_Number;

------------------------------------------------------------------------------
--  Element - Specifies the element to query
--
--  Returns the first line number on which the text of the element resides.
--
--  Returns 0 if not Is_Text_Available(Element).
--
--  --|AN Application Note:
--  --|AN
--  --|AN The line number recorded for a particular element may or may not
--  --|AN match the "true" line number of the program text for that element if
--  --|AN the Ada environment and the local text editors do not agree on the
--  --|AN definition of "line". For example, the Reference Manual states that
--  --|AN any occurrence of an Ascii.Cr character is to be treated as one or
--  --|AN more end-of-line occurrences.  On most Unix systems, the editors do
--  --|AN not treat a carriage return as being an end-of-line character.
--  --|AN
--  --|AN Ada treats all of the following as end-of-line characters: Ascii.Cr,
--  --|AN Ascii.Lf, Ascii.Ff, Ascii.Vt.  It is up to the compilation system to
--  --|AN determine whether sequences of these characters causes one, or more,
--  --|AN end-of-line occurrences.  Be warned, if the Ada environment and the
--  --|AN system editor (or any other line-counting program) do not use the
--  --|AN same end-of-line conventions, then the line numbers reported by ASIS
--  --|AN may not match those reported by those other programs.
--
------------------------------------------------------------------------------
--  20.9  function Last_Line_Number
------------------------------------------------------------------------------

   function Last_Line_Number (Element : in Asis.Element) return Line_Number;

------------------------------------------------------------------------------
--  Element - Specifies the element to query
--
--  Returns the last line number on which the text of the element resides.
--
--  Returns 0 if not Is_Text_Available(Element).
--
------------------------------------------------------------------------------
--  20.10 function Element_Span
------------------------------------------------------------------------------

   function Element_Span (Element : in Asis.Element) return Span;

------------------------------------------------------------------------------
--  Element - Specifies the element to query
--
--  Returns the span of the given element.
--
--  Returns a Nil_Span if the text of a Compilation_Unit (Compilation) cannot
--  be located for any reason.
--  --|AN
--  --|AN For this query, Element is only a means to access the
--  --|AN Compilation_Unit (Compilation), the availability of the text of this
--  --|AN Element itself is irrelevant to the result of the query.
--
------------------------------------------------------------------------------
--  20.11 function Compilation_Unit_Span
------------------------------------------------------------------------------

   function Compilation_Unit_Span (Element : in Asis.Element) return Span;

------------------------------------------------------------------------------
--  Element - Specifies the element to query
--
--  Returns the span of the text comprising the enclosing compilation unit of
--  the given element.
--
--  Returns a Nil_Span if the text of a Compilation_Unit (Compilation) cannot
--  be located for any reason.
--  --|AN
--  --|AN For this query, Element is only a means to access the
--  --|AN Compilation_Unit (Compilation), the availability of the text of this
--  --|AN Element itself is irrelevant to the result of the query.
--
------------------------------------------------------------------------------
--  20.12 function Compilation_Span
------------------------------------------------------------------------------

   function Compilation_Span (Element : in Asis.Element) return Span;

------------------------------------------------------------------------------
--  Element - Specifies the element to query
--
--  Returns the span of the text comprising the compilation to which the
--  element belongs.  The text span may include one or more compilation units.
--
--  Returns a Nil_Span if not Is_Text_Available(Element).
--
------------------------------------------------------------------------------
--  20.13 function Is_Nil
------------------------------------------------------------------------------

   function Is_Nil (Right : in Line) return Boolean;

------------------------------------------------------------------------------
--  Right   - Specifies the line to check
--
--  Returns True if the argument is the Nil_Line.
--
--  A Line from a Line_List obtained from any of the Lines functions
--  will not be Is_Nil even if it has a length of zero.
--
------------------------------------------------------------------------------
--  20.14 function Is_Nil
------------------------------------------------------------------------------

   function Is_Nil (Right : in Line_List) return Boolean;

------------------------------------------------------------------------------
--  Right   - Specifies the line list to check
--
--  Returns True if the argument has a 'Length of zero.
--

------------------------------------------------------------------------------
--  20.15 function Is_Nil
------------------------------------------------------------------------------

   function Is_Nil (Right : in Span) return Boolean;

------------------------------------------------------------------------------
--  Right   - Specifies the Span to check
--
--  Returns True if the argument has a Nil_Span.
--
------------------------------------------------------------------------------
--  20.16 function Is_Equal
------------------------------------------------------------------------------

   function Is_Equal (Left  : in Line; Right : in Line) return Boolean;

------------------------------------------------------------------------------
--  Left    - Specifies the first of the two lines
--  Right   - Specifies the second of the two lines
--
--  Returns True if the two lines encompass the same text (have the same Span
--  and are from the same compilation).
--
------------------------------------------------------------------------------
--  20.17 function Is_Identical
------------------------------------------------------------------------------

   function Is_Identical (Left  : in Line; Right : in Line) return Boolean;

------------------------------------------------------------------------------
--  Left    - Specifies the first of the two lines
--  Right   - Specifies the second of the two lines
--
--  Returns True if the two lines encompass the same text (have the same Span
--  and are from the same compilation) and are from the same Context.
--
------------------------------------------------------------------------------
--  20.18 function Length
------------------------------------------------------------------------------

   function Length (The_Line : in Line) return Character_Position;

------------------------------------------------------------------------------
--  The_Line    - Specifies the line to query
--
--  Returns the length of the line.
--
--  Raises ASIS_Inappropriate_Line if Is_Nil (The_Line).
--
------------------------------------------------------------------------------
--  20.19 function Lines
------------------------------------------------------------------------------

   function Lines (Element : in Asis.Element) return Line_List;

------------------------------------------------------------------------------
--  Element - Specifies the element to query
--
--  Returns a list of lines covering the span of the given program element.
--
--  Returns a Nil_Span if the text of a Compilation containing a given
--  Element cannot be located for any reason.
--
--  Line lists can be indexed to obtain individual lines.  The bounds of each
--  list correspond to the lines with those same numbers in the compilation
--  text.
--
--  The first Line of the result contains text from the compilation starting at
--  the First_Line/First_Column of Element's Span.  The last Line of the result
--  contains text from the compilation ending at the Last_Line/Last_Column of
--  the Element's Span.  Text before or after those limits is not reflected
--  in the returned list.
--  --|AN
--  --|AN For this query, Element is only a means to access the
--  --|AN Compilation_Unit (Compilation), the availability of the text of this
--  --|AN Element itself is irrelevant to the result of the query.
--
------------------------------------------------------------------------------
--  20.20 function Lines
------------------------------------------------------------------------------

   function Lines
     (Element  : in Asis.Element;
      The_Span : in Span)
      return Line_List;

------------------------------------------------------------------------------
--  Element  - Specifies the element to query
--  The_Span - Specifies the textual span to return
--
--  Returns a list of lines covering the given span from the compilation
--  containing the given program element.
--
--  Returns a Nil_Span if the text of a Compilation containing a given
--  Element cannot be located for any reason.
--
--  This operation can be used to access lines from text outside the span of an
--  element, but still within the compilation.  For example, lines containing
--  preceding comments or lines between two elements.
--
--  Line lists can be indexed to obtain individual lines.  The bounds of each
--  list correspond to the lines with those same numbers in the compilation
--  text.
--
--  The first Line of the result contains text from the compilation starting at
--  line Span.First_Line and column Span.First_Column.  The last Line of the
--  result contains text from the compilation ending at line Span.Last_Line and
--  column Span.Last_Column.  Text before or after those limits is not
--  reflected in the returned list.
--
--  Raises ASIS_Inappropriate_Line_Number if Is_Nil (The_Span). If
--  The_Span defines a line whose number is outside the range of text lines
--  that can be accessed through the Element, the implementation is encouraged,
--  but not required to raise ASIS_Inappropriate_Line_Number.
--  --|AN
--  --|AN For this query, Element is only a means to access the
--  --|AN Compilation_Unit (Compilation), the availability of the text of this
--  --|AN Element itself is irrelevant to the result of the query.
--
------------------------------------------------------------------------------
--  20.21 function Lines
------------------------------------------------------------------------------

   function Lines
     (Element    : in Asis.Element;
      First_Line : in Line_Number_Positive;
      Last_Line  : in Line_Number)
      return Line_List;

------------------------------------------------------------------------------
--  Element     - Specifies the element to query
--  First_Line  - Specifies the first line to return
--  Last_Line   - Specifies the last line to return
--
--  Returns a list of Lines covering the full text for each of the indicated
--  lines from the compilation containing the given element.  This operation
--  can be used to access lines from text outside the span of an element, but
--  still within the compilation.
--
--  Returns a Nil_Span if the text of a Compilation containing a given
--  Element cannot be located for any reason.
--
--  Line lists can be indexed to obtain individual lines.  The bounds of each
--  list correspond to the lines with those same numbers in the compilation
--  text.
--
--  Raises ASIS_Inappropriate_Line_Number if the span is nil. If the span
--  defines a line whose number is outside the range of text lines that can be
--  accessed through the Element, the implementation is encouraged, but not
--  required to raise ASIS_Inappropriate_Line_Number.
--  --|AN
--  --|AN For this query, Element is only a means to access the
--  --|AN Compilation_Unit (Compilation), the availability of the text of this
--  --|AN Element itself is irrelevant to the result of the query.
--
------------------------------------------------------------------------------
--  20.22 function Delimiter_Image
------------------------------------------------------------------------------

   function Delimiter_Image return Wide_String;

------------------------------------------------------------------------------
--  Returns the string used as the delimiter separating individual lines of
--  text within the program text image of an element. It is also used as the
--  delimiter separating individual lines of strings returned by Debug_Image.
--
------------------------------------------------------------------------------
--  20.23 function Element_Image
------------------------------------------------------------------------------

   function Element_Image (Element : in Asis.Element) return Program_Text;

------------------------------------------------------------------------------
--  Element - Specifies the element to query
--
--  Returns a program text image of the element.  The image of an element can
--  span more than one line, in which case the program text returned by the
--  function Delimiter_Image separates the individual lines.  The bounds on
--  the returned program text value are 1..N, N is as large as necessary.
--
--  Returns a null string if not Is_Text_Available(Element).
--
--  If an Element's Span begins at column position P, the returned program text
--  will be padded at the beginning with P-1 white space characters (Ascii.' '
--  or Ascii.Ht).  The first character of the Element's image will thus begin
--  at character P of the returned program text. Due to the possible presence
--  of Ascii.Ht characters, the "column" position of characters within the
--  image might not be the same as their print-column positions when the image
--  is displayed on a screen or printed.
--
--  NOTE: The image of a large element can exceed the range of Program_Text.
--  In this case, the exception ASIS_Failed is raised with a Status of
--  Capacity_Error. Use the Lines function to operate on the image of large
--  elements.
--
------------------------------------------------------------------------------
--  20.24 function Line_Image
------------------------------------------------------------------------------

   function Line_Image (The_Line : in Line) return Program_Text;

------------------------------------------------------------------------------
--  The_Line    - Specifies the line to query
--
--  Returns a program text image of the line.  The image of a single lexical
--  element can be sliced from the returned value using the first and last
--  column character positions from the Span of the Element.  The bounds on the
--  returned program text are 1 .. Length(Line).
--
--  If the Line is the first line from the Lines result for an Element, it can
--  represent only a portion of a line from the original compilation.  If the
--  span began at character position P, the first Line of it's Lines
--  result is padded at the beginning with P-1 white space characters
--  (Ascii.' ' or Ascii.Ht).  The first character of the image will
--  thus begin at character P of the program text for the first Line. Due to
--  the possible presence of Ascii.Ht characters, the "column" position of
--  characters within the image may not be the same as their print-column
--  positions when the image is displayed or printed.
--
--  Similarly, if the Line is the last line from the Lines result for an
--  Element, it may represent only a portion of a line from the original
--  compilation.  The program text image of such a Line is shorter than the
--  line from compilation and will contain only the initial portion of
--  that line.
--
--  Raises ASIS_Inappropriate_Line if Is_Nil (The_Line).
--
------------------------------------------------------------------------------
--  20.25 function Non_Comment_Image
------------------------------------------------------------------------------

   function Non_Comment_Image (The_Line : in Line) return Program_Text;

------------------------------------------------------------------------------
--  The_Line    - Specifies the line to query
--
--  Returns a program text image of a Line up to, but excluding, any comment
--  appearing in that Line.
--
--  The value returned is the same as that returned by the Image function,
--  except that any hyphens ("--") that start a comment, and any characters
--  that follow those hyphens, are dropped.
--
--  The bounds on the returned program text are 1..N, where N is one less than
--  the column of any hyphens ("--") that start a comment on the line.
--
--  Raises ASIS_Inappropriate_Line if Is_Nil (The_Line).
--
------------------------------------------------------------------------------
--  20.26 function Comment_Image
------------------------------------------------------------------------------

   function Comment_Image (The_Line : in Line) return Program_Text;

------------------------------------------------------------------------------
--  The_Line    - Specifies the line to query
--
--  Returns a program text image of any comment on that line, excluding any
--  lexical elements preceding the comment.
--
--  The value returned is the same as that returned by the Image function,
--  except that any program text prior to the two adjacent hyphens ("--") which
--  start a comment is replaced by an equal number of spaces.  If the hyphens
--  began in column P of the Line, they will also begin in character position
--  P of the returned program text.
--
--  A null string is returned if the line has no comment.
--
--  The bounds of the program text are 1..N, where N is as large as necessary.
--
--  Raises ASIS_Inappropriate_Line if Is_Nil (The_Line).
--
------------------------------------------------------------------------------
--  20.27 function Is_Text_Available
------------------------------------------------------------------------------

   function Is_Text_Available (Element : in Asis.Element) return Boolean;

------------------------------------------------------------------------------
--  Element - Specifies the element to query
--
--  Returns True if the implementation can return a valid text image for the
--  given element.
--
--  Returns False for any Element that Is_Nil, Is_Part_Of_Implicit, or
--  Is_Part_Of_Instance.
--
--  Returns False if the text of the element cannot be located for any reason
--  such as renaming, deletion, or moving of text.
--
--  --|IR Implementation Requirements:
--  --|IR
--  --|IR An implementation shall make text available for all explicit
--  --|IR elements.
--
------------------------------------------------------------------------------
--  20.28 function Debug_Image
------------------------------------------------------------------------------

   function Debug_Image (The_Line : in Line) return Wide_String;

------------------------------------------------------------------------------
--  The_Line    - Specifies the line to convert
--
--  Returns a string value containing implementation-defined debug
--  information associated with the line.
--
--  The return value uses Asis.Text.Delimiter_Image to separate the lines
--  of multi-line results.  The return value does not end with
--  Asis.Text.Delimiter_Image.
--
--  These values are intended for two purposes.  They are suitable for
--  inclusion in problem reports sent to the ASIS implementor.  They can
--  be presumed to contain information useful when debugging the
--  implementation itself. They are also suitable for use by the ASIS
--  application when printing simple application debugging messages during
--  application development.  They are intended to be, to some worthwhile
--  degree, intelligible to the user.
--
------------------------------------------------------------------------------

private

   --  The content of this private part is specific for the ASIS
   --  implementation for GNAT

------------------------------------------------------------------------------

   type Line is
      record
         Sloc              : Source_Ptr         := No_Location;
         Length            : Character_Position := 0;
         Rel_Sloc          : Source_Ptr         := No_Location;
         Enclosing_Unit    : Unit_Id            := Nil_Unit;
         Enclosing_Context : Context_Id         := Non_Associated;
         Enclosing_Tree    : Tree_Id            := Nil_Tree;
         Obtained          : ASIS_OS_Time       := Nil_ASIS_OS_Time;
      end record;

   Nil_Line : constant Line := (Sloc              => No_Location,
                                Length            => 0,
                                Rel_Sloc          => No_Location,
                                Enclosing_Unit    => Nil_Unit,
                                Enclosing_Context => Non_Associated,
                                Enclosing_Tree    => Nil_Tree,
                                Obtained          => Nil_ASIS_OS_Time);

   --  Note, that Line does not have the predefined "=" operation (it is
   --  overridden by an abstract "=". The predefined "=" is explicitly
   --  simulated in the implementation of Is_Nil query, so, if the full
   --  declaration for Line is changed, the body of Is_Nil should be revised.

   -----------------------------
   -- Fields in the Line type --
   -----------------------------

   --  Sloc : Source_Ptr         := No_Location;
   --    indicates the beginning of the corresponding line in the Source
   --    Buffer. If a given Line is the first line covering the Image of
   --    some Element, the position in the Source Buffer pointed by Sloc
   --    may or may not correspond to the beginning of the source text
   --    line
   --  Length : Character_Position := 0;
   --    represents the length of the Line, excluding any character
   --    signifying end of line (RM95, 2.2(2))
   --  Rel_Sloc : Source_Ptr := No_Location;
   --    needed to compare string representing elements of the same
   --    compilation units, but probably obtained from different trees
   --    containing this unit. Obtained in the same way as for Elements -
   --    by subtracting from Sloc field the source location of the
   --    N_Compilation_Unit node
   --  Enclosing_Unit    : Unit_Id    := Nil_Unit;
   --  Enclosing_Context : Context_Id := Non_Associated;
   --    These fields represent the Context in which and the Compilation
   --    Unit from which the given line was obtained, they are needed
   --    for comparing Lines and for tree swapping when obtaining
   --    Line_Image
   --  Enclosing_Tree : Tree_Id := Nil_Tree;
   --    Sloc field may be used for obtaining the image of a Line only in
   --    the tree from which it was obtained. So the Line has to keep
   --    the reference to the tree for tree swapping
   --  Obtained : ASIS_OS_Time := Nil_ASIS_OS_Time;
   --    Lines, as well as Elements, cannot be used after closing the
   --    Context from which they were obtained. We use time comparing
   --    to check the validity of a Line

   --  In the current implementation, ASIS Lines are mapped onto logical
   --  GNAT lines, as defined in the Sinput package.

   --  The child package Asis.Text.Set_Get defines operations for
   --  accessing and updating fields of Lines, for checking the validity
   --  of a Line and for creating the new value of the Line type.
   --  (This package is similar to the Asis.Set_Get package, which
   --  defines similar things for other ASIS abstractions - Element,
   --  Context, Compilation_Unit.)

   Nil_Line_List : constant Line_List (1 .. 0) := (1 .. 0 => Nil_Line);

------------------------------------------------------------------------------

end Asis.Text