aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/stdlib/src')
-rw-r--r--lib/stdlib/src/erl_lint.erl49
-rw-r--r--lib/stdlib/src/erl_pp.erl195
-rw-r--r--lib/stdlib/src/otp_internal.erl147
-rw-r--r--lib/stdlib/src/stdlib.appup.src8
4 files changed, 201 insertions, 198 deletions
diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl
index 3ec78a2667..e0c37ca030 100644
--- a/lib/stdlib/src/erl_lint.erl
+++ b/lib/stdlib/src/erl_lint.erl
@@ -79,6 +79,8 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
-type fa() :: {atom(), arity()}. % function+arity
-type ta() :: {atom(), arity()}. % type+arity
+-type module_or_mfa() :: module() | mfa().
+
-record(typeinfo, {attr, line}).
%% Usage of records, functions, and imports. The variable table, which
@@ -115,6 +117,8 @@ value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) ->
:: erl_anno:anno(),
clashes=[], %Exported functions named as BIFs
not_deprecated=[], %Not considered deprecated
+ not_removed=gb_sets:empty() %Not considered removed
+ :: gb_sets:set(module_or_mfa()),
func=[], %Current function
warn_format=0, %Warn format calls
enabled_warnings=[], %All enabled warnings (ordset).
@@ -573,7 +577,10 @@ start(File, Opts) ->
false, Opts)},
{missing_spec_all,
bool_option(warn_missing_spec_all, nowarn_missing_spec_all,
- false, Opts)}
+ false, Opts)},
+ {removed,
+ bool_option(warn_removed, nowarn_removed,
+ true, Opts)}
],
Enabled1 = [Category || {Category,true} <- Enabled0],
Enabled = ordsets:from_list(Enabled1),
@@ -670,8 +677,9 @@ forms(Forms0, St0) ->
no_auto = AutoImportSuppressed}),
St2 = bif_clashes(Forms, St1),
St3 = not_deprecated(Forms, St2),
- St4 = foldl(fun form/2, pre_scan(Forms, St3), Forms),
- post_traversal_check(Forms, St4).
+ St4 = not_removed(Forms, St3),
+ St5 = foldl(fun form/2, pre_scan(Forms, St4), Forms),
+ post_traversal_check(Forms, St5).
pre_scan([{attribute,L,compile,C} | Fs], St) ->
case is_warn_enabled(export_all, St) andalso
@@ -846,6 +854,24 @@ not_deprecated(Forms, #lint{compile=Opts}=St0) ->
end, St0, ML),
St1#lint{not_deprecated = ordsets:from_list(Nowarn)}.
+%% not_removed(Forms, State0) -> State
+
+not_removed(Forms, #lint{compile=Opts}=St0) ->
+ %% There are no line numbers in St0#lint.compile.
+ MFAsL = [{MFA,L} ||
+ {attribute, L, compile, Args} <- Forms,
+ {nowarn_removed, MFAs0} <- lists:flatten([Args]),
+ MFA <- lists:flatten([MFAs0])],
+ Nowarn = [MFA ||
+ {nowarn_removed, MFAs0} <- Opts,
+ MFA <- lists:flatten([MFAs0])],
+ St1 = foldl(fun ({{M, _F, _A}, L}, St2) ->
+ check_module_name(M, L, St2);
+ ({M,L}, St2) ->
+ check_module_name(M, L, St2)
+ end, St0, MFAsL),
+ St1#lint{not_removed = gb_sets:from_list(Nowarn)}.
+
%% The nowarn_bif_clash directive is not only deprecated, it's actually an error from R14A
disallowed_compile_flags(Forms, St0) ->
%% There are (still) no line numbers in St0#lint.compile.
@@ -2250,6 +2276,9 @@ expr({'fun',Line,Body}, Vt, St) ->
case Body of
{clauses,Cs} ->
fun_clauses(Cs, Vt, St);
+ {function,record_info,2} ->
+ %% It is illegal to call record_info/2 with unknown arguments.
+ {[],add_error(Line, illegal_record_info, St)};
{function,F,A} ->
%% BifClash - Fun expression
%% N.B. Only allows BIFs here as well, NO IMPORTS!!
@@ -3769,13 +3798,23 @@ deprecated_function(Line, M, F, As, St) ->
add_warning(Line, {deprecated, MFA, Replacement, Rel}, St)
end;
{removed, String} when is_list(String) ->
- add_warning(Line, {removed, MFA, String}, St);
+ add_removed_warning(Line, MFA, {removed, MFA, String}, St);
{removed, Replacement, Rel} ->
- add_warning(Line, {removed, MFA, Replacement, Rel}, St);
+ add_removed_warning(Line, MFA, {removed, MFA, Replacement, Rel}, St);
no ->
St
end.
+add_removed_warning(Line, {M, _, _}=MFA, Warning, #lint{not_removed=NotRemoved}=St) ->
+ case is_warn_enabled(removed, St) andalso
+ not gb_sets:is_element(M, NotRemoved) andalso
+ not gb_sets:is_element(MFA, NotRemoved) of
+ true ->
+ add_warning(Line, Warning, St);
+ false ->
+ St
+ end.
+
-dialyzer({no_match, deprecated_type/5}).
deprecated_type(L, M, N, As, St) ->
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index ada3ff5de3..255c0ae81f 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -26,7 +26,7 @@
attribute/1,attribute/2,function/1,function/2,
guard/1,guard/2,exprs/1,exprs/2,exprs/3,expr/1,expr/2,expr/3,expr/4]).
--import(lists, [append/1,foldr/3,mapfoldl/3,reverse/1,reverse/2]).
+-import(lists, [append/1,foldr/3,map/2,mapfoldl/3,reverse/1,reverse/2]).
-import(io_lib, [write/1,format/2]).
-import(erl_parse, [inop_prec/1,preop_prec/1,func_prec/0,max_prec/0,
type_inop_prec/1, type_preop_prec/1]).
@@ -41,10 +41,11 @@
io_lib:chars())).
-type(option() :: {hook, hook_function()}
- | {encoding, latin1 | unicode | utf8}).
+ | {encoding, latin1 | unicode | utf8}
+ | {quote_singleton_atom_types, boolean()}).
-type(options() :: hook_function() | [option()]).
--record(pp, {value_fun, string_fun, char_fun}).
+-record(pp, {value_fun, singleton_atom_type_fun, string_fun, char_fun}).
-record(options, {hook, encoding, opts}).
@@ -206,22 +207,43 @@ options(Hook) ->
#options{hook = Hook, encoding = encoding([]), opts = Hook}.
state(Options) when is_list(Options) ->
+ Quote = proplists:get_bool(quote_singleton_atom_types, Options),
case encoding(Options) of
- latin1 -> state();
- unicode -> unicode_state()
+ latin1 -> latin1_state(Quote);
+ unicode -> unicode_state(Quote)
end;
state(_Hook) ->
- state().
+ latin1_state(false).
-state() ->
+latin1_state(Quote) ->
Options = [{encoding,latin1}],
- #pp{value_fun = fun(V) -> io_lib_pretty:print(V, Options) end,
+ ValueFun = fun(V) -> io_lib_pretty:print(V, Options) end,
+ SingletonFun =
+ case Quote of
+ true ->
+ fun(A) ->
+ io_lib:write_string_as_latin1(atom_to_list(A), $')
+ end; %'
+ false ->
+ ValueFun
+ end,
+ #pp{value_fun = ValueFun,
+ singleton_atom_type_fun = SingletonFun,
string_fun = fun io_lib:write_string_as_latin1/1,
char_fun = fun io_lib:write_char_as_latin1/1}.
-unicode_state() ->
+unicode_state(Quote) ->
Options = [{encoding,unicode}],
- #pp{value_fun = fun(V) -> io_lib_pretty:print(V, Options) end,
+ ValueFun = fun(V) -> io_lib_pretty:print(V, Options) end,
+ SingletonFun =
+ case Quote of
+ true ->
+ fun(A) -> io_lib:write_string(atom_to_list(A), $') end; %'
+ false ->
+ ValueFun
+ end,
+ #pp{value_fun = ValueFun,
+ singleton_atom_type_fun = SingletonFun,
string_fun = fun io_lib:write_string/1,
char_fun = fun io_lib:write_char/1}.
@@ -350,7 +372,7 @@ ltype({user_type,Line,T,Ts}, _) ->
ltype({remote_type,Line,[M,F,Ts]}, _) ->
simple_type({remote,Line,M,F}, Ts);
ltype({atom,_,T}, _) ->
- {atom,T};
+ {singleton_atom_type,T};
ltype(E, P) ->
lexpr(E, P, options(none)).
@@ -360,7 +382,12 @@ binary_type(I1, I2) ->
P = max_prec(),
E1 = [[leaf("_:"),lexpr(I1, P, options(none))] || B],
E2 = [[leaf("_:_*"),lexpr(I2, P, options(none))] || U],
- {seq,'<<','>>',[$,],E1++E2}.
+ case E1++E2 of
+ [] ->
+ leaf("<<>>");
+ Es ->
+ {seq,'<<','>>',[$,],Es}
+ end.
map_type(Fs) ->
{first,[$#],map_pair_types(Fs)}.
@@ -386,6 +413,8 @@ typed(B, Type) ->
{_L,_P,R} = type_inop_prec('::'),
{list,[{cstep,[B,' ::'],ltype(Type, R)}]}.
+tuple_type([], _) ->
+ leaf("{}");
tuple_type(Ts, F) ->
{seq,${,$},[$,],ltypes(Ts, F, 0)}.
@@ -454,7 +483,7 @@ pname(A) when is_atom(A) ->
write(A).
falist([]) ->
- [leaf("[]")];
+ ['[]'];
falist(Falist) ->
L = [begin
{Name,Arity} = Fa,
@@ -562,22 +591,22 @@ lexpr({map, _, Map, Fs}, Prec, Opts) ->
El = {first,[Rl,$#],map_fields(Fs, Opts)},
maybe_paren(P, Prec, El);
lexpr({block,_,Es}, _, Opts) ->
- {list,[{step,'begin',body(Es, Opts)},'end']};
+ {list,[{step,'begin',body(Es, Opts)},{reserved,'end'}]};
lexpr({'if',_,Cs}, _, Opts) ->
- {list,[{step,'if',if_clauses(Cs, Opts)},'end']};
+ {list,[{step,'if',if_clauses(Cs, Opts)},{reserved,'end'}]};
lexpr({'case',_,Expr,Cs}, _, Opts) ->
- {list,[{step,{list,[{step,'case',lexpr(Expr, Opts)},'of']},
+ {list,[{step,{list,[{step,'case',lexpr(Expr, Opts)},{reserved,'of'}]},
cr_clauses(Cs, Opts)},
- 'end']};
+ {reserved,'end'}]};
lexpr({'cond',_,Cs}, _, Opts) ->
- {list,[{step,leaf("cond"),cond_clauses(Cs, Opts)},'end']};
+ {list,[{step,leaf("cond"),cond_clauses(Cs, Opts)},{reserved,'end'}]};
lexpr({'receive',_,Cs}, _, Opts) ->
- {list,[{step,'receive',cr_clauses(Cs, Opts)},'end']};
+ {list,[{step,'receive',cr_clauses(Cs, Opts)},{reserved,'end'}]};
lexpr({'receive',_,Cs,To,ToOpt}, _, Opts) ->
Al = {list,[{step,[lexpr(To, Opts),' ->'],body(ToOpt, Opts)}]},
{list,[{step,'receive',cr_clauses(Cs, Opts)},
{step,'after',Al},
- 'end']};
+ {reserved,'end'}]};
lexpr({'fun',_,{function,F,A}}, _Prec, _Opts) ->
[leaf("fun "),{atom,F},leaf(format("/~w", [A]))];
lexpr({'fun',L,{function,_,_}=Func,Extra}, Prec, Opts) ->
@@ -596,15 +625,17 @@ lexpr({'fun',_,{function,M,F,A}}, _Prec, Opts) ->
ArityItem = lexpr(A, Opts),
["fun ",NameItem,$:,CallItem,$/,ArityItem];
lexpr({'fun',_,{clauses,Cs}}, _Prec, Opts) ->
- {list,[{first,'fun',fun_clauses(Cs, Opts, unnamed)},'end']};
+ {list,[{first,'fun',fun_clauses(Cs, Opts, unnamed)},{reserved,'end'}]};
lexpr({named_fun,_,Name,Cs}, _Prec, Opts) ->
- {list,[{first,['fun', " "],fun_clauses(Cs, Opts, {named, Name})},'end']};
+ {list,[{first,['fun', " "],fun_clauses(Cs, Opts, {named, Name})},
+ {reserved,'end'}]};
lexpr({'fun',_,{clauses,Cs},Extra}, _Prec, Opts) ->
{force_nl,fun_info(Extra),
- {list,[{first,'fun',fun_clauses(Cs, Opts, unnamed)},'end']}};
+ {list,[{first,'fun',fun_clauses(Cs, Opts, unnamed)},{reserved,'end'}]}};
lexpr({named_fun,_,Name,Cs,Extra}, _Prec, Opts) ->
{force_nl,fun_info(Extra),
- {list,[{first,['fun', " "],fun_clauses(Cs, Opts, {named, Name})},'end']}};
+ {list,[{first,['fun', " "],fun_clauses(Cs, Opts, {named, Name})},
+ {reserved,'end'}]}};
lexpr({call,_,{remote,_,{atom,_,M},{atom,_,F}=N}=Name,Args}, Prec, Opts) ->
case erl_internal:bif(M, F, length(Args)) of
true ->
@@ -619,7 +650,7 @@ lexpr({'try',_,Es,Scs,Ccs,As}, _, Opts) ->
Scs =:= [] ->
{step,'try',body(Es, Opts)};
true ->
- {step,{list,[{step,'try',body(Es, Opts)},'of']},
+ {step,{list,[{step,'try',body(Es, Opts)},{reserved,'of'}]},
cr_clauses(Scs, Opts)}
end,
if
@@ -634,7 +665,7 @@ lexpr({'try',_,Es,Scs,Ccs,As}, _, Opts) ->
true ->
{step,'after',body(As, Opts)}
end,
- 'end']};
+ {reserved,'end'}]};
lexpr({'catch',_,Expr}, Prec, Opts) ->
{P,R} = preop_prec('catch'),
El = {list,[{step,'catch',lexpr(Expr, R, Opts)}]},
@@ -647,7 +678,7 @@ lexpr({match,_,Lhs,Rhs}, Prec, Opts) ->
maybe_paren(P, Prec, El);
lexpr({op,_,Op,Arg}, Prec, Opts) ->
{P,R} = preop_prec(Op),
- Ol = leaf(format("~s ", [Op])),
+ Ol = {reserved, leaf(format("~s ", [Op]))},
El = [Ol,lexpr(Arg, R, Opts)],
maybe_paren(P, Prec, El);
lexpr({op,_,Op,Larg,Rarg}, Prec, Opts) when Op =:= 'orelse';
@@ -655,14 +686,14 @@ lexpr({op,_,Op,Larg,Rarg}, Prec, Opts) when Op =:= 'orelse';
%% Breaks lines since R12B.
{L,P,R} = inop_prec(Op),
Ll = lexpr(Larg, L, Opts),
- Ol = leaf(format("~s", [Op])),
+ Ol = {reserved, leaf(format("~s", [Op]))},
Lr = lexpr(Rarg, R, Opts),
El = {prefer_nl,[[]],[Ll,Ol,Lr]},
maybe_paren(P, Prec, El);
lexpr({op,_,Op,Larg,Rarg}, Prec, Opts) ->
{L,P,R} = inop_prec(Op),
Ll = lexpr(Larg, L, Opts),
- Ol = leaf(format("~s", [Op])),
+ Ol = {reserved, leaf(format("~s", [Op]))},
Lr = lexpr(Rarg, R, Opts),
El = {list,[Ll,Ol,Lr]},
maybe_paren(P, Prec, El);
@@ -882,16 +913,18 @@ lc_qual(Q, Opts) ->
lexpr(Q, 0, Opts).
proper_list(Es, Opts) ->
- {seq,$[,$],$,,lexprs(Es, Opts)}.
+ {seq,$[,$],[$,],lexprs(Es, Opts)}.
improper_list(Es, Opts) ->
- {seq,$[,$],{$,,$|},lexprs(Es, Opts)}.
+ {seq,$[,$],[{$,,' |'}],lexprs(Es, Opts)}.
tuple(L, Opts) ->
tuple(L, fun lexpr/2, Opts).
+tuple([], _F, _Opts) ->
+ leaf("{}");
tuple(Es, F, Opts) ->
- {seq,${,$},$,,lexprs(Es, F, Opts)}.
+ {seq,${,$},[$,],lexprs(Es, F, Opts)}.
args(As, Opts) ->
{seq,$(,$),[$,],lexprs(As, Opts)}.
@@ -939,6 +972,7 @@ frmt(Item, I, PP) ->
%%% - {prefer_nl,Sep,IPs}: forces linebreak between Is unlesss negative
%%% indentation.
%%% - {atom,A}: an atom
+%%% - {singleton_atom_type,A}: an singleton atom type
%%% - {char,C}: a character
%%% - {string,S}: a string.
%%% - {value,T}: a term.
@@ -983,8 +1017,10 @@ f({seq,Before,After,Sep,LItems}, I0, ST, WT, PP) ->
end,
{BCharsL++Chars,Size};
no ->
- {BCharsL++insert_newlines(CharsSizeL, I, ST),
- nsz(lists:last(Sizes), I0)}
+ CharsList = handle_step(CharsSizeL, I, ST),
+ {LChars, LSize} =
+ maybe_newlines(CharsList, LItems, I, NSepChars, ST),
+ {[BCharsL,LChars],nsz(LSize, I0)}
end;
f({force_nl,_ExtraInfoItem,Item}, I, ST, WT, PP) when I < 0 ->
%% Extra info is a comment; cannot have that on the same line
@@ -1000,23 +1036,28 @@ f({prefer_nl,Sep,LItems}, I0, ST, WT, PP) ->
Sizes =:= [] ->
{[], 0};
true ->
- {insert_newlines(CharsSize2L, I0, ST),nsz(lists:last(Sizes), I0)}
+ {insert_newlines(CharsSize2L, I0, ST),
+ nsz(lists:last(Sizes), I0)}
end;
f({value,V}, I, ST, WT, PP) ->
f(write_a_value(V, PP), I, ST, WT, PP);
f({atom,A}, I, ST, WT, PP) ->
f(write_an_atom(A, PP), I, ST, WT, PP);
+f({singleton_atom_type,A}, I, ST, WT, PP) ->
+ f(write_a_singleton_atom_type(A, PP), I, ST, WT, PP);
f({char,C}, I, ST, WT, PP) ->
f(write_a_char(C, PP), I, ST, WT, PP);
f({string,S}, I, ST, WT, PP) ->
f(write_a_string(S, I, PP), I, ST, WT, PP);
+f({reserved,R}, I, ST, WT, PP) ->
+ f(R, I, ST, WT, PP);
f({hook,HookExpr,Precedence,Func,Options}, I, _ST, _WT, _PP) ->
Chars = Func(HookExpr, I, Precedence, Options),
{Chars,indentation(Chars, I)};
f({ehook,HookExpr,Precedence,{Mod,Func,Eas}=ModFuncEas}, I, _ST, _WT, _PP) ->
Chars = apply(Mod, Func, [HookExpr,I,Precedence,ModFuncEas|Eas]),
{Chars,indentation(Chars, I)};
-f(WordName, _I, _ST, WT, _PP) -> % when is_atom(WordName)
+f(WordName, _I, _ST, WT, _PP) when is_atom(WordName) ->
word(WordName, WT).
-define(IND, 4).
@@ -1038,12 +1079,18 @@ fl(CItems, Sep0, I0, After, ST, WT, PP) ->
true ->
[CharSize1,f([Item2,S], incr(I0, ?IND), ST, WT, PP)]
end;
+ ({reserved,Word}, S) ->
+ [f([Word,S], I0, ST, WT, PP),{[],0}];
(Item, S) ->
[f([Item,S], I0, ST, WT, PP),{[],0}]
end,
- {Sep,LastSep} = case Sep0 of {_,_} -> Sep0; _ -> {Sep0,Sep0} end,
+ {Sep,LastSep} = sep(Sep0),
fl1(CItems, F, Sep, LastSep, After).
+sep([{S,LS}]) -> {[S],[LS]};
+sep({_,_}=Sep) -> Sep;
+sep(S) -> {S, S}.
+
fl1([CItem], F, _Sep, _LastSep, After) ->
[F(CItem,After)];
fl1([CItem1,CItem2], F, _Sep, LastSep, After) ->
@@ -1069,20 +1116,64 @@ unz1(CharSizes) ->
nonzero(CharSizes) ->
lists:filter(fun({_,Sz}) -> Sz =/= 0 end, CharSizes).
-insert_newlines(CharsSizesL, I, ST) when I >= 0 ->
- insert_nl(foldr(fun([{_C1,0},{_C2,0}], A) ->
- A;
- ([{C1,_Sz1},{_C2,0}], A) ->
- [C1|A];
- ([{C1,_Sz1},{C2,Sz2}], A) when Sz2 > 0 ->
- [insert_nl([C1,C2], I+?IND, ST)|A]
- end, [], CharsSizesL), I, ST).
+maybe_newlines([{Chars,Size}], [], _I, _NSepChars, _ST) ->
+ {Chars,Size};
+maybe_newlines(CharsSizeList, Items, I, NSepChars, ST) when I >= 0 ->
+ maybe_sep(CharsSizeList, Items, I, NSepChars, nl_indent(I, ST)).
+
+maybe_sep([{Chars1,Size1}|CharsSizeL], [Item|Items], I0, NSepChars, Sep) ->
+ I1 = case classify_item(Item) of
+ atomic ->
+ I0 + Size1;
+ _ ->
+ ?MAXLINE+1
+ end,
+ maybe_sep1(CharsSizeL, Items, I0, I1, Sep, NSepChars, Size1, [Chars1]).
+
+maybe_sep1([{Chars,Size}|CharsSizeL], [Item|Items],
+ I0, I, Sep, NSepChars, Sz0, A) ->
+ case classify_item(Item) of
+ atomic when is_integer(Size) ->
+ Size1 = Size + 1,
+ I1 = I + Size1,
+ if
+ I1 =< ?MAXLINE ->
+ A1 = if
+ NSepChars > 0 -> [Chars,$\s|A];
+ true -> [Chars|A]
+ end,
+ maybe_sep1(CharsSizeL, Items, I0, I1, Sep, NSepChars,
+ Sz0 + Size1, A1);
+ true ->
+ A1 = [Chars,Sep|A],
+ maybe_sep1(CharsSizeL, Items, I0, I0 + Size, Sep,
+ NSepChars, Size1, A1)
+ end;
+ _ ->
+ A1 = [Chars,Sep|A],
+ maybe_sep1(CharsSizeL, Items, I0, ?MAXLINE+1, Sep, NSepChars,
+ 0, A1)
+ end;
+maybe_sep1(_CharsSizeL, _Items, _Io, _I, _Sep, _NSepChars, Sz, A) ->
+ {lists:reverse(A), Sz}.
+insert_newlines(CharsSizesL, I, ST) when I >= 0 ->
+ {CharsL, _} = unz1(handle_step(CharsSizesL, I, ST)),
+ insert_nl(CharsL, I, ST).
+
+handle_step(CharsSizesL, I, ST) ->
+ map(fun([{_C1,0},{_C2,0}]) ->
+ {[], 0};
+ ([{C1,Sz1},{_C2,0}]) ->
+ {C1, Sz1};
+ ([{C1,Sz1},{C2,Sz2}]) when Sz2 > 0 ->
+ {insert_nl([C1,C2], I+?IND, ST),line_size([Sz1,Sz2])}
+ end, CharsSizesL).
insert_nl(CharsL, I, ST) ->
insert_sep(CharsL, nl_indent(I, ST)).
-insert_sep([Chars1 | CharsL], Sep) ->
+insert_sep([Chars1|CharsL], Sep) ->
[Chars1 | [[Sep,Chars] || Chars <- CharsL]].
nl_indent(0, _T) ->
@@ -1090,6 +1181,12 @@ nl_indent(0, _T) ->
nl_indent(I, T) when I > 0 ->
[$\n|spaces(I, T)].
+classify_item({atom, _}) -> atomic;
+classify_item({singleton_atom_type, _}) -> atomic;
+classify_item(Atom) when is_atom(Atom) -> atomic;
+classify_item({leaf, _, _}) -> atomic;
+classify_item(_) -> complex.
+
same_line(I0, SizeL, NSepChars) ->
try
Size = lists:sum(SizeL) + NSepChars,
@@ -1150,6 +1247,9 @@ write_a_value(V, PP) ->
write_an_atom(A, PP) ->
flat_leaf(write_atom(A, PP)).
+write_a_singleton_atom_type(A, PP) ->
+ flat_leaf(write_singleton_atom_type(A, PP)).
+
write_a_char(C, PP) ->
flat_leaf(write_char(C, PP)).
@@ -1184,6 +1284,9 @@ write_value(V, PP) ->
write_atom(A, PP) ->
(PP#pp.value_fun)(A).
+write_singleton_atom_type(A, PP) ->
+ (PP#pp.singleton_atom_type_fun)(A).
+
write_string(S, PP) ->
(PP#pp.string_fun)(S).
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index b95cb8f525..fa34f19637 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -323,90 +323,6 @@ obsolete_1(snmp, N, A) ->
obsolete_1(snmpa, old_info_format, 1) ->
{deprecated, "Deprecated; (will be removed in OTP 18); use \"new\" format instead"};
-obsolete_1(snmpm, agent_info, 3) ->
- {removed, {snmpm, agent_info, 2}, "R16B"};
-obsolete_1(snmpm, update_agent_info, 5) ->
- {removed, {snmpm, update_agent_info, 4}, "R16B"};
-obsolete_1(snmpm, g, 3) ->
- {removed, {snmpm, sync_get, 3}, "R16B"};
-obsolete_1(snmpm, g, 4) ->
- {removed, {snmpm, sync_get, [3,4]}, "R16B"};
-obsolete_1(snmpm, g, 5) ->
- {removed, {snmpm, sync_get, [4,5]}, "R16B"};
-obsolete_1(snmpm, g, 6) ->
- {removed, {snmpm, sync_get, [5,6]}, "R16B"};
-obsolete_1(snmpm, g, 7) ->
- {removed, {snmpm, sync_get, 6}, "R16B"};
-obsolete_1(snmpm, ag, 3) ->
- {removed, {snmpm, async_get, 3}, "R16B"};
-obsolete_1(snmpm, ag, 4) ->
- {removed, {snmpm, async_get, [3,4]}, "R16B"};
-obsolete_1(snmpm, ag, 5) ->
- {removed, {snmpm, async_get, [4,5]}, "R16B"};
-obsolete_1(snmpm, ag, 6) ->
- {removed, {snmpm, async_get, [5,6]}, "R16B"};
-obsolete_1(snmpm, ag, 7) ->
- {removed, {snmpm, async_get, 6}, "R16B"};
-obsolete_1(snmpm, gn, 3) ->
- {removed, {snmpm, sync_get_next, 3}, "R16B"};
-obsolete_1(snmpm, gn, 4) ->
- {removed, {snmpm, sync_get_next, [3,4]}, "R16B"};
-obsolete_1(snmpm, gn, 5) ->
- {removed, {snmpm, sync_get_next, [4,5]}, "R16B"};
-obsolete_1(snmpm, gn, 6) ->
- {removed, {snmpm, sync_get_next, [5,6]}, "R16B"};
-obsolete_1(snmpm, gn, 7) ->
- {removed, {snmpm, sync_get_next, 6}, "R16B"};
-obsolete_1(snmpm, agn, 3) ->
- {removed, {snmpm, async_get_next, 3}, "R16B"};
-obsolete_1(snmpm, agn, 4) ->
- {removed, {snmpm, async_get_next, [3,4]}, "R16B"};
-obsolete_1(snmpm, agn, 5) ->
- {removed, {snmpm, async_get_next, [4,5]}, "R16B"};
-obsolete_1(snmpm, agn, 6) ->
- {removed, {snmpm, async_get_next, [5,6]}, "R16B"};
-obsolete_1(snmpm, agn, 7) ->
- {removed, {snmpm, async_get_next, 6}, "R16B"};
-obsolete_1(snmpm, s, 3) ->
- {removed, {snmpm, sync_set, 3}, "R16B"};
-obsolete_1(snmpm, s, 4) ->
- {removed, {snmpm, sync_set, [3,4]}, "R16B"};
-obsolete_1(snmpm, s, 5) ->
- {removed, {snmpm, sync_set, [4,5]}, "R16B"};
-obsolete_1(snmpm, s, 6) ->
- {removed, {snmpm, sync_set, [5,6]}, "R16B"};
-obsolete_1(snmpm, s, 7) ->
- {removed, {snmpm, sync_set, 6}, "R16B"};
-obsolete_1(snmpm, as, 3) ->
- {removed, {snmpm, async_set, 3}, "R16B"};
-obsolete_1(snmpm, as, 4) ->
- {removed, {snmpm, async_set, [3,4]}, "R16B"};
-obsolete_1(snmpm, as, 5) ->
- {removed, {snmpm, async_set, [4,5]}, "R16B"};
-obsolete_1(snmpm, as, 6) ->
- {removed, {snmpm, async_set, [5,6]}, "R16B"};
-obsolete_1(snmpm, as, 7) ->
- {removed, {snmpm, async_set, 6}, "R16B"};
-obsolete_1(snmpm, gb, 5) ->
- {removed, {snmpm, sync_get_bulk, 5}, "R16B"};
-obsolete_1(snmpm, gb, 6) ->
- {removed, {snmpm, sync_get_bulk, [5,6]}, "R16B"};
-obsolete_1(snmpm, gb, 7) ->
- {removed, {snmpm, sync_get_bulk, [6,7]}, "R16B"};
-obsolete_1(snmpm, gb, 8) ->
- {removed, {snmpm, sync_get_bulk, [7,8]}, "R16B"};
-obsolete_1(snmpm, gb, 9) ->
- {removed, {snmpm, sync_get_bulk, 8}, "R16B"};
-obsolete_1(snmpm, agb, 5) ->
- {removed, {snmpm, async_get_bulk, 5}, "R16B"};
-obsolete_1(snmpm, agb, 6) ->
- {removed, {snmpm, async_get_bulk, [5,6]}, "R16B"};
-obsolete_1(snmpm, agb, 7) ->
- {removed, {snmpm, async_get_bulk, [6,7]}, "R16B"};
-obsolete_1(snmpm, agb, 8) ->
- {removed, {snmpm, async_get_bulk, [7,8]}, "R16B"};
-obsolete_1(snmpm, agb, 9) ->
- {removed, {snmpm, async_get_bulk, 8}, "R16B"};
%% *** MEGACO ***
@@ -417,6 +333,7 @@ obsolete_1(megaco, format_versions, 1) ->
%% *** OS-MON-MIB ***
+%% FIXME: Remove this warning in OTP 24.
obsolete_1(os_mon_mib, _, _) ->
{removed, "was removed in 22.0"};
@@ -431,64 +348,6 @@ obsolete_1(auth, node_cookie, 1) ->
obsolete_1(auth, node_cookie, 2) ->
{deprecated, "Deprecated; use erlang:set_cookie/2 and net_adm:ping/1 instead"};
-obsolete_1(http, request, 1) -> {removed,{httpc,request,1},"R15B"};
-obsolete_1(http, request, 2) -> {removed,{httpc,request,2},"R15B"};
-obsolete_1(http, request, 4) -> {removed,{httpc,request,4},"R15B"};
-obsolete_1(http, request, 5) -> {removed,{httpc,request,5},"R15B"};
-obsolete_1(http, cancel_request, 1) -> {removed,{httpc,cancel_request,1},"R15B"};
-obsolete_1(http, cancel_request, 2) -> {removed,{httpc,cancel_request,2},"R15B"};
-obsolete_1(http, set_option, 2) -> {removed,{httpc,set_option,2},"R15B"};
-obsolete_1(http, set_option, 3) -> {removed,{httpc,set_option,3},"R15B"};
-obsolete_1(http, set_options, 1) -> {removed,{httpc,set_options,1},"R15B"};
-obsolete_1(http, set_options, 2) -> {removed,{httpc,set_options,2},"R15B"};
-obsolete_1(http, verify_cookies, 2) -> {removed,{httpc,store_cookies,2},"R15B"};
-obsolete_1(http, verify_cookies, 3) -> {removed,{httpc,store_cookies,3},"R15B"};
-obsolete_1(http, cookie_header, 1) -> {removed,{httpc,cookie_header,1},"R15B"};
-obsolete_1(http, cookie_header, 2) -> {removed,{httpc,cookie_header,2},"R15B"};
-obsolete_1(http, stream_next, 1) -> {removed,{httpc,stream_next,1},"R15B"};
-obsolete_1(http, default_profile, 0) -> {removed,{httpc,default_profile,0},"R15B"};
-
-%% Added in R13A.
-obsolete_1(regexp, _, _) ->
- {removed, "removed in R15; use the re module instead"};
-
-%% Added in R13B04.
-obsolete_1(erlang, concat_binary, 1) ->
- {removed,{erlang,list_to_binary,1},"R15B"};
-
-%% Added in R14A.
-obsolete_1(ssl, peercert, 2) ->
- {removed ,"removed in R15A; use ssl:peercert/1 and public_key:pkix_decode_cert/2 instead"};
-
-%% Added in R14B.
-obsolete_1(public_key, pem_to_der, 1) ->
- {removed,"removed in R15A; use file:read_file/1 and public_key:pem_decode/1"};
-obsolete_1(public_key, decode_private_key, A) when A =:= 1; A =:= 2 ->
- {removed, "removed in R15A; use public_key:pem_entry_decode/1"};
-
-%% Added in R14B03.
-obsolete_1(docb_gen, _, _) ->
- {removed,"the DocBuilder application was removed in R15B"};
-obsolete_1(docb_transform, _, _) ->
- {removed,"the DocBuilder application was removed in R15B"};
-obsolete_1(docb_xml_check, _, _) ->
- {removed,"the DocBuilder application was removed in R15B"};
-
-%% Added in R15B
-obsolete_1(asn1rt, F, _) when F == load_driver; F == unload_driver ->
- {removed,"removed (will be removed in OTP 18); has no effect as drivers are no longer used"};
-obsolete_1(ssl, pid, 1) ->
- {removed,"was removed in R16; is no longer needed"};
-obsolete_1(inviso, _, _) ->
- {removed,"the inviso application was removed in R16"};
-
-%% Added in R15B01.
-obsolete_1(ssh, sign_data, 2) ->
- {removed,"removed in R16A; use public_key:pem_decode/1, public_key:pem_entry_decode/1 "
- "and public_key:sign/3 instead"};
-obsolete_1(ssh, verify_data, 3) ->
- {removed,"removed in R16A; use public_key:ssh_decode/1, and public_key:verify/4 instead"};
-
%% Added in R16
obsolete_1(wxCalendarCtrl, enableYearChange, _) -> %% wx bug documented?
{deprecated,"deprecated function not available in wxWidgets-2.9 and later"};
@@ -609,10 +468,8 @@ obsolete_1(queue, lait, 1) ->
%% Removed in OTP 19.
-obsolete_1(overload, _, _) ->
- {removed, "removed in OTP 19"};
obsolete_1(rpc, safe_multi_server_call, A) when A =:= 2; A =:= 3 ->
- {removed, {rpc, multi_server_call, A}, "removed in OTP 19"};
+ {removed, {rpc, multi_server_call, A}, "19.0"};
%% Added in OTP 20.
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index 37ea97c353..08612ed17f 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -41,7 +41,9 @@
{<<"^3\\.6\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.7$">>,[restart_new_emulator]},
{<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}],
+ {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.8$">>,[restart_new_emulator]},
+ {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}],
[{<<"^3\\.4$">>,[restart_new_emulator]},
{<<"^3\\.4\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.4\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
@@ -56,4 +58,6 @@
{<<"^3\\.6\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
{<<"^3\\.7$">>,[restart_new_emulator]},
{<<"^3\\.7\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]},
- {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]}]}.
+ {<<"^3\\.7\\.1(?:\\.[0-9]+)*$">>,[restart_new_emulator]},
+ {<<"^3\\.8$">>,[restart_new_emulator]},
+ {<<"^3\\.8\\.0(?:\\.[0-9]+)+$">>,[restart_new_emulator]}]}.