anchor.diff:  %% </li>
   %% </p>
   %% <p>
  -%% Known problems: this refactoring does not move the include attributes, type/record/macro definitions
  -%% on which the function to be moved depends; while it tries to move the type specification associated 
  -%% with the function, it does not move the type definitions on which the type specification depends, therefore,
  -%% manual inspection is needed after the refactoring.
  +%% Known problems: this refactoring does not move the include/include_lib attributes, and type 
  +%% declarations on which the functions to be moved depend; In the case that some other internal
  +%% functions are solely depended by the functions to be moved, they are moved together with the functions
  +%% specified only if the pre-conditions are not violated. Therefore manual inspection is 
  +%% needed after the refactorings.
   %% </p>
   %% @end
   %% @author Huiqing Li <hl@kent.ac.uk>
  
positive.code: move_fun(FName, Line, Col, TargetModorFileName, SearchPaths, TabWidth) ->
      move_fun(FName, Line, Col, TargetModorFileName, SearchPaths, TabWidth, emacs).
  
  -spec(move_fun_1/6::(filename(),integer(),integer(), string(), [dir()], integer())->
  	     {ok, [filename()]} | {error, string()}).
  move_fun_1(FName, Line, Col, TargetModorFileName, SearchPaths, TabWidth) ->
      move_fun_1(FName, Line, Col, TargetModorFileName, SearchPaths, TabWidth, emacs).
  
  
  -spec(move_fun_eclipse/6::(filename(),integer(),integer(), string(),[dir()], integer())
  
negative.code:     refac_syntax_lib:map(Fun, Node).
  
  
  
  
  %%================================================================================
  %%              Side Condition Checking. 
  %%================================================================================
  
  analyze_file(FName, SearchPaths, TabWidth) ->   
      Dir = filename:dirname(FName),
      DefaultIncls = [filename:join(Dir, X) || X <- refac_misc:default_incls()],
      NewSearchPaths = SearchPaths ++ DefaultIncls,
      case refac_epp:parse_file(FName, NewSearchPaths, [], TabWidth,
  			      refac_util:file_format(FName)) of
  	{ok, TargetAST, {MDefs, _MUses1}} ->
  	    MacroDefs= [{Name, {Args, refac_util:concat_toks(Toks)}}
  			|| {{_, Name}, {Args, Toks}} <- MDefs],
  	    TargetModInfo = get_mod_info_from_parse_tree(TargetAST),
  	    RecordDefs=case lists:keysearch(records,1, TargetModInfo) of
  			   {value, {records, RecordDefsInTargetFile}} ->
  			       [{Name, lists:keysort(1, [{F, prettyprint(FDef)} || {F, FDef} <- Fields])}
  				|| {Name, Fields} <- RecordDefsInTargetFile];
  			   _ -> []
  		       end,
  	    {ok, {AnnAST, Info}} = refac_util:parse_annotate_file(FName, true, SearchPaths, TabWidth),
  	    Forms = refac_syntax:form_list_elements(AnnAST),
  	    Includes=lists:append([lists:flatmap(fun (A) -> 
  					    case refac_syntax:type(A) of
  						string-> [refac_syntax:string_value(A)];
  						_ -> []
  					    end
  				    end, Args)
  		      ||F<-Forms, is_attribute(F, include) orelse is_attribute(F, include_lib),
  			Args<-[refac_syntax:attribute_arguments(F)]]),		       
  	    InscopeFuns = refac_misc:inscope_funs(TargetModInfo),
  	    #module_info{filename=FName,
  			 modname=get_module_name(Info),
  			 inscope_funs=InscopeFuns, 
  			 macro_defs=MacroDefs, 
  			 record_defs=RecordDefs,
  			 includes=Includes, 
  			 ast=AnnAST,
  			 info=Info};
  	_ ->
  	    throw({error, "Refactoring failed because Wrangler could not parse the target module."})
      end.
  
  side_cond_check(FunDefs, CurModInfo, TargetModInfo, NewTargetFile, CheckCond) ->
      try side_cond_check(FunDefs, CurModInfo, TargetModInfo, CheckCond) 
      catch
  	E1:E2 ->
  	    case NewTargetFile of 
  		true -> 
  		    TargetFName=TargetModInfo#module_info.filename,
  		    file:delete(TargetFName);
  		false-> ok
  	    end,
  	    throw({E1,E2})
      end.
  
  
  side_cond_check(FunDefs, CurModInfo, TargetModInfo, CheckCond) ->
      case CheckCond of
        true ->
  	  check_fun_name_clash(FunDefs, TargetModInfo);
        false ->
  	  ok
      end,
      check_macros_records(FunDefs, CurModInfo, TargetModInfo).
  
  check_macros_records(FunDefs, CurModInfo, TargetModInfo) ->
      CurRecordDefs=CurModInfo#module_info.record_defs,
      TargetRecordDefs=TargetModInfo#module_info.record_defs,
      UnDefinedRecords = check_records(FunDefs, CurRecordDefs, TargetRecordDefs),
      CurMacroDefs=CurModInfo#module_info.macro_defs,
      TargetMacroDefs=TargetModInfo#module_info.macro_defs,
      UnDefinedMacros = check_macros(FunDefs,CurMacroDefs, TargetMacroDefs),
      {UnDefinedMacros, UnDefinedRecords}.
  
  
  check_fun_name_clash(FunDefs=[{{ModName, _, _},_}|_T],TargetModInfo)->
      TargetInscopeFuns=TargetModInfo#module_info.inscope_funs,
      TargetForms=refac_syntax:form_list_elements(TargetModInfo#module_info.ast),
      FAs = [{F, A}||{{_M, F, A},_}<-FunDefs],
      Clash = lists:filter(fun ({M, F, A}) ->
  				 lists:member({F,A}, FAs) andalso ModName =/= M
  			 end, TargetInscopeFuns),
      case Clash of
  	[] ->true;
  	_ ->
  	    SameFuns= [get_fun_mfa(Form)|| 
  			  Form <- TargetForms, 
  			  defines(Form, Clash),
  			  {_M,F,A}<-[get_fun_mfa(Form)],
  			  is_the_same_fun(
  			    Form, hd([Def||{{M1, F1,A1}, Def}<-FunDefs,
  					   {M1,F1,A1}=={ModName, F,A}]))],
  	    Clash1=Clash--SameFuns, 
  	    case Clash1 of 
  		[] -> true;
  		_ ->
  		    throw({error, "Moving function(s): "++format_funs(Clash1)++ 
  			   "will cause confliction in the target module."})
  	    end
      end.
  
  check_records(FunDefs,CurRecordDefs,TargetRecordDefs) -> 
      UsedRecords = lists:usort(lists:append([refac_misc:collect_used_records(FunDef)
  					    || {_, FunDef} <- FunDefs])),
      UsedRecordDefs=[{Name, lists:keysort(1, Fields)}
  		    || {Name, Fields} <- CurRecordDefs, lists:member(Name, UsedRecords)],
      CurUnDefinedUsedRecords = UsedRecords -- [Name || {Name, _Fields} <- UsedRecordDefs],
      UsedRecordDefsInTargetFile = [{Name, lists:keysort(1, Fields)}
  				  || {Name, Fields} <- TargetRecordDefs,
  				     lists:member(Name, UsedRecords)],
      RecordsWithDiffDefs=[R||{R, Def}<-UsedRecordDefs,
  			   case lists:keysearch(R, 1, UsedRecordDefsInTargetFile) of
  			   {value, {R, Def1}} ->
  			       Def /= Def1;
  			   false ->
  			       false 
  		       end],
      UnDefinedRecords = UsedRecords-- element(1, lists:unzip(UsedRecordDefsInTargetFile)),
      case RecordsWithDiffDefs of
  	[] ->
  	    ok;
  	[_] ->
  	    Msg = format("Record: ~p, used by the function(s) to be moved, "
  			 "is defined differently in the target module.",RecordsWithDiffDefs),
  	    throw({error, Msg});
  	_ ->
  	    Msg= "The following records: "++format_names(RecordsWithDiffDefs)++" used by the function(s) to be moved,"
  		"are defined differently in the target module.",
  	    throw({error, Msg})
      end,
      case CurUnDefinedUsedRecords of 
  	[] -> 
  	    UnDefinedRecords;
  	[_R] ->
  	    Msg1=format("Record: ~p, is used by the function(s) to be moved, but not defined in the current module.",
  			CurUnDefinedUsedRecords),
  	    throw({error, Msg1});
  	_->
  	    Msg1=format("The following records: ~p are used by the function(s) to be moved, but not defined in the current module",
  			[CurUnDefinedUsedRecords]),
  	    throw({error, Msg1})
      end.   
  
  
  check_macros(FunDefs, CurMacroDefs,TargetMacroDefs) ->
      UsedMacros = lists:usort(lists:append([refac_misc:collect_used_macros(FunDef) || {_, FunDef} <- FunDefs])),
      UsedMacroDefs =[{Name, {Args, Def}}
  		    || {Name, {Args, Def}} <- CurMacroDefs,
  		       lists:member(Name, UsedMacros)],
      UnDefinedUsedMacros =  UsedMacros -- [Name || {Name, _Def} <- UsedMacroDefs],
      UsedMacroDefsInTargetFile =
  	[{Name, {Args, Def}}
  	 || {Name, {Args, Def}} <- TargetMacroDefs, lists:member(Name, UsedMacros)],
      UnDefinedMacros = UsedMacros-- element(1, lists:unzip(UsedMacroDefsInTargetFile)),
      MsWithDiffDefs=[M||{M, Def}<-UsedMacroDefs,
  		       case lists:keysearch(M, 1,UsedMacroDefsInTargetFile) of
  			   {value, {M, Def1}} ->
  			       Def /= Def1;
  			   false ->
  			       false
  		       end],
      case UnDefinedUsedMacros of
  	[] -> ok;
  	[_] ->Msg=format("Macro: ~p, is used by the function(s) to be moved, but not defined in the current module",
  			 UnDefinedUsedMacros),
  	      throw({error, Msg});	       
  	_ -> Msg =format("The following macros: ~p are used by the function(s) to be moved, but not defined in the current module",
  			 [UnDefinedUsedMacros]),
  	     throw({error, Msg})
      end,
      case MsWithDiffDefs of
  	[] -> UnDefinedMacros;
  	[_] -> Msg1 = format("Macro: ~p, used by the function(s) to be moved "
  			     "is defined differently in the target module", MsWithDiffDefs),
  	       throw({warning, Msg1 ++ ", still continue?"});
  	_ -> Msg1 = "Macros: "++format_names(MsWithDiffDefs)++" used by the function(s) to be moved "
  		 "are defined differently in the target module",		      
  	     throw({warning, Msg1 ++ ", still continue?"})
      end.
  
  
  get_mod_info_from_parse_tree(AST) ->
      AST1 = lists:filter(fun (F) ->
  				case F of
  				    {attribute, _, file, _} -> false;
  				    {attribute, _, type, {{record, _}, _, _}} -> false;
  				    _ -> true
  				end
  			end, AST),
      SyntaxTree = refac_recomment:recomment_forms(AST1, []),
      refac_syntax_lib:analyze_forms(SyntaxTree).
  
  %%================================================================================
  %%              Some Utility Functions 
  %%================================================================================
  
  get_attrs(Forms, Ms,Rs, TargetIncludes) ->
      Attrs=[F || F<-Forms, defines(F, Ms, Rs)],
      case length(Attrs)==length(Ms++Rs) of
  	true ->
  	    Attrs;
  	false ->
  	    Includes=get_includes(Forms, TargetIncludes),
  	    Includes++Attrs
      end.
  
  defines(Form, Ms, Rs) ->
      case refac_syntax:type(Form) of
  	attribute ->
  	    Name = refac_syntax:attribute_name(Form),
  	    case refac_syntax:type(Name) of
  		atom ->
  		    AttrName = refac_syntax:atom_value(Name),
  		    case AttrName == record orelse AttrName == define of
  			true ->
  			    Type = hd(refac_syntax:attribute_arguments(Form)),
  			    case refac_syntax:type(Type) of
  				atom ->
  				    TypeName = refac_syntax:atom_value(Type),
  				    AttrName == record andalso lists:member(TypeName, Rs) orelse
  					AttrName == define andalso lists:member(TypeName, Ms);
  				variable ->
  				    TypeName= refac_syntax:variable_name(Type),
  				    AttrName == define andalso lists:member(TypeName, Ms);
  				application ->
  				    Op = refac_syntax:application_operator(Type),
  				    case refac_syntax:type(Op) of
  					atom ->
  					    TypeName= refac_syntax:atom_value(Op),
  					    AttrName == define andalso lists:member(TypeName, Ms); 
  					variable ->
  					    TypeName= refac_syntax:variable_name(Op),
  					    AttrName == define andalso lists:member(TypeName, Ms);
  					_ -> false
  				    end;
  				_ -> false
  			    end;
  			_ -> false
  		    end;
  		_ ->
  		    false
  	    end;
  	_ -> false
      end.
  
  get_includes(Forms, Incs) ->
      [F||F<-Forms,
  	is_attribute(F, include) orelse is_attribute(F, include_lib),
  	Arg<-refac_syntax:attribute_arguments(F),
  	case refac_syntax:type(Arg) of
  	    string -> not(lists:member(refac_syntax:string_value(Arg), Incs));
  	    _ -> false
  	end
      ].
  
  
  type_specifies(Form, MFAs) ->
      FAs =[{F,A}||{_M,F,A}<-MFAs],
      case refac_syntax:type(Form) of
  	attribute ->
  	    Name = refac_syntax:attribute_name(Form),
  	    case refac_syntax:type(Name) of
  		atom -> case refac_syntax:atom_value(Name) of
  			    'spec' ->
  				FA = hd(refac_syntax:attribute_arguments(Form)),
  				case refac_syntax:type(FA) of
  				    tuple ->
  					[A1, F1|_T] = lists:reverse(refac_syntax:tuple_elements(FA)),
  					lists:member({refac_syntax:atom_value(F1),
  						      refac_syntax:integer_value(A1)},FAs);
  				    _ -> false
  				end;
  			    _ -> false
  			end;
  		_ -> false
  	    end;
  	_ -> false
      end.
  
  
  
  
  get_moveable_dependent_funs(MFAs, CurModInfo, TargetModInfo, CG) ->
      Info = CurModInfo#module_info.info,
      DepMFAs=get_dependent_funs(Info, MFAs, CG),
      case DepMFAs of 
  	[] -> {[],[],[]};
  	_ ->
  	    Forms = refac_syntax:form_list_elements(CurModInfo#module_info.ast),
  	    DepDefs = [{get_fun_mfa(F), F} || F <- Forms, defines(F, DepMFAs)],
  	    check_dependent_funs(DepMFAs, DepDefs, CurModInfo, TargetModInfo,CG)
  
      end.
  	    
  
    
  get_dependent_funs(Info, MFAs = [{ModName, _, _}| _], CG) ->
      Reachable = digraph_utils:reachable(MFAs, CG),
      Reachable1 = [{M, F, A} || {M, F, A} <- Reachable, M == ModName,
  			       not refac_misc:is_exported({F, A}, Info)],
      Funs = get_closed_dependent_funs(Reachable1, MFAs, CG),
      Funs -- MFAs.
  
  get_closed_dependent_funs([], MFAs, _CG) ->
      MFAs;
  get_closed_dependent_funs(Vs, MFAs, CG) ->
      Vs1=[V||V<-Vs, not lists:member(V, MFAs),
  		     digraph:in_neighbours(CG, V)--Vs/=[]],
      case Vs1 of
  	[] ->
  	    Vs;
  	_ -> get_closed_dependent_funs(Vs--Vs1, MFAs, CG)
      end.
       
  check_dependent_funs(MFAs=[{ModName,_,_}|_T], FunDefs, CurModInfo, TargetModInfo, CG) ->
      TargetInScopeFuns = TargetModInfo#module_info.inscope_funs,
      FAs = [{F, A}||{_M, F, A}<-MFAs],
      Clash = lists:filter(fun ({M, F, A}) ->
  				 lists:member({F,A}, FAs) andalso ModName =/= M
  			 end, TargetInScopeFuns),
      NewMFAs = MFAs--Clash,
      NewFunDefs=[{F, Def}||{F, Def}<-FunDefs, lists:member(F, NewMFAs)],
      FMRs=lists:append([try check_macros_records([{F,FunDef}], CurModInfo,TargetModInfo) of
  	     {Ms, Rs} ->
  		   [{F, Ms,Rs}]
  	  catch
  	      _E1:_E2 ->
  		  []
  	  end ||{F,FunDef}<-NewFunDefs]),
      NewMFAs1=element(1, lists:unzip3(FMRs)),
      ClosedNewMFAs=get_closed_dependent_funs(NewMFAs1, MFAs, CG),
      FMRs1=[{F, Ms, Rs}||{F,Ms,Rs}<-FMRs,
  			 lists:member(F,ClosedNewMFAs)],
      {Fs, Ms1, Rs1} =lists:unzip3(FMRs1),
      {Fs, lists:append(Ms1), lists:append(Rs1)}.
  
  format_funs([]) ->
     "";
  format_funs([{_M, F, A}|Fs]) ->
      lists:flatten(io_lib:format("~p/~p,", [F, A])++format_funs(Fs)).
  
  format_names([])->
      "";
  format_names([N|Ns]) ->
      lists:flatten(io_lib:format("~p,", [N])++format_names(Ns)).
  
  get_target_file_name(CurrentFName, TargetModorFileName) ->
      ErrMsg = {error, "Illegal target module/file name."},
      TargetModName = case filename:extension(TargetModorFileName) of
  		      ".erl" -> filename:basename(TargetModorFileName, ".erl");
  		      [] -> filename:basename(TargetModorFileName, ".erl");
  		      _ -> throw(ErrMsg)
  		    end,
      TargetFileName = filename:join([filename:dirname(CurrentFName), filename:dirname(TargetModorFileName),
  				    TargetModName ++ ".erl"]),
      case refac_misc:is_fun_name(TargetModName) of
        true ->
  	  TargetFileName;
        _ -> throw(ErrMsg)
      end.
  
  
  create_new_file(TargetFName, TargetModName) ->
      S = "-module("++atom_to_list(TargetModName)++").",
      file:write_file(TargetFName, list_to_binary(S)).
  
  defines(Form, MFAs) ->
      case refac_syntax:type(Form) of
  	function ->
  	  case lists:keysearch(fun_def, 1, refac_syntax:get_ann(Form)) of
  	      {value, {fun_def, {M, F, A, _, _}}} ->
  		  lists:member({M,F,A}, MFAs);
  	      _ -> false
  	  end;
  	_ -> false
      end.
    
  get_fun_mfa(Form) ->
      case refac_syntax:type(Form) of
  	function ->
  	    {value, {fun_def, {M, F, A, _, _}}} =
  		lists:keysearch(fun_def,1, refac_syntax:get_ann(Form)),
  	    {M,F,A};
  	_ -> throw({error, "error in function refac_move_fun:get_fun_mfa/1"})
      end.
  	
  output_refactor_results(FName, TargetFName, Editor, Cmd, NewTargetFile, AnnAST1, TargetAnnAST1, Results) ->
      case Editor of
  	emacs ->
  	    refac_util:write_refactored_files_for_preview([{{FName, FName}, AnnAST1},
  							   {{TargetFName, TargetFName, NewTargetFile}, TargetAnnAST1}| Results], Cmd),
  	    ChangedClientFiles = [F ||{{F, _F}, _AST} <- Results],
  	    ChangedFiles = [FName, TargetFName| ChangedClientFiles],
  	    ?wrangler_io("The following files are to be changed by this refactoring:\n~p\n", [ChangedFiles]),
  	    {ok, ChangedFiles};
        eclipse ->
  	    Results1 = [{{FName, FName}, AnnAST1}, {{TargetFName, TargetFName}, TargetAnnAST1}| Results],
  	    Res = [{FName1, NewFName1, refac_prettypr:print_ast(refac_util:file_format(FName1), AST)} ||			    
  		      {{FName1, NewFName1}, AST}<-Results1],
  	    {ok, Res}
      end.
  
  pos_to_export(AnnAST, Pos) ->
      Forms = refac_syntax:form_list_elements(AnnAST),
      Fs=[F||F<-Forms,
  	   is_export_attribute(F),
  	   {Start, End} <-[refac_misc:get_start_end_loc(F)],
  	   Start=<Pos,
  	   End>=Pos],
      case Fs of 
  	[F] ->
  	    {ok,F};
  	_ ->{error,"No export attribute has been selected."}
      end.
      
  is_export_attribute(Form) ->
      case refac_syntax:type(Form) of
  	attribute ->
  	    Name = refac_syntax:attribute_name(Form),
  	    refac_syntax:type(Name)==atom andalso
  		refac_syntax:atom_value(Name)=='export';
  	_ -> false
      end.
  
  
  get_exported_funs(ModName,ExportAttr) ->
      [L]=refac_syntax:attribute_arguments(ExportAttr),
      Es = refac_syntax:list_elements(L),
      [{ModName,F,A}|| E<-Es, 
  	       F<-[refac_syntax:atom_value(refac_syntax:arity_qualifier_body(E))],
  	       A<-[refac_syntax:integer_value(refac_syntax:arity_qualifier_argument(E))]].
  
  
  make_export(Names) ->
      Es = [refac_syntax:arity_qualifier(refac_syntax:atom(F),refac_syntax:integer(A))
  	  || {F, A} <- Names],
      refac_syntax:attribute(refac_syntax:atom('export'), [refac_syntax:list(Es)]).
  
  copy_pos_attrs(E1, E2) ->
      refac_syntax:copy_pos(E1, refac_syntax:copy_attrs(E1, E2)).    
  
      
  is_attribute(F, Name) ->
      refac_syntax:type(F) == attribute andalso
        refac_syntax:type(refac_syntax:attribute_name(F)) == atom andalso
  	refac_syntax:atom_value(refac_syntax:attribute_name(F)) == Name.
  
  prettyprint(none) ->
      none;
  