0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Cognitive Complexity の Sequences of logical operators の考え方のメモ

Last updated at Posted at 2021-11-19

Cognitive Complexity とは

以下の記事が参考になったり、ググると色々と情報が見つかると思います。ここでは省略します。

Sequences of logical operators の扱い

以下のドキュメントが Cognitive Complexity の提案元です。

この中の Sequences of logical operators の考え方がいまいち理解できていません。

ドキュメントでは

Cognitive Complexity does not increment for each binary logical operator. Instead, it assesses a fundamental increment for each sequence of binary logical operators.

Because boolean expressions become more difficult to understand with mixed operators, Cognitive complexity increments for each new sequence of like operators.

と記載があり、また、以下のような例が示されています。

if (a          // +1 for `if`
    && b && c  // +1
    || d || e  // +1
    && f)      // +1

if (a          // +1 for `if`
    &&         // +1
    !(b && c)) // +1

二つ目の例で、論理演算のところで Cognitive Complexity が +2 になるのが理解できていません。

Cognitive Complexity のツールでどうしているか、テスト用のソースコードを調べました。

clang-tidy

単に丸括弧で囲んだだけの場合は、丸括弧が無い場合と同様に扱っています。

論理演算の途中に関数呼び出しがあり、その引数に論理演算がある場合は、別扱いで加算しています。

前述の提案元のドキュメントにある a && !(b && c) の場合はテストに入っていないようです。

Cognitive-Complexity-TS

丸括弧の有無について clang-tidy と同じようで、ただ、以下のテストが用意されている点が違います。

function parenthesesCanBreakSequence() {
    true && (true && true || true)  // → +3 としている
}

前述の提案元のドキュメントにある a && !(b && c) の場合はテストに入っていないようです。

gocognit

前述の提案元のドキュメントにある a && !(b && c) がテストに入っていて +2 としています。

phpcs-cognitive-complexity

前述の提案元のドキュメントにある a && !(b && c) がテストに入っていて +2 としています。

SonarQube C++ Community plugin (cxx plugin)

前述の提案元のドキュメントにある a && !(b && c) がテストに入っていて +2 としています。

clang-tidy で試してみる

実際の動作も確認してみます。

ayweak@localhost:~/workspace/tmp$ clang-tidy-12 --version
LLVM (http://llvm.org/):
  LLVM version 12.0.0

以下のような内容のソースコードを対象にします。

test3.c
# include <stdbool.h>

bool func1(bool a);
bool func2(bool a, bool b);

int main(int argc, char* argv[]) {
    true && true && true || true || true && true;

    true && !(true && true);

    true && func1(true && true) && true;
    true && func2(true && true, true && true) && true;

    true &&  true && true  && true;
    true && (true && true) && true;

    true ||  true && true  || true;
    true || (true && true) || true;

    true && (true && true || true);
    true && (true && true || true) && true;
}

compile_commands.json を用意しておきます。

compile_commands.json
[
  { "directory": "/home/ayweak/workspace/tmp",
    "command": "/usr/bin/clang-12 -std=c11 -c -o test3.o test3.c",
    "file": "test3.c"
  }
]

Cognitive Complexity 以外のチェックを抑制、また、Cognitive Complexity の出力の閾値を下げるように設定ファイルを作成します。

config.json
{
    "Checks": "-*,readability-function-cognitive-complexity",
    "CheckOptions": [
        { "key": "readability-function-cognitive-complexity.Threshold", "value": 1 }
    ]
}

以下のような結果になりました。

ayweak@localhost:~/workspace/tmp$ clang-tidy-12 --config-file=config.json test3.c
9 warnings generated.
test3.c:6:5: warning: function 'main' has cognitive complexity of 21 (threshold 1) [readability-function-cognitive-complexity]
int main(int argc, char* argv[]) {
    ^
test3.c:7:34: note: +1  → 提案元のドキュメントの例と同じ
    true && true && true || true || true && true;
                                 ^
test3.c:7:18: note: +1
    true && true && true || true || true && true;
                 ^
test3.c:7:42: note: +1
    true && true && true || true || true && true;
                                         ^
test3.c:9:10: note: +1  → 提案元のドキュメントの例と異なる
    true && !(true && true);
         ^
test3.c:11:33: note: +1
    true && func1(true && true) && true;
                                ^
test3.c:11:24: note: +1
    true && func1(true && true) && true;
                       ^
test3.c:12:47: note: +1
    true && func2(true && true, true && true) && true;
                                              ^
test3.c:12:24: note: +1
    true && func2(true && true, true && true) && true;
                       ^
test3.c:12:38: note: +1
    true && func2(true && true, true && true) && true;
                                     ^
test3.c:14:28: note: +1
    true &&  true && true  && true;
                           ^
test3.c:15:28: note: +1  → 丸括弧は影響しない
    true && (true && true) && true;
                           ^
test3.c:17:28: note: +1
    true ||  true && true  || true;
                           ^
test3.c:17:19: note: +1
    true ||  true && true  || true;
                  ^
test3.c:18:28: note: +1  → 丸括弧は影響しない
    true || (true && true) || true;
                           ^
test3.c:18:19: note: +1
    true || (true && true) || true;
                  ^
test3.c:20:10: note: +1  → Cognitive-Complexity-TS と同じく +3
    true && (true && true || true);
         ^
test3.c:20:27: note: +1
    true && (true && true || true);
                          ^
test3.c:20:19: note: +1
    true && (true && true || true);
                  ^
test3.c:21:36: note: +1
    true && (true && true || true) && true;
                                   ^
test3.c:21:27: note: +1
    true && (true && true || true) && true;
                          ^
test3.c:21:19: note: +1
    true && (true && true || true) && true;
                  ^
Suppressed 8 warnings (8 with check filters).
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?