39
39
bc_options /1 , deterministic_include /1 , deterministic_paths /1 ,
40
40
compile_attribute /1 , message_printing /1 , other_options /1 ,
41
41
transforms /1 , erl_compile_api /1 , types_pp /1 , bs_init_writable /1 ,
42
- annotations_pp /1
42
+ annotations_pp /1 , option_order / 1
43
43
]).
44
44
45
45
suite () -> [{ct_hooks ,[ts_install_cth ]}].
@@ -59,7 +59,8 @@ all() ->
59
59
env_compiler_options , custom_debug_info , bc_options ,
60
60
custom_compile_info , deterministic_include , deterministic_paths ,
61
61
compile_attribute , message_printing , other_options , transforms ,
62
- erl_compile_api , types_pp , bs_init_writable , annotations_pp ].
62
+ erl_compile_api , types_pp , bs_init_writable , annotations_pp ,
63
+ option_order ].
63
64
64
65
groups () ->
65
66
[].
@@ -906,10 +907,10 @@ strict_record(Config) when is_list(Config) ->
906
907
{ok ,M } = c :c (M , [no_strict_record_tests |Opts ]),
907
908
Turtle = test_sloppy (),
908
909
909
- % % The option first given wins.
910
- {ok ,M } = c :c (M , [no_strict_record_tests ,strict_record_tests |Opts ]),
911
- Turtle = test_sloppy (),
910
+ % % The option last given wins.
912
911
{ok ,M } = c :c (M , [strict_record_tests ,no_strict_record_tests |Opts ]),
912
+ Turtle = test_sloppy (),
913
+ {ok ,M } = c :c (M , [no_strict_record_tests ,strict_record_tests |Opts ]),
913
914
Turtle = test_strict (),
914
915
915
916
% % Default (possibly influenced by ERL_COMPILER_OPTIONS).
@@ -2120,6 +2121,146 @@ get_annotations(Key, [_|Lines]) ->
2120
2121
get_annotations (_ , []) ->
2121
2122
[].
2122
2123
2124
+ option_order (Config ) ->
2125
+ Ts = [{spec1 ,
2126
+ ~ """
2127
+ -compile(nowarn_missing_spec).
2128
+ foo() -> ok.
2129
+ """ ,
2130
+ [], % Environment
2131
+ [warn_missing_spec ],
2132
+ []},
2133
+ {spec2 ,
2134
+ ~ """
2135
+ foo() -> ok.
2136
+ """ ,
2137
+ [{" ERL_COMPILER_OPTIONS" , " warn_missing_spec" }],
2138
+ [nowarn_missing_spec ],
2139
+ []},
2140
+ {spec3 ,
2141
+ ~ """
2142
+ -compile(nowarn_missing_spec).
2143
+ foo() -> ok.
2144
+ """ ,
2145
+ [{" ERL_COMPILER_OPTIONS" , " nowarn_missing_spec" }],
2146
+ [warn_missing_spec ],
2147
+ []},
2148
+ {spec4 ,
2149
+ ~ """
2150
+ -compile(warn_missing_spec).
2151
+ foo() -> ok.
2152
+ """ ,
2153
+ [{" ERL_COMPILER_OPTIONS" , " nowarn_missing_spec" }],
2154
+ [],
2155
+ {warnings ,[{{2 ,1 },erl_lint ,{missing_spec ,{foo ,0 }}}]}
2156
+ },
2157
+ {spec5 ,
2158
+ ~ """
2159
+ -compile([warn_missing_spec,nowarn_missing_spec]).
2160
+ foo() -> ok.
2161
+ """ ,
2162
+ [{" ERL_COMPILER_OPTIONS" , " nowarn_missing_spec" }],
2163
+ [warn_missing_spec ],
2164
+ []},
2165
+ {records1 ,
2166
+ ~ """
2167
+ -record(r, {x,y}).
2168
+ rec_test(#r{x=X,y=Y}) -> X + Y.
2169
+ """ ,
2170
+ [],
2171
+ [strict_record_tests ],
2172
+ fun (M ) ->
2173
+ try M :rec_test ({r ,1 ,2 ,3 }) of
2174
+ 3 ->
2175
+ fail ()
2176
+ catch
2177
+ error :function_clause ->
2178
+ ok
2179
+ end
2180
+ end },
2181
+ {records2 ,
2182
+ ~ """
2183
+ -record(r, {x,y}).
2184
+ rec_test(R) -> R#r.x + R#r.y.
2185
+ """ ,
2186
+ [],
2187
+ [no_strict_record_tests ],
2188
+ fun (M ) ->
2189
+ 3 = M :rec_test ({r ,1 ,2 ,3 }),
2190
+ ok
2191
+ end },
2192
+ {records3 ,
2193
+ ~ """
2194
+ -compile(no_strict_record_tests).
2195
+ -record(r, {x,y}).
2196
+ rec_test(R) -> R#r.x + R#r.y.
2197
+ """ ,
2198
+ [],
2199
+ [strict_record_tests ],
2200
+ fun (M ) ->
2201
+ 3 = M :rec_test ({r ,1 ,2 ,3 }),
2202
+ ok
2203
+ end },
2204
+ {records4 ,
2205
+ ~ """
2206
+ -record(r, {x,y}).
2207
+ rec_test(#r{x=X,y=Y}) -> X + Y.
2208
+ """ ,
2209
+ [{" ERL_COMPILER_OPTIONS" , " strict_record_tests" }],
2210
+ [],
2211
+ fun (M ) ->
2212
+ try M :rec_test ({r ,1 ,2 ,3 }) of
2213
+ 3 ->
2214
+ fail ()
2215
+ catch
2216
+ error :function_clause ->
2217
+ ok
2218
+ end
2219
+ end },
2220
+ {records5 ,
2221
+ ~ """
2222
+ -record(r, {x,y}).
2223
+ rec_test(R) -> R#r.x + R#r.y.
2224
+ """ ,
2225
+ [{" ERL_COMPILER_OPTIONS" , " strict_record_tests" }],
2226
+ [no_strict_record_tests ],
2227
+ fun (M ) ->
2228
+ 3 = M :rec_test ({r ,1 ,2 ,3 }),
2229
+ ok
2230
+ end },
2231
+ {records6 ,
2232
+ ~ """
2233
+ -compile(no_strict_record_tests).
2234
+ -record(r, {x,y}).
2235
+ rec_test(R) -> R#r.x + R#r.y.
2236
+ """ ,
2237
+ [{" ERL_COMPILER_OPTIONS" , " strict_record_tests" }],
2238
+ [],
2239
+ fun (M ) ->
2240
+ 3 = M :rec_test ({r ,1 ,2 ,3 }),
2241
+ ok
2242
+ end },
2243
+ {records7 ,
2244
+ ~ """
2245
+ -record(r, {x,y}).
2246
+ rec_test(R) -> R#r.x + R#r.y.
2247
+ """ ,
2248
+ [{" ERL_COMPILER_OPTIONS" , " no_strict_record_tests" }],
2249
+ [no_strict_record_tests , strict_record_tests ],
2250
+ fun (M ) ->
2251
+ try M :rec_test ({r ,1 ,2 ,3 }) of
2252
+ 3 ->
2253
+ fail ()
2254
+ catch
2255
+ error :{badrecord ,{r ,1 ,2 ,3 }} ->
2256
+ ok
2257
+ end
2258
+ end }
2259
+
2260
+ ],
2261
+ run (Config , Ts ),
2262
+ ok .
2263
+
2123
2264
% %%
2124
2265
% %% Utilities.
2125
2266
% %%
@@ -2149,3 +2290,104 @@ is_lfe_module(File, Ext) ->
2149
2290
" lfe_" ++ _ -> true ;
2150
2291
_ -> false
2151
2292
end .
2293
+
2294
+ % % Compiles a test module and returns the list of errors and warnings.
2295
+
2296
+ run (Config , Tests ) ->
2297
+ F = fun ({N ,P ,Env ,Ws ,Run }, _BadL ) when is_function (Run , 1 ) ->
2298
+ case catch run_test (Config , P , Env , Ws , Run ) of
2299
+ ok ->
2300
+ ok ;
2301
+ Bad ->
2302
+ io :format (" ~n Test ~p failed. Expected~n ~p~n "
2303
+ " but got~n ~p~n " , [N , ok , Bad ]),
2304
+ fail ()
2305
+ end ;
2306
+ ({N ,P ,Env ,Ws ,Expected }, BadL )
2307
+ when is_list (Expected ); is_tuple (Expected ) ->
2308
+ io :format (" ### ~s \n " , [N ]),
2309
+ case catch run_test (Config , P , Env , Ws , none ) of
2310
+ Expected ->
2311
+ BadL ;
2312
+ Bad ->
2313
+ io :format (" ~n Test ~p failed. Expected~n ~p~n "
2314
+ " but got~n ~p~n " , [N , Expected , Bad ]),
2315
+ fail ()
2316
+ end
2317
+ end ,
2318
+ lists :foldl (F , [], Tests ).
2319
+
2320
+ run_test (Conf , Test0 , Env , Options , Run ) ->
2321
+ run_test_putenv (Env ),
2322
+ Module = " warnings" ++ test_lib :uniq (),
2323
+ Filename = Module ++ " .erl" ,
2324
+ DataDir = proplists :get_value (priv_dir , Conf ),
2325
+ Test1 = [" -module(" , Module , " ). -file( \" " , Filename , " \" , 1). " , Test0 ],
2326
+ Test = iolist_to_binary (Test1 ),
2327
+ File = filename :join (DataDir , Filename ),
2328
+ Opts = [binary ,export_all ,return |Options ],
2329
+ ok = file :write_file (File , Test ),
2330
+
2331
+ % % Compile once just to print all warnings (and cover more code).
2332
+ _ = compile :file (File , [binary ,export_all ,report |Options ]),
2333
+
2334
+ % % Test result of compilation.
2335
+ {ok , Mod , Beam , Warnings } = compile :file (File , Opts ),
2336
+ _ = file :delete (File ),
2337
+
2338
+ if
2339
+ is_function (Run , 1 ) ->
2340
+ {module ,Mod } = code :load_binary (Mod , " " , Beam ),
2341
+ ok = Run (Mod ),
2342
+ run_test_unsetenv (Env ),
2343
+ true = code :delete (Mod ),
2344
+ _ = code :purge (Mod ),
2345
+ ok ;
2346
+ Run =:= none ->
2347
+ run_test_unsetenv (Env ),
2348
+ Res = get_warnings (Warnings ),
2349
+ case Res of
2350
+ [] ->
2351
+ [];
2352
+ {warnings , Ws } ->
2353
+ print_warnings (Ws , Test ),
2354
+ Res
2355
+ end
2356
+ end .
2357
+
2358
+ run_test_putenv (Env ) ->
2359
+ _ = [_ = os :putenv (Name , Value ) || {Name ,Value } <- Env ],
2360
+ ok .
2361
+
2362
+ run_test_unsetenv (Env ) ->
2363
+ _ = [_ = os :unsetenv (Name ) || {Name ,_Value } <- Env ],
2364
+ ok .
2365
+
2366
+ get_warnings ([]) ->
2367
+ [];
2368
+ get_warnings (WsL ) ->
2369
+ case WsL of
2370
+ [{_File ,Ws }] -> {warnings , Ws };
2371
+ _ -> {warnings , WsL }
2372
+ end .
2373
+
2374
+ print_warnings (Warnings , Source ) ->
2375
+ Lines = binary :split (Source , <<" \n " >>, [global ]),
2376
+ Cs = [print_warning (W , Lines ) || W <- Warnings ],
2377
+ io :put_chars (Cs ),
2378
+ ok .
2379
+
2380
+ print_warning ({{LineNum ,Column },Mod ,Data }, Lines ) ->
2381
+ Line0 = lists :nth (LineNum , Lines ),
2382
+ <<Line1 :(Column - 1 )/binary ,_ /binary >> = Line0 ,
2383
+ Spaces = re :replace (Line1 , <<" [^\t ]" >>, <<" " >>, [global ]),
2384
+ CaretLine = [Spaces ," ^" ],
2385
+ [io_lib :format (" ~p :~p : ~ts \n " ,
2386
+ [LineNum ,Column ,Mod :format_error (Data )]),
2387
+ Line0 , " \n " ,
2388
+ CaretLine , " \n\n " ];
2389
+ print_warning (_ , _ ) ->
2390
+ [].
2391
+
2392
+ fail () ->
2393
+ ct :fail (failed ).
0 commit comments