6.6. Langkit support

These units are part of Libadalang’s public API indirectly. Libadalang is a library generated via the Langkit framework, and as such, it depends on Langkit’s runtime, which is Langkit support. Some parts of Langkit support are thus part of the public API of Libadalang.

6.6.1. Langkit_Support.Diagnostics

This package provides a data type for diagnostics produced by Langkit generated libraries.

type Diagnostic
Components:
  • Sloc_Range (Langkit_Support.Slocs.Source_Location_Range) – The source location range that the diagnostic message refers to

  • Message (Unbounded_Text_Type) – Message for this diagnostic

Message for this diagnostic

function To_Pretty_String (D : Diagnostic) Standard.String

Pretty prints the given diagnostic.

Note

This is only intended for quick pretty printing in debugging for example. If you want more powerful and pretty output of diagnostics, use :ada:ref`Langkit_Support.Diagnostics.Output`.

function Create (Sloc_Range : Langkit_Support.Slocs.Source_Location_Range; Message : Standard.Wide_Wide_String) Diagnostic

Shortcut to create a diagnostic

package Diagnostics_Vectors is new Ada.Containers.Vectors
package Diagnostics_Vectors is new Ada.Containers.Vectors
     (Index_Type   => Positive,
      Element_Type => Diagnostic);
Instantiated generic package:

Diagnostics_Vectors

type Diagnostics_Array
procedure Append (Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector; Sloc_Range : Langkit_Support.Slocs.Source_Location_Range; Message : Standard.Wide_Wide_String)

Shortcut to append a diagnostic to a vector

procedure Append (Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector; Sloc_Range : Langkit_Support.Slocs.Source_Location_Range; Exc : Ada.Exceptions.Exception_Occurrence)

Shortcut to append an exception message to a vector

procedure Sort (Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector)

Sort diagnostics by sloc range

procedure Print (Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector; Prefix : Standard.String; Indent : Standard.Natural)

Print all diagnostics in Diagnostics on the standard output, with Prefix before each message. For multi-line messages, insert Indent spaces before each line except the first one.

6.6.2. Langkit_Support.Diagnostics.Output

This package supports outputting Diagnostic for a source buffer, in a pretty colorized format akin to GCC’s verbose diagnostic format.

Note

For the moment, this package has a few limitations, namely:

  • Only source buffers with LF line endings are handled.

  • Only error messages spanning one line are gracefully handled. eventually we want to have something more powerful that has a syntax for error spanning multiple lines.

type Diagnostic_Style
Components:
  • Label (Unbounded_Text_Type) – Label for the diagnostic

  • Color (GNATCOLL.Terminal.ANSI_Color) – Color for the diagnostic

Color for the diagnostic

Default_Diagnostic_Style : constant Diagnostic_Style
Object type:

Diagnostic_Style

Default value:

(To_Unbounded_Text ("error"), Red)

Default style

Info_Diagnostic_Style : constant Diagnostic_Style
Object type:

Diagnostic_Style

Default value:

(To_Unbounded_Text ("info"), Grey)

