242 lines
8.3 KiB
ReStructuredText
242 lines
8.3 KiB
ReStructuredText
.. 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.
|