aboutsummaryrefslogtreecommitdiffstats
path: root/lib/tools
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tools')
-rw-r--r--lib/tools/doc/src/xref.xml2
-rw-r--r--lib/tools/emacs/erlang.el52
-rw-r--r--lib/tools/src/cover.erl80
-rw-r--r--lib/tools/src/lcnt.erl3
-rw-r--r--lib/tools/test/cover_SUITE.erl104
-rw-r--r--lib/tools/test/xref_SUITE.erl3
6 files changed, 213 insertions, 31 deletions
diff --git a/lib/tools/doc/src/xref.xml b/lib/tools/doc/src/xref.xml
index 17de66bb22..9706ae6746 100644
--- a/lib/tools/doc/src/xref.xml
+++ b/lib/tools/doc/src/xref.xml
@@ -1453,7 +1453,7 @@ Evaluates a predefined analysis.
Note however that the code path will be traversed once for
each used <seealso marker="#library_module">library module</seealso> while setting up module data.
On the other hand, if there are only a few modules that are
- used by not analyzed, using <c>code_path</c> may be faster
+ used but not analyzed, using <c>code_path</c> may be faster
than setting the library path to <c>code:get_path()</c>.
</p>
<p>If the library path is set to <c>code_path</c>, the set of
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index e2bcd37def..2967acf310 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -997,6 +997,22 @@ behaviour.")
1 'font-lock-function-name-face t))
"Font lock keyword highlighting a function header.")
+(defface erlang-font-lock-exported-function-name-face
+ '((default (:inherit font-lock-function-name-face)))
+ "Face used for highlighting exported functions.")
+
+(defvar erlang-font-lock-exported-function-name-face
+ 'erlang-font-lock-exported-function-name-face)
+
+(defvar erlang-inhibit-exported-function-name-face nil
+ "Inhibit separate face for exported functions")
+
+(defvar erlang-font-lock-keywords-exported-function-header
+ (list
+ (list #'erlang-match-next-exported-function
+ 1 'erlang-font-lock-exported-function-name-face t))
+ "Font lock keyword highlighting an exported function header.")
+
(defvar erlang-font-lock-keywords-int-bifs
(list
(list (concat erlang-int-bif-regexp "\\s-*(")
@@ -1132,7 +1148,8 @@ There exists three levels of Font Lock keywords for Erlang:
`erlang-font-lock-keywords-1' - Function headers and reserved keywords.
`erlang-font-lock-keywords-2' - Bifs, guards and `single quotes'.
`erlang-font-lock-keywords-3' - Variables, macros and records.
- `erlang-font-lock-keywords-4' - Function names, Funs, LCs (not Atoms)
+ `erlang-font-lock-keywords-4' - Exported functions, Function names,
+ Funs, LCs (not Atoms).
To use a specific level, please set the variable
`font-lock-maximum-decoration' to the appropriate level. Note that the
@@ -1174,6 +1191,7 @@ Example:
(defvar erlang-font-lock-keywords-4
(append erlang-font-lock-keywords-3
+ erlang-font-lock-keywords-exported-function-header
erlang-font-lock-keywords-int-function-calls
erlang-font-lock-keywords-ext-function-calls
erlang-font-lock-keywords-fun-n
@@ -3662,6 +3680,38 @@ In the future the list may contain more elements."
str)
(store-match-data md))))
+(defun erlang-match-next-exported-function (max)
+ "Returns non-nil if there is an exported function in the current
+buffer between point and MAX."
+ (block nil
+ (while (and (not erlang-inhibit-exported-function-name-face)
+ (erlang-match-next-function max))
+ (when (erlang-last-match-exported-p)
+ (return (match-data))))))
+
+(defun erlang-match-next-function (max)
+ "Searches forward in current buffer for the next erlang function,
+bounded by position MAX."
+ (re-search-forward erlang-defun-prompt-regexp max 'move-point))
+
+(defun erlang-last-match-exported-p ()
+ "Returns non-nil if match-data describes the name and arity of an
+exported function."
+ (save-excursion
+ (save-match-data
+ (goto-char (match-beginning 1))
+ (erlang-function-exported-p
+ (erlang-remove-quotes (erlang-get-function-name))
+ (erlang-get-function-arity)))))
+
+(defun erlang-function-exported-p (name arity)
+ "Returns non-nil if function of name and arity is exported in current buffer."
+ (save-excursion
+ (let* ((old-match-data (match-data))
+ (exports (erlang-get-export)))
+ (store-match-data old-match-data)
+ (member (cons name arity) exports))))
+
;;; Check module name
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 10f14b0a49..ab29d156aa 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -705,7 +705,9 @@ main_process_loop(State) ->
remote_collect('_',Nodes,true),
reply(From, ok),
Nodes1 = State#main_state.nodes--Nodes,
- main_process_loop(State#main_state{nodes=Nodes1});
+ LostNodes1 = State#main_state.lost_nodes--Nodes,
+ main_process_loop(State#main_state{nodes=Nodes1,
+ lost_nodes=LostNodes1});
{From, {flush,Nodes}} ->
remote_collect('_',Nodes,false),
@@ -792,8 +794,15 @@ main_process_loop(State) ->
{'DOWN', _MRef, process, {?SERVER,Node}, _Info} ->
%% A remote cover_server is down, mark as lost
- Nodes = State#main_state.nodes--[Node],
- Lost = [Node|State#main_state.lost_nodes],
+ {Nodes,Lost} =
+ case lists:member(Node,State#main_state.nodes) of
+ true ->
+ N = State#main_state.nodes--[Node],
+ L = [Node|State#main_state.lost_nodes],
+ {N,L};
+ false -> % node stopped
+ {State#main_state.nodes,State#main_state.lost_nodes}
+ end,
main_process_loop(State#main_state{nodes=Nodes,lost_nodes=Lost});
{nodeup,Node} ->
@@ -2087,30 +2096,40 @@ do_analyse_to_file(Module, OutFile, ErlFile, HTML) ->
case file:open(OutFile, [write]) of
{ok, OutFd} ->
if HTML ->
- io:format(OutFd,
- "<html>\n"
- "<head><title>~s</title></head>"
- "<body bgcolor=white text=black>\n"
- "<pre>\n",
- [OutFile]);
+ Encoding = encoding(ErlFile),
+ Header =
+ ["<!DOCTYPE HTML PUBLIC "
+ "\"-//W3C//DTD HTML 3.2 Final//EN\">\n"
+ "<html>\n"
+ "<head>\n"
+ "<meta http-equiv=\"Content-Type\""
+ " content=\"text/html; charset=",
+ Encoding,"\"/>\n"
+ "<title>",OutFile,"</title>\n"
+ "</head>"
+ "<body style='background-color: white;"
+ " color: black'>\n"
+ "<pre>\n"],
+ file:write(OutFd,Header);
true -> ok
end,
%% Write some initial information to the output file
{{Y,Mo,D},{H,Mi,S}} = calendar:local_time(),
- io:format(OutFd, "File generated from ~s by COVER "
- "~p-~s-~s at ~s:~s:~s~n",
- [ErlFile,
- Y,
- string:right(integer_to_list(Mo), 2, $0),
- string:right(integer_to_list(D), 2, $0),
- string:right(integer_to_list(H), 2, $0),
- string:right(integer_to_list(Mi), 2, $0),
- string:right(integer_to_list(S), 2, $0)]),
- io:format(OutFd, "~n"
- "**************************************"
- "**************************************"
- "~n~n", []),
+ Timestamp =
+ io_lib:format("~p-~s-~s at ~s:~s:~s",
+ [Y,
+ string:right(integer_to_list(Mo), 2, $0),
+ string:right(integer_to_list(D), 2, $0),
+ string:right(integer_to_list(H), 2, $0),
+ string:right(integer_to_list(Mi), 2, $0),
+ string:right(integer_to_list(S), 2, $0)]),
+ file:write(OutFd,
+ ["File generated from ",ErlFile," by COVER ",
+ Timestamp,"\n\n"
+ "**************************************"
+ "**************************************"
+ "\n\n"]),
print_lines(Module, InFd, OutFd, 1, HTML),
@@ -2405,3 +2424,20 @@ pmap(Fun, [], [], Limit, Cnt, Acc) ->
{'DOWN', _Ref, process, X, _} when is_pid(X) ->
pmap(Fun, [], [], Limit, Cnt - 1, Acc)
end.
+
+%%%-----------------------------------------------------------------
+%%% Read encoding from source file
+encoding(File) ->
+ Encoding =
+ case epp:read_encoding(File) of
+ none ->
+ epp:default_encoding();
+ E ->
+ E
+ end,
+ html_encoding(Encoding).
+
+html_encoding(latin1) ->
+ "iso-8859-1";
+html_encoding(utf8) ->
+ "utf-8".
diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl
index 989a661b75..70d62307c8 100644
--- a/lib/tools/src/lcnt.erl
+++ b/lib/tools/src/lcnt.erl
@@ -1,7 +1,8 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 3bf1b44af8..57260a3869 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -23,7 +23,9 @@
init_per_group/2,end_per_group/2]).
-export([start/1, compile/1, analyse/1, misc/1, stop/1,
- distribution/1, reconnect/1, die_and_reconnect/1, export_import/1,
+ distribution/1, reconnect/1, die_and_reconnect/1,
+ dont_reconnect_after_stop/1, stop_node_after_disconnect/1,
+ export_import/1,
otp_5031/1, eif/1, otp_5305/1, otp_5418/1, otp_6115/1, otp_7095/1,
otp_8188/1, otp_8270/1, otp_8273/1, otp_8340/1]).
@@ -47,6 +49,7 @@ all() ->
undefined ->
[start, compile, analyse, misc, stop,
distribution, reconnect, die_and_reconnect,
+ dont_reconnect_after_stop, stop_node_after_disconnect,
export_import, otp_5031, eif, otp_5305, otp_5418,
otp_6115, otp_7095, otp_8188, otp_8270, otp_8273,
otp_8340];
@@ -86,8 +89,11 @@ init_per_testcase(TC, Config) when TC =:= misc;
init_per_testcase(_TestCase, Config) ->
Config.
-end_per_testcase(_TestCase, _Config) ->
- %cover:stop(),
+end_per_testcase(TestCase, _Config) ->
+ case lists:member(TestCase,[start,compile,analyse,misc]) of
+ true -> ok;
+ false -> cover:stop()
+ end,
ok.
start(suite) -> [];
@@ -447,8 +453,8 @@ reconnect(Config) ->
%% Disconnect and check that node is removed from main cover node
net_kernel:disconnect(N1),
+ timer:sleep(500), % allow some to detect disconnect and for f:f2() call
[] = cover:which_nodes(),
- timer:sleep(500), % allow some time for the f:f2() call
%% Do some add one module (b) and remove one module (a)
code:purge(a),
@@ -520,6 +526,94 @@ die_and_reconnect(Config) ->
?t:stop_node(N1),
ok.
+%% Test that a stopped node is not marked as lost, i.e. that it is not
+%% reconnected if it is restarted (OTP-10638)
+dont_reconnect_after_stop(Config) ->
+ DataDir = ?config(data_dir, Config),
+ ok = file:set_cwd(DataDir),
+
+ {ok,f} = compile:file(f),
+
+ NodeName = cover_SUITE_dont_reconnect_after_stop,
+ {ok,N1} = ?t:start_node(NodeName,peer,
+ [{args," -pa " ++ DataDir},{start_cover,false}]),
+ {ok,f} = cover:compile(f),
+ {ok,[N1]} = cover:start(nodes()),
+
+ %% A call to check later
+ rpc:call(N1,f,f1,[]),
+
+ %% Stop cover on the node, then terminate the node
+ cover:stop(N1),
+ rpc:call(N1,erlang,halt,[]),
+ [] = cover:which_nodes(),
+
+ check_f_calls(1,0),
+
+ %% Restart the node and check that cover does not reconnect
+ {ok,N1} = ?t:start_node(NodeName,peer,
+ [{args," -pa " ++ DataDir},{start_cover,false}]),
+ timer:sleep(300),
+ [] = cover:which_nodes(),
+ Beam = rpc:call(N1,code,which,[f]),
+ false = (Beam==cover_compiled),
+
+ %% One more call...
+ rpc:call(N1,f,f1,[]),
+ cover:flush(N1),
+
+ %% Ensure that the last call is not counted
+ check_f_calls(1,0),
+
+ cover:stop(),
+ ?t:stop_node(N1),
+ ok.
+
+%% Test that a node which is stopped while it is marked as lost is not
+%% reconnected if it is restarted (OTP-10638)
+stop_node_after_disconnect(Config) ->
+ DataDir = ?config(data_dir, Config),
+ ok = file:set_cwd(DataDir),
+
+ {ok,f} = compile:file(f),
+
+ NodeName = cover_SUITE_stop_node_after_disconnect,
+ {ok,N1} = ?t:start_node(NodeName,peer,
+ [{args," -pa " ++ DataDir},{start_cover,false}]),
+ {ok,f} = cover:compile(f),
+ {ok,[N1]} = cover:start(nodes()),
+
+ %% A call to check later
+ rpc:call(N1,f,f1,[]),
+
+ %% Flush the node, then terminate the node to make it marked as lost
+ cover:flush(N1),
+ rpc:call(N1,erlang,halt,[]),
+
+ check_f_calls(1,0),
+
+ %% Stop cover on node
+ cover:stop(N1),
+
+ %% Restart the node and check that cover does not reconnect
+ {ok,N1} = ?t:start_node(NodeName,peer,
+ [{args," -pa " ++ DataDir},{start_cover,false}]),
+ timer:sleep(300),
+ [] = cover:which_nodes(),
+ Beam = rpc:call(N1,code,which,[f]),
+ false = (Beam==cover_compiled),
+
+ %% One more call...
+ rpc:call(N1,f,f1,[]),
+ cover:flush(N1),
+
+ %% Ensure that the last call is not counted
+ check_f_calls(1,0),
+
+ cover:stop(),
+ ?t:stop_node(N1),
+ ok.
+
export_import(suite) -> [];
export_import(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
@@ -908,7 +1002,7 @@ otp_8270(Config) when is_list(Config) ->
ok.
otp_8273(doc) ->
- ["OTP-8270. Bug."];
+ ["OTP-8273. Bug."];
otp_8273(suite) -> [];
otp_8273(Config) when is_list(Config) ->
Test = <<"-module(t).
diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl
index fd3e111d8d..cf49526156 100644
--- a/lib/tools/test/xref_SUITE.erl
+++ b/lib/tools/test/xref_SUITE.erl
@@ -1,3 +1,4 @@
+%% -*- coding: utf-8 -*-
%%
%% %CopyrightBegin%
%%
@@ -2521,7 +2522,7 @@ otp_10192(doc) ->
otp_10192(Conf) when is_list(Conf) ->
PrivDir = ?privdir,
{ok, _Pid} = xref:start(s),
- Dir = filename:join(PrivDir, "�"),
+ Dir = filename:join(PrivDir, "ä"),
ok = file:make_dir(Dir),
{ok, []} = xref:add_directory(s, Dir),
xref:stop(s),