Skip to content

Latest commit

 

History

History
60 lines (45 loc) · 2.2 KB

unreachable-analyzer.md

File metadata and controls

60 lines (45 loc) · 2.2 KB

The MixUnused.Analyzers.Unreachable check analyses the call graph by visiting all the functions reachable from a well-known set of functions, that act as starting points.

All the non reachable functions are considered unused. By default only the functions that have no caller are reported to the user.

Configuration

It has a specific configuration:

[
  checks: [
    {MixUnused.Analyzers.Unreachable,
      %{
        usages: [
          {Foo, :bar, 1},
          # ...
        ]
      }}
  ]
]

In the example above, Foo.bar/1 is declared as "used", so the check will consume all the functions reachable from it.

In addition to the user declared functions, the analyzer uses a set of "discovery modules", defined with the option usages_discovery:

[
  checks: [
    {MixUnused.Analyzers.Unreachable,
      %{
        usages_discovery: [
          MyDiscovery,
          # ...
        ]
      }}
  ]
]

A discovery module implements the MixUnused.Analyzers.Unreachable.Usages behaviour and it's called during the analysis to try to discover functions that should be considered as used.

Some discovery modules are included by default: check them under the MixUnused.Analyzers.Unreachable.Usages namespace (i.e. PhoenixDiscovery).

All these modules are not perfect and can report false positives, but in summary they help to identify dynamically used code automatically.

Other options

  • report_transitively_unused: if true the analyzer reports also the unused functions that are only called by other unused functions (default to false).

    For instance, if a() calls b() that calls c(), by default only a() is reported as unused. Additionally, if a() is explicitly ignored or is defined out of the configured paths, nothing is reported.

Corner cases

  • Behaviours implementers are not considered used by default.
  • Functions generated by a macro are not reported, since they generally are out of our control.
  • Structs must be used in the code (i.e. %MyStruct{} somewhere) or declared (i.e. ignore: [{MyStruct, :__struct__, 0}]).