================================================================================
module attribute
================================================================================

-module(foo).
-'module'(foo).

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

(source_file
  (module_attribute
    (atom))
  (module_attribute
    (atom)))

================================================================================
behaviour attribute
================================================================================

-behaviour(gen_server).
-behavior(gen_server).
-'behaviour'(gen_server).
-'behavior'(gen_server).

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

(source_file
  (behaviour_attribute
    (atom))
  (behaviour_attribute
    (atom))
  (behaviour_attribute
    (atom))
  (behaviour_attribute
    (atom)))

================================================================================
deprecated attribute with arity
================================================================================

-deprecated({f,1}).

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

(source_file
  (deprecated_attribute
    (deprecated_fa
      (atom)
      (integer))))

================================================================================
deprecated attribute with arity wildcard
================================================================================

-deprecated({f,'_'}).

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

(source_file
  (deprecated_attribute
    (deprecated_fa
      (atom)
      (deprecated_wildcard))))

================================================================================
deprecated module attribute
================================================================================

-deprecated(module).

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

(source_file
  (deprecated_attribute
    (deprecated_module
      (atom))))

================================================================================
deprecated '_', '_' attribute
================================================================================

-deprecated({'_','_'}).

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

(source_file
  (deprecated_attribute
    (deprecated_fa
      (atom)
      (deprecated_wildcard))))

================================================================================
deprecated function/arity/desc attribute
================================================================================

-deprecated({f,1,"Use g/1 instead"}).

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

(source_file
  (deprecated_attribute
    (deprecated_fa
      (atom)
      (integer)
      (deprecation_desc
        (multi_string
          (string))))))

================================================================================
deprecated '_', '_', atom attribute
================================================================================

-deprecated({'_','_',eventually}).

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

(source_file
  (deprecated_attribute
    (deprecated_fa
      (atom)
      (deprecated_wildcard)
      (deprecation_desc
        (atom)))))

================================================================================
deprecated list attribute with func, arity and atom desc
================================================================================

-deprecated([{g,1,next_version}]).

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

(source_file
  (deprecated_attribute
    (deprecated_fas
      (deprecated_fa
        (atom)
        (integer)
        (deprecation_desc
          (atom))))))

================================================================================
deprecated list attribute
================================================================================

-deprecated([{foo,'_',next}, {bar,1,"desc"}, {baz, 2}, {'_', '_', "all"}]).

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

(source_file
  (deprecated_attribute
    (deprecated_fas
      (deprecated_fa
        (atom)
        (deprecated_wildcard)
        (deprecation_desc
          (atom)))
      (deprecated_fa
        (atom)
        (integer)
        (deprecation_desc
          (multi_string
            (string))))
      (deprecated_fa
        (atom)
        (integer))
      (deprecated_fa
        (atom)
        (deprecated_wildcard)
        (deprecation_desc
          (multi_string
            (string)))))))

================================================================================
deprecated multi-string description
================================================================================

-deprecated({new, 1, "str1" "str2"}).

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

(source_file
  (deprecated_attribute
    (deprecated_fa
      (atom)
      (integer)
      (deprecation_desc
        (multi_string
          (string)
          (string))))))

================================================================================
include attribute
================================================================================

-include("foo.h").
-'include'("foo.h").

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

(source_file
  (pp_include
    (string))
  (pp_include
    (string)))

================================================================================
include attribute, concatenation
================================================================================

-include("root" "foo.h").

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

(source_file
  (pp_include
    (string)
    (string)))

================================================================================
include_lib attribute
================================================================================

-include_lib("foo.h").
-'include_lib'("foo.h").

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

(source_file
  (pp_include_lib
    (string))
  (pp_include_lib
    (string)))

================================================================================
include_lib attribute, concatenation
================================================================================

-include_lib(?APP "foo.h").

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

(source_file
  (pp_include_lib
    (macro_call_expr
      (var))
    (string)))

================================================================================
export attribute
================================================================================

-export([foo/1]).
-'export'([]).

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

(source_file
  (export_attribute
    (fa
      (atom)
      (arity
        (integer))))
  (export_attribute))

================================================================================
import attribute
================================================================================

-import(bar, [foo/1, baz/3]).
-'import'(baz, []).

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

(source_file
  (import_attribute
    (atom)
    (fa
      (atom)
      (arity
        (integer)))
    (fa
      (atom)
      (arity
        (integer))))
  (import_attribute
    (atom)))

================================================================================
export type attribute
================================================================================

-export_type([foo/0]).
-'export_type'([]).

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

(source_file
  (export_type_attribute
    (fa
      (atom)
      (arity
        (integer))))
  (export_type_attribute))

================================================================================
compile attribute
================================================================================

-compile(export_all).
-'compile'([export_all, blah]).

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

(source_file
  (compile_options_attribute
    (atom))
  (compile_options_attribute
    (list
      (atom)
      (atom))))

================================================================================
file attribute
================================================================================

-file("baz.erl", 45).
-'file'("baz.erl", 45).

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

(source_file
  (file_attribute
    (string)
    (integer))
  (file_attribute
    (string)
    (integer)))

================================================================================
record decl
================================================================================

-record(foo, {f1, f2 = 3}).

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

(source_file
  (record_decl
    (atom)
    (record_field
      (atom))
    (record_field
      (atom)
      (field_expr
        (integer)))))

================================================================================
record decl with types
================================================================================

-record(foo, {f1 :: atom(), f2 = 3}).

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

(source_file
  (record_decl
    (atom)
    (record_field
      (atom)
      (field_type
        (call
          (atom)
          (expr_args))))
    (record_field
      (atom)
      (field_expr
        (integer)))))

================================================================================
record decl from manual
================================================================================

-record(name, {first = "Robert", last = "Ericsson"}).
-record(person, {name = #name{}, phone}).

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

(source_file
  (record_decl
    (atom)
    (record_field
      (atom)
      (field_expr
        (string)))
    (record_field
      (atom)
      (field_expr
        (string))))
  (record_decl
    (atom)
    (record_field
      (atom)
      (field_expr
        (record_expr
          (record_name
            (atom)))))
    (record_field
      (atom))))

================================================================================
record decl - empty record
================================================================================

-'record'(state, {}).

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

(source_file
  (record_decl
    (atom)))

================================================================================
type decl
================================================================================

-type my_struct_type() :: atom() | integer().
-opaque my_opaq_type() :: term().
-'type' orddict(Key, Val) :: [{Key, Val}].
-'opaque' useless(A) :: A.

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

(source_file
  (type_alias
    (type_name
      (atom)
      (var_args))
    (pipe
      (call
        (atom)
        (expr_args))
      (call
        (atom)
        (expr_args))))
  (opaque
    (type_name
      (atom)
      (var_args))
    (call
      (atom)
      (expr_args)))
  (type_alias
    (type_name
      (atom)
      (var_args
        (var)
        (var)))
    (list
      (tuple
        (var)
        (var))))
  (opaque
    (type_name
      (atom)
      (var_args
        (var)))
    (var)))

================================================================================
function spec 1
================================================================================

-spec my_function(integer()) -> integer().

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

(source_file
  (spec
    (atom)
    (type_sig
      (expr_args
        (call
          (atom)
          (expr_args)))
      (call
        (atom)
        (expr_args)))))

================================================================================
function spec 2
================================================================================

-spec empty_map_02() -> map().

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

(source_file
  (spec
    (atom)
    (type_sig
      (expr_args)
      (call
        (atom)
        (expr_args)))))

================================================================================
function spec 3
================================================================================

-spec foo() -> #{A => B} when A :: integer(), B :: float().

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

(source_file
  (spec
    (atom)
    (type_sig
      (expr_args)
      (map_expr
        (map_field
          (var)
          (var)))
      (type_guards
        (ann_type
          (ann_var
            (var))
          (call
            (atom)
            (expr_args)))
        (ann_type
          (ann_var
            (var))
          (call
            (atom)
            (expr_args)))))))

================================================================================
wild attribute 1
================================================================================

-foo(bar).

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

(source_file
  (wild_attribute
    (attr_name
      (atom))
    (paren_expr
      (atom))))

================================================================================
wild attribute 2
================================================================================

-oncall("whatsapp_c3").

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

(source_file
  (wild_attribute
    (attr_name
      (atom))
    (paren_expr
      (string))))

================================================================================
function declaration
================================================================================

foo(Bar, Baz) -> ok.

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args
        (var)
        (var))
      (clause_body
        (atom)))))

================================================================================
undef attribute
================================================================================

-undef(FOO).
-'undef'(FOO).

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

(source_file
  (pp_undef
    (var))
  (pp_undef
    (var)))

================================================================================
ifdef attribute
================================================================================

-ifdef(FOO).
-'ifdef'(FOO).

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

(source_file
  (pp_ifdef
    (var))
  (pp_ifdef
    (var)))

================================================================================
ifndef attribute
================================================================================

-ifndef(FOO).
-'ifndef'(FOO).

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

(source_file
  (pp_ifndef
    (var))
  (pp_ifndef
    (var)))

================================================================================
else attribute
================================================================================

-else.
-'else'.

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

(source_file
  (pp_else)
  (pp_else))

================================================================================
endif attribute
================================================================================

-endif.
-'endif'.

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

(source_file
  (pp_endif)
  (pp_endif))

================================================================================
if $.expression
================================================================================

-if 1.
-'if'(1).

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

(source_file
  (pp_if
    (integer))
  (pp_if
    (paren_expr
      (integer))))

================================================================================
elif attribute
================================================================================

-elif(TRUE).
-'elif'(TRUE).

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

(source_file
  (pp_elif
    (paren_expr
      (var)))
  (pp_elif
    (paren_expr
      (var))))

================================================================================
simple spec
================================================================================

-spec foo() -> ok.
-'spec' foo() -> ok.

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

(source_file
  (spec
    (atom)
    (type_sig
      (expr_args)
      (atom)))
  (spec
    (atom)
    (type_sig
      (expr_args)
      (atom))))

================================================================================
callback
================================================================================

-callback foo(Bar) -> ok.
-'callback' foo(Bar) -> ok.

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

(source_file
  (callback
    (atom)
    (type_sig
      (expr_args
        (var))
      (atom)))
  (callback
    (atom)
    (type_sig
      (expr_args
        (var))
      (atom))))

================================================================================
string with % in it
================================================================================

foo() -> "\"%".

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (string)))))

================================================================================
string
================================================================================

foo() -> ("whatsapp_c3").

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (paren_expr
          (string))))))

================================================================================
char %
================================================================================

foo() -> $%.

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (char)))))

================================================================================
char space
================================================================================

foo() -> $ .

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (char)))))

================================================================================
char \]
================================================================================

foo() -> $\].

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (char)))))

================================================================================
char \^g
================================================================================

foo() -> $\^g.

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (char)))))

================================================================================
char \\
================================================================================

foo() -> $\\.

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (char)))))

================================================================================
char \^]
================================================================================

foo() -> $\^].

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (char)))))

================================================================================
char \^Z
================================================================================

foo() -> $\^Z.

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (char)))))

================================================================================
char \%
================================================================================

foo() -> $\%.

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

(source_file
  (fun_decl
    (function_clause
      (atom)
      (expr_args)
      (clause_body
        (char)))))

================================================================================
optional_callbacks attribute
================================================================================

-optional_callbacks([foo/1, bar/2]).

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

(source_file
  (optional_callbacks_attribute
    (fa
      (atom)
      (arity
        (integer)))
    (fa
      (atom)
      (arity
        (integer)))))