procedure Print_Diagnostic (Self : Diagnostic; Buffer : Text_Buffer_Ifc'Class; Path : Standard.String; Style : Diagnostic_Style; Output_File : Ada.Text_IO.File_Type)

Pretty-print given diagnostic. Outputs the diagnostic on stdout in a form that is developer friendly when used in a command line application.

Error messages format supports backticked parts that should correspond to references to source entities, and that will be highlighted in the resulting source.

Here is an example of output:

foo.bar:1:9: Incorrect call to `Foolize`
1 | Foo.Bar.Foolize
            ^^^^^^^

Output_File is set by default to Standard_Output, you can use Standard_Error alternatively.

You can also customize the style, which allows you to change the label of the diagnostic (by default it’s “error”), and the color of the message (red by default).

TODO: All the information necessary to print a diagnostic should eventually be self contained.

6.6.3. Langkit_Support.Errors

This package contains definitions for exceptions common to all Langkit-generated libraries.

Native_Exception: exception
Precondition_Failure: exception
Property_Error: exception
Invalid_Unit_Name_Error: exception
Invalid_Symbol_Error: exception
Stale_Reference_Error: exception
Unknown_Charset: exception
Invalid_Input: exception
Syntax_Error: exception
File_Read_Error: exception
package Langkit_Support.Errors.Introspection
Bad_Type_Error: exception
Out_Of_Bounds_Error: exception
package Langkit_Support.Errors.Unparsing
Malformed_Tree_Error: exception
package Langkit_Support.Errors.Rewriting
Template_Format_Error: exception
Template_Args_Error: exception
Template_Instantiation_Error: exception

6.6.4. Langkit_Support.File_Readers

This packages provides an interface to abstract away the action of reading a source file to parse. Depending on use cases, it allows to override bytes-to-text decoding and preprocess sources (before actual lexing/parsing).

type File_Contents
Components:
  • Buffer (Ada.Strings.Unbounded.String_Access) –

  • First (Standard.Positive) –

  • Last (Standard.Natural) –

function Create_File_Contents (Buffer : Standard.String) File_Contents

Create a File_Contents value that contains a copy of Buffer

type Decoded_File_Contents
Components:
  • Buffer (Text_Access) –

  • First (Standard.Positive) –

  • Last (Standard.Natural) –

function Create_Decoded_File_Contents (Buffer : Text_Type) Decoded_File_Contents

Create a Decoded_File_Contents value that contains a copy of Buffer.

procedure Decode_Buffer (Buffer : Standard.String; Charset : Standard.String; Read_BOM : Standard.Boolean; Contents : Decoded_File_Contents; Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector)

Decode the bytes in Buffer according to Charset/Read_BOM into Contents. The bytes decoding itself is delegated to GNATCOLL.Iconv.

If there is an error during this process, append an error message to Diagnostics. In that case, Contents is considered uninitialized.

procedure Direct_Read (Filename : Standard.String; Charset : Standard.String; Read_BOM : Standard.Boolean; Contents : Decoded_File_Contents; Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector)

Simple implementation of Read to read the source file through GNATCOLL.Mmap and to decode it using GNATCOLL.Iconv.

procedure Canonicalize_Line_Endings (Self : Decoded_File_Contents)

Canonicalize CRLF to LF in place

type File_Fetcher_Interface

Interface to override how source files are fetched

procedure Fetch (Self : File_Fetcher_Interface; Filename : Standard.String; Contents : File_Contents; Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector)

Fetch the content of the source at Filename.

If there is an error during this process, append an error message to Diagnostics.

Whether there are errors or not, allocate a String buffer, fill it and initialize Contents to refer to it.

procedure Release (Self : File_Fetcher_Interface)

Actions to perform when releasing resources associated to Self

procedure Do_Release (Self : File_Fetcher_Interface'Class)

Helper for the instantiation below

package File_Fetcher_References is new GNATCOLL.Refcount.Shared_Pointers
package File_Fetcher_References is new GNATCOLL.Refcount.Shared_Pointers
     (File_Fetcher_Interface'Class, Do_Release);
Instantiated generic package:

File_Fetcher_References

type File_Fetcher_Reference
No_File_Fetcher_Reference : File_Fetcher_Reference renames File_Fetcher_References.Null_Ref
Object type:

File_Fetcher_Reference

Renames:

File_Fetcher_References.Null_Ref

function Create_File_Fetcher_Reference (File_Fetcher : File_Fetcher_Interface'Class) File_Fetcher_Reference

Simple wrapper around the GNATCOLL.Refcount API to create file fetcher references.

function Create_Filesystem_Fetcher () File_Fetcher_Reference

Return a file fetcher instance that just reads file from the filesystem

type File_Stub_Store

Store for file stubs: filename/file content associations that “override” the actual files on the filesystem. This is the data structure that powers the “stubbing” file fetcher: see the Create_File_Stubbing_Fetcher function below.

Note that this type has by-reference semantics, so that the store passed to Create_File_Stubbing_Store can be mutated with the Stub_File and Reset_File procedures even after the file fetcher has been created.

function Create_File_Stub_Store () File_Stub_Store

Return an empty file stub store

procedure Stub_File (Self : File_Stub_Store; Filename : Standard.String; Content : Ada.Strings.Unbounded.Unbounded_String)

Add an association for Filename/Content to Self. If there aws already an association for Filename, this new association replaces it.

procedure Reset_File (Self : File_Stub_Store; Filename : Standard.String)

If Self contains a stub for Filename, remove it. This is a no-op otherwise.

function Create_Stubbing_Fetcher (Store : File_Stub_Store) File_Fetcher_Reference

Create a file fetcher backed by the given file stub Store

type File_Refiner_Interface

Interface to override how the contents of source files (as bytes) are refined.

procedure Refine (Self : File_Refiner_Interface; Filename : Standard.String; Contents : File_Contents; Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector)

Refine the content of a source file (Contents, the bytes content for the file fetched at Filename) in place.

If there is an error during this process, append an error message to Diagnostics.

Whether there are errors or not, Contents must refer to a correctly initialized buffer.

procedure Release (Self : File_Refiner_Interface)

Actions to perform when releasing resources associated to Self

procedure Do_Release (Self : File_Refiner_Interface'Class)

Helper for the instantiation below

package File_Refiner_References is new GNATCOLL.Refcount.Shared_Pointers
package File_Refiner_References is new GNATCOLL.Refcount.Shared_Pointers
     (File_Refiner_Interface'Class, Do_Release);
Instantiated generic package:

File_Refiner_References

type File_Refiner_Reference
No_File_Refiner_Reference : File_Refiner_Reference renames File_Refiner_References.Null_Ref
Object type:

File_Refiner_Reference

Renames:

File_Refiner_References.Null_Ref

function Create_File_Refiner_Reference (File_Refiner : File_Refiner_Interface'Class) File_Refiner_Reference

Simple wrapper around the GNATCOLL.Refcount API to create file fetcher references.

type File_Refiner_Array
Empty_File_Refiner_Array : constant File_Refiner_Array
Object type:

File_Refiner_Array

Default value:

(1 .. 0 => <>)

function Create_File_Reader_Reference (Fetcher : File_Fetcher_Reference; Refiners : File_Refiner_Array) File_Reader_Reference

Create a file reader as the composition of a file fetcher and a chain of file refiners. The resulting file buffers are decoded using Decode_Buffer.

type File_Reader_Interface

Interface to override how source files are fetched and decoded

procedure Read (Self : File_Reader_Interface; Filename : Standard.String; Charset : Standard.String; Read_BOM : Standard.Boolean; Contents : Decoded_File_Contents; Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector)

Read the content of the source at Filename, decoding it using the given Charset and decoding the byte order mark if Read_BOM is True.

If there is an error during this process, append an error message to Diagnostics.

Whether there are errors or not, allocate a Text_Type buffer, fill it and initialize Contents to refer to it.

procedure Release (Self : File_Reader_Interface)

Actions to perform when releasing resources associated to Self

procedure Do_Release (Self : File_Reader_Interface'Class)

Helper for the instantiation below

package File_Reader_References is new GNATCOLL.Refcount.Shared_Pointers
package File_Reader_References is new GNATCOLL.Refcount.Shared_Pointers
     (File_Reader_Interface'Class, Do_Release);
Instantiated generic package:

File_Reader_References

type File_Reader_Reference
No_File_Reader_Reference : File_Reader_Reference renames File_Reader_References.Null_Ref
Object type:

File_Reader_Reference

Renames:

File_Reader_References.Null_Ref

function Create_File_Reader_Reference (File_Reader : File_Reader_Interface'Class) File_Reader_Reference

Simple wrapper around the GNATCOLL.Refcount API to create file reader references.

6.6.5. Langkit_Support.Generic_API

Note

At this stage, this package is considered as internal.

This package and its children provide generic APIs so that programs can work with all Langkit-generated libraries.

type Any_Language_Id
No_Language_Id : constant Any_Language_Id
Object type:

Any_Language_Id

function Language_Name (Id : Language_Id) Name_Type

Return the name of the language that the library corresponding to Id analyzes.

function Default_Grammar_Rule (Id : Language_Id) Grammar_Rule_Ref

Return the default grammar rule for the given language

function Last_Grammar_Rule (Id : Language_Id) Grammar_Rule_Index

Return the index of the last grammar rule for the given language

type Language_Id

Unique identifier for a Langkit-generated library.

All operations done using the generic API are done in the context of a Langkit-generated library. Because of this, all subprograms in the Generic_API packages take, in one way or another, an argument that contains a reference to the language ID for that library: a Language_Id argument directly, or for instance a Lk_Node argument (analysis contexts/units/nodes contain references to the language ID).

Note however that some subprograms accept null values for library-sensitive arguments, for instance they accept No_Lk_Node for their Lk_Node argument. The special No_Lk_Node value contains no reference to a particular Langkit-generated library. So even though such subprograms take a Lk_Node argument, they also need to take a Language_Id argument to receive the language ID information in all cases.

type Grammar_Rule_Ref

Reference to a grammar rule for a given language

No_Grammar_Rule_Ref : constant Grammar_Rule_Ref
Object type:

Grammar_Rule_Ref

Special value to express no grammar rule reference

function Language (Rule : Grammar_Rule_Ref) Language_Id

Return the language ID corresponding to the given grammar rule. Raise a Precondition_Failure exception if Rule is No_Grammar_Rule_Ref.

function Grammar_Rule_Name (Rule : Grammar_Rule_Ref) Name_Type

Return the name for the given grammar rule. Raise a Precondition_Failure exception if Rule is No_Grammar_Rule_Ref.

function Is_Public (Rule : Grammar_Rule_Ref) Standard.Boolean

Return whether the given grammar rule is public. Raise a Precondition_Failure exception if Rule is No_Grammar_Rule_Ref.

function Grammar_Rule_Doc (Rule : Grammar_Rule_Ref) Text_Type

Return the doc associated to this grammar rule. Raise a Precondition_Failure exception if Rule is No_Grammar_Rule_Ref.

function To_Index (Rule : Grammar_Rule_Ref) Grammar_Rule_Index

Return the index of the given grammar rule. Raise a Precondition_Failure exception if Rule is No_Grammar_Rule_Ref.

function From_Index (Id : Language_Id; Rule : Grammar_Rule_Index) Grammar_Rule_Ref

Return the grammar rule for the given language corresponding to the Rule index. Raise a Precondition_Failure exception if Rule is not a valid grammar rule index for the given language.

type Any_Grammar_Rule_Index
No_Grammar_Rule_Index : constant Any_Grammar_Rule_Index
Object type:

Any_Grammar_Rule_Index

Default value:

0

Language-specific index to designate a grammar rule.

A given languages accepts N grammar rules, so the only valid indexes for it are 1 .. N. The Last_Grammar_Rule function below gives the actual N for a given language.

type Grammar_Rule_Index
type Token_Kind_Ref

Reference to a token kind for a given language

No_Token_Kind_Ref : constant Token_Kind_Ref
Object type:

Token_Kind_Ref

Special value to express no token kind reference

function Language (Kind : Token_Kind_Ref) Language_Id

Return the language ID corresponding to the given token kind. Raise a Precondition_Failure exception if Kind is No_Token_Kind_Ref.

function Token_Kind_Name (Kind : Token_Kind_Ref) Name_Type

Return the name for the given token kind. Raise a Precondition_Failure exception if Kind is No_Token_Kind_Ref.

function Is_Comment (Kind : Token_Kind_Ref) Standard.Boolean

Return whether unparsing must treat the given token kind as a comment, i.e. a trivia to preserve in unparsed sources. Raise a Precondition_Failure exception if Kind is No_Token_Kind_Ref.

function To_Index (Kind : Token_Kind_Ref) Token_Kind_Index

Return the index of the given token kind. Raise a Precondition_Failure exception if Kind is No_Token_Kind_Ref.

function From_Index (Id : Language_Id; Kind : Token_Kind_Index) Token_Kind_Ref

Return the token kind for the given language corresponding to the Kind index. Raise a Precondition_Failure exception if Kind is not a valid token kind index for the given language.

function Last_Token_Kind (Id : Language_Id) Token_Kind_Index

Return the index of the last token kind for the given language

function Token_Family (Kind : Token_Kind_Ref) Token_Family_Ref

Return the token family that owns tokens of the given Kind. Raise a Precondition_Failure exception if Kind is No_Token_Kind.

type Any_Token_Kind_Index
No_Token_Kind_Index : constant Any_Token_Kind_Index
Object type:

Any_Token_Kind_Index

Default value:

0

Language-specific index to designate a token kind.

A given languages accepts N token kinds, so the only valid indexes for it are 1 .. N. The Last_Token_Kind function below gives the actual N for a given language.

type Token_Kind_Index
type Token_Family_Ref

Reference to a token family for a given language

No_Token_Family_Ref : constant Token_Family_Ref
Object type:

Token_Family_Ref

Special value to express no token family reference

function Language (Family : Token_Family_Ref) Language_Id

Return the language ID corresponding to the given token family. Raise a Precondition_Failure exception if Family is No_Token_Family_Ref.

function Token_Family_Name (Family : Token_Family_Ref) Name_Type

Return the name for the given token family. Raise a Precondition_Failure exception if Family is No_Token_Family_Ref.

function To_Index (Family : Token_Family_Ref) Token_Family_Index

Return the index of the given token family. Raise a Precondition_Failure exception if Family is No_Token_Family_Ref.

function From_Index (Id : Language_Id; Family : Token_Family_Index) Token_Family_Ref

Return the token family for the given language corresponding to the Family index. Raise a Precondition_Failure exception if Family is not a valid token family index for the given language.

function Last_Token_Family (Id : Language_Id) Token_Family_Index

Return the index of the last token family for the given language

type Any_Token_Family_Index
No_Token_Family_Index : constant Any_Token_Family_Index
Object type:

Any_Token_Family_Index

Default value:

0

Language-specific index to designate a token family.

A given languages accepts N token families, so the only valid indexes for it are 1 .. N. The Last_Token_Family function below gives the actual N for a given language.

type Token_Family_Index

6.6.6. Langkit_Support.Generic_API.Analysis

Note

At this stage, this package is considered as internal.

This package provides a generic API so that programs can work with the $.Analysis packages of all Langkit-generated libraries.

type Lk_Context
No_Lk_Context : constant Lk_Context
Object type:

Lk_Context

Special value to mean the absence of analysis context

function Create_Context (Language : Language_Id; Charset : Standard.String; File_Reader : File_Reader_Reference; With_Trivia : Standard.Boolean; Tab_Stop : Standard.Natural) Lk_Context

Create a new analysis context.

Charset will be used as a default charset to decode input sources in analysis units. Please see GNATCOLL.Iconv for several supported charsets. Be careful: passing an unsupported charset is not guaranteed to raise an error here. If no charset is provided, use the language default.

When With_Trivia is true, the parsed analysis units will contain trivias.

If provided, File_Reader will be used to fetch the contents of source files instead of the default, which is to just read it from the filesystem and decode it using the regular charset rules. Note that if provided, all parsing APIs that provide a buffer are forbidden, and any use of the rewriting API with the returned context is rejected.

Tab_Stop is a positive number to describe the effect of tabulation characters on the column number in source files.

function Language (Self : Lk_Context) Language_Id

Return the unique identifier for the Langkit-generated library that implements Context.

function Hash (Self : Lk_Context) Ada.Containers.Hash_Type

Hash function to use Lk_Context in hashed containers

function Has_With_Trivia (Self : Lk_Context) Standard.Boolean

Return whether Context keeps trivia when parsing units

function Has_Unit (Self : Lk_Context; Unit_Filename : Standard.String) Standard.Boolean

Return whether Context contains a unit corresponding to Unit_Filename.

function Context (Self : Lk_Unit'Class) Lk_Context

Return the context that owns this unit

type Lk_Unit
No_Lk_Unit : constant Lk_Unit
Object type:

Lk_Unit

Special value to mean the absence of analysis unit

function Get_From_File (Self : Lk_Context'Class; Filename : Standard.String; Charset : Standard.String; Reparse : Standard.Boolean; Rule : Grammar_Rule_Ref) Lk_Unit

Create a new analysis unit for Filename or return the existing one if any. If Reparse is true and the analysis unit already exists, reparse it from Filename.

Rule controls which grammar rule is used to parse the unit. If No_Grammar_Rule_Ref, use the default grammar rule for this language.

Use Charset in order to decode the source. If Charset is empty then use the context’s default charset.

If any failure occurs, such as file opening, decoding, lexing or parsing failure, return an analysis unit anyway: errors are described as diagnostics of the returned analysis unit.

It is invalid to pass True to Reparse if a rewriting context is active.

function Get_From_Buffer (Self : Lk_Context'Class; Filename : Standard.String; Buffer : Standard.String; Charset : Standard.String; Rule : Grammar_Rule_Ref) Lk_Unit

Create a new analysis unit for Filename or return the existing one if any. Whether the analysis unit already exists or not, (re)parse it from the source code in Buffer.

Rule controls which grammar rule is used to parse the unit. If No_Grammar_Rule_Ref, use the default grammar rule for this language.

Use Charset in order to decode the source. If Charset is empty then use the context’s default charset.

If any failure occurs, such as file opening, decoding, lexing or parsing failure, return an analysis unit anyway: errors are described as diagnostics of the returned analysis unit.

Calling this is invalid if a rewriting context is active.

function Language (Self : Lk_Unit) Language_Id

Return the unique identifier corresponding to Self

function Hash (Self : Lk_Unit) Ada.Containers.Hash_Type

Hash function to use Lk_Unit in hashed containers

procedure Reparse_From_File (Self : Lk_Unit; Charset : Standard.String)

Reparse Self from the associated file.

Use Charset in order to decode the source. If Charset is empty then use the context’s default charset.

procedure Reparse_From_Buffer (Self : Lk_Unit; Buffer : Standard.String; Charset : Standard.String)

Reparse Self from an in-memory buffer.

Use Charset in order to decode the source. If Charset is empty then use the context’s default charset.

function Get_Line (Self : Lk_Unit; Line_Number : Standard.Positive) Text_Type

Return the line of text at line number Line_Number

function Filename (Self : Lk_Unit) Standard.String

Return the filename this unit is associated to

function Charset (Self : Lk_Unit) Standard.String

Return the charset that was used to parse Self

function Has_Diagnostics (Self : Lk_Unit) Standard.Boolean

Return whether this unit has associated diagnostics

function Diagnostics (Self : Lk_Unit) Diagnostics_Array

Return an array that contains the diagnostics associated to this unit

function Format_GNU_Diagnostic (Self : Lk_Unit; D : Diagnostic) Standard.String

Format a diagnostic in a GNU fashion. See <https://www.gnu.org/prep/standards/html_node/Errors.html>.

function Text (Self : Lk_Unit) Text_Type

Return the source buffer associated to this unit

procedure Print (Self : Lk_Unit; Show_Slocs : Standard.Boolean)

Debug helper: output this unit’s parse tree and any diagnostics it has on standard output.

If Show_Slocs is true, include the nodes source locations in the output.

function Unit (Self : Lk_Node'Class) Lk_Unit

Return the unit that owns this node

function Unit (Self : Lk_Token'Class) Lk_Unit

Return the unit that owns this token

type Lk_Node
No_Lk_Node : constant Lk_Node
Object type:

Lk_Node

Special value to mean the absence of analysis node

function Root (Self : Lk_Unit'Class) Lk_Node

Return the root node for this unit, or No_Lk_Node if there is none.

function Language (Self : Lk_Node) Language_Id

Return the unique identifier corresponding to Self

function Hash (Self : Lk_Node) Ada.Containers.Hash_Type

Hash function to use Lk_Node in hashed containers

function Is_Null (Self : Lk_Node) Standard.Boolean

Return whether Node is a null node reference

function "=" (Left, Right : Lk_Node) Standard.Boolean

Return whether Left and Right designate the same node.

Note that, unlike other operations accepting multiple generic types, checking equality is allowed for nodes coming from different languages.

function Image (Self : Lk_Node) Standard.String

Return a short string describing Node, or "None" if Node.Is_Null is true.

procedure Print (Node : Lk_Node; Show_Slocs : Standard.Boolean; Line_Prefix : Standard.String)

Debug helper: print to standard output Node and all its children.

If Show_Slocs, include the source location of each node in the output.

Line_Prefix is prepended to each output line.

function Parent (Self : Lk_Node'Class) Lk_Node

Return the syntactic parent for Node. Return a null node for the root one.

function Parents (Self : Lk_Node; With_Self : Standard.Boolean) Lk_Node_Array

Return an array that contains the lexical parents, this node included iff with_self is True. Nearer parents are first in the list.

function Children_Count (Self : Lk_Node) Standard.Natural

Return the number of children Node has

procedure Get_Child (Self : Lk_Node'Class; Index : Standard.Positive; Index_In_Bounds : Standard.Boolean; Result : Lk_Node)

Return the Index’th child of node, storing it into Result.

Child indexing is 1-based. Store in Index_In_Bounds whether Node had such a child: if not (i.e. Index is out-of-bounds), set Result to a null node.

function Child (Self : Lk_Node'Class; Index : Standard.Positive) Lk_Node

Return the Index’th child of Node, or null if Node has no such child.

function Children (Self : Lk_Node) Lk_Node_Array

Return the children in Node

function Next_Sibling (Self : Lk_Node'Class) Lk_Node

Return the Node’s next sibling, or null if there is no such sibling

function Previous_Sibling (Self : Lk_Node'Class) Lk_Node

Return the Node’s previous sibling, or null if there is no such sibling.

function Closest_Common_Parent (Self, Other : Lk_Node'Class) Lk_Node

If Self and Other do not belong to the same analysis unit, return No_Lk_Node. Otherwise, return the deepest node in the tree that is a parent for both Self and Other.

function Is_Ghost (Self : Lk_Node) Standard.Boolean

Return whether the node is a ghost.

Unlike regular nodes, ghost nodes cover no token in the input source: they are logically located instead between two tokens. Both the token_start and the token_end of all ghost nodes is the token right after this logical position.

function Traverse (Self : Lk_Node; Visit : access function (Node : Lk_Node) return Visit_Status) Visit_Status

Call Visit on Node and all its children, transitively. Calls happen in prefix order (i.e. top-down and left first). The traversal is controlled as follows by the result returned by Visit:

Into

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

Over

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

Stop

The entire traversal is immediately abandoned, and the original call to Traverse returns Stop.

procedure Traverse (Self : Lk_Node; Visit : access function (Node : Lk_Node) return Visit_Status)

This is the same as Traverse function except that no result is returned i.e. the Traverse function is called and the result is simply discarded.

function Text (Self : Lk_Node) Text_Type

Return the source buffer slice corresponding to the text that spans between the first and the last tokens of this node.

Note that this returns the empty string for synthetic nodes.

function Sloc_Range (Self : Lk_Node) Langkit_Support.Slocs.Source_Location_Range

Return the spanning source location range for this node.

Note that this returns the sloc of the parent for synthetic nodes.

function Compare (Node : Lk_Node; Sloc : Langkit_Support.Slocs.Source_Location) Langkit_Support.Slocs.Relative_Position

Compare Sloc to the sloc range of Node

function Lookup (Self : Lk_Node'Class; Sloc : Langkit_Support.Slocs.Source_Location) Lk_Node

Look for the bottom-most node in the Self subtree whose sloc range contains Sloc. Return it, or No_Lk_Node if no such node was found.

function Is_Incomplete (Self : Lk_Node) Standard.Boolean

Return whether this node is incomplete, i.e. whether its parsing partially failed.

function Children_And_Trivia (Self : Lk_Node) Node_Or_Token_Sequence

Return the children of this node interleaved with Trivia token nodes, so that:

  • Every trivia contained between Node.Start_Token and Node.End_Token.Previous will be part of the returned array.

  • Nodes and trivias will be lexically ordered.

type Lk_Token

Reference types to actual context/unit/node/token objects. Only Lk_Context and Lk_Unit are strong references (designated object lives as long as the reference exists): Lk_Node and Lk_Token_Ref are weak references (designated object may be destroyed even if there are still references to it, but usage of such a stale reference is properly rejected).

No_Lk_Token : constant Lk_Token
Object type:

Lk_Token

function First_Token (Self : Lk_Unit'Class) Lk_Token

Return a reference to the first token scanned in this unit

function Last_Token (Self : Lk_Unit'Class) Lk_Token

Return a reference to the last token scanned in this unit

function Lookup_Token (Self : Lk_Unit'Class; Sloc : Langkit_Support.Slocs.Source_Location) Lk_Token

Look for a token in Self that contains the given source location. If this falls before the first token, return the first token. If this falls between two tokens, return the token that appears before. If this falls after the last token, return the last token. If there is no token in this unit, return No_Lk_Token.

function Token_Start (Self : Lk_Node'Class) Lk_Token

Return the first token used to parse this node

function Token_End (Self : Lk_Node'Class) Lk_Token

Return the last token used to parse this node

function Language (Self : Lk_Token) Language_Id

Return the unique identifier corresponding to Self

function Hash (Self : Lk_Token) Ada.Containers.Hash_Type

Hash function to use Lk_Token in hashed containers

function Is_Null (Self : Lk_Token) Standard.Boolean

Return whether Self is a null token reference

function Kind (Self : Lk_Token) Token_Kind_Ref

Return the token kind for Self

function "<" (Left, Right : Lk_Token) Standard.Boolean

Assuming Left and Right belong to the same analysis unit, return whether Left came before Right in the source file.

Raise a Precondition_Failure error if they do not belong to the same analysis unit.

function Next (Self : Lk_Token'Class; Exclude_Trivia : Standard.Boolean) Lk_Token

Return a reference to the next token in the corresponding analysis unit

function Previous (Self : Lk_Token'Class; Exclude_Trivia : Standard.Boolean) Lk_Token

Return a reference to the previous token in the corresponding analysis unit.

function Image (Self : Lk_Token) Standard.String

Debug helper: return a human-readable text to represent a token

function Text (Self : Lk_Token) Text_Type

Return the text of the token as Text_Type

function Text (First, Last : Lk_Token) Text_Type

Compute the source buffer slice corresponding to the text that spans between the First and Last tokens (both included). This yields an empty slice if Last actually appears before First.

This raises a Precondition_Failure if First and Last don’t belong to the same analysis unit.

function Is_Comment (Self : Lk_Token) Standard.Boolean

Return whether unparsing must treat the given token kind as a comment, i.e. a trivia to preserve in unparsed sources. Return False if passed a null token.

function Is_Trivia (Self : Lk_Token) Standard.Boolean

Return whether this token is not null and is a trivia

function Index (Self : Lk_Token) Langkit_Support.Token_Data_Handlers.Token_Index

One-based index for this token/trivia. Tokens and trivias get their own index space.

function Sloc_Range (Self : Lk_Token) Langkit_Support.Slocs.Source_Location_Range

Source location range for this token. Note that the end bound is exclusive.

function Is_Equivalent (Left, Right : Lk_Token) Standard.Boolean

Return whether Left and Right are structurally equivalent tokens. This means that their position in the stream won’t be taken into account, only the kind and text of the token.

function Origin_Filename (Self : Lk_Token) Standard.String

Return the name of the file whose content was scanned to create Token. Return an empty string if the source comes from a memory buffer instead of a file.

function Origin_Charset (Self : Lk_Token) Standard.String

Return the charset used to decode the source that was scanned to create Token. Return an empty string if the source was already decoded during the scan.

function Token_Count (Self : Lk_Unit'Class) Standard.Natural

Return the number of tokens in this unit

function Trivia_Count (Self : Lk_Unit'Class) Standard.Natural

Return the number of trivias in this unit. This is 0 for units that were parsed with trivia analysis disabled.

type Lk_Node_Array
function Is_Token_Node (Self : Lk_Node'Class) Standard.Boolean

Shortcut for Is_Token_Node (Type_Of (Self))

function Is_List_Node (Self : Lk_Node'Class) Standard.Boolean

Shortcut for Is_List_Node (Type_Of (Self))

type Visit_Status

Helper type to control the node traversal process. See the Traverse subprograms below.

type Node_Or_Token
Discriminants:
  • Is_Node (Standard.Boolean) –

Components:
type Node_Or_Token_Sequence

Iterable over a sequence of nodes and tokens.

Note that in principle, we would like to expose a vector of Node_Or_Token here. However, Ada validy rules prevent us from instantiating a generic with Lk_Node and Lk_Token, as they are private types.

function First (Self : Node_Or_Token_Sequence) Standard.Natural

Return the first item in Self (helper for the Iterable aspect)

function Last (Self : Node_Or_Token_Sequence) Standard.Natural

Return the last item in Self (helper for the Iterable aspect)

function Next (Self : Node_Or_Token_Sequence; Pos : Standard.Natural) Standard.Natural

Return the next item in Self (helper for the Iterable aspect)

function Previous (Self : Node_Or_Token_Sequence; Pos : Standard.Natural) Standard.Natural

Return the previous item in Self (helper for the Iterable aspect).

function Has_Element (Self : Node_Or_Token_Sequence; Pos : Standard.Natural) Standard.Boolean

Return if Pos is in Self’s iteration range (elper for the Iterable aspect).

function Element (Self : Node_Or_Token_Sequence; Pos : Standard.Natural) Node_Or_Token

Return the element at position Pos in Self (helper for the Iterable aspect).

6.6.7. Langkit_Support.Generic_API.Introspection

To facilitate use from a -gnatX project, since we don’t use the [] syntax

type Type_Ref

Reference to the type of a polymorphic value: boolean, integer, character, …

No_Type_Ref : constant Type_Ref
Object type:

Type_Ref

Special value to express no type reference

function Language (T : Type_Ref) Language_Id

Return the language ID corresponding to the given type. Raise a Precondition_Failure exception if T is No_Type_Ref.

function Debug_Name (T : Type_Ref) Standard.String

Return the free-form name of this type for debug purposes, or “<No_Type_Ref>” if T is No_Type_Ref.

function To_Index (T : Type_Ref) Type_Index

Return the index of the given type. Raise a Precondition_Failure exception if T is No_Type_Ref.

function Category (T : Type_Ref) Type_Category

Return the category of the given type

function Type_Of (Node : Lk_Node) Type_Ref

Return the type of Node. Raise a Precondition_Failure if Node is No_Lk_Node.

function Type_Matches (Node : Lk_Node; T : Type_Ref) Standard.Boolean

Overload of the Type_Matches function taking a Value_Ref argument, for convenience.

function Is_Enum_Type (T : Type_Ref) Standard.Boolean

Return whether T references an enum type.

All functions below will raise a Precondition_Failure if passed a type which does not satisfy this predicate as Enum formals.

function Enum_Type_Name (Enum : Type_Ref) Name_Type

Return the name of the given enum type

function Enum_Default_Value (Enum : Type_Ref) Enum_Value_Ref

Return the index of the default enum value for the given Enum enum type, or No_Enum_Value_Ref if this type does not have a default value.

function All_Enum_Values (Enum : Type_Ref) Enum_Value_Ref_Array

Return the list of all enum values for the given enum type

function From_Index (Enum : Type_Ref; Value : Enum_Value_Index) Enum_Value_Ref

Return the value for the given enum type corresponding to the Value index. Raise a Precondition_Failure exception if Value is not a valid value index for that enum type.

function Enum_Last_Value (Enum : Type_Ref) Enum_Value_Index

Return the index of the last enum value for the given Enum enum type

function Is_Array_Type (T : Type_Ref) Standard.Boolean

Return whether T references an array type.

All functions below will raise a Precondition_Failure if passed a type which does not satisfy this predicate as T formals.

function Array_Element_Type (T : Type_Ref) Type_Ref

Return the type of elements in T arrays

function Create_Array (T : Type_Ref; Values : Value_Ref_Array) Value_Ref

Create an array of the given T type, with the given Values. Raise a Precondition_Failure if any of the following is true:

  • T is null;

  • Values contains a null value reference;

  • Values contains a value that does not match T’s element type;

  • one Values item does not belong to the same language as T.

function Is_Iterator_Type (T : Type_Ref) Standard.Boolean

Return whether T references an iterator type.

All functions below will raise a Precondition_Failure if passed a type which does not satisfy this predicate as T formals.

function Iterator_Element_Type (T : Type_Ref) Type_Ref

Return the type of elements in T iterators

function Is_Base_Struct_Type (T : Type_Ref) Standard.Boolean

Return whether T references a struct or node type.

All functions below will raise a Precondition_Failure if passed a type which does not satisfy this predicate as T formals.

function Base_Struct_Type_Name (T : Type_Ref) Name_Type

Return the name for the given struct/node type

function Is_Struct_Type (T : Type_Ref) Standard.Boolean

Return whether T references a struct type.

All functions below will raise a Precondition_Failure if passed a type which does not satisfy this predicate as Struct formals.

function Struct_Type_Name (Struct : Type_Ref) Name_Type

Return the name for the given struct type

function Create_Struct (T : Type_Ref; Values : Value_Ref_Array) Value_Ref

Create a struct of the given T type, with the given Values. Raise a Precondition_Failure if any of the following is true:

  • T is null;

  • Values contains a null value reference;

  • Values does not match T’s fields, both in number or in types;

  • one Values item does not belong to the same language as T.

function Is_Node_Type (T : Type_Ref) Standard.Boolean

Return whether T references a node type.

All functions below will raise a Precondition_Failure if passed a type which does not satisfy this predicate as Node/Parent formals.

function Root_Node_Type (Id : Language_Id) Type_Ref

Return the type for the root node in the given language

function Node_Type_Name (Node : Type_Ref) Name_Type

Return the name for the given node type

function Node_Type_Repr_Name (Node : Type_Ref) Text_Type

Return the “representation” name (i.e. name used in text dumps) for the given node type.

function Is_Abstract (Node : Type_Ref) Standard.Boolean

Return whether Node designates an abstract node

function Is_Error_Node (Node : Type_Ref) Standard.Boolean

Return whether Node designates an error node

function Is_Synthetic (Node : Type_Ref) Standard.Boolean

Return whether Node designates a synthetic node

function Is_Token_Node (Node : Type_Ref) Standard.Boolean

Return whether Node designates a token node

function Token_Node_Kind (Node : Type_Ref) Token_Kind_Ref

Assuming that Node designates a token node and that the owning language has unparsers enabled, return the associated token kind.

function Is_List_Node (Node : Type_Ref) Standard.Boolean

Return whether Node designates a list node

function List_Element_Type (Node : Type_Ref) Type_Ref

Assuming that Node designates a list node, return the type for its elements. Raise a Precondition_Failure if Node does not designates a list node.

function Is_Concrete (Node : Type_Ref) Standard.Boolean
function Base_Type (Node : Type_Ref) Type_Ref

If Node is the root node type, raise a Bad_Type_Error exception. Otherwise, return Node’s base type.

function Derived_Types (Node : Type_Ref) Type_Ref_Array

Return type references for all direct derivations for Node

function Last_Derived_Type (Node : Type_Ref) Type_Index

Return the index of the Result type so that the Node .. Result range contains exactly all node types that derive (directly or indirectly) from Node.

function Is_Derived_From (Node, Parent : Type_Ref) Standard.Boolean

Return whether the Node node type derives (directly or indirectly) from Parent.

function Grammar_Rule_Type (Rule : Grammar_Rule_Ref) Type_Ref

Return the type for nodes that the given parsing Rule can create

function Members (Struct : Type_Ref) Struct_Member_Ref_Array

Return the list of members that Struct has

type Type_Ref_Array
function All_Types (Id : Language_Id) Type_Ref_Array

Return the list of all types that the given language defines

function All_Enum_Types (Id : Language_Id) Type_Ref_Array

Return the list of all enum types that the given language defines

function All_Array_Types (Id : Language_Id) Type_Ref_Array

Return the list of all array types that the given language defines

function All_Iterator_Types (Id : Language_Id) Type_Ref_Array

Return the list of all iterator types that the given language defines

function All_Base_Struct_Types (Id : Language_Id) Type_Ref_Array

Return the list of all base struct types that the given language defines

function All_Struct_Types (Id : Language_Id) Type_Ref_Array

Return the list of all struct types that the given language defines

function All_Node_Types (Id : Language_Id) Type_Ref_Array

Return the list of all node types that the given language defines

type Any_Type_Index

Language-specific index to designate a type.

A given language defines types for the 1 .. Last_Type (Language) range: see the Last_Type function below.

No_Type_Index : constant Any_Type_Index
Object type:

Any_Type_Index

Default value:

0

Special Any_Type_Index to mean: no reference to a type

function From_Index (Id : Language_Id; T : Type_Index) Type_Ref

Return the type for the given language corresponding to the T index. Raise a Precondition_Failure exception if T is not a valid type index for the given language.

function Last_Type (Id : Language_Id) Type_Index

Return the last type index that is valid for the given language

type Type_Index
type Type_Category

Each type has a category, which determines the kind of operation that can be performed on that type: for instance one can get the length of Array_Category-typed values.

type Value_Ref

Reference to a polymorphic value: boolean, integer, character, …

No_Value_Ref : constant Value_Ref
Object type:

Value_Ref

Special constant to express no value reference

function "=" (Left, Right : Value_Ref) Standard.Boolean

Return whether Left and Right are structurally equivalent

function Language (Value : Value_Ref) Language_Id

Return the language ID corresponding to the given value. Raise a Precondition_Failure exception if Value is No_Value_Ref.

function Type_Of (Value : Value_Ref) Type_Ref

Return the type of the Value polymorphic value. Raise a Precondition_Error if Value is No_Value_Ref.

function Type_Matches (Value : Value_Ref; T : Type_Ref) Standard.Boolean

Return whether Value is a valid value to be passed as a T argument.

Raise a Precondition_Error if:

  • Value is No_Value_Ref;

  • T is No_Type_Ref;

  • Value and T do not belong to the same language.

function Image (Value : Value_Ref) Standard.String

Return a string that represents Value, for logging/debugging purposes. Note that the goal here is to return a short human-readable string, not a string that contains all the information in Value.

Unlike other Value_Ref primitives, it is valid to call Image on No_Value_Ref.

function From_Unit (Id : Language_Id; Value : Lk_Unit) Value_Ref
function As_Unit (Value : Value_Ref) Lk_Unit
function From_Big_Int (Id : Language_Id; Value : GNATCOLL.GMP.Integers.Big_Integer) Value_Ref
function As_Big_Int (Value : Value_Ref) GNATCOLL.GMP.Integers.Big_Integer
function From_Bool (Id : Language_Id; Value : Standard.Boolean) Value_Ref
function As_Bool (Value : Value_Ref) Standard.Boolean
function From_Char (Id : Language_Id; Value : Character_Type) Value_Ref
function As_Char (Value : Value_Ref) Character_Type
function From_Int (Id : Language_Id; Value : Standard.Integer) Value_Ref
function As_Int (Value : Value_Ref) Standard.Integer
function From_Source_Location (Id : Language_Id; Value : Langkit_Support.Slocs.Source_Location) Value_Ref
function As_Source_Location (Value : Value_Ref) Langkit_Support.Slocs.Source_Location
function From_Source_Location_Range (Id : Language_Id; Value : Langkit_Support.Slocs.Source_Location_Range) Value_Ref
function As_Source_Location_Range (Value : Value_Ref) Langkit_Support.Slocs.Source_Location_Range
function From_String (Id : Language_Id; Value : Text_Type) Value_Ref
function As_String (Value : Value_Ref) Text_Type
function From_Token (Id : Language_Id; Value : Lk_Token) Value_Ref
function As_Token (Value : Value_Ref) Lk_Token
function From_Symbol (Id : Language_Id; Value : Text_Type) Value_Ref
function As_Symbol (Value : Value_Ref) Text_Type
function From_Node (Id : Language_Id; Value : Lk_Node) Value_Ref
function As_Node (Value : Value_Ref) Lk_Node
function As_Enum (Value : Value_Ref) Enum_Value_Ref

Assuming Value is an enum value, return the corresponding Enum_Value_Ref. Raise a Precondition_Failure exception if Value is not an enum value.

function As_Array (Value : Value_Ref) Value_Ref_Array

Return values for all items in the Value array. Raise a Precondition_Failure if Value is null or if it does not reference an array.

function Array_Length (Value : Value_Ref) Standard.Natural

Return the length of the given Value array. Raise a Precondition_Failure if Value is null or if it does not reference an array.

function Array_Item (Value : Value_Ref; Index : Standard.Positive) Value_Ref

Return the item at the given Index in the Value array. Raise a Precondition_Failure if any of the following is true:

  • Value is null;

  • it does not reference an array;

  • Index is out of bounds for this array value.

function Iterator_Next (Value : Value_Ref) Value_Ref

Return the next item in the Value iterator, or No_Value_Ref if there is no item left in the iterator. Raise a Precondition_Failure if Value is null or not a reference to an iterator.

function Eval_Member (Value : Value_Ref; Member : Struct_Member_Ref; Arguments : Value_Ref_Array) Value_Ref

Evaluate the given Member of Value with the given Arguments and return the result value. Raise a Precondition_Failure if any of the following is true:

  • Value is null, or not a struct;

  • Member is null, does not belong to the same language as Value, or not a valid member for Value;

  • Arguments does not match the arguments that Member expects.

function Eval_Member (Value : Value_Ref; Member : Struct_Member_Ref; Arguments : Value_Ref_Array) Value_Or_Error

Likewise, but also return an exception occurrence if the evaluation triggers a managed error.

Note that this function may still propagate an exception itself, but in that case, it is because Eval_Member is incorrectly used: an error is returned only if it is the evaluated member that raises an exception.

type Value_Ref_Array
type Enum_Value_Ref

Reference to an enum type value

No_Enum_Value_Ref : constant Enum_Value_Ref
Object type:

Enum_Value_Ref

Special value to express no enum value reference

function Enum_For (Value : Enum_Value_Ref) Type_Ref

Return the enum type that owns the given value

function Enum_Value_Name (Value : Enum_Value_Ref) Name_Type

Return the name corresponding to the Index``th value for the ``Enum enum type. This raises a Out_Of_Bounds_Error if Index is too big for this enum type.

function Debug_Name (Value : Enum_Value_Ref) Standard.String

Return “X.Y” where X is the enum type and Y is the name of this value, or “<No_Enum_Value_Ref>” if Value is null.

function To_Index (Value : Enum_Value_Ref) Enum_Value_Index

Return the index of the given type. Raise a Precondition_Failure exception if Value is No_Enum_Value_Ref.

function Create_Enum (Value : Enum_Value_Ref) Value_Ref

Convert an Enum_Value_Ref into the corresponding Value_Ref

type Enum_Value_Ref_Array
type Any_Enum_Value_Index
No_Enum_Value_Index : constant Any_Enum_Value_Index
Object type:

Any_Enum_Value_Index

Default value:

0

Special Any_Enum_Value_Index to mean: no reference to a type

type Enum_Value_Index

Index of an enum value for a given enum type

type Struct_Member_Ref

Reference to a struct member (field or property)

No_Struct_Member_Ref : constant Struct_Member_Ref
Object type:

Struct_Member_Ref

Special value to express no struct member reference

function Language (Member : Struct_Member_Ref) Language_Id

Return the language ID corresponding to the given struct member. Raise a Precondition_Failure exception if Member is No_Struct_Member_Ref.

function Debug_Name (Member : Struct_Member_Ref) Standard.String

Return “X.Y” where X is the type that owns this member and Y is the name of this member, or “<No_Struct_Member_Ref>” if Member is null.

function Owner (Member : Struct_Member_Ref) Type_Ref

Return the type that owns this member. Raise a Precondition_Failure exception if Member is No_Struct_Member_Ref.

function Is_Property (Member : Struct_Member_Ref) Standard.Boolean

Whether Member is a property

function Is_Field (Member : Struct_Member_Ref) Standard.Boolean

Whether Member is a field (simple field for structs, syntax field for nodes).

function Is_Null_For (Member : Struct_Member_Ref; Node : Type_Ref) Standard.Boolean

Return whether Member is a syntax field that is always null for Node.

function Syntax_Field_Index (Member : Struct_Member_Ref; Node : Type_Ref) Standard.Positive

Return the 1-based index corresponding to the given Member in the given Node type.

Raise a Precondition_Failure exception if:

  • Node is not a valid node type;

  • Node is not a concrete node type;

  • Member is not a syntax field for Node;

  • Member is a null syntax field for Node.

function Member_Name (Member : Struct_Member_Ref) Name_Type

Return the name of Member

function Member_Type (Member : Struct_Member_Ref) Type_Ref

Return the type of Member

function To_Index (Member : Struct_Member_Ref) Struct_Member_Index

Return the index of the given struct member. Raise a Precondition_Failure exception if Member is No_Struct_Member.

function Member_Argument_Type (Member : Struct_Member_Ref; Argument : Argument_Index) Type_Ref

Return the type of the given property argument

function Member_Argument_Name (Member : Struct_Member_Ref; Argument : Argument_Index) Name_Type

Return the name of the given property argument

function Member_Argument_Default_Value (Member : Struct_Member_Ref; Argument : Argument_Index) Value_Ref

Return the default value for the given property argument, or No_Value_Ref if it has no default value.

function Member_Last_Argument (Member : Struct_Member_Ref) Any_Argument_Index

Return the index of Member’s last argument according to the given language. If it has no argument, return No_Argument_Index.

function Eval_Node_Member (Value : Lk_Node; Member : Struct_Member_Ref; Arguments : Value_Ref_Array) Value_Ref

Shortcut for Eval_Member, working directly on a node

function Eval_Node_Member (Value : Lk_Node; Member : Struct_Member_Ref; Arguments : Value_Ref_Array) Value_Or_Error

Shortcut for Eval_Member, working directly on a node and returning exception occurences.

function Eval_Syntax_Field (Value : Lk_Node; Member : Struct_Member_Ref) Lk_Node

Shortcut for Eval_Member, valid for syntax fields only

type Struct_Member_Ref_Array
function All_Members (Id : Language_Id) Struct_Member_Ref_Array

Return all struct members that the given language defines

type Any_Struct_Member_Index
No_Struct_Member : constant Any_Struct_Member_Index
Object type:

Any_Struct_Member_Index

Default value:

0

Special Any_Struct_Member_Index to mean: no reference to an argument

function From_Index (Id : Language_Id; Member : Struct_Member_Index) Struct_Member_Ref

Return the struct member for the given language corresponding to the Member index. Raise a Precondition_Failure exception if Member is not a valid member index for the given language.

function Last_Struct_Member (Id : Language_Id) Struct_Member_Index

Return the last struct member index that is valid for the given language

type Struct_Member_Index

Language-specific index to designate a struct member.

A given language defines members for the 1 .. Last_Struct_Member (Language) range: see the Last_Struct_Member function below.

type Any_Argument_Index
No_Argument_Index : constant Any_Argument_Index
Object type:

Any_Argument_Index

Default value:

0

type Argument_Index

Index of a property argument

type Value_Or_Error
Discriminants:
  • Is_Error (Standard.Boolean) –

Components:
  • Value (Value_Ref) –

  • Error (Ada.Exceptions.Exception_Occurrence) –

type Name_Map

Map from names to enum types, enum values, struct types and struct members for a given casing convention and a given language.

function Create_Name_Map (Id : Language_Id; Symbols : Symbol_Table; Enum_Types : Casing_Convention; Enum_Values : Casing_Convention; Struct_Types : Casing_Convention; Struct_Members : Casing_Convention) Name_Map

Return a map from names to types, values and members for the given language. Names are encoded according to the given casing convention for each kind of entity, and internalized using the Symbols symbol table.

function Lookup_Type (Self : Name_Map; Name : Symbol_Type) Type_Ref

Look for an enum/struct type indexed in Self called Name. Return it if there is one, or No_Type_Ref is no type matches that name. The casing convention used for Name must match with the one used to create Self.

function Lookup_Enum_Value (Self : Name_Map; Enum : Type_Ref; Name : Symbol_Type) Enum_Value_Ref

Look in Self for the enum value called Name for the given Enum type. Return it if there is one, or No_Enum_Value_Ref is no value matches that name. The casing convention used for Name must match with the one used to create Self.

function Lookup_Struct_Member (Self : Name_Map; Struct : Type_Ref; Name : Symbol_Type) Struct_Member_Ref

Look for the Struct member called Name. Return it if there is one, or No_Struct_Member_Ref if this struct type has no such member. The casing convention used for Name must match with the one used to create Self.

6.6.8. Langkit_Support.Generic_API.Rewriting

This package provides support for tree-based source code rewriting.

6.6.8.1. General workflow

The starting point to rewrite a source file is to parse it into a Lk_Unit object, which belongs to a Lk_Context object (see Analysis). At this point, a rewriting session must be started for the whole analysis context. This is done calling the Start_Rewriting function, which returns a context-wide rewriting handle. A rewriting session keeps track of all tree modification requests, which are not applied to the analysis context/units/nodes until the Apply function returns successfully.

Once the context-wide rewriting handle exists:

  • The Handle functions can be used to get a rewriting handle for each analysis unit (Unit_Rewriting_Handle) and parsing node (Node_Rewriting_Handle). Note that attempting to get the rewriting handle for a unit or a node is valid only for units with no syntax error): tree-based rewriting is supported only for source files that were successfully parsed.

  • Nodes can be modified through their rewriting handles using the Set_Child, Set_Text, Insert_*, Remove_Child, Replace and Rotate procedures.

  • They can also be created from scratch using the Clone, Create_* and Create_From_Template functions.

  • The root of an analysis unit can be changed with the Set_Root procedure.

  • Once done with all the desired tree modifications, the Apply function must be called to propagate all the requested changes to the analysis units/nodes (Lk_Unit / Lk_Node). Note that this does not modify the actual source files, but only their in-memomy representations. Since all tree transformations may not yield a correct syntax tree, Apply may fail: in that case, no modification is done, and this function returns a failing Apply_Result record that indicates which unit could not be re-parsed after unparsing, and the corresponding parsing errors.

    If Apply succeeds, the rewriting context is destroyed upon return. If it fails, the rewriting context is left unchanged.

  • Once a rewriting session has been started, it is also possible to discard it and all the tree modification it kept track of: calling the Abort_Rewriting procedure destroys the rewriting context.

Analysis contexts can have at most one rewriting session at a given time: once Start_Rewriting has returned a new rewriting context, a successful Apply function call or a Abort_Rewriting procedure call must be done before attempting to call :ada:ref``Start_Rewriting` again.

6.6.8.2. Comments/formatting preservation

The rewriting engine keeps track of the original node (Lk_Node) for each node rewriting handle: the handles created from parsing nodes (i.e. returned by the Handle function have an original node, and so does the handles returned by the Clone function when called on a rewriting handle that itself has an original node.

When unparsing a node rewriting handle that has an original node, trivias (comments and whitespaces) are recovered from the original node on a best effort basis. Comments and trivias that follow a removed/replaced node are lost.

type Rewriting_Handle

Handle for an analysis context rewriting session

No_Rewriting_Handle : constant Rewriting_Handle
Object type:

Rewriting_Handle

function Handle (Context : Lk_Context) Rewriting_Handle

Return the rewriting handle associated to Context, or No_Rewriting_Handle if Context is not being rewritten.

function Context (Handle : Rewriting_Handle) Lk_Context

Return the analysis context associated to Handle

function Language (Handle : Rewriting_Handle) Language_Id

Return the language associated to the given handle

function Start_Rewriting (Context : Lk_Context) Rewriting_Handle

Start a rewriting session for Context.

This handle will keep track of all changes to do on Context’s analysis units. Once the set of changes is complete, call the Apply procedure to actually update Context. This makes it possible to inspect the “old” Context state while creating the list of changes.

There can be only one rewriting session per analysis context, so this will raise an Existing_Rewriting_Handle_Error exception if Context already has a living rewriting session.

procedure Abort_Rewriting (Handle : Rewriting_Handle)

Discard all modifications registered in Handle and close Handle. This invalidates all related unit/node handles.

function Apply (Handle : Rewriting_Handle) Apply_Result

Apply all modifications to Handle’s analysis context. If that worked, close Handle and return (Success => True). Otherwise, reparsing did not work, so keep Handle and its Context unchanged and return details about the error that happened.

Note that on success, this invalidates all related unit/node handles.

function Unit_Handles (Handle : Rewriting_Handle) Unit_Rewriting_Handle_Array

Return the list of unit rewriting handles in the given context handle for units that the Apply primitive will modify.

function Create_Node (Handle : Rewriting_Handle; Kind : Type_Ref) Node_Rewriting_Handle

Create a new node of the given type, with empty text (for token nodes) or children (for regular nodes).

function Create_Token_Node (Handle : Rewriting_Handle; Kind : Type_Ref; Text : Text_Type) Node_Rewriting_Handle

Create a new token node with the given type and Text

function Create_Regular_Node (Handle : Rewriting_Handle; Kind : Type_Ref; Children : Node_Rewriting_Handle_Array) Node_Rewriting_Handle

Create a new regular node of the given type and assign it the given Children.

Except for lists, which can have any number of children, the size of Children must match the number of children associated to the given type. Besides, all given children must not be tied.

function Create_From_Template (Handle : Rewriting_Handle; Template : Text_Type; Arguments : Node_Rewriting_Handle_Array; Rule : Grammar_Rule_Ref) Node_Rewriting_Handle

Create a tree of new nodes from the given Template string, replacing placeholders with nodes in Arguments and parsed according to the given grammar Rule.

type Unit_Rewriting_Handle

Handle for the process of rewriting an analysis unit. Such handles are owned by a Rewriting_Handle instance.

No_Unit_Rewriting_Handle : constant Unit_Rewriting_Handle
Object type:

Unit_Rewriting_Handle

function Handle (Unit : Lk_Unit) Unit_Rewriting_Handle

Return the rewriting handle corresponding to Unit

function Unit (Handle : Unit_Rewriting_Handle) Lk_Unit

Return the unit corresponding to Handle

function Language (Handle : Unit_Rewriting_Handle) Language_Id
function Root (Handle : Unit_Rewriting_Handle) Node_Rewriting_Handle

Return the node handle corresponding to the root of the unit which Handle designates.

procedure Set_Root (Handle : Unit_Rewriting_Handle; Root : Node_Rewriting_Handle)

Set the root node for the unit Handle to Root. This unties the previous root handle. If Root is not No_Node_Rewriting_Handle, this also ties Root to Handle.

Root must not already be tied to another analysis unit handle.

function Unparse (Handle : Unit_Rewriting_Handle) Unbounded_Text_Type

Return the text associated to the given unit

type Node_Rewriting_Handle

Handle for the process of rewriting an AST node. Such handles are owned by a Rewriting_Handle instance.

No_Node_Rewriting_Handle : constant Node_Rewriting_Handle
Object type:

Node_Rewriting_Handle

function Handle (Node : Lk_Node) Node_Rewriting_Handle

Return the rewriting handle corresponding to Node`.

The owning unit of Node must be free of diagnostics.

function Node (Handle : Node_Rewriting_Handle) Lk_Node

Return the node which the given rewriting Handle relates to. This can be No_Lk_Node if this handle designates a new node.

function Context (Handle : Node_Rewriting_Handle) Rewriting_Handle

Return a handle for the rewriting context to which Handle belongs

function Language (Handle : Node_Rewriting_Handle) Language_Id
function Unparse (Handle : Node_Rewriting_Handle) Text_Type

Turn the given rewritten node Handle designates into text. This is the text that is used in Apply in order to re-create an analysis unit.

function Type_Of (Handle : Node_Rewriting_Handle) Type_Ref

Return the type reference corresponding to Handle’s node

function Image (Handle : Node_Rewriting_Handle) Standard.String

Return a representation of Handle as a string

function Tied (Handle : Node_Rewriting_Handle) Standard.Boolean

Return whether Handle is tied to an analysis unit. If it is not, it can be passed as the Child parameter to Set_Child.

function Parent (Handle : Node_Rewriting_Handle) Node_Rewriting_Handle

Return a handle for the node that is the parent of Handle’s node. This is No_Rewriting_Handle for a node that is not tied to any tree yet.

function Children_Count (Handle : Node_Rewriting_Handle) Standard.Natural

Return the number of children the node represented by Handle has

function Child (Handle : Node_Rewriting_Handle; Field : Struct_Member_Ref) Node_Rewriting_Handle

Return the node that is in the syntax Field for Handle

function Child (Handle : Node_Rewriting_Handle; Fields : Struct_Member_Ref_Array) Node_Rewriting_Handle

Return a child deep in the tree Handle.

Assuming Fields'Range is 1 .. N, this is a shortcut for:

C1 := Child (Handle, Fields (1));
C2 := Child (C1, Fields (2));
...
CN_1 := Child (CN_2, Fields (N - 1));
CN := Child (CN_1, Fields (N));
function Children (Handle : Node_Rewriting_Handle) Node_Rewriting_Handle_Array

Return the list of children for Handle

procedure Set_Child (Handle : Node_Rewriting_Handle; Field : Struct_Member_Ref; Child : Node_Rewriting_Handle)

If Child is No_Rewriting_Node, untie the syntax field in Handle corresponding to Field, so it can be attached to another one. Otherwise, Child must have no parent as it will be tied to Handle’s tree.

function Text (Handle : Node_Rewriting_Handle) Text_Type

Return the text associated to the given token node

procedure Set_Text (Handle : Node_Rewriting_Handle; Text : Text_Type)

Override text associated to the given token node

procedure Replace (Handle, New_Node : Node_Rewriting_Handle)

If Handle is the root of an analysis unit, untie it and set New_Node as its new root. Otherwise, replace Handle with New_Node in Handle’s parent node.

Note that:

  • Handle must be tied to an existing analysis unit handle.

  • New_Node must not already be tied to another analysis unit handle.

function Is_List_Node (Handle : Node_Rewriting_Handle) Standard.Boolean

Return whether Handle represents a list node

function First_Child (Handle : Node_Rewriting_Handle) Node_Rewriting_Handle

Assuming Handle refers to a list node, return a handle to its first child, or No_Node_Rewriting_Handle` if it has no child node.

function Last_Child (Handle : Node_Rewriting_Handle) Node_Rewriting_Handle

Assuming Handle refers to a list node, return a handle to its last child, or No_Node_Rewriting_Handle` if it has no child node.

function Next_Child (Handle : Node_Rewriting_Handle) Node_Rewriting_Handle

Assuming Handle refers to the child of a list node, return a handle to its next sibling, or No_Node_Rewriting_Handle` if it is the last sibling.

function Previous_Child (Handle : Node_Rewriting_Handle) Node_Rewriting_Handle

Assuming Handle refers to the child of a list node, return a handle to its previous sibling, or No_Node_Rewriting_Handle` if it is the first sibling.

procedure Insert_Before (Handle, New_Sibling : Node_Rewriting_Handle)

Assuming Handle refers to the child of a list node, insert New_Sibling as a new child in this list, right before Handle.

procedure Insert_After (Handle, New_Sibling : Node_Rewriting_Handle)

Assuming Handle refers to the child of a list node, insert New_Sibling as a new child in this list, right before Handle.

procedure Insert_First (Handle, New_Child : Node_Rewriting_Handle)

Assuming Handle refers to a list node, insert New_Child to be the first child in this list.

procedure Insert_Last (Handle, New_Child : Node_Rewriting_Handle)

Assuming Handle refers to a list node, insert New_Child to be the last child in this list.

procedure Remove_Child (Handle : Node_Rewriting_Handle)

Assuming Handle refers to the child of a list node, remove it from that list.

function Clone (Handle : Node_Rewriting_Handle) Node_Rewriting_Handle

Create a clone of the Handle node tree. The result is not tied to any analysis unit tree.

type Unit_Rewriting_Handle_Array
type Node_Rewriting_Handle_Array
procedure Rotate (Handles : Node_Rewriting_Handle_Array)

Given a list of node rewriting handles H1, H2, … HN, replace H1 by H2 in the rewritten tree, replace H2 by H3, etc. and replace HN by H1.

Note that this operation is atomic: if it fails, no replacement is actually performed.

type Apply_Result
Discriminants:
  • Success (Standard.Boolean) –

Components:
  • Unit (Lk_Unit) – Reference to the analysis unit that was being processed when the error occurred.

  • Diagnostics (Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector) – Corresponding list of error messages

Corresponding list of error messages

6.6.9. Langkit_Support.Generic_API.Unparsing

Note

At this stage, this package is considered as internal.

This package provides a generic API so that programs can unparse trees for any Langkit-generated library, i.e. turn parse trees back to text sources, with custom formatting. Formatting features are based on the Prettier_Ada library.

Here is a simplistic pretty-printing program using this API:

with Ada.Command_Line;
with Ada.Strings.Unbounded;    use Ada.Strings.Unbounded;
with Ada.Text_IO;              use Ada.Text_IO;
with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO;

with Langkit_Support.Diagnostics; use Langkit_Support.Diagnostics;
with Langkit_Support.Generic_API; use Langkit_Support.Generic_API;
with Langkit_Support.Generic_API.Analysis;
use Langkit_Support.Generic_API.Analysis;
with Langkit_Support.Generic_API.Unparsing;
use Langkit_Support.Generic_API.Unparsing;

with Libfoolang.Generic_API; use Libfoolang.Generic_API;

with Prettier_Ada.Documents;
use Prettier_Ada.Documents;

procedure Unparse is

   --  Load the unparsing configuration file, that determines how to
   --  format source code for the "foo" language: see the
   --  Load_Unparsing_Config function for more information about this
   --  file.

   Diagnostics : Diagnostics_Vectors.Vector;
   Config      : constant Unparsing_Configuration :=
      Load_Unparsing_Config (Self_Id, "config.json", Diagnostics);

   --  Parse the source file to reformat

   Ctx : constant Lk_Context :=
     Create_Context (Libfoolang.Generic_API.Self_Id);
   U   : constant Lk_Unit :=
     Ctx.Get_From_File (Ada.Command_Line.Argument (1));
begin
   --  If we were unable to load the unparsing configuration, bail out

   if Config = No_Unparsing_Configuration then
      Put_Line ("Error when loading the unparsing configuration:");
      Print (Diagnostics);
      raise Program_Error;
   end if;

   --  If the source file to reformat has parsing errors, bail out

   if U.Has_Diagnostics then
      Put_Line ("Parsing errors:");
      for D of U.Diagnostics loop
         Put_Line (U.Format_GNU_Diagnostic (D));
      end loop;
      raise Program_Error;
   end if;

   --  Otherwise, print the reformatted source to the standard output

   declare
      Doc       : constant Document_Type :=
        Unparse_To_Prettier (U.Root, Config);
      Formatted : constant Unbounded_String :=
        Format (Doc, Default_Format_Options);
   begin
      Put_Line (Formatted);
   end;
end Unparse;
type Unparsing_Configuration

Configuration that customizes how source fragments are turned into a prettier document.

No_Unparsing_Configuration : constant Unparsing_Configuration
Object type:

Unparsing_Configuration

Special value to mean the absence of an unparsing configuration

function Default_Unparsing_Configuration (Language : Language_Id) Unparsing_Configuration

Return the default unparsing configuration for the given language

function Load_Unparsing_Config (Language : Language_Id; Filename : Standard.String; Diagnostics : Langkit_Support.Diagnostics.Diagnostics_Vectors.Vector; Check_All_Nodes : Standard.Boolean) Unparsing_Configuration

Read and parse the unparsing configuration for the given Language from Filename. Append error messages to Diagnostics and return No_Unparsing_Configuration if an error occurs while reading the configuration file.

If Check_All_Nodes is true, ensure that the configuration covers all possible parse nodes (creating an error if this is not the case).

The configuration is a JSON file that provides “document templates”: patterns to generate Prettier documents:

  • The default template to unparse nodes or node fields is the “recurse” one. Instantiating it just yields the default unparsing for that node/field:

    "recurse"
    
  • The “breakParent” template yields a “breakParent” Prettier Document:

    "breakParent"
    
  • The “line”/”hardline”/”hardLineWithoutBreakPararent”/”softline”/ “literalline” templates yield the corresponding Prettier documents:

    "line"
    "hardline"
    "hardlineWithoutBreakParent"
    "softline"
    "literalline"
    
  • The “flushLineBreaks” template is used as a placeholder to emit potential line breaks that come from the source code to reformat:

    "flushLineBreaks"
    
  • The “trim” template yields a “trim” Prettier Document:

    "trim"
    
  • The “whitespace” template yields a “text” document with the specified amount of spaces:

    {"kind": "whitespace", "length": 2}
    
    /* or just, for length = 1 */
    
    "whitespace"
    
  • The “align” template yields a “align” Prettier document:

    {
      "kind": "align",
      "width": <number or string>,
      "contents": <sub-template>
    }
    
  • The “dedent” template yields a “dedent” Prettier document:

    {"kind": "dedent", "document": <sub-template>}
    
  • The “dedentToRoot” template yields a “dedentToRoot” Prettier document:

    {"kind": "dedentToRoot", "document": <sub-template>}
    
  • The “fill” template yields a “fill” Prettier document:

    {"kind": "fill", "document": <sub-template>}
    
  • The “group” template yields a “group” Prettier document:

    {"kind": "group", "document": <sub-template>}
    {"kind": "group", "document": <sub-template>, "shouldBreak": true}
    

    An optional “id” field makes it define a symbol to reference in the same template:

    {“kind”: “group”, “document”: <sub-template>, “id”: “mySymbol”}

  • The “ifBreak” template yields an “ifBreak” Prettier document:

    {"kind": "ifBreak", "breakContents": <sub-template>}
    {
      "kind": "ifBreak",
      "breakContents": <sub-template>,
      "flatContents": <sub-template>
    }
    {
      "kind": "ifBreak",
      "breakContents": <sub-template>,
      "flatContents": <sub-template>,
      "groupId": <symbol>
    }
    
  • The “ifEmpty” template is valid only inside a fields configuration. It yields its “then” alternative if the field is an empty list, and its “else” alternative otherwise:

    {
      "kind": "ifEmpty",
      "then": <sub-template>,
      "else": <sub-template>
    }
    
  • The “ifKind” template is valid only inside a node configuration. The “absent” entry is optional. If “field” is not present, “absent” is yielded if defined, otherwise fallback to “default”.

    If “field” is present, the entry in “matchers” that corresponds to the field’s kind is looked up (“kind” is either the name of a node, or a list of node names): the “document” template for the first entry that matches is used. The “default” template is used if there is no match:

    {
      "kind": "ifKind",
      "field": "<field-name>",
      "matchers": [
        {"kind": <node-name>, "document": <sub-template>},
        ...
      ],
      "default": <sub-template>
      "absent": <sub-template>
    }
    

    A variant is available in field templates. It has no “field” entry: the alternative is picked depending on the field that owns this template.

  • The “indent” template yields an “indent” Prettier document:

    {"kind": "indent", "contents": <sub-template>}
    

    It also accepts the optional “bubbleUpLeadingTrivias” and “bubbleUpTrailingTrivias” boolean entries to override the default behavior for trivias bubbling up.

  • The “markAsRoot” template yields a “markAsRoot” Prettier document:

    {"kind": "markAsRoot", "contents": <sub-template>}
    
  • The “innerRoot” template yields a “innerRoot” Prettier document:

    {"kind": "innerRoot", "contents": <sub-template>}
    
  • The “continuationLineIndent” template yields a “continuationLineIndent” Prettier document:

    {"kind": "continuationLineIndent", "contents": <sub-template>}
    
  • The “recurse_field” template is valid only in “node” templates for concrete nodes that are neither abstract, token nor list nodes. When used, the whole template cannot contain any “recurse”/”recurse_flatten” template, and the template, once linearized, must reflect how the node is unparsed.

    For example, let’s consider that the VarDecl node is created parsing the following chunks:

    "var" [f_name] ":" [f_type] ";"
    

    Then its “node” template must contain two “recurse_field” templates for the two fields, in the same order, and with the same tokens in between. For instance:

    [
      {"kind": "text", "text": "var"},
      {"kind": "recurse_field", "text": "f_name"},
      {
        "kind": "group",
        "document": [
          {"kind": "text", "text": ":"},
          {"kind": "recurse_field", "text": "f_type"}
        ]
      },
      {"kind": "text", "text": ";"},
    ]
    
  • The “recurse_flatten” template acts like “recurse” but refines its result so that the document nested in “align”, “fill”, “group”, “indent” templates and in 1-item document lists is returned instead (recursively):

    {"kind": "recurse_flatten", "if": ["Node1" ,"Node2", ...]}
    

    The “if” entry is optional. If provided, it must contain a list of node type names; in this case the flattening is applied only for templates that were instantiated for nodes that match at least one of the node types.

  • The “tableSeparator” template yields the corresponding Prettier document:

    {"kind": "tableSeparator", "text": "some_text_to_unparse"}
    
  • The “text” template yields a “text” Prettier document:

    {"kind": "text", "text": "some_text_to_unparse"}
    

    Using this template is valid in specific contexts only:

    • For “node” templates, when used with “recurse_field” template: see the documentation for “recurse_field”;

    • For “fields” templates: in this case, the linearized template must reflect how the field is unparsed. See the documentation for “recurse_field” to have more information about linearization.

  • A JSON list yields the corresponding “list” Prettier document:

    [{"kind": "whitespace"}, {"kind": "recurse"}]
    

The following commands also accept the optional “bubbleUpLeadingTrivias” and “bubbleUpTrailingTrivias” boolean entries to override the default behavior for trivias bubbling up.

  • align,

  • continuationLineIndent,

  • dedent,

  • dedentToRoot,

  • fill,

  • group,

  • indent,

  • innerRoot,

  • markAsRoot.

The configuration file has the following format:

{
  "node_configs": {<node-name>: <node-config>},
  "max_empty_lines": <natural-number>
}

For each node to configure, the inner “node_configs” mapping associates the name of the node (as a string key) to another mapping with the following format:

{
  "node": <template>,
  "fields": {<field-name>: <template>},
  "sep": <template>,
  "leading_sep": <template>,
  "trailing_sep": <template>,
  "flush_before_children": <boolean>
}

The “node” component is optional. If present, it contains a document template to wrap the basic unparsing of the node.

The “fields” component is optional. If present, it contains a mapping from field names to document templates.

The “sep” component is optional, valid for list nodes only. If present, it contains a document template to unparse the list separator.

The “table” component is optional, valid for list nodes only. If present, unparsing such lists yield a list of table documents, each list child being unparsing to a list row. If present, it must contain an object that accepts the following entries:

  • “sep_before”: Whether list separators must be inserted at the end of the previous row ("sep_before": true) or at the beginning of the next row ("sep_before": false). This is optional, and defaults to true.

  • “split”: Determine which kind of trivia found between two list children trigger a table split (i.e. the presence of such trivias end the current table, and trigger the creation of a new table for the next children). This field is optional (by default: nothing splits table), and when present, must be an array of strings, with the following possible values: "empty_line", "line_comment".

  • “must_break”: Whether each row for this table must go on its own line. If false (the default), rows go on each line only when a break occurs in the table.

  • “join”: Determine whether a list child must be put on the previous table row, i.e. whether to join what would instead be two rows.

    If present, this must be an object with a mandatory “predicate” entry, that must be a reference to a predicate property i.e. a property that each list child has and that returns whether to join rows, as a boolean.

    The optional “template” entry must be a template that describes how to join two rows: the first row is substituted to the “recurse_left” template and the second row is substituted to the “recurse_right” template. For example:

    "join": {
      "predicate": "p_my_predicate",
      "sep": [
        "recurse_left",
        {"kind": "tableSeparator", "text": ""},
        {"kind": "group", "document": ["line", "recurse_right"]}
      ]
    }
    

The “leading_sep” and “trailing_sep” components are optional, and valid only for list nodes that accept respectively leading and trailing separators. If present, they contain document templates to unparse leading/trailing separators.

The “flush_before_children” component is optional, and valid for list nodes only. It must be a boolean (true by default), that controls whether line breaks recovered from the source to reformat are flushed before each list element.

Standard node derivation rules apply to configurations: if node B derives from node A, and if node B does not specify a configuration for its field F, then the configuration of field F for node A applies (same for the list separator).

The “max_empty_lines” entry is optional. If provided, it must be a natural number that indicates the maximum number of consecutive empty lines to preserve during the source code reformatting. If omitted, all empty lines are preserved.

function Unparse_To_Prettier (Node : Lk_Node; Config : Unparsing_Configuration; Process_Error : access procedure (Node : Lk_Node; Message : String)) Prettier_Ada.Documents.Document_Type

Unparse Node into a prettier document according to the given configuration.

Process_Error is called for each non-critical error (i.e. errors that do not prevent the unparsing). For each error, Node is the node that was processed when the error occured, and Message gives a short description of the error. If Process_Error is null, errors are printed on the standard output.

procedure Pretty_Print_Main (Language : Language_Id)

Implementation of the “*_unparse” test program for the given Language.

Load the configuration file, the source to pretty-print and formatting options from the command line, then dump the pretty-printed source on the standard output.

Current_Token_Trace : GNATCOLL.Traces.Trace_Handle
Object type:

GNATCOLL.Traces.Trace_Handle

Default value:

GNATCOLL.Traces.Create ("LANGKIT.UNPARSING.CURRENT_TOKEN", Default => GNATCOLL.Traces.From_Config)

Trace to print the evolution of the “current token” information

Trivias_Trace : GNATCOLL.Traces.Trace_Handle
Object type:

GNATCOLL.Traces.Trace_Handle

Default value:

GNATCOLL.Traces.Create ("LANGKIT.UNPARSING.TRIVIAS", Default => GNATCOLL.Traces.From_Config)

Trace to log information about the handling of trivias

Expanded_Trace : GNATCOLL.Traces.Trace_Handle
Object type:

GNATCOLL.Traces.Trace_Handle

Default value:

GNATCOLL.Traces.Create ("LANGKIT.UNPARSING.EXPANDED", Default => GNATCOLL.Traces.From_Config)

Trace to dump the internal document right after expansion from parse tree and templates.

Bubble_Up_Trace : GNATCOLL.Traces.Trace_Handle
Object type:

GNATCOLL.Traces.Trace_Handle

Default value:

GNATCOLL.Traces.Create ("LANGKIT.UNPARSING.BUBBLE_UP", Default => GNATCOLL.Traces.From_Config)

Trace to dump the internal document right after the pass that bubbles up trivias.

Broken_Groups_Trace : GNATCOLL.Traces.Trace_Handle
Object type:

GNATCOLL.Traces.Trace_Handle

Default value:

GNATCOLL.Traces.Create ("LANGKIT.UNPARSING.BROKEN_GROUPS", Default => GNATCOLL.Traces.From_Config)

Trace to dump the internal document just after the broken groups detection.

Final_Trace : GNATCOLL.Traces.Trace_Handle
Object type:

GNATCOLL.Traces.Trace_Handle

Default value:

GNATCOLL.Traces.Create ("LANGKIT.UNPARSING.FINAL", Default => GNATCOLL.Traces.From_Config)

Trace to dump the final internal document, just before the conversion to a Prettier document.

6.6.10. Langkit_Support.Names

This package provides helpers to deal with names regarding of casing conventions (camel case, lower case, …). What we call a “name” here is a sequence of at least one word, a word being a sequence of at least one non-blank ASCII alphanumericals. In addition, the first word must start with a letter, and each first alphanumerical in a word must be upper case.

type Casing_Convention

Designate a specific casing convention for names formatting. For instance, to format the HTML_Document_Root name:

Camel_With_Underscores: HTML_Document_Root
Camel:                  HTMLDocumentRoot
Lower:                  html_document_root
Upper:                  HTML_DOCUMENT_ROOT

Note that Camel_With_Underscores is the convention which preserves the most information about a name: for instance it is not possible to know from HTML_DOCUMENT_ROOT (an Upper formatted name) whether its Camel_With_Underscores format is HTML_Document_ROOT, Html_Document_Root or any other casing variation, while the reciprocal is true.

Because of this, different names can have different formattings in some conventions and same formattings in other conventions.

function Is_Valid_Name (Name : Text_Type; Casing : Casing_Convention) Standard.Boolean

Return whether Name is a valid name in the given casing convention

function Create_Name (Name : Text_Type; Casing : Casing_Convention) Name_Type

Create a name, decoding Name according to the given casing convention. Raise an Invalid_Name_Error exception if Name is not a valid in this convention.

type Name_Type
function Format_Name (Name : Name_Type; Casing : Casing_Convention) Text_Type

Format a name to the given casing convention. Raise an Invalid_Name_Error exception if Name is not initialized.

function Image (Name : Name_Type) Standard.String

Debug helper: return a human-readable text to represent a name

function Hash (Name : Name_Type) Ada.Containers.Hash_Type
Invalid_Name_Error: exception

6.6.11. Langkit_Support.Symbols

This package provides a symbol table for text (Text_Type) identifiers. This is used in Langkit for the interning of symbols.

The main interest is to:

  1. Use less memory by interning strings.

  2. Be faster when using the symbol as map keys for example, because hashing is faster.

type Symbol_Table_Record
type Symbol_Table

Represents a symbol table. The symbol table is the holder of the memory allocated for each symbol, and serves as a single access point if you want to find back an existing symbol.

No_Symbol_Table : constant Symbol_Table
Object type:

Symbol_Table

Value to use as a default for unallocated symbol tables

function Get (Self : Symbol_Table; TS : Thin_Symbol) Text_Access

Return the text for this Thin_Symbol instance

function To_Symbol (Self : Symbol_Table; TS : Thin_Symbol) Symbol_Type

Go from thin symbol + symbol table to fat symbol representation.

Note that this is unsafe: You can take a thin symbol originally from table A and pass table B to this function. If there is a valid symbol at the thin symbol’s location, it will return it silently, which might create unexpected results.

function Create_Symbol_Table () Symbol_Table

Allocate a new symbol table and return it

function Find (ST : Symbol_Table; T : Text_Type; Create : Standard.Boolean) Thin_Symbol

Look for an entry for the T text in the ST symbol table. If there is such an entry, return it. Otherwise, create it and return it if Create is true. Otherwise, return null.

Non-null returned accesses are guaranteed to be the same if the text passed in was the same.

function Find (ST : Symbol_Table; T : Text_Type; Create : Standard.Boolean) Symbol_Type

Overload of Find which returns a Symbol_Type directly.

procedure Destroy (ST : Symbol_Table)

Deallocate a symbol table and all the text returned by the corresponding calls to Find.

type Symbol_Type

Main symbol type.

Warning

For usability reasons, we use the access to the string as a symbol type. This is very convenient because you can access the text of a symbol without a reference to the symbol table, but is also unsafe, because if the symbol table has been freed, the symbol will be a dangling pointer.

No_Symbol : constant Symbol_Type
Object type:

Symbol_Type

function Get (S : Symbol_Type) Text_Access
function Image (S : Symbol_Type) Text_Type
function "+" (S : Symbol_Type) Text_Type
function Image (S : Symbol_Type; With_Quotes : Standard.Boolean) Standard.String

Return the text associated with this symbol, as a string

function Thin (S : Symbol_Type) Thin_Symbol

Go from fat symbol representation to thin symbol representation

function Hash (ST : Symbol_Type) Ada.Containers.Hash_Type
type Thin_Symbol

Thin symbol type. This type is a bit heavier to use than the main symbol type, because you need a reference to the symbol table to get the text of the symbol, but:

  1. It consumes less memory (which is the primary reason it is used in Langkit).

  2. It is safer, as long as you never store Symbol_Type instances returned by Get_Symbol you should be safe.

No_Thin_Symbol : constant Thin_Symbol
Object type:

Thin_Symbol

function Hash (ST : Thin_Symbol) Ada.Containers.Hash_Type

Default hash function for symbols.

Warning

It assumes that you don’t mix symbols from different symbol tables, but doesn’t verify it!

type Symbolization_Result
Discriminants:
  • Success (Standard.Boolean) –

  • Size (Standard.Natural) –

Components:
  • Symbol (Text_Type) – Text for successfully symbolized identifiers

  • Error_Message (Text_Type) – Message describing why symbolization failed

Message describing why symbolization failed

function Create_Symbol (Name : Text_Type) Symbolization_Result

Shortcut to create successful symbolization results

function Create_Error (Message : Text_Type) Symbolization_Result

Shortcut to create failed symbolization results

function Fold_Case (Name : Text_Type) Symbolization_Result

Convert Name to lowercase (cannot fail).

This is the default symbol canonicalizer when case insensitivity is enabled.

6.6.12. Langkit_Support.Text

This package is a convenience package providing an alias for Wide_Wide_String and related types. Those aliases are mainly for readability and writing shorter code. Alongside, a bunch of utility functions are provided, such as conversion functions.

All our strings are encoded in UTF-32 (native endianness). This type, which is not a subtype of String, makes it obvious when conversions are needed.

type Character_Type

Alias for Wide_Wide_Character. Main character type in Langkit and generated libraries.

type Text_Type

Alias for Wide_Wide_String. Main string type in Langkit and generated libraries.

type Unbounded_Text_Type

Alias for Ada.Strings.Wide_Wide_Unbounded.Unbounded_Wide_Wide_String. Main unbounded string type in Langkit and generated libraries.

function Hash (Self : Unbounded_Text_Type) Ada.Containers.Hash_Type

Shortcut for the unbounded text type hash function

function Hash (Self : Text_Type) Ada.Containers.Hash_Type

Shortcut for the text type hash function

function "=" (L, R : Unbounded_Text_Type) Standard.Boolean

Shortcut for the unbounded text type equality operator

function Text_Charset () Standard.String

Return the name of the charset used to encode Text_Type values.

function To_Text (S : Standard.String) Text_Type

Convenience converter for pure ASCII strings. Raises a Constraint_Error if a non-ASCII character is met.

function To_Text (UT : Unbounded_Text_Type) Text_Type
function To_Unbounded_Text (T : Text_Type) Unbounded_Text_Type
function Image (T : Text_Type; With_Quotes : Standard.Boolean) Standard.String

Return a Python-style escaped string for T. If With_Quote is True, the return string will include boundary quotes.

procedure Process_As_String (Text : Text_Type; Proc : access procedure (S : String))

Call Proc, passing to it Text as a String. This is useful to call APIs that work on mere strings to do conversions, such as GNATCOLL.Iconv.

function Encode (Text : Text_Type; Charset : Standard.String) Standard.String

Use GNATCOLL.Iconv to convert Text into a String encoded using the given Charset. Note that this is only a convenience wrapper around GNATCOLL.Iconv: for instance, if performance needs dictate to avoid secondary stack usage, please use directly GNATCOLL.Iconv.

function Decode (S : Standard.String; Charset : Standard.String) Text_Type

Like Encode, but converts a string to text.

function To_UTF8 (Text : Text_Type) Ada.Strings.UTF_Encoding.UTF_8_String

Encode the given text into an UTF-8 string

function From_UTF8 (S : Ada.Strings.UTF_Encoding.UTF_8_String) Text_Type

Decode the given UTF-8 string into text

function To_Lower (C : Character_Type) Character_Type

Wrapper around Ada.Wide_Wide_Characters.Handling.To_Lower to be fast on the ASCII subset.

Because of the table lookups involved, case folding Unicode codepoints is expensive, whereas it’s very fast for the ASCII subset. Since we expect most sources to contain mostly codepoints in the ASCII subset, this function will be a faster alternative to Ada.Wide_Wide_Characters.Handling.To_Lower.

function To_Lower (Text : Text_Type) Text_Type

Run To_Lower on each character of a copy of Text and return the result.

type Text_Access
type Text_Cst_Access
package Langkit_Support.Text.Chars
NUL : constant Character_Type
Object type:

Character_Type

Default value:

Wide_Wide_Character'Val (Character'Pos (ASCII.NUL))

LF : constant Character_Type
Object type:

Character_Type

Default value:

Wide_Wide_Character'Val (Character'Pos (ASCII.LF))

CR : constant Character_Type
Object type:

Character_Type

Default value:

Wide_Wide_Character'Val (Character'Pos (ASCII.CR))

HT : constant Character_Type
Object type:

Character_Type

Default value:

Wide_Wide_Character'Val (Character'Pos (ASCII.HT))

FF : constant Character_Type
Object type:

Character_Type

Default value:

Wide_Wide_Character'Val (Character'Pos (ASCII.FF))

ESC : constant Character_Type
Object type:

Character_Type

Default value:

Wide_Wide_Character'Val (Character'Pos (ASCII.ESC))

type Text_Buffer_Ifc

Text buffer base class type. This defines a type that encapsulates a text buffer, and can return a specific line of it.

Analysis unit types implemented by libraries implement this interface, which in turns allows users to use features of Langkit_Support, like pretty printing of diagnostics implemented in Output.

function Get_Line (Self : Text_Buffer_Ifc; Line_Number : Standard.Positive) Text_Type

Return line at index Line_Number