| .. title:: clang-tidy - readability-suspicious-call-argument |
| |
| readability-suspicious-call-argument |
| ==================================== |
| |
| Finds function calls where the arguments passed are provided out of order, |
| based on the difference between the argument name and the parameter names |
| of the function. |
| |
| Given a function call ``f(foo, bar);`` and a function signature |
| ``void f(T tvar, U uvar)``, the arguments ``foo`` and ``bar`` are swapped if |
| ``foo`` (the argument name) is more similar to ``uvar`` (the other parameter) |
| than ``tvar`` (the parameter it is currently passed to) **and** ``bar`` is |
| more similar to ``tvar`` than ``uvar``. |
| |
| Warnings might indicate either that the arguments are swapped, or that the |
| names' cross-similarity might hinder code comprehension. |
| |
| .. _heuristics: |
| |
| Heuristics |
| ---------- |
| |
| The following heuristics are implemented in the check. |
| If **any** of the enabled heuristics deem the arguments to be provided out of |
| order, a warning will be issued. |
| |
| The heuristics themselves are implemented by considering pairs of strings, and |
| are symmetric, so in the following there is no distinction on which string is |
| the argument name and which string is the parameter name. |
| |
| Equality |
| ^^^^^^^^ |
| |
| The most trivial heuristic, which compares the two strings for case-insensitive |
| equality. |
| |
| .. _abbreviation_heuristic: |
| |
| Abbreviation |
| ^^^^^^^^^^^^ |
| |
| Common abbreviations can be specified which will deem the strings similar if |
| the abbreviated and the abbreviation stand together. |
| For example, if ``src`` is registered as an abbreviation for ``source``, then |
| the following code example will be warned about. |
| |
| .. code-block:: c++ |
| |
| void foo(int source, int x); |
| |
| foo(b, src); |
| |
| The abbreviations to recognise can be configured with the |
| :ref:`Abbreviations<opt_Abbreviations>` check option. |
| This heuristic is case-insensitive. |
| |
| Prefix |
| ^^^^^^ |
| |
| The *prefix* heuristic reports if one of the strings is a sufficiently long |
| prefix of the other string, e.g. ``target`` to ``targetPtr``. |
| The similarity percentage is the length ratio of the prefix to the longer |
| string, in the previous example, it would be `6 / 9 = 66.66...`\%. |
| |
| This heuristic can be configured with :ref:`bounds<opt_Bounds>`. |
| The default bounds are: below `25`\% dissimilar and above `30`\% similar. |
| This heuristic is case-insensitive. |
| |
| Suffix |
| ^^^^^^ |
| |
| Analogous to the `Prefix` heuristic. |
| In the case of ``oldValue`` and ``value`` compared, the similarity percentage |
| is `8 / 5 = 62.5`\%. |
| |
| This heuristic can be configured with :ref:`bounds<opt_Bounds>`. |
| The default bounds are: below `25`\% dissimilar and above `30`\% similar. |
| This heuristic is case-insensitive. |
| |
| Substring |
| ^^^^^^^^^ |
| |
| The substring heuristic combines the prefix and the suffix heuristic, and tries |
| to find the *longest common substring* in the two strings provided. |
| The similarity percentage is the ratio of the found longest common substring |
| against the *longer* of the two input strings. |
| For example, given ``val`` and ``rvalue``, the similarity is `3 / 6 = 50`\%. |
| If no characters are common in the two string, `0`\%. |
| |
| This heuristic can be configured with :ref:`bounds<opt_Bounds>`. |
| The default bounds are: below `40`\% dissimilar and above `50`\% similar. |
| This heuristic is case-insensitive. |
| |
| Levenshtein distance (as `Levenshtein`) |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| The `Levenshtein distance <http://en.wikipedia.org/wiki/Levenshtein_distance>`_ |
| describes how many single-character changes (additions, changes, or removals) |
| must be applied to transform one string into another. |
| |
| The Levenshtein distance is translated into a similarity percentage by dividing |
| it with the length of the *longer* string, and taking its complement with |
| regards to `100`\%. |
| For example, given ``something`` and ``anything``, the distance is `4` edits, |
| and the similarity percentage is `100`\% `- 4 / 9 = 55.55...`\%. |
| |
| This heuristic can be configured with :ref:`bounds<opt_Bounds>`. |
| The default bounds are: below `50`\% dissimilar and above `66`\% similar. |
| This heuristic is case-sensitive. |
| |
| Jaro--Winkler distance (as `JaroWinkler`) |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| The `Jaro--Winkler distance <http://en.wikipedia.org/wiki/Jaro–Winkler_distance>`_ |
| is an edit distance like the Levenshtein distance. |
| It is calculated from the amount of common characters that are sufficiently |
| close to each other in position, and to-be-changed characters. |
| The original definition of Jaro has been extended by Winkler to weigh prefix |
| similarities more. |
| The similarity percentage is expressed as an average of the common and |
| non-common characters against the length of both strings. |
| |
| This heuristic can be configured with :ref:`bounds<opt_Bounds>`. |
| The default bounds are: below `75`\% dissimilar and above `85`\% similar. |
| This heuristic is case-insensitive. |
| |
| Sørensen--Dice coefficient (as `Dice`) |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| The `Sørensen--Dice coefficient <http://en.wikipedia.org/wiki/Sørensen–Dice_coefficient>`_ |
| was originally defined to measure the similarity of two sets. |
| Formally, the coefficient is calculated by dividing `2 * #(intersection)` with |
| `#(set1) + #(set2)`, where `#()` is the cardinality function of sets. |
| This metric is applied to strings by creating bigrams (substring sequences of |
| length 2) of the two strings and using the set of bigrams for the two strings |
| as the two sets. |
| |
| This heuristic can be configured with :ref:`bounds<opt_Bounds>`. |
| The default bounds are: below `60`\% dissimilar and above `70`\% similar. |
| This heuristic is case-insensitive. |
| |
| |
| Options |
| ------- |
| |
| .. option:: MinimumIdentifierNameLength |
| |
| Sets the minimum required length the argument and parameter names |
| need to have. Names shorter than this length will be ignored. |
| Defaults to `3`. |
| |
| .. _opt_Abbreviations: |
| |
| .. option:: Abbreviations |
| |
| For the **Abbreviation** heuristic |
| (:ref:`see here<abbreviation_heuristic>`), this option configures the |
| abbreviations in the `"abbreviation=abbreviated_value"` format. |
| The option is a string, with each value joined by `";"`. |
| |
| By default, the following abbreviations are set: |
| |
| * `addr=address` |
| * `arr=array` |
| * `attr=attribute` |
| * `buf=buffer` |
| * `cl=client` |
| * `cnt=count` |
| * `col=column` |
| * `cpy=copy` |
| * `dest=destination` |
| * `dist=distance` |
| * `dst=distance` |
| * `elem=element` |
| * `hght=height` |
| * `i=index` |
| * `idx=index` |
| * `len=length` |
| * `ln=line` |
| * `lst=list` |
| * `nr=number` |
| * `num=number` |
| * `pos=position` |
| * `ptr=pointer` |
| * `ref=reference` |
| * `src=source` |
| * `srv=server` |
| * `stmt=statement` |
| * `str=string` |
| * `val=value` |
| * `var=variable` |
| * `vec=vector` |
| * `wdth=width` |
| |
| The configuration options for each implemented heuristic (see above) is |
| constructed dynamically. |
| In the following, `<HeuristicName>` refers to one of the keys from the |
| heuristics implemented. |
| |
| .. option:: <HeuristicName> |
| |
| `True` or `False`, whether a particular heuristic, such as `Equality` or |
| `Levenshtein` is enabled. |
| |
| Defaults to `True` for every heuristic. |
| |
| .. _opt_Bounds: |
| |
| .. option:: <HeuristicName>DissimilarBelow, <HeuristicName>SimilarAbove |
| |
| A value between `0` and `100`, expressing a percentage. |
| The bounds set what percentage of similarity the heuristic must deduce |
| for the two identifiers to be considered similar or dissimilar by the |
| check. |
| |
| Given arguments ``arg1`` and ``arg2`` passed to ``param1`` and ``param2``, |
| respectively, the bounds check is performed in the following way: |
| If the similarity of the currently passed argument order |
| (``arg1`` to ``param1``) is **below** the `DissimilarBelow` threshold, and |
| the similarity of the suggested swapped order (``arg1`` to ``param2``) is |
| **above** the `SimilarAbove` threshold, the swap is reported. |
| |
| For the defaults of each heuristic, :ref:`see above<heuristics>`. |
| |
| |
| Name synthesis |
| -------------- |
| |
| When comparing the argument names and parameter names, the following logic is |
| used to gather the names for comparison: |
| |
| Parameter names are the identifiers as written in the source code. |
| |
| Argument names are: |
| |
| * If a variable is passed, the variable's name. |
| * If a subsequent function call's return value is used as argument, the called |
| function's name. |
| * Otherwise, empty string. |
| |
| Empty argument or parameter names are ignored by the heuristics. |