thrift_generator_semantic (thrift_generator v0.7.0)
View SourceSemantic analysis: turns documents loaded by thrift_generator_loader
into the validated #tg_model{} IR consumed by the code emitter.
The pass numbers enum members and implicit field ids, resolves constant
and enum references, merges inherited service functions and validates
the result: duplicate names and field ids, union field requiredness,
oneway function shapes, throw clauses pointing at exceptions,
unresolved type references, typedef cycles and constant type
mismatches. All errors are collected as {File, Loc, Message}
triples before failing, where Loc is a line number or a
{Line, Column} pair (whatever the error site knows).
Summary
Functions
Analyzes loaded documents (root first, as returned by the loader) into a model, or returns every validation error found.
Analyzes with invocation-wide options. Each axis applies only to
definitions without an explicit annotation: repr (record, the
default, map or native) is the representation for structures and
exceptions without erl.struct_type, union_type (record or sum)
is the union representation for unions without erl.union_type, set
(list, the default, sets or ordset) is the set implementation for
sets without erl.set, and typedef_type (alias, the default, or
nominal) is the typedef flavor for typedefs without erl.type. A
file-wide namespace default (erl.set, erl.union_type on the
namespace header) overrides the option for its file.
Types
-type ast_node() :: #thrift_generator_node{line :: non_neg_integer(), col :: non_neg_integer(), doc :: doc(), annotations :: erl_annotations(), payload :: term(), type_module :: module()}.
-type base_type() :: bool | i8 | i16 | i32 | i64 | double | string | binary | uuid.
-type const_value() :: {ref, Name :: binary()} | boolean() | integer() | float() | binary() | {list, [const_value()]} | {map, [{const_value(), const_value()}]}.
-type constant() :: #thrift_generator_constant{name :: constant_name(), type :: thrift_type(), value :: const_value()}.
-nominal constant_name() :: binary().
-type cpp_include() :: #thrift_generator_cpp_include{path :: include_path()}.
-type doc() :: binary() | undefined.
-type enum_() :: #thrift_generator_enum{name :: enum_name(), values :: [enum_value()]}.
-nominal enum_name() :: binary().
-type enum_value() :: {Name :: binary(), Value :: integer() | undefined, annotations(), doc()}.
-type exception_() :: #thrift_generator_exception{name :: exception_name(), fields :: [ast_node()]}.
-nominal exception_name() :: binary().
-type field_() :: #thrift_generator_field{id :: integer() | undefined, required :: requiredness(), type :: thrift_type(), name :: field_name(), default :: const_value() | undefined}.
-nominal field_name() :: binary().
-type function_() :: #thrift_generator_function{oneway :: boolean(), return_type :: thrift_type() | void, name :: function_name(), fields :: [ast_node()], throws :: [ast_node()]}.
-nominal function_name() :: binary().
-type generate_semantic_opts() ::
#{repr => record | map | native,
union_type => record | sum,
set => list | sets | ordset,
typedef_type => alias | nominal}.
-type include_() :: #thrift_generator_include{path :: include_path()}.
-nominal include_path() :: binary().
-type loc() :: non_neg_integer() | {non_neg_integer(), non_neg_integer()}.
-type namespace_() :: #thrift_generator_namespace{scope :: namespace_scope(), name :: namespace_name()}.
-nominal namespace_name() :: binary().
-nominal namespace_scope() :: binary().
-type node_payload() :: document() | include_() | cpp_include() | namespace_() | constant() | typedef() | enum_() | struct_() | union_def() | exception_() | service() | function_() | field_().
-type requiredness() :: required | optional | default.
-type service() :: #thrift_generator_service{name :: service_name(), extends :: service_parent() | undefined, functions :: [ast_node()]}.
-nominal service_name() :: binary().
-nominal service_parent() :: binary().
-type struct_() :: #thrift_generator_struct{name :: struct_name(), fields :: [ast_node()]}.
-nominal struct_name() :: binary().
-type thrift_type() :: {base, base_type(), annotations()} | type_ref() | {list, Element :: thrift_type(), annotations()} | {set, Element :: thrift_type(), annotations()} | {map, Key :: thrift_type(), Value :: thrift_type(), annotations()}.
-type type_ref() :: {ref, Name :: binary(), annotations()}.
-type typedef() :: #thrift_generator_typedef{name :: typedef_name(), type :: thrift_type()}.
-nominal typedef_name() :: binary().
-type union_def() :: #thrift_generator_union{name :: union_name(), fields :: [ast_node()]}.
-nominal union_name() :: binary().
Functions
-spec analyze([#tg_loaded{name :: binary(), prefix :: binary(), path :: binary(), includes :: [binary()], doc :: ast_node()}]) -> {ok, #tg_model{root :: binary(), modules :: [#tg_module{name :: binary(), prefix :: binary(), path :: binary(), includes :: [binary()], structs :: [#tg_struct{kind :: struct | union | exception, name :: binary(), fields :: [#tg_field{id :: integer(), required :: requiredness(), type :: thrift_type(), name :: binary(), default :: const_value() | undefined, doc :: doc()}], erl :: erl_annotations(), doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}], enums :: [#tg_enum{name :: binary(), values :: [{integer(), binary()}], doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}], typedefs :: [#tg_typedef{name :: binary(), type :: thrift_type(), erl :: erl_annotations(), doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}], consts :: [#tg_const{name :: binary(), type :: thrift_type(), value :: const_value(), doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}], services :: [#tg_service{name :: binary(), extends :: binary() | undefined, functions :: [#tg_function{name :: binary(), oneway :: boolean(), return_type :: thrift_type() | void, params :: [#tg_field{id :: integer(), required :: requiredness(), type :: thrift_type(), name :: binary(), default :: const_value() | undefined, doc :: doc()}], throws :: [#tg_field{id :: integer(), required :: requiredness(), type :: thrift_type(), name :: binary(), default :: const_value() | undefined, doc :: doc()}], doc :: doc()}], doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}]}]}} | {error, [sem_error()]}.
Analyzes loaded documents (root first, as returned by the loader) into a model, or returns every validation error found.
-spec analyze([#tg_loaded{name :: binary(), prefix :: binary(), path :: binary(), includes :: [binary()], doc :: ast_node()}], generate_semantic_opts()) -> {ok, #tg_model{root :: binary(), modules :: [#tg_module{name :: binary(), prefix :: binary(), path :: binary(), includes :: [binary()], structs :: [#tg_struct{kind :: struct | union | exception, name :: binary(), fields :: [#tg_field{id :: integer(), required :: requiredness(), type :: thrift_type(), name :: binary(), default :: const_value() | undefined, doc :: doc()}], erl :: erl_annotations(), doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}], enums :: [#tg_enum{name :: binary(), values :: [{integer(), binary()}], doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}], typedefs :: [#tg_typedef{name :: binary(), type :: thrift_type(), erl :: erl_annotations(), doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}], consts :: [#tg_const{name :: binary(), type :: thrift_type(), value :: const_value(), doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}], services :: [#tg_service{name :: binary(), extends :: binary() | undefined, functions :: [#tg_function{name :: binary(), oneway :: boolean(), return_type :: thrift_type() | void, params :: [#tg_field{id :: integer(), required :: requiredness(), type :: thrift_type(), name :: binary(), default :: const_value() | undefined, doc :: doc()}], throws :: [#tg_field{id :: integer(), required :: requiredness(), type :: thrift_type(), name :: binary(), default :: const_value() | undefined, doc :: doc()}], doc :: doc()}], doc :: doc(), line :: non_neg_integer(), col :: non_neg_integer()}]}]}} | {error, [sem_error()]}.
Analyzes with invocation-wide options. Each axis applies only to
definitions without an explicit annotation: repr (record, the
default, map or native) is the representation for structures and
exceptions without erl.struct_type, union_type (record or sum)
is the union representation for unions without erl.union_type, set
(list, the default, sets or ordset) is the set implementation for
sets without erl.set, and typedef_type (alias, the default, or
nominal) is the typedef flavor for typedefs without erl.type. A
file-wide namespace default (erl.set, erl.union_type on the
namespace header) overrides the option for its file.