anchor.diff: +%% Copyright (c) 2010, Huiqing Li, Simon Thompson
  +%% All rights reserved.
  +%%
  +%% Redistribution and use in source and binary forms, with or without
  +%% modification, are permitted provided that the following conditions are met:
  +%%     %% Redistributions of source code must retain the above copyright
  +%%       notice, this list of conditions and the following disclaimer.
  +%%     %% Redistributions in binary form must reproduce the above copyright
  +%%       notice, this list of conditions and the following disclaimer in the
  +%%       documentation and/or other materials provided with the distribution.
  +%%     %% Neither the name of the copyright holders nor the
  +%%       names of its contributors may be used to endorse or promote products
  +%%       derived from this software without specific prior written permission.
  +%%
  +%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS''
  +%% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  +%% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  +%% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  +%% BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  +%% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
  +%% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  +%% BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  +%% WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
  +%% OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
  +%% ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  +%%
  +%%@author  Huiqing Li <H.Li@kent.ac.uk>
  +%%
  +%%@doc This refactoring can be used when a parameter of a WS operation has 
  +%%     been renamed. To invoke this refactoring, point the cursor to the original 
  +%%     variable name in the wrapper function, then select the 
  +%%    'rename WS operation argument' for the 'Refactorings for QuickCheck' sub-menu.
  +%%    This refactoring does not work with ```eqc_statem''' group syntax yet.
   %%@hidden
   %%@private
   -module(refac_rename_op_arg).
  
positive.code: 
  -compile(export_all).
  
  input_par_prompts() ->
      ["WS operation name: ", 
       "WS operation arity: ", 
       "Index of parameter to be renamed: ",
       "New parameter name: "]. 
  
  select_focus(_Args) ->
      {ok, none}.
  
  composite_refac(_Args=#args{
                    current_file_name = File, 
                    user_inputs=[OpName, Arity0, Index0, NewParName]
                   }) ->
      Index=list_to_integer(Index0),
      Arity=list_to_integer(Arity0),
      Op = list_to_atom(OpName),
      Refacs = [ ?while(
                    begin
                        PreCands=collect_cands_in_precondition(File, OpName,Index, NewParName),
                        {PreCands/=[], PreCands}
                    end,
                    fun([{{Start, End}, OldVarName}|_]) ->
                            ?refac_(rename_var,
                                    [File, {precondition, 2}, {range, {File, [{Start, End}]}, OldVarName}, 
                                     mk_new_par_name(OldVarName, NewParName), [File]])
                    end
                   ),
                 ?while(
                    begin
                        PostCands=collect_cands_in_postcondition(File, OpName,Index, NewParName),
                        {PostCands/=[], PostCands}
                    end,
                    fun([{Loc, OldVarName}|_])->
                            ?refac_(rename_var,
                                    [File, {postcondition, 3},  {range, {File, [Loc]}, OldVarName}, 
                                     mk_new_par_name(OldVarName, NewParName), [File]])
                    end
                   ),
                 ?while(
                    begin
                        NextCands=collect_cands_in_nextstate(File, OpName,Index, NewParName),
                        {NextCands/=[], NextCands}
                    end,
                    fun([{Loc, OldVarName}|_])->
                            ?refac_(rename_var,
                                    [File, {next_state, 3},  {range, {File, [Loc]}, OldVarName}, 
                                     mk_new_par_name(OldVarName, NewParName), [File]])
                    end
                   ),
                 ?while(
                    begin
                        OpCands=collect_cands_in_op(File, OpName,Index, NewParName),
                        {OpCands/=[], OpCands}
                     end,
                     fun([{Loc, OldVarName}|_])->
                             ?refac_(rename_var,
                                     [File, {Op, Arity},  {range, {File, [Loc]}, OldVarName}, 
                                       mk_new_par_name(OldVarName, NewParName), [File]])
                     end
                    )               
               ],                
          ?non_atomic(Refacs).
  
  
  mk_new_par_name(_OldParName=[95|_], NewParName) ->
  
negative.code:     NewParName.
  
  
  collect_cands_in_precondition(File, OpName, Index, NewVarName) ->
      ?STOP_TD_TU(
         [?COLLECT(?T("precondition(S@, {call, ?MODULE, OpName@, [Args@@]}) when Guards@@ -> Body@@;"),
                    {api_refac:start_end_loc(lists:nth(Index, Args@@)), ?PP(lists:nth(Index, Args@@))},
                    ?PP(OpName@)==OpName andalso api_refac:type(lists:nth(Index,Args@@))==variable andalso
                   not lists:member(?PP(lists:nth(Index,Args@@)), [NewVarName, "_"++NewVarName])),
          ?COLLECT(?T("precondition(S@, {call, ?MODULE, OpName@, [{Args@@}]}) when Guards@@ -> Body@@;"),
                    {api_refac:start_end_loc(lists:nth(Index, Args@@)), ?PP(lists:nth(Index, Args@@))},
                    ?PP(OpName@)==OpName andalso api_refac:type(lists:nth(Index,Args@@))==variable andalso
                    not lists:member(?PP(lists:nth(Index,Args@@)), [NewVarName, "_"++NewVarName]))
         ],[File]).
  
  
  collect_cands_in_postcondition(File, OpName, Index, NewVarName) ->
      ?STOP_TD_TU(
         [?COLLECT(?T("postcondition(S@, {call, ?MODULE, OpName@, [Args@@]}, Res@) when Guards@@ -> Body@@;"),
                    {api_refac:start_end_loc(lists:nth(Index, Args@@)), ?PP(lists:nth(Index, Args@@))},
                    ?PP(OpName@)==OpName andalso api_refac:type(lists:nth(Index,Args@@))==variable andalso
                   not lists:member(?PP(lists:nth(Index,Args@@)), [NewVarName, "_"++NewVarName])),
          ?COLLECT(?T("postcondition(S@, {call, ?MODULE, OpName@, [{Args@@}]}, Res@) when Guards@@ -> Body@@;"),
                    {api_refac:start_end_loc(lists:nth(Index, Args@@)), ?PP(lists:nth(Index, Args@@))},
                    ?PP(OpName@)==OpName andalso api_refac:type(lists:nth(Index,Args@@))==variable andalso
                    not lists:member(?PP(lists:nth(Index,Args@@)), [NewVarName, "_"++NewVarName]))
         ],[File]).
  
  
  collect_cands_in_nextstate(File, OpName, Index, NewVarName) ->
      ?STOP_TD_TU(
         [?COLLECT(?T("next_state(S@, R@, {call, ?MODULE, OpName@, [Args@@]}) when Guards@@ -> Body@@;"),
                    {api_refac:start_end_loc(lists:nth(Index, Args@@)), ?PP(lists:nth(Index, Args@@))},
                    ?PP(OpName@)==OpName andalso api_refac:type(lists:nth(Index,Args@@))==variable andalso
                   not lists:member(?PP(lists:nth(Index,Args@@)), [NewVarName, "_"++NewVarName])),
          ?COLLECT(?T("next_state(S@, R@, {call, ?MODULE, OpName@, [{Args@@}]}) when Guards@@ -> Body@@;"),
                    {api_refac:start_end_loc(lists:nth(Index, Args@@)), ?PP(lists:nth(Index, Args@@))},
                    ?PP(OpName@)==OpName andalso api_refac:type(lists:nth(Index,Args@@))==variable andalso
                    not lists:member(?PP(lists:nth(Index,Args@@)), [NewVarName, "_"++NewVarName]))
         ],[File]).
  
  
  collect_cands_in_op(File, OpName, Index, NewVarName) ->
       ?STOP_TD_TU(
          [?COLLECT(?T("f@(Args@@) when Guards@@ -> Body@@;"),
                    {api_refac:start_end_loc(lists:nth(Index, Args@@)), ?PP(lists:nth(Index, Args@@))},
                    ?PP(f@)==OpName andalso api_refac:type(lists:nth(Index,Args@@))==variable andalso
                    not lists:member(?PP(lists:nth(Index,Args@@)), [NewVarName, "_"++NewVarName])),
           ?COLLECT(?T("f@({Args@@}) when Guards@@ -> Body@@;"),
                    {api_refac:start_end_loc(lists:nth(Index, Args@@)), ?PP(lists:nth(Index, Args@@))},
                    ?PP(f@)==OpName andalso api_refac:type(lists:nth(Index,Args@@))==variable andalso
                    not lists:member(?PP(lists:nth(Index,Args@@)), [NewVarName, "_"++NewVarName]))
          ],[File]).
          
  