anchor.diff:           end ||{File,{{Line, _}, _}}<-Calls],
       {ok, Res}.
   
  +%% Give the type (according to syntax_tools) of the patterns
  +%% in a function definition.
  +
  +classify_pattern_match(File) ->
  +    Classify = ?FULL_TD_TU([?COLLECT(?T("f@(Args@@@) when _Guard@@@ -> _Body@@@."), 
  +				     {api_refac:fun_define_info(f@),
  +				      api_refac:start_end_loc(_This@),
  +				      overall_classify([pattern_type(Pat) || Pat <- lists:flatten(Args@@@)])},
  +				     true
  +				    )],
  +			   [File]),
  +    MsgFun = fun (mixed)    -> " patterns made up entirely of variables or of literals.";
  +		 (variable) -> " mixed patterns or patterns of literals only.";
  +		 (literal)  -> " mixed patterns or patterns of variables only."
  +	  end,
  +    Res=[begin
  +             Msg=lists:flatten(
  +                   io_lib:format("This function could be defined differently: try it with~s~n", [MsgFun(Kind)])),
  +             {Msg, [{file, File}, 
  +                    {line_from, integer_to_list(LineFrom)},
  +		    {line_to, integer_to_list(LineTo)}]}
  +         end ||{_, {{LineFrom,_},{LineTo,_}}, Kind}<-Classify, Kind /= none],
  +    {ok, Res}.
  +
  +-spec pattern_type(syntaxTree()) -> variable | literal | mixed.
  +pattern_type(Pat) ->
  +    case wrangler_syntax:is_literal(Pat) of
  +	true -> literal;
  +	false -> case api_refac:type(Pat) of
  +		     variable -> variable;
  +		     _ -> mixed
  +		 end
  +    end.
  +    
  +-spec overall_classify([atom()]) -> atom().
  +overall_classify([]) ->
  +     none;
  +overall_classify([X|Xs]) ->
  +    overall_classify(X,Xs).
  +
  +-spec overall_classify(atom(),[atom()]) -> atom().
  +
  +overall_classify(X,[]) ->
  +     X;
  +overall_classify(X,[Y|Ys]) ->
  +    case X==Y of
  +	true ->
  +	    overall_classify(X,Ys);
  +	false ->
  +	     mixed
  +    end.
  +    
  +
  +
  +%% Collect all the function applications within a function definition.
  +%% Returns {erlang,apply,3} for uses of apply.
  +collect_function_apps({M, F, A}, SearchPaths) ->
  +    ?FULL_TD_TU([?COLLECT(?T("f@(Args@@) when _Guard@@ -> Body@@;"), 
  +                          collect_apps_within(_This@),
  +			  {M, F, A} == api_refac:fun_define_info(f@))
  +			 ],
  +                [SearchPaths]).
  +
  +collect_apps_within(Node) ->
  +    ?FULL_TD_TU([?COLLECT(?T("F@(Argss@@)"),
  +			  api_refac:fun_define_info(F@),
  +			  true)
  +		],
  +		Node).
  +
  +collect_function_apps2({M, F, A}, SearchPaths) ->
  +    ?FULL_TD_TU([?COLLECT(?T("f@(Args@@) when _Guard@@ -> Body@@;"), 
  +                          collect_apps_within2(_This@),
  +			  {M, F, A} == api_refac:fun_define_info(f@))
  +			 ],
  +                [SearchPaths]).
  +
  +collect_apps_within2(Node) ->
  +    ?FULL_TD_TU([?COLLECT(?T("F@(Argss@@)"),
  +			  ?SPLICE(api_refac:get_app_mod(_This@)),
  +			  true)
  +		],
  +		Node).
  +
  +-spec top_level_if([dir()|filename()]) ->
  +                            {ok, [{message(), [{tag(), list()}]}]}.
  +top_level_if(SearchPaths)->
  +    Funs=?FULL_TD_TU([?COLLECT(?T("f@(Args@@) when Guard@@ ->Body@."), 
  +                          {_File@, api_refac:fun_define_info(f@), api_refac:start_end_loc(_This@)},
  +                          api_refac:type(Body@) == if_expr)],
  +                     [SearchPaths]),
  +    Res = [begin
  +               Msg = lists:flatten(
  +                       io_lib:format("The function ~p:~p/~p consists of a top-level if expression.",
  +                                     [M, F, A])),
  +               {Msg, [{file, File},
  +                      {line, integer_to_list(Ln)}]}
  +           end || {File, {M, F, A}, {{Ln, _}, _}}<-Funs],
  +    {ok, Res}.
  +
  +-spec unnecessary_match([dir()|filename()]) ->
  +                               {ok, [{message(), [{tag(), list()}]}]}.
  +unnecessary_match(SearchPaths) ->
  +    Funs=?FULL_TD_TU([?COLLECT(?T("Body@@, V@=Expr@, V@"), 
  +                               {_File@, wrangler_misc:start_end_loc(lists:nthtail(length(Body@@), _This@))},
  +                               api_refac:type(V@) == variable andalso length(api_refac:var_refs(V@))==1)],
  +                     SearchPaths),
  +    Res = [begin
  +               Msg = lists:flatten(
  +                       io_lib:format("This is an unnecessary match expression at line ~p.",
  +                                     [Ln])),
  +               {Msg, [{file, File},
  +                      {line, integer_to_list(Ln)}]}
  +           end || {File, {{Ln, _}, _}}<-Funs],
  +    {ok, Res}.
  +
  +
  +-spec append_two_lists([dir()|filename()]) ->
  +                              {ok, [{message(), [{tag(), list()}]}]}.
  +append_two_lists(SearchPaths) ->
  +    Uses=?STOP_TD_TU([?COLLECT(?T("F@(L1@, L2@)"), 
  +                              {_File@, wrangler_misc:start_end_loc(_This@)},
  +                              {lists, append, 2} == api_refac:fun_define_info(F@))],
  +                    SearchPaths),
  +    Res = [begin
  +               Msg = lists:flatten(
  +                       io_lib:format("This is a use of lists:append/2 at line ~p.",
  +                                     [Ln])),
  +               {Msg, [{file, File},
  +                      {line, integer_to_list(Ln)}]}
  +           end || {File, {{Ln, _}, _}}<-Uses],
  +    {ok, Res}.
  +
  +-spec non_tail_recursive_function([dir()|filename()]) ->
  +                              {ok, [{message(), [{tag(), list()}]}]}.
  +non_tail_recursive_function(SearchPaths) ->
  +    Funs=?FULL_TD_TU([?COLLECT(?T("f@(Args@@@) when Guard@@@-> Body@@@."), 
  +                               {_File@, api_refac:fun_define_info(f@),wrangler_misc:start_end_loc(_This@)},
  +                               inspec_examples:is_non_tail_recursive(_This@))],
  +                     [SearchPaths]),
  +    Res = [begin
  +               Msg = lists:flatten(
  +                       io_lib:format("Function ~p:~p/~p is not tail recursive.",
  +                                     [M,F, A])),
  +               {Msg, [{file, File},
  +                      {line, integer_to_list(Ln)}]}
  +           end || {File, {M, F, A},{{Ln, _}, _}}<-Funs],
  +    {ok, Res}.
   
   %% In this test, I try to detect two code code smells. One is 
   %% function definitions with 40 or more lines of code, and the
  
positive.code:          end ||{{M, F, A}, {File, Line}}<-LongFuns],
      {ok, Res}.
  
  -spec calls_to_specific_function(mfa(), [dir()|filename()]) ->    
                                          {ok, [{message(), [{tag(), list()}]}]}.
  calls_to_specific_function({M, F, A}, SearchPaths) ->
  
negative.code: 
  -export([do_code_inspection/2]).
  
  %% API for feedback tool.
  -export([long_functions/2, 
           large_modules/2,
           calls_to_specific_function/2,
           classify_pattern_match/1, 
           nested_if_exprs/2,
           nested_case_exprs/2,
           nested_receive_exprs/2,
           not_flush_unknown_messages/1,
           top_level_if/1,
           unnecessary_match/1,
           append_two_lists/1,
           non_tail_recursive_function/1
          ]).
  
  -export([test/1,
  	 collect_function_apps/2,
  	 collect_function_apps2/2]).
  
  -include("../include/wrangler.hrl").
  
  