Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exclude macro expansions from complexity metrics/checks #1552

Merged
merged 1 commit into from
Sep 10, 2018

Commits on Sep 5, 2018

  1. exclude macro expansions from complexity metrics/checks

    * partial solution for SonarOpenCommunity#1547
    
    MOTIVATION:
    
    * SonarOpenCommunity#1494 made visible the fact, that preprocessor affects the complexity
    metric. E.g. if function uses macros, the underlying (hidden) complexity
    of theses macros increases the complexity of the function. This is wrong
    because of many reasons:
    
    1. Cognitive complexity:
    Macros do not increase the cognitive complexity of the source code. To
    the reader they are similar to the function invocations.
    Example ASSERT_XX/EXPECT_XX macros of GTest.
    
    2. Cyclomatic complexity:
    Similar logic might be applied to the cyclomatic complexity: macro expansions
    are similar to the function calls (which become inlined). In this case
    the cyclomatic complexity of the caller should not be increased.
    [Cyclomatic] complexity of the callee must be calculated separately.
    
    3. Preprocessor doesn't distinguish between the macros, which
    were declared inside of the analyzed project or were included from the
    external header. Obviously the external source code (e.g. again very
    complex GTest macros) should not affect the complexity of someone's
    custom SonarQube project.
    
    SOLUTION:
    
    In general it's impossible to build a valid C/C++ AST without
    performing of preprocessor step. The original source code might
    be syntactically incorrect (e.g. if macros are used to "invent" some
    domain specific language out of C/C++). All metrics of sonar-cxx
    are however AST-based. (This is a very questionably decision
    e.g. because #if/#ifdef etc might affect the resulting complexity or [NC]LOC
    in dramatic way). So we cannot skip preprocessor step entirely and/or
    perform metrics calculation/checks on the non-preprocessed code.
    
    Sonar SSLR has a possibility to mark some tokens as generated.
    This property (`Token::isGeneratedCode()`) is for example used
    in order to ignore generated while
    * [NC]LOC counting (see `AbstractLineLengthCheck<>`)
    * CDP analysis (see `CxxCpdVisitor`) or
    * Highlighting (see `CxxHighlighterVisitor`)
    
    This patch ensures, that
    * all `AstNode`s, which were created while macro expansion are marked as
    generated
    * all complexity related visitors ignore generated `AstNode`s
    
    RESULT:
    
    PRO:
    1. The complexity of "callers" is not affected by macro anymore.
       This fact makes the complexity check look logical again.
    
    CON:
    1. the complexity of "callees" is not calculated at all. This
    is correct in case of external macros, but wrong w.r.t. to the
    project intern macros. Possible solution: preprocessor must try
    to extract the function-like macro declaration into some special AST-subtree.
    Afterwards complexity metrics/check will be able to calculate/check
    macros as separate language construct.
    
    By the way: it must be analyzed if and how macros affect other metrics.
    For example LOC etc.
    
    2. This patch might change the complexity related metrics. Depending
    on how many macros were used in the analyzed project, the reduction
    can be radical.
    ivangalkin committed Sep 5, 2018
    Configuration menu
    Copy the full SHA
    b7aac5b View commit details
    Browse the repository at this point in the history