diff options
| -rw-r--r-- | lib/edoc/src/edoc_doclet.erl | 2 | ||||
| -rw-r--r-- | lib/edoc/src/edoc_layout.erl | 10 | ||||
| -rw-r--r-- | lib/edoc/src/edoc_lib.erl | 2 | ||||
| -rw-r--r-- | lib/edoc/src/edoc_parser.yrl | 16 | ||||
| -rw-r--r-- | lib/edoc/src/edoc_scanner.erl | 2 | ||||
| -rw-r--r-- | lib/edoc/src/edoc_specs.erl | 13 | ||||
| -rw-r--r-- | lib/edoc/src/edoc_tags.erl | 2 | ||||
| -rw-r--r-- | lib/edoc/src/edoc_types.erl | 4 | ||||
| -rw-r--r-- | lib/edoc/src/edoc_types.hrl | 4 | ||||
| -rw-r--r-- | lib/erl_docgen/src/docgen_otp_specs.erl | 5 | ||||
| -rw-r--r-- | lib/syntax_tools/src/erl_syntax.erl | 36 | 
11 files changed, 91 insertions, 5 deletions
diff --git a/lib/edoc/src/edoc_doclet.erl b/lib/edoc/src/edoc_doclet.erl index ce1e94a26a..5653b5894b 100644 --- a/lib/edoc/src/edoc_doclet.erl +++ b/lib/edoc/src/edoc_doclet.erl @@ -200,7 +200,7 @@ source({M, P, Name, Path}, Dir, Suffix, Env, Set, Private, Hidden,  		    {Set, Error}  	    end;  	R -> -	    report("skipping source file '~ts': ~W.", [File, R, 15]), +	    report("skipping source file '~ts': ~P.", [File, R, 15]),  	    {Set, true}      end. diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl index 7bd0615f5c..e164ff060f 100644 --- a/lib/edoc/src/edoc_layout.erl +++ b/lib/edoc/src/edoc_layout.erl @@ -829,6 +829,10 @@ t_type([#xmlElement{name = list, content = Es}]) ->      t_list(Es);  t_type([#xmlElement{name = nonempty_list, content = Es}]) ->      t_nonempty_list(Es); +t_type([#xmlElement{name = map, content = Es}]) -> +    t_map(Es); +t_type([#xmlElement{name = map_field, content=Es}]) -> +    t_map_field(Es);  t_type([#xmlElement{name = tuple, content = Es}]) ->      t_tuple(Es);  t_type([#xmlElement{name = 'fun', content = Es}]) -> @@ -877,6 +881,12 @@ t_fun(Es) ->      ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es),  		 [") -> "] ++ t_utype(get_elem(type, Es))). +t_map(Es) -> +    ["#{"] ++ seq(fun t_utype_elem/1, Es, ["}"]). + +t_map_field([K,V]) -> +    [t_utype_elem(K) ++ " => " ++ t_utype_elem(V)]. +  t_record(E, Es) ->      Name = ["#"] ++ t_type(get_elem(atom, Es)),      case get_elem(field, Es) of diff --git a/lib/edoc/src/edoc_lib.erl b/lib/edoc/src/edoc_lib.erl index ca9df2b632..c46338a2e1 100644 --- a/lib/edoc/src/edoc_lib.erl +++ b/lib/edoc/src/edoc_lib.erl @@ -1032,7 +1032,7 @@ run_plugin(Name, Key, Default, Fun, Opts) when is_atom(Name) ->  	{ok, Value} ->  	    Value;  	R -> -	    report("error in ~ts '~w': ~W.", [Name, Module, R, 20]), +	    report("error in ~ts '~w': ~P.", [Name, Module, R, 20]),  	    exit(error)      end. diff --git a/lib/edoc/src/edoc_parser.yrl b/lib/edoc/src/edoc_parser.yrl index 7762f2da7d..c6f8a04775 100644 --- a/lib/edoc/src/edoc_parser.yrl +++ b/lib/edoc/src/edoc_parser.yrl @@ -29,13 +29,14 @@ Nonterminals  start spec func_type utype_list utype_tuple utypes utype ptypes ptype  nutype function_name where_defs defs defs2 def typedef etype  throws qname ref aref mref lref pref var_list vars fields field +utype_map utype_map_fields utype_map_field  futype_list bin_base_type bin_unit_type.  Terminals  atom float integer var an_var string start_spec start_typedef start_throws  start_ref -'(' ')' ',' '.' '->' '{' '}' '[' ']' '|' '+' ':' '::' '=' '/' '//' '*' +'(' ')' ',' '.' '=>' '->' '{' '}' '[' ']' '|' '+' ':' '::' '=' '/' '//' '*'  '#' 'where' '<<' '>>' '..' '...'.  Rootsymbol start. @@ -69,6 +70,14 @@ utype_list -> '(' utypes ')' : {lists:reverse('$2'), tok_line('$1')}.  futype_list -> utype_list : '$1'.  futype_list -> '(' '...' ')' : {[#t_var{name = '...'}], tok_line('$1')}. +utype_map -> '#' '{' utype_map_fields '}' : lists:reverse('$3'). + +utype_map_fields -> '$empty' : []. +utype_map_fields -> utype_map_field : ['$1']. +utype_map_fields -> utype_map_fields ',' utype_map_field : ['$3' | '$1']. + +utype_map_field -> utype '=>' utype : #t_map_field{ k_type = '$1', v_type = '$3'}. +  utype_tuple -> '{' utypes '}' : lists:reverse('$2').  %% Produced in reverse order. @@ -91,9 +100,10 @@ ptype -> var : #t_var{name = tok_val('$1')}.  ptype -> atom : #t_atom{val = tok_val('$1')}.  ptype -> integer: #t_integer{val = tok_val('$1')}.  ptype -> integer '..' integer: #t_integer_range{from = tok_val('$1'), -                                                   to = tok_val('$3')}. +                                                  to = tok_val('$3')}.  ptype -> float: #t_float{val = tok_val('$1')}.  ptype -> utype_tuple : #t_tuple{types = '$1'}. +ptype -> utype_map : #t_map{types = '$1'}.  ptype -> '[' ']' : #t_nil{}.  ptype -> '[' utype ']' : #t_list{type = '$2'}.  ptype -> '[' utype ',' '...' ']' : #t_nonempty_list{type = '$2'}. @@ -462,3 +472,5 @@ throw_error(parse_param, L) ->      throw({error, L, "missing parameter name"});  throw_error({Where, E}, L) when is_list(Where) ->      throw({error,L,{"unknown error parsing ~ts: ~P.",[Where,E,15]}}). + +%% vim: ft=erlang diff --git a/lib/edoc/src/edoc_scanner.erl b/lib/edoc/src/edoc_scanner.erl index 754fcef643..6ff97a134c 100644 --- a/lib/edoc/src/edoc_scanner.erl +++ b/lib/edoc/src/edoc_scanner.erl @@ -137,6 +137,8 @@ scan1([$"|Cs0], Toks, Pos) ->				% String  	    scan_error({illegal, string}, Pos)      end;  %% Punctuation characters and operators, first recognise multiples. +scan1([$=,$>|Cs], Toks, Pos) -> +    scan1(Cs, [{'=>',Pos}|Toks], Pos);  scan1([$<,$<|Cs], Toks, Pos) ->      scan1(Cs, [{'<<',Pos}|Toks], Pos);  scan1([$>,$>|Cs], Toks, Pos) -> diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl index 5acf8ac0d5..466c9df951 100644 --- a/lib/edoc/src/edoc_specs.erl +++ b/lib/edoc/src/edoc_specs.erl @@ -358,6 +358,14 @@ d2e({type,_,tuple,any}) ->  d2e({type,_,binary,[Base,Unit]}) ->      #t_binary{base_size = element(3, Base),                unit_size = element(3, Unit)}; +d2e({type,_,map,any}) -> +    #t_map{ types = []}; +d2e({type,_,map,Es}) -> +    #t_map{ types = d2e(Es) }; +d2e({type,_,map_field_assoc,K,V}) -> +    #t_map_field{ k_type = d2e(K), v_type=d2e(V) }; +d2e({type,_,map_field_exact,K,V}) -> +    #t_map_field{ k_type = d2e(K), v_type=d2e(V) };  d2e({type,_,tuple,Ts0}) ->      Ts = d2e(Ts0),      typevar_anno(#t_tuple{types = Ts}, Ts); @@ -476,6 +484,11 @@ xrecs(#t_fun{args = Args0, range = Range0}=T, P) ->      Args = xrecs(Args0, P),      Range = xrecs(Range0, P),      T#t_fun{args = Args, range = Range}; +xrecs(#t_map{ types = Ts0 }=T,P) -> +    Ts = xrecs(Ts0, P), +    T#t_map{ types = Ts }; +xrecs(#t_map_field{ k_type=Kt, v_type=Vt}=T, P) -> +    T#t_map_field{ k_type=xrecs(Kt,P), v_type=xrecs(Vt,P)};  xrecs(#t_tuple{types = Types0}=T, P) ->      Types = xrecs(Types0, P),      T#t_tuple{types = Types}; diff --git a/lib/edoc/src/edoc_tags.erl b/lib/edoc/src/edoc_tags.erl index eb41f1922a..74702102f0 100644 --- a/lib/edoc/src/edoc_tags.erl +++ b/lib/edoc/src/edoc_tags.erl @@ -460,6 +460,8 @@ check_type(#t_var{}, P, Ls, Ts) ->      check_types3(Ts, P, Ls);  check_type(#t_fun{args = Args, range = Range}, P, Ls, Ts) ->      check_type(Range, P, Ls, Args++Ts); +check_type(#t_map{}, P, Ls, Ts) -> +    check_types3(Ts, P, Ls);  check_type(#t_tuple{types = Types}, P, Ls, Ts) ->      check_types3(Types ++Ts, P, Ls);  check_type(#t_list{type = Type}, P, Ls, Ts) -> diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl index 60c6cecb97..af8f1230fb 100644 --- a/lib/edoc/src/edoc_types.erl +++ b/lib/edoc/src/edoc_types.erl @@ -141,6 +141,10 @@ to_xml(#t_type{name = N, args = As}, Env) ->  to_xml(#t_fun{args = As, range = T}, Env) ->      {'fun', [{argtypes, map(fun wrap_utype/2, As, Env)},  	     wrap_utype(T, Env)]}; +to_xml(#t_map{ types = Ts}, Env) -> +    {map, map(fun wrap_utype/2, Ts, Env)}; +to_xml(#t_map_field{ k_type=K, v_type=V}, Env) -> +    {map_field, [wrap_utype(K,Env), wrap_utype(V, Env)]};  to_xml(#t_tuple{types = Ts}, Env) ->      {tuple, map(fun wrap_utype/2, Ts, Env)};  to_xml(#t_list{type = T}, Env) -> diff --git a/lib/edoc/src/edoc_types.hrl b/lib/edoc/src/edoc_types.hrl index 05c61d70ff..7fec10d936 100644 --- a/lib/edoc/src/edoc_types.hrl +++ b/lib/edoc/src/edoc_types.hrl @@ -155,3 +155,7 @@  %% @type t_paren() = #t_paren{a = list(), type = type()}  -record(t_paren, {a=[], type}).		% parentheses + +-record(t_map, {a=[], types=[]}). +-record(t_map_field, {a=[], k_type, v_type}). + diff --git a/lib/erl_docgen/src/docgen_otp_specs.erl b/lib/erl_docgen/src/docgen_otp_specs.erl index 3929e66515..3240edd68e 100644 --- a/lib/erl_docgen/src/docgen_otp_specs.erl +++ b/lib/erl_docgen/src/docgen_otp_specs.erl @@ -388,6 +388,8 @@ t_type([#xmlElement{name = nonempty_list, content = Es}]) ->      t_nonempty_list(Es);  t_type([#xmlElement{name = tuple, content = Es}]) ->      t_tuple(Es); +t_type([#xmlElement{name = map}]) -> +    t_map();  t_type([#xmlElement{name = 'fun', content = Es}]) ->      ["fun("] ++ t_fun(Es) ++ [")"];  t_type([E = #xmlElement{name = record, content = Es}]) -> @@ -430,6 +432,9 @@ t_nonempty_list(Es) ->  t_tuple(Es) ->      ["{"] ++ seq(fun t_utype_elem/1, Es, ["}"]). +t_map() -> +    ["#{}"]. +  t_fun(Es) ->      ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es),  		 [") -> "] ++ t_utype(get_elem(type, Es))). diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 4f7f9e83ac..78a37445ed 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -582,6 +582,9 @@ type(Node) ->  	{match, _, _, _} -> match_expr;  	{op, _, _, _, _} -> infix_expr;  	{op, _, _, _} -> prefix_expr; +	{map,_,_} -> map; +	{map_field_assoc,_,_,_} -> map_field_assoc; +	{map_field_exact,_,_,_} -> map_field_exact;  	{record, _, _, _, _} -> record_expr;  	{record, _, _, _} -> record_expr;  	{record_field, _, _, _, _} -> record_access; @@ -1910,6 +1913,28 @@ atom_literal(Node) ->  %% ===================================================================== + +map_elements(Node) -> +    case unwrap(Node) of +	{map, _, List} -> +	    List; +	Node1 -> +	    data(Node1) +    end. + +map_field_elements({_,_,K,V}) -> +    [K,V]. + +map(List) -> +    tree(map, List). + +map_field_assoc(List) -> +    tree(map_field_assoc, List). + +map_field_exact(List) -> +    tree(map_field_exact, List). + +%% =====================================================================  %% @doc Creates an abstract tuple. If `Elements' is  %% `[X1, ..., Xn]', the result represents  %% "<code>{<em>X1</em>, ..., <em>Xn</em>}</code>". @@ -6396,6 +6421,12 @@ subtrees(T) ->  		     try_expr_clauses(T),  		     try_expr_handlers(T),  		     try_expr_after(T)]; +	        map -> +		    [map_elements(T)]; +		map_field_assoc -> +		    [map_field_elements(T)]; +		map_field_exact -> +		    [map_field_elements(T)];  		tuple ->  		    [tuple_elements(T)]  	    end @@ -6491,7 +6522,10 @@ make_tree(record_index_expr, [[T], [F]]) ->  make_tree(rule, [[N], C]) -> rule(N, C);  make_tree(size_qualifier, [[N], [A]]) -> size_qualifier(N, A);  make_tree(try_expr, [B, C, H, A]) -> try_expr(B, C, H, A); -make_tree(tuple, [E]) -> tuple(E). +make_tree(tuple, [E]) -> tuple(E); +make_tree(map, [E]) -> map(E); +make_tree(map_field_assoc, [E]) -> map_field_assoc(E); +make_tree(map_field_exact, [E]) -> map_field_exact(E).  %% =====================================================================  | 
