[[PageOutline]] = Module and Function Dependencies = == Concerning terminology == We say that module ''A'' depends on module ''B'' (''A -> B'') if there is at least one function call from ''A'' to ''B''. There is a ''cyclic dependency'', if ''B'' also depends directly (''B -> A'') or indirectly (e.g. ''B -> C -> A'') on ''A''. Apparently, dependency can be defined on the function level as well. For instance, in our previous example, function level cycle is only present if both ''A'' and ''B'' define functions called ''foo'', such that ''A:foo'' calls ''B:foo'' and ''B:foo'' calls ''A:foo''. Note that it is possible to have a cyclic dependency among modules while having no cyclic dependencies among their functions. For example, function calls from ''A:foo'' to ''B:foo'' and from ''B:foo2'' to ''A:foo2'' imply a cyclic dependency on the module level, but no one on the function level. == Capabilities == Mainly, you can ''check for cycles'' among entities within the !RefactorErl database. This means that the program looks for loops on the given level, and returns with paths of cycles. In case of vast databases, dependencies can be very complex, and hard to represent. To avoid producing useless, huge dependency graphs, we provide some options that you can use for narrowing down the result. For instance, you can reduce the graph to only contain the cycles, or you can exclude the standard OTP modules from the result. You can also specify a list of entities, called exceptions, that should be excluded from the analysis. Additionally, you can specify a list of those entities, called leaves, which should be included in the analysis, but their children should not (and consequently the children become exceptions). Also, you can ask to only cover dependencies starting from given function(s) or module(s). === Visualisation If you would like to visualise the result, you can put it into a graph. Namely, we generate a ''.dot'' graph description file, which can be converted to any desired image format. On function level, for example, the graph shows the modules and their functions along with the calls between the functions, while red edges represent cycles. == Usage Dependency analysis can be done via the following interfaces: * [ErlangShellInterface#Analysis Erlang shell] * [WebInterface/DependencyExaminations Web interface] == Semantics of dependency graphs == === Function Level === Function dependency graphs look like the following. [[Image(dep_fun_before.png, 700px)]] In such graphs, * '''ROOT triangle''' represents a formal starting point if no one has been specified * '''Rectangle''' nodes (e.g. {{{cycle1, a, test2}}}) represent modules (''deep purple'') * '''Hexagon''' nodes (e.g. {{{f1/1, apply/3, test2/2}}}) represent functions (''black'') * '''Solid, continuous edge, normal arrowhead''': to modules from the root, and the from modules to their functions (''black'') * '''Dashed edge, normal arrowhead''' indicates that a function calls another function ({{{funcall}}}) (''black'') * '''Dashed edge, special arrowhead''' indicates a function call, but also that it is a cyclic edge (''red'') After performing [DynamicCallAnalysis dynamic call analysis], dynamic function calls are put into the call graph, and this obviously changes some dependency relations. The following figure shows a graph with dynamic function call dependencies. [[Image(dep_fun_after.png, 900px)]] In such graphs, * '''Double octagon''' nodes represent opaque nodes (''black''/''gray'') * '''Dotted edge, normal arrowhead''' indicates an {{{ambcall, dyncall}}} or {{{may_be}}} edge (''black'') Every node and edge has tooltips. In the case of nodes it shows the corresponding graph node within the database, while considering edges it depicts the type of the function call ({{{funcall, may_be, ambcall, dyncall}}}). Static calls are labelled by {{{funcall}}}. {{{#!comment és mi van a modulokba vezető éleken...? }}} {{{#!comment TODO esetleg egy normális leírás erről a dynanal oldalra {{{Dyncall}}} means unambiguous dynamic calls, when the identifiers of the callee may be defined not at the call but at another program part, and their values are can be calculated by data-flow reaching. {{{Ambcall}}} relation denotes the fact that some of the arguments of the dynamic function call can not be detected statically. If the number of parameters is uncertain, then after the arity of the function will be -1. It is also indicated with a special node. For further details about the dynamic calls and their representation can be found in (wiki:DynamicCallAnalysis). When the applied function or module is uncertain, the tool represents it with an {{{opaque}}} node, and connects the possible functions/modules with {{{may_be}}} edges. The representation in the analysis now follows this, indicating the opaque nodes differently (described in the previous section, concerning drawings). }}} === Module Level === Module dependency graphs capture call relations on a higher level. [[Image(dep_mod.png, 500px)]] In module dependency graphs, * '''Rectangle''' nodes (e.g. {{{cycle1, erlang, test2}}}) represent modules (''deep purple'') {{{#!comment * '''Double octagon''' nodes represent opaque nodes (''black''/''gray'') }}} * '''Dotted edge, normal arrowhead''' indicates that a module calls another module (''black'') * '''Dotted edge, special arrowhead''' indicates a call loop (''red'') {{{#!comment TODO értelmes magyarázat az itteni tooltipekre }}} == Examples == {{{#!erlang ri:draw_dep([{level, mod}, {gnode, erlang}]). }}} {{{#!erlang ri:draw_dep([{level, mod}, {gnode, erlang}, {dot, "/home/working/dot/test.dot" }]). }}} {{{#!erlang ri:draw_dep([{level, func}, {gnode, ["lists:hd/1"]}]). }}} {{{#!erlang ri:draw_dep([{level, mod},{gnode, [ri, ris]}]). }}} {{{#!erlang ri:draw_dep([{type, all}, {level, func}, {gnode, ["ri:q/1"]}, {otp, true}]). }}} {{{#!erlang ri:draw_dep([{type, all}, {level, mod}, {otp, true}, {exception, [ri, ris]}, {leaves, [reflib_ui]}]). }}}