Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:24
erlang
3572-features-Clean-up-naming-and-more.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3572-features-Clean-up-naming-and-more.patch of Package erlang
From 14c58f82e7c229e3d34eb99af3188521f2c25add Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cons=20T=20=C3=85hs?= <cons@erlang.org> Date: Tue, 26 Apr 2022 15:57:22 +0200 Subject: [PATCH 2/6] [features] Clean up naming and more * Improve naming in erl_features * feature_info/1 -> info/1 * features/0 -> all/0 * features_used/1 -> used/1 * features_enabled/0 -> enabled/0 * Rename and unexport internal functions * Add specs and improve typing * Testing * Improve possibilities to debug tests on failure * Add simple tests for info/1 and features/0 * Add tests for long/short feature descriptions * Fix typos in test features --- erts/test/lux/bad_feature_erlc.lux | 4 +- erts/test/lux/feature_erl.lux | 38 ++++++-- erts/test/lux/feature_erlc.lux | 26 ++++- erts/test/lux/feature_runtime.lux | 14 +-- erts/test/lux/features.luxinc | 10 +- lib/stdlib/src/epp.erl | 5 +- lib/stdlib/src/erl_compile.erl | 11 ++- lib/stdlib/src/erl_features.erl | 152 +++++++++++++++-------------- lib/stdlib/src/erl_lint.erl | 2 +- 9 files changed, 159 insertions(+), 103 deletions(-) diff --git a/erts/test/lux/bad_feature_erlc.lux b/erts/test/lux/bad_feature_erlc.lux index 903696d2ce..bd8b8b76e8 100644 --- a/erts/test/lux/bad_feature_erlc.lux +++ b/erts/test/lux/bad_feature_erlc.lux @@ -186,14 +186,14 @@ [shell erl] # Verify that only ifn_expr is used - !Fs = erl_features:features_used(f_directives_2). + !Fs = erl_features:used(f_directives_2). ?$ERLPROMPT [invoke same-members Fs "[ifn_expr,cond_expr,maps]"] !f(Fs). ?$ERLPROMPT # Verify that only ifn_expr is used - !Fs = erl_features:features_used(f_directives_3). + !Fs = erl_features:used(f_directives_3). ?$ERLPROMPT [invoke same-members Fs "[ifn_expr,cond_expr,maps]"] !f(Fs). diff --git a/erts/test/lux/feature_erl.lux b/erts/test/lux/feature_erl.lux index 88d71a06a6..1205f9a601 100644 --- a/erts/test/lux/feature_erl.lux +++ b/erts/test/lux/feature_erl.lux @@ -10,39 +10,59 @@ -undefined function [invoke start-erl ""] - [invoke same-members "erl_features:enabled_features()" "[maps,cond_expr]"] + # Verify that the known test features are returned + [invoke same-members "erl_features:all()" "[maps,cond_expr,while_expr,ifn_expr,ifnot_expr,unless_expr]"] + + # Verify that we get an error if trying to get information about + # an unknown feature. + !erl_features:info(loop_expr). + ?error.*invalid_feature + ?unknown feature + ?$ERLPROMPT + + # Verify that we get a map with info for a known feature + !IMap = erl_features:info(maps). + ?$ERLPROMPT + !is_map(IMap). + ?true + ?$ERLPROMPT + !lists:all(fun(K) -> is_map_key(K, IMap) end, [status,type,description,short,experimental]). + ?true + ?$ERLPROMPT + + [invoke same-members "erl_features:enabled()" "[maps,cond_expr]"] [invoke quit-erl] [invoke start-erl "-enable-feature ifn_expr"] - [invoke same-members "erl_features:enabled_features()" "[maps,cond_expr,ifn_expr]"] + [invoke same-members "erl_features:enabled()" "[maps,cond_expr,ifn_expr]"] [invoke quit-erl] [invoke start-erl "-enable-feature ifn_expr -enable-feature while_expr"] - [invoke same-members "erl_features:enabled_features()" "[maps,cond_expr,while_expr,ifn_expr]"] + [invoke same-members "erl_features:enabled()" "[maps,cond_expr,while_expr,ifn_expr]"] [invoke quit-erl] [invoke start-erl "-enable-feature ifn_expr while_expr"] - [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,while_expr,ifn_expr]"] + [invoke same-members "erl_features:enabled()" "[cond_expr,maps,while_expr,ifn_expr]"] [invoke quit-erl] [invoke start-erl "-enable-feature ifn_expr while_expr -enable-feature ifnot_expr"] - [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,while_expr,ifn_expr,ifnot_expr]"] + [invoke same-members "erl_features:enabled()" "[cond_expr,maps,while_expr,ifn_expr,ifnot_expr]"] [invoke quit-erl] # Enabling the same feature twice does not hurt [invoke start-erl "-enable-feature ifn_expr while_expr -enable-feature ifnot_expr ifn_expr"] - [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,while_expr,ifn_expr,ifnot_expr]"] + [invoke same-members "erl_features:enabled()" "[cond_expr,maps,while_expr,ifn_expr,ifnot_expr]"] [invoke quit-erl] @@ -52,18 +72,18 @@ # problem since we have a lazy init of the feature set. [invoke start-erl "-enable-feature no_ftr"] - [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps]"] + [invoke same-members "erl_features:enabled()" "[cond_expr,maps]"] [invoke quit-erl] [invoke start-erl "-disable-feature cond_expr"] - [invoke same-members "erl_features:enabled_features()" "[maps]"] + [invoke same-members "erl_features:enabled()" "[maps]"] # FIXME Need to check that keywords have changed as well! [invoke quit-erl] [invoke start-erl "-disable-feature all"] - !erl_features:enabled_features(). + !erl_features:enabled(). ??[] ?$ERLPROMPT diff --git a/erts/test/lux/feature_erlc.lux b/erts/test/lux/feature_erlc.lux index 3a033d0aad..5082f56ad1 100644 --- a/erts/test/lux/feature_erlc.lux +++ b/erts/test/lux/feature_erlc.lux @@ -196,7 +196,7 @@ ??{error,not_allowed} ?$ERLPROMPT - !Fs = erl_features:features_used(f_maybe_ifn). + !Fs = erl_features:used(f_maybe_ifn). [invoke same-members Fs "[cond_expr,maps,while_expr,ifn_expr]"] !f(Fs). ?$ERLPROMPT @@ -249,7 +249,7 @@ ?$ERLPROMPT # Check which features were used during compilation - !Fs = erl_features:features_used(f_macros). + !Fs = erl_features:used(f_macros). ?$ERLPROMPT [invoke same-members Fs "[maps,cond_expr,ifn_expr]"] !f(Fs). @@ -405,7 +405,7 @@ [invoke ok] [shell erl] - !Fs = erl_features:features_used(foo). + !Fs = erl_features:used(foo). ?$ERLPROMPT [invoke same-members Fs "[unless_expr,ifn_expr,while_expr,cond_expr,maps,ifnot_expr]"] !f(Fs). @@ -419,7 +419,7 @@ [invoke ok] [shell erl] - !Fs = erl_features:features_used(foo). + !Fs = erl_features:used(foo). ?$ERLPROMPT !maps:from_keys([ifn_expr,while_expr,cond_expr,maps,ifnot_expr], foo) == maps:from_keys(Fs, foo). ?true @@ -427,6 +427,24 @@ !f(Fs). ?$ERLPROMPT +[shell cmds] + !erlc -list-features + ?cond_expr + ?ifn_expr + ?ifnot_expr + ?maps + ?unless_expr + ?while_expr + ?SH-PROMPT: + + !erlc -describe-feature maps + ?Add new data type for maps + ?SH-PROMPT: + + !erlc -describe-feature loop_macro + ?Unknown feature: loop_macro + [invoke notok] + [cleanup] [invoke no-dump] !rm -fr $outdir diff --git a/erts/test/lux/feature_runtime.lux b/erts/test/lux/feature_runtime.lux index 723d650d5a..1048164a52 100644 --- a/erts/test/lux/feature_runtime.lux +++ b/erts/test/lux/feature_runtime.lux @@ -11,7 +11,7 @@ !erl ?$ERLPROMPT - [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps]"] + [invoke same-members "erl_features:enabled()" "[cond_expr,maps]"] !erl_features:keywords(). ??[] @@ -33,14 +33,14 @@ [invoke same-members "erl_features:enable_feature(while_expr)" "[cond_expr,maps,ifn_expr,while_expr]"] - [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,ifn_expr,while_expr]"] + [invoke same-members "erl_features:enabled()" "[cond_expr,maps,ifn_expr,while_expr]"] !erl_features:keywords(). ??['while','until','ifn'] [invoke same-members "erl_features:disable_feature(ifn_expr)" "[cond_expr,maps,while_expr]"] - [invoke same-members "erl_features:enabled_features()" "[cond_expr,maps,while_expr]"] + [invoke same-members "erl_features:enabled()" "[cond_expr,maps,while_expr]"] !erl_features:keywords(). ??['while','until'] @@ -68,21 +68,21 @@ # If there is no Meta chunk, we should just get [] as answer, # not a failure. We use a file compiled with an older release to be # sure no meta chunk is present - !erl_features:features_used(older). + !erl_features:used(older). ???[] ?$ERLPROMPT - !erl_features:features_used("older.beam"). + !erl_features:used("older.beam"). ???[] ?$ERLPROMPT # Test getting used features for unknown modules and files - !erl_features:features_used(no_module). + !erl_features:used(no_module). ??not_found ?$ERLPROMPT - !erl_features:features_used("none.beam"). + !erl_features:used("none.beam"). ??not_found ?$ERLPROMPT diff --git a/erts/test/lux/features.luxinc b/erts/test/lux/features.luxinc index 2998f67dd9..376aca4b97 100644 --- a/erts/test/lux/features.luxinc +++ b/erts/test/lux/features.luxinc @@ -68,12 +68,18 @@ [endmacro] # Nifty way to compare that two lists have the same members -# One drawback is that it os not easy to debug, i.e., see the actual +# One drawback is that it is not easy to debug, i.e., see the actual # members. [macro same-members l1 l2] - !maps:from_keys($l1,foo) == maps:from_keys($l2,foo). + !{L1, L2} = {$l1, $l2}. + ?$ERLPROMPT + !maps:from_keys(L1,foo) == maps:from_keys(L2,foo). ?true ?$ERLPROMPT + !f(L1). + ?$ERLPROMPT + !f(L2). + ?$ERLPROMPT [endmacro] [macro no-dump] diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl index 066b02f483..95a933c9fa 100644 --- a/lib/stdlib/src/epp.erl +++ b/lib/stdlib/src/epp.erl @@ -647,7 +647,7 @@ predef_macros(File, EnabledFeatures) -> Machine = list_to_atom(erlang:system_info(machine)), Anno = line1(), OtpVersion = list_to_integer(erlang:system_info(otp_release)), - AvailableFeatures = erl_features:features(), + AvailableFeatures = erl_features:all(), Defs = [{'FILE', {none,[{string,Anno,File}]}}, {'FUNCTION_NAME', undefined}, {'FUNCTION_ARITY', undefined}, @@ -1038,10 +1038,9 @@ update_features(St0, Ind, Ftr, Loc) -> case erl_features:keyword_fun(Ind, Ftr, Ftrs0, KeywordFun) of {error, Reason} -> {error, {Reason, Loc}}; - {ok, ResWordFun1, Ftrs1} -> + {ok, {Ftrs1, ResWordFun1}} -> Macs0 = St0#epp.macs, Macs1 = Macs0#{'FEATURE_ENABLED' => [ftr_macro(Ftrs1)]}, - %% ?liof("ok!\n", []), %% FIXME WE need to keep any other scan_opts %% present. Right now, there are no other, but %% that might change. diff --git a/lib/stdlib/src/erl_compile.erl b/lib/stdlib/src/erl_compile.erl index 6cb8590f13..84923f21fb 100644 --- a/lib/stdlib/src/erl_compile.erl +++ b/lib/stdlib/src/erl_compile.erl @@ -329,13 +329,20 @@ show_info(#options{specific = Spec}) -> case G([list_features, describe_feature]) of {list_features, true} -> - Features = erl_features:features(), + Features = erl_features:all(), Msg = ["Available features:\n", [io_lib:format(" ~-13s ~s\n", [Ftr, erl_features:short(Ftr)]) || Ftr <- Features]], {ok, Msg}; {describe_feature, Ftr} -> - {ok, erl_features:long(Ftr)}; + Description = + try + erl_features:long(Ftr) + catch + error:invalid_feature -> + io_lib:format("Unknown feature: ~p\n", [Ftr]) + end, + {ok, Description}; _ -> false end. diff --git a/lib/stdlib/src/erl_features.erl b/lib/stdlib/src/erl_features.erl index 77ada029cb..edb1e71d52 100644 --- a/lib/stdlib/src/erl_features.erl +++ b/lib/stdlib/src/erl_features.erl @@ -19,15 +19,11 @@ %% -module(erl_features). -%% FIXME divide the exported functions in public and internal for the -%% sake of documentation. --export([features/0, - feature_info/1, - collect_features/1, +-export([all/0, + info/1, short/1, long/1, - enabled_features/0, - is_valid_feature/1, + enabled/0, load_allowed/1, keywords/0, keywords/1, @@ -35,21 +31,21 @@ keyword_fun/4, enable_feature/1, disable_feature/1, + used/1, format_error/1, format_error/2]). --export([features_used/1]). - -type type() :: 'extension' | 'backwards_incompatible_change'. -type status() :: 'experimental' | 'approved' | 'permanent' | 'rejected'. -type release() :: non_neg_integer(). +-type feature() :: atom(). -type error() :: {?MODULE, {'invalid_features', [atom()]}}. -define(VALID_FEATURE(Feature), - (case is_valid_feature(Feature) of + (case is_valid(Feature) of false -> error(invalid_feature, [Feature], [{error_info, @@ -70,31 +66,32 @@ feature_specs() -> keywords => ['maybe', 'else'], type => extension}}. -%% Currently known features --spec features() -> [atom()]. -features() -> +%% Return all currently known features. +-spec all() -> [feature()]. +all() -> Map = case persistent_term:get({?MODULE, feature_specs}, none) of none -> init_specs(); M -> M end, maps:keys(Map). -is_valid_feature(Ftr) -> - lists:member(Ftr, features()). +is_valid(Ftr) -> + lists:member(Ftr, all()). --spec short(atom()) -> iolist(). +-spec short(feature()) -> iolist() | no_return(). short(Feature) -> #{short := Short, - status := Status} = Info = feature_info(Feature), + status := Status} = Info = info(Feature), #{Status := Release} = Info, io_lib:format("~-40s ~-12s (~p)", [Short, Status, Release]). +-spec long(feature()) -> iolist() | no_return(). long(Feature) -> #{short := Short, description := Description, status := Status, keywords := Keywords, - type := Type} = Info = feature_info(Feature), + type := Type} = Info = info(Feature), StatusFmt = " ~-10s ~-12s (~p)\n", History = [io_lib:format(StatusFmt, [T, S, R]) || {T, S, R} <- history(Status, Info)], @@ -148,7 +145,7 @@ adjust(Col, [{W, L}| WLs], Ws) -> end. --spec feature_info(atom()) -> FeatureInfoMap | no_return() +-spec info(feature()) -> FeatureInfoMap | no_return() when Description :: string(), FeatureInfoMap :: @@ -162,19 +159,18 @@ adjust(Col, [{W, L}| WLs], Ws) -> permanent => release(), rejected => release() }. -feature_info(Feature) -> +info(Feature) -> ?VALID_FEATURE(Feature), Map = persistent_term:get({?MODULE, feature_specs}), maps:get(Feature, Map). -%% New keywords for a feature. The current set is just for -%% tests and development. --spec keywords(atom()) -> [atom()]. +%% New keywords introduced by a feature. +-spec keywords(feature()) -> [atom()] | no_return(). keywords(Ftr) -> ?VALID_FEATURE(Ftr), - #{keywords := Keywords} = feature_info(Ftr), + #{keywords := Keywords} = info(Ftr), Keywords. %% Internal - Ftr is valid @@ -183,9 +179,9 @@ keywords(Ftr, Map) -> %% Utilities %% Returns list of enabled features and a new keywords function -%% -spec keyword_fun_add_feature(atom(), fun((atom()) -> boolean())) -> -%% {'ok', fun((atom()) -> boolean())} -%% | {'error', error()}. +-spec keyword_fun([term()], fun((atom()) -> boolean())) -> + {'ok', {[feature()], fun((atom()) -> boolean())}} + | {'error', error()}. keyword_fun(Opts, KeywordFun) -> %% Get items enabling or disabling features, preserving order. IsFtr = fun({feature, _, enable}) -> true; @@ -197,9 +193,9 @@ keyword_fun(Opts, KeywordFun) -> %% FIXME check that all features are known at this stage so we %% don't miss out on reporting any unknown features. - case keyword_fun_add_features(AddFeatures, KeywordFun) of + case add_features_fun(AddFeatures, KeywordFun) of {ok, Fun} -> - case keyword_fun_remove_features(DelFeatures, Fun) of + case remove_features_fun(DelFeatures, Fun) of {ok, FunX} -> {ok, {AddFeatures -- DelFeatures, FunX}}; {error, _} = Error -> @@ -211,36 +207,33 @@ keyword_fun(Opts, KeywordFun) -> Error end. -%% -spec keyword_fun_add_feature(atom(), fun((atom()) -> boolean())) -> -%% {'ok', fun((atom()) -> boolean())} -%% | {'error', error()}. +-spec keyword_fun('enable' | 'disable', feature(), [feature()], + fun((atom()) -> boolean())) -> + {'ok', {[feature()], fun((atom()) -> boolean())}} + | {'error', error()}. keyword_fun(Ind, Feature, Ftrs, KeywordFun) -> - case is_valid_feature(Feature) of + case is_valid(Feature) of true -> case Ind of enable -> - {ok, - add_feature(Feature, KeywordFun), - [Feature | Ftrs]}; + {ok, {[Feature | Ftrs], + add_feature_fun(Feature, KeywordFun)}}; disable -> - {ok, - remove_feature(Feature, KeywordFun), - Ftrs -- [Feature]} + {ok, {Ftrs -- [Feature], + remove_feature_fun(Feature, KeywordFun)}} end; false -> {error, {?MODULE, {invalid_features, [Feature]}}} end. -%% FIXME Rename this to reflect that it returns a function! -add_feature(Feature, F) -> +add_feature_fun(Feature, F) -> Words = keywords(Feature), fun(Word) -> lists:member(Word, Words) orelse F(Word) end. -%% FIXME Rename this to reflect that it returns a function! -remove_feature(Feature, F) -> +remove_feature_fun(Feature, F) -> Words = keywords(Feature), fun(Word) -> case lists:member(Word, Words) of @@ -249,37 +242,46 @@ remove_feature(Feature, F) -> end end. --spec keyword_fun_add_features([atom()], fun((atom()) -> boolean())) -> +-spec add_features_fun([feature()], fun((atom()) -> boolean())) -> {'ok', fun((atom()) -> boolean())} | {'error', error()}. -keyword_fun_add_features(Features, F) -> - case lists:all(fun is_valid_feature/1, Features) of +add_features_fun(Features, F) -> + case lists:all(fun is_valid/1, Features) of true -> - {ok, lists:foldl(fun add_feature/2, F, Features)}; + {ok, lists:foldl(fun add_feature_fun/2, F, Features)}; false -> - IsInvalid = fun(Ftr) -> not is_valid_feature(Ftr) end, + IsInvalid = fun(Ftr) -> not is_valid(Ftr) end, Invalid = lists:filter(IsInvalid, Features), {error, {?MODULE, {invalid_features, Invalid}}} end. --spec keyword_fun_remove_features([atom()], fun((atom()) -> boolean())) -> +-spec remove_features_fun([feature()], fun((atom()) -> boolean())) -> {'ok', fun((atom()) -> boolean())} | {'error', error()}. -keyword_fun_remove_features(Features, F) -> - case lists:all(fun is_valid_feature/1, Features) of +remove_features_fun(Features, F) -> + case lists:all(fun is_valid/1, Features) of true -> - {ok, lists:foldl(fun remove_feature/2, F, Features)}; + {ok, lists:foldl(fun remove_feature_fun/2, F, Features)}; false -> - IsInvalid = fun(Ftr) -> not is_valid_feature(Ftr) end, + IsInvalid = fun(Ftr) -> not is_valid(Ftr) end, Invalid = lists:filter(IsInvalid, Features), {error, {?MODULE, {invalid_features, Invalid}}} end. +-spec format_error(Reason, StackTrace) -> ErrorDescription + when Reason :: term(), + StackTrace :: erlang:stacktrace(), + ArgumentPosition :: pos_integer(), + ErrorDescription :: #{ArgumentPosition => unicode:chardata(), + general => unicode:chardata(), + reason => unicode:chardata()}. format_error(Reason, [{_M, _F, _Args, Info}| _St]) -> ErrorInfo = proplists:get_value(error_info, Info, #{}), ErrorMap = maps:get(cause, ErrorInfo), ErrorMap#{reason => io_lib:format("~p: ~p", [?MODULE, Reason])}. +-spec format_error(Reason) -> iolist() + when Reason :: term(). format_error({invalid_features, Features}) -> Fmt = fun F([Ftr]) -> io_lib:fwrite("'~p'", [Ftr]); F([Ftr1, Ftr2]) -> @@ -326,7 +328,7 @@ init_features() -> F = fun({Tag, String}) -> try Atom = list_to_atom(String), - case is_valid_feature(Atom) of + case is_valid(Atom) of true -> {true, {feature, Atom, Cnv(Tag)}}; false when Atom == all -> {true, {feature, Atom, Cnv(Tag)}}; @@ -377,7 +379,7 @@ ensure_init() -> enable_feature(Feature) -> ?VALID_FEATURE(Feature), - Features = enabled_features(), + Features = enabled(), case lists:member(Feature, Features) of true -> %% already there, maybe raise an error @@ -394,7 +396,7 @@ enable_feature(Feature) -> disable_feature(Feature) -> ?VALID_FEATURE(Feature), - Features = enabled_features(), + Features = enabled(), case lists:member(Feature, Features) of true -> NewFeatures = Features -- [Feature], @@ -408,13 +410,17 @@ disable_feature(Feature) -> Features end. -enabled_features() -> +%% Return list of currently enabled features +-spec enabled() -> [feature()]. +enabled() -> ensure_init(), persistent_term:get({?MODULE, enabled_features}). enabled_features(Ftrs) -> persistent_term:put({?MODULE, enabled_features}, Ftrs). +%% Return list of keywords activated by enabled features +-spec keywords() -> [atom()]. keywords() -> ensure_init(), persistent_term:get({?MODULE, keywords}). @@ -434,7 +440,7 @@ load_allowed(Binary) -> undefined -> true; Used -> - Enabled = enabled_features(), + Enabled = enabled(), lists:all(fun(UFtr) -> lists:member(UFtr, Enabled) end, @@ -444,14 +450,15 @@ load_allowed(Binary) -> %% Return features used by module or beam file -features_used(Module) when is_atom(Module) -> +-spec used(module() | file:filename()) -> [feature()]. +used(Module) when is_atom(Module) -> case code:get_object_code(Module) of error -> not_found; {_Mod, Bin, _Fname} -> features_in(Bin) end; -features_used(FName) when is_list(FName) -> +used(FName) when is_list(FName) -> features_in(FName). features_in(NameOrBin) -> @@ -465,33 +472,33 @@ features_in(NameOrBin) -> not_found end. -approved_features() -> - [Ftr || Ftr <- features(), - maps:get(status, feature_info(Ftr)) == approved]. +approved() -> + [Ftr || Ftr <- all(), + maps:get(status, info(Ftr)) == approved]. -permanent_features() -> - [Ftr || Ftr <- features(), - maps:get(status, feature_info(Ftr)) == permanent]. +permanent() -> + [Ftr || Ftr <- all(), + maps:get(status, info(Ftr)) == permanent]. %% Interpret feature ops (enable or disable) to build the full set of %% features. The meta feature 'all' is expanded to all known %% features. collect_features(FOps) -> %% Features enabled by default - Enabled = approved_features() ++ permanent_features(), + Enabled = approved() ++ permanent(), collect_features(FOps, Enabled, []). collect_features([], Add, Del) -> {Add, Del}; collect_features([{feature, all, enable}| FOps], Add, _Del) -> - All = features(), + All = all(), Add1 = lists:foldl(fun add_ftr/2, Add, All), collect_features(FOps, Add1, []); collect_features([{feature, Feature, enable}| FOps], Add, Del) -> collect_features(FOps, add_ftr(Feature, Add), Del -- [Feature]); collect_features([{feature, all, disable}| FOps], _Add, Del) -> %% Start over - All = features(), + All = all(), collect_features(FOps, [], Del -- All); collect_features([{feature, Feature, disable}| FOps], Add, Del) -> collect_features(FOps, Add -- [Feature], @@ -532,7 +539,7 @@ test_features() -> keywords => ['ifnot'], type => extension}, unless_expr => - #{short => "`unless <cond> -> <bodby> end", + #{short => "`unless <cond> -> <body> end", description => "Introduction of new expression `unless <cond> -> <body> end." " Truly experimental.", @@ -542,9 +549,8 @@ test_features() -> type => extension}, maps => #{short => "Add maps as new data type", - description => "Add new low data type maps with syntactic " - "support in Erlang as well native support in the beam. " - "Insert, lookup and delete are asymptotically constant.", + description => "Add new data type for maps with syntactic " + "support in Erlang as well native support in the beam.", status => permanent, experimental => 17, approved => 18, diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index 3ae2bc41c4..cc76090c59 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -4174,7 +4174,7 @@ test_overriden_by_local(Anno, OldTest, Arity, St) -> keyword_warning(Anno, Atom, St) -> case is_warn_enabled(keyword_warning, St) of true -> - Ftrs = erl_features:features(), + Ftrs = erl_features:all(), Reserved = fun(Ftr) -> lists:member(Atom, erl_features:keywords(Ftr)) -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor