Changes between Version 21 and Version 22 of ErlangShellInterface


Ignore:
Timestamp:
Sep 28, 2012, 12:26:09 PM (12 years ago)
Author:
manualwiki
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • ErlangShellInterface

    v21 v22  
    1 {{{#!comment 
    21[[PageOutline]] 
    32 
     
    462461* '''delete_graph(Name)''': removes the given graph. \\ 
    463462* '''delete_all_graphs()''': removes all graphs. \\ 
    464  
    465 }}} 
    466 [[PageOutline]] 
    467  
    468 = !RefactorErl Console Interface = 
    469  
    470 When running !RefactorErl, you can control the tool via function calls typed into the Erlang shell. !RefactorErl has many features, and is quite a complex system with dozen of functions whose name we do not expect our users to remember. In order to ease and unify the command-level access to all the analysis and refactoring functionality, we have designed a group of Erlang functions that cover the most frequently used features of the tool. The module these functions are located in is called {{{ri}}}, you can use this module to interact easily with the tool. You can add files/directories to the database, run [[SemanticQuery|semantic queries]], create backups, or even do [[RefactoringSteps|transformations]] via this Erlang-level interface. 
    471  
    472 == Command-line help == 
    473  
    474 Help can be acquired in {{{ri}}} with 
    475  
    476 {{{ 
    477 #!erlang 
    478 ri:help(). 
    479 }}} 
    480  
    481 or even shorter as 
    482  
    483 {{{ 
    484 #!erlang 
    485 ri:h(). 
    486 }}} 
    487  
    488 This function lists several topics, on which further help is available by 
    489  
    490 {{{ 
    491 #!erlang 
    492 ri:h(Topic). 
    493 }}} 
    494  
    495 If you need specific help with a function, simply call it with an {{{_h}}} postfix to the name. For example, help for the function add is available by calling 
    496  
    497 {{{ 
    498 #!erlang 
    499 ri:add_h() 
    500 }}} 
    501  
    502  
    503 == Compiling the tool == 
    504  
    505 The tool can be compiled/recompiled by invoking 
    506  
    507 {{{ 
    508 #!erlang 
    509 ri:build(). 
    510 }}} 
    511  
    512 You can also specify build parameters, but this feature is mostly applied through the development, so please find the module documentation for the details. Note that this build function tries to compile the [[NifDB|NIF graph representation]] as well, if these have not been compiled yet. If you want to prevent this, you can use the {{{no_nif}}} build parameter. 
    513  
    514 == Managing files == 
    515  
    516 You can add files to the !RefactorErl database by calling the 
    517 add function with either a filename as a string or a module name as an atom. 
    518 Note that in the latter case, "ri" defaults to the current working directory 
    519 (which you may work around by including a path in your singe-quoted atom). 
    520 If you specify a directory instead of a regular filename, then it will be recursively 
    521 traversed. You may just as well give a list of atoms or strings to add more files 
    522 at once. All of the following example commands would add the same file: 
    523  
    524 {{{ 
    525 #!erlang 
    526  cd(dir), ri:add(modname). 
    527  ri:add('dir/modname'). 
    528  ri:add(['dir/modname']). 
    529  ri:add("dir/modname.erl"). 
    530  ri:add("/current/dir/modname.erl"). 
    531 }}} 
    532  
    533 The module displays the progression of loading. 
    534 Removing files from the database is similarly easy and also recursive, except 
    535 for one difference. You need not restrict yourself to dropping a 
    536 module relative to the current directory, but in exchange you must use real module 
    537 names that do not contain path delimiters. The following will equally work: 
    538  
    539 {{{ 
    540 #!erlang 
    541  ri:drop(modname). 
    542  ri:drop([modname]). 
    543  ri:drop("dir/modname.erl"). 
    544  ri:drop("/current/dir/modname.erl"). 
    545 }}} 
    546  
    547 Modules can be loaded as applications, but the base of your library has to 
    548 be set before: 
    549  
    550 {{{ 
    551 #!erlang 
    552 ri:addenv(appbase, "path/to/my/applib"). 
    553 }}} 
    554  
    555 You can check the already given application base directories: 
    556  
    557 {{{ 
    558 #!erlang 
    559 ri:envs(). 
    560 }}} 
    561  
    562 Let's see an example: 
    563  
    564 {{{ 
    565 #!erlang 
    566 % Here 'appbase' contains 'usr'. 
    567 (refactorerl@localhost)18> ri:envs(). 
    568 output = original 
    569 appbase = "/usr/local/lib/erlang/lib" 
    570  
    571 (refactorerl@localhost)19> ri:add(usr, synatx_tools). 
    572 Application synatx_tools not found under usr 
    573 not_found 
    574  
    575 % 'appbase' contains 'usr', so syntax_tools will be loaded from 
    576 % '/usr/local/lib/erlang/lib' 
    577 (refactorerl@localhost)20> ri:add(usr, syntax_tools). 
    578 Adding: /usr/local/lib/erlang/lib/syntax_tools-1.6.7.1/src 
    579 ... 
    580 }}} 
    581  
    582 You can also set include directories to your include files using: 
    583  
    584 {{{ 
    585 #!erlang 
    586 ri:addenv(include, "path/to/my/include"). 
    587 }}} 
    588  
    589 It is possible to delete the defined environment variables: 
    590  
    591 {{{ 
    592 #!erlang 
    593 ri:delenv(include). 
    594 }}} 
    595  
    596 Or you can set an environmental variable to another value: 
    597 {{{ 
    598 #!erlang 
    599 ri:setenv(env_name, "path/to/new_value"). 
    600 }}} 
    601  
    602  
    603 For convenience, both the filenames and the directory names can be given 
    604 as atoms as well as strings. 
    605 The list of loaded files can be obtained by calling 
    606  
    607 {{{ 
    608 #!erlang 
    609 ri:ls(). 
    610 }}} 
    611  
    612 This call also displays the status of the loaded files (error or no_error). 
    613 If the module m is loaded, 
    614  
    615 {{{ 
    616 #!erlang 
    617 ri:ls(m). 
    618 }}} 
    619  
    620 will give information about the functions, records and macros in the file. 
    621 The contents of a file can be listed by 
    622  
    623 {{{ 
    624 #!erlang 
    625 ri:cat(m). 
    626 }}} 
    627  
    628 Usually, Erlang source files (having the extension 
    629 .erl) are loaded into !RefactorErl. In addition, !RefactorErl is also capable of 
    630 loading compiled .beam files. 
    631  
    632 {{{ 
    633 #!erlang 
    634 ri:add("compiled.beam"). 
    635 }}} 
    636  
    637 Note that this feature is applicable only to those .beam files that were compiled 
    638 with the debug_info option. Also note that the resulting file will be pretty 
    639 printed by !RefactorErl. 
    640  
    641 == Using transformations == 
    642 Transformations can be called using their abbreviated 
    643 names, and the list of required parameters. These commands are listed in 
    644 [[RefactoringSteps|refactoring functionalities]]. 
    645 There is another way to call a transormation. This way let the user to 
    646 choose: user wants to specify all of arguments or not. There are lots of cases 
    647 when the user can not specify all of the required arguments. In this case the 
    648 tool can help the user with interactions. The tool ask questions and the user 
    649 has to answer it to specify the missing arguments. The interactions also work if 
    650 there are problems with the given arguments. 
    651  
    652 == Manipulating the graph == 
    653 You can reset the database by invoking 
    654  
    655 {{{ 
    656 #!erlang 
    657 ri:reset(). 
    658 }}} 
    659  
    660 This will remove all loaded files. This function should be called if the graph 
    661 gets corrupted. 
    662 You can add a checkpoint using 
    663  
    664 {{{ 
    665 #!erlang 
    666 ri:backup(). 
    667 }}} 
    668  
    669 If the transformations you have performed are not satisfactory, you can go 
    670 back to the previous checkpoint using 
    671  
    672 {{{ 
    673 #!erlang 
    674 ri:undo(). 
    675 }}} 
    676  
    677 If you use [[NifDB|NIF graph database]], then it is little different:[[BR]] 
    678 You can create backups with '''ri:backup/0''' or '''ri:backup/1''' and you can load 
    679 these backups with '''ri:restore/1'''. 
    680 When execute a transformation a backup will be created, which name differs 
    681 from the ordinary backups, and the '''ri:undo/0''' function will restore that. 
    682  
    683 == Inspecting the graph == 
    684 You can draw the semantic representation graph of !RefactorErl by calling 
    685  
    686 {{{ 
    687 #!erlang 
    688 ri:graph(). 
    689 }}} 
    690  
    691 This function produces a .dot file (by default, graph.dot, although this can be 
    692 customised), which can be transformed to several visual formats using Graphviz. 
    693 One of these transformations is available from !RefactorErl for convenience: 
    694  
    695 {{{ 
    696 #!erlang 
    697 ri:svg(). 
    698 }}} 
    699  
    700 The representation can be altered: 
    701  
    702 {{{ 
    703 #!erlang 
    704 ri:svg(OutFile, Filter). 
    705 }}} 
    706  
    707 where Filter is one of the following:\\ 
    708 * '''all''': default, all edges except environmental ones are shown.\\ 
    709 * '''syn''': only syntactic edges are shown.\\ 
    710 * '''sem''': only semantic edges are shown.\\ 
    711 * '''lex''': only lexical edges are shown.\\ 
    712 * '''all_env''': all edges are shown, no filtering.\\ 
    713 * '''ctx''': context related edges are shown.\\ 
    714 * '''not_lex''': all edges except lexical ones are shown.\\ 
    715 * '''dataflow''': dataflow related edges are shown.\\ 
    716 * '''a list of the above''': shows the union of the designated subgraphs.\\ 
    717  
    718 == Using queries == 
    719 Queries can be invoked by either 
    720  
    721 {{{ 
    722 #!erlang 
    723 ri:q(Query). 
    724 }}} 
    725  
    726 or 
    727  
    728 {{{ 
    729 #!erlang 
    730 ri:q(Module, Regexp, Query). 
    731 }}} 
    732  
    733 The former is applicable when a query starts generally, such as 
    734  
    735 {{{ 
    736 #!erlang 
    737 ri:q("mods.funs.name"). 
    738 }}} 
    739  
    740 For those queries that begin from a selected position (these queries start 
    741 with "@" when used from Emacs), the second variant is required. As the console 
    742 cannot mark a position, the first and the second component indicate the starting 
    743 point for the query. The following example shows how to get all the variables 
    744 used in the body of the function '''f/2''' from the module '''m'''. 
    745  
    746 {{{ 
    747 #!erlang 
    748 ri:q(m, "f\\(X, Y\\)", "@fun.var"). 
    749 }}} 
    750  
    751 Additional options can be given to a [[SemanticQuery|semantic query]] in a proplist as the last 
    752 argument. The following arguments are currently recognized:\\ 
    753 * '''{out,!FileName}''': write the textual output of a query to a file.\\ 
    754 * '''linenum''': prepends match sites with file and line number information.\\ 
    755 similar to '''grep -n'''. 
    756 The following example outputs all defined functions with line numbers to a 
    757 file named result.txt. 
    758  
    759 {{{ 
    760 #!erlang 
    761 ri:q("mods.funs",[linenum,{out,"result.txt"}]). 
    762 }}} 
    763  
    764 There is a [[SemanticQuery|semantic queries]] page, where you can learn more about this topic. 
    765  
    766 == Analysis == 
    767 === Dependency analysis on function or module level === 
    768 There is a [[/wiki/Dependency/Functions|Module and Function Dependencies]] page, where you can learn more about this topic.  
    769  
    770 The command-line interface offers two interface functions, which are: 
    771  
    772 1. For drawing: 
    773 {{{#!erlang 
    774 ri:draw_dep/1 
    775 }}} 
    776 2. For printing the result to stdout: 
    777 {{{#!erlang 
    778 ri:print_dep/1 
    779 }}} 
    780  
    781 ==== Options ==== 
    782  
    783 The parameter of the interface functions is a proplist setting the options of the analysis. The available options are: 
    784  
    785  * {{{level (mod | func)}}} 
    786     The level of the dependency query (module or function). 
    787  * {{{type (all | cycles)}}} 
    788     Whether the investigation should be done on the whole graph, or just on the cyclic part (if exists). When printing out the cycles, type {{{all}}} returns graph nodes, while {{{cycles}}} returns names. 
    789  * {{{otp (true | false)}}} 
    790     Whether Erlang/OTP standard modules should be included in the analysis or not. 
    791  * {{{gnode}}} 
    792     List of entity or entities that should be the starting point of the analysis. Especially at function level, the list is compulsory when the functions are identified by their module, name, arity. 
    793  * exception 
    794     List of entities excluded from the analysis. 
    795  * leaves 
    796     List of those entities which should be included in the analysis, but their children should not (and consequently the children become exceptions). 
    797  * {{{dot}}} 
    798     The file path of the generated {{{.dot}}} graph description. Unless it is a non-existing absolute path, the graph will be placed into the {{{./dep_files}}} directory. This option is only available when using {{{draw_dep}}}. 
    799  
    800 You can specify entities either with graph nodes (such as {{{{'$gn', func, 123}}}}) or with their identifier. Modules can be specified with their names as atoms (e.g. 'mnesia'), while functions are specified by their MFA descriptor as a string (e.g. "io:format/2") 
    801  
    802 ==== Examples for listing results ==== 
    803  
    804 * Checking for cycles in module level. 
    805 {{{#!erlang 
    806 ri:print_dep([{level, mod}, {type, all}]). 
    807 }}} 
    808    
    809  
    810 * Checking for cycles in function level, and printing out names of the functions (Module:Function/Arity). 
    811 {{{#!erlang 
    812 ri:print_dep([{level, func}, {type, cycles}]). 
    813 }}} 
    814 {{{#!erlang 
    815   [['foo:fv4/1','foo:fv4/1'], 
    816   ['test3:p/1','test:fv6/1','test3:p/1'], 
    817   ['cycle4:f4/1','cycle3:f3/1','cycle4:f4/1'], 
    818   ['cycle2:fv2/1','cycle1:fv1/0','cycle2:fv2/1'], 
    819   ['test:fv5/1','test:fv4/2','test:fv5/1'], 
    820   ['cycle4:f5/1','cycle3:f6/1','cycle4:f5/1']] 
    821 }}} 
    822  
    823  
    824 * Checking for cycles in function level, and printing out the graph nodes of the functions. 
    825 {{{#!erlang 
    826 ri:print_dep([{level, func}, {type, all}]). 
    827 }}} 
    828 {{{#!erlang 
    829   {"6 cycle(s)", 
    830   {[[{'$gn',func,28},{'$gn',func,28}],  
    831   [{'$gn',func,29},{'$gn',func,37},{'$gn',func,29}], 
    832   [{'$gn',func,7},{'$gn',func,9},{'$gn',func,7}], 
    833   [{'$gn',func,2},{'$gn',func,1},{'$gn',func,2}], 
    834   [{'$gn',func,36},{'$gn',func,35},{'$gn',func,36}], 
    835   [{'$gn',func,8},{'$gn',func,6},{'$gn',func,8}]]} 
    836 }}} 
    837  
    838 * Checking for cycles in module level from a given node 
    839 {{{#!erlang 
    840 ri:print_dep([{level, mod}, {gnode, {'$gn', module, 24}}]).  
    841 }}} 
    842 {{{#!erlang 
    843   {true,[[{'$gn',module,24}, 
    844           {'$gn',module,25}, 
    845           {'$gn',module,24}]]} 
    846 }}} 
    847  
    848 * Checking for cycles in function level from a node given with its identifier 
    849 {{{#!erlang 
    850 ri:print_dep([{level, func}, {gnode, ["cycle4:f5/1"]}]). 
    851 }}} 
    852  
    853 === Function block dependencies === 
    854 In large systems, sets of applications (which themselves consist of several modules) are organised into bigger units; keeping in line with Ericsson terminology, we shall call these function blocks. We also seek dependencies between them, which is conceptually similar to dependencies between modules: a function block FB1 is dependent on a function block FB2 if a module from FB1 is dependent on one from FB2. This examination is also available from the command-line interface. You can read about the usage and about the topic on [[/wiki/Dependency/FunctionBlocks|Function blocks]] page.  
    855  
    856 === Logical layers analysis === 
    857 In large program systems, groups of compilation units (in the case of Erlang, modules) usually form logical layers. A desired property of such systems is that code in one layer should only use the layer immediately below it, and conversely, provide functionality only for the layer immediately above it. If you would like to check whether a system observes this rule, you should visit the [[InterfaceLayers|Interface Layers]] page, which show you how to check it. 
    858  
    859 === Duplicated code analysis === 
    860 In large program systems often occure duplicated code, which is a computer programming term for a sequence of source code that occurs more than once. There are two ways in which two code sequences can be duplicates of each other: syntactically and functionally. This new feature can detect the syntactically similar duplicates. You can learn more about this topic and about the usage, especially about the command-line usage,  on [[DuplicateCodeAnalysis| Duplicate code analysis]] page. 
    861  
    862 == Server management command list == 
    863  
    864 Here's the list of supported server management commands:\\ 
    865 * '''add(FDML)''': add a module, file, directory or a list of these to the database. \\ 
    866 * '''drop(FDML)''': drop a module from the database. \\ 
    867 * '''ls()''': list files that are in the database. \\ 
    868 * '''backup()''': update the backup (checkpoint). \\ 
    869 * '''undo()''': undo the transformation (rollback, only one step). \\ 
    870 * '''clean()''': clean backups (delete all checkpoints). \\ 
    871 * '''reset()''': reset the database to an empty state, but valid schema. \\ 
    872 * '''graph(Target)''': assume no options and call one of the next two. \\ 
    873 * '''graph(Atom,Options)''': assume ".dot" extension and call the one below. \\ 
    874 * '''graph(File,Options)''': draw the graph with the given options. \\ 
    875 * '''svg()''': draw the graph to graph.svg and call Graphviz. \\ 
    876 * '''svg(File)''' \\ 
    877 * '''svg(File, Options)''' \\ 
    878 The additional/modied commands, that you can use, if you use the [[NifDB|NIF database engine]]:\\ 
    879 * '''backup()''': creates a backup. \\ 
    880 * '''backup(!CommitLog)''': creates a backup as '''ri:backup/0''', but here the user can attach a commit log to the backup file. \\ 
    881 * '''ls_backups()''': returns a lists of backups, that has been created before with '''ri:backup/0''' or '''ri:backup/1'''. \\ 
    882 * '''backup_info(Backup)''': returns information about the given backup. \\ 
    883 * '''restore(Backup)''': restores the given backup. \\ 
    884 * '''create_graph(Name)''': creates a graph with the given name. \\ 
    885 * '''rename_graph(!OldName, !NewName)''': renames a graph that has the given !OldName, with the given !NewName. \\ 
    886 * '''ls_graphs()''': returns a list of the created graphs. \\ 
    887 * '''actual_graph()''': returns the actual graph's name. \\ 
    888 * '''load_graph(Name)''': loads the given graph. \\ 
    889 * '''delete_graph(Name)''': removes the given graph. \\ 
    890 * '''delete_all_graphs()''': removes all graphs. \\