LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File 1561-stdlib-Add-option-quote_singleton_atom_types-to-erl_.patch of Package erlang (Project home:Ledest:erlang:20)

From 16055085f761531ed1679c55fdcc14928aec1e1d Mon Sep 17 00:00:00 2001
From: Hans Bolinder <hasse@erlang.org>
Date: Thu, 21 Mar 2019 09:25:16 +0100
Subject: [PATCH] stdlib: Add option 'quote_singleton_atom_types' to erl_pp

The new option can be used by Dialyzer, which has traditionally quoted
singleton atom types.

The OTP team has decided not to use the convention in OTP
documentation, at least not for now. That is why the option is needed.

EDoc does not use the new option.

Syntax Tools does not have a similar option.
---
 lib/stdlib/doc/src/erl_pp.xml    |  6 ++++-
 lib/stdlib/src/erl_pp.erl        | 51 ++++++++++++++++++++++++++++++++--------
 lib/stdlib/test/erl_pp_SUITE.erl | 18 +++++++++++++-
 3 files changed, 63 insertions(+), 12 deletions(-)

diff --git a/lib/stdlib/doc/src/erl_pp.xml b/lib/stdlib/doc/src/erl_pp.xml
index f1c3aa5a41..0a46139db6 100644
--- a/lib/stdlib/doc/src/erl_pp.xml
+++ b/lib/stdlib/doc/src/erl_pp.xml
@@ -5,7 +5,7 @@
   <header>
     <copyright>
       <year>1996</year>
-      <year>2016</year>
+      <year>2019</year>
       <holder>Ericsson AB, All Rights Reserved</holder>
     </copyright>            
     <legalnotice>
@@ -65,6 +65,10 @@
     </datatype>
     <datatype>
       <name name="option"/>
+      <desc>
+        <p>The option <c>quote_singleton_atom_types</c>
+          is used to add quotes to all singleton atom types.</p>
+      </desc>
     </datatype>
     <datatype>
       <name name="options"/>
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index 3e68c1b225..2630c60859 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -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)).
 
@@ -933,6 +955,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.
@@ -1000,6 +1023,8 @@ 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) ->
@@ -1144,6 +1169,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)).
 
@@ -1178,6 +1206,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/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index e5d1910070..c79e29eb11 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -47,6 +47,7 @@
 	  hook/1,
 	  neg_indent/1,
 	  maps_syntax/1,
+          quoted_atom_types/1,
 
 	  otp_6321/1, otp_6911/1, otp_6914/1, otp_8150/1, otp_8238/1,
 	  otp_8473/1, otp_8522/1, otp_8567/1, otp_8664/1, otp_9147/1,
@@ -74,7 +75,7 @@ groups() ->
     [{expr, [],
       [func, call, recs, try_catch, if_then, receive_after,
        bits, head_tail, cond1, block, case1, ops,
-       messages, maps_syntax
+       messages, maps_syntax, quoted_atom_types
     ]},
      {attributes, [], [misc_attrs, import_export, dialyzer_attrs]},
      {tickets, [],
@@ -912,6 +913,21 @@ maps_syntax(Config) when is_list(Config) ->
     ok = pp_forms(F),
     ok.
 
+quoted_atom_types(Config) when is_list(Config) ->
+    Q = [{quote_singleton_atom_types, true}],
+    U = [{encoding,unicode}],
+    L = [{encoding,latin1}],
+    F = "-type t() :: a | a().",
+    "-type t() :: 'a' | a().\n" =
+        lists:flatten(parse_and_pp_forms(F, Q ++ L)),
+    "-type t() :: 'a' | a().\n" =
+        lists:flatten(parse_and_pp_forms(F, Q ++ U)),
+    UF = "-type t() :: '\x{400}' | '\x{400}'().",
+    "-type t() :: '\\x{400}' | '\\x{400}'().\n" =
+        lists:flatten(parse_and_pp_forms(UF, Q ++ L)),
+    "-type t() :: '\x{400}' | '\x{400}'().\n" =
+        lists:flatten(parse_and_pp_forms(UF, Q ++ U)),
+    ok.
 
 %% OTP_8567. Avoid duplicated 'undefined' in record field types.
 otp_8567(Config) when is_list(Config) ->
-- 
2.16.4