Giter Club home page Giter Club logo

cognitive_complexity's People

Contributors

fhightower avatar melevir avatar pkolbus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

cognitive_complexity's Issues

Try-blocks counts every line

From https://www.sonarsource.com/docs/CognitiveComplexity.pdf: instance, in the following example, there is no nesting increment for the method itself or for the try because neither structure results in either a structural or a hybrid increment:

also:

However, the if, for, while, and catch structures are all subject to both structural and
nesting increments.

In [1]: get_code_snippet_compexity('''
    ...: def my_method():
    ...:   try:
    ...:     print('hello')
    ...:     print('hello')
    ...:   except Exception as e:    # +1 nesting = 0
    ...:       return 0
    ...:         ''')
Out[1]: 2

In [2]: get_code_snippet_compexity('''
    ...: def my_method():
    ...:   try:
    ...:     print('hello')
    ...:     print('hello')
    ...:     print('hello')
    ...:   except Exception as e:    # +1 nesting = 0
    ...:       return 0
    ...:         ''')
Out[2]: 3

All these should be 1...?

Increment nesting, but not increment complexity for lambdas and nested methods

Additionally, while top-level methods are ignored, and there is no structural increment for
lambdas, nested methods, and similar features, such methods do increment the nesting
level when nested inside other method-like structures

Current algorithms skips lambdas and increments complexity for nested methods.

Add test on big function

Should test on complex function with nested nodes etc.

This is required to check that recursive get_cognitive_complexity_for_node calls passes all params correctly.

Not increment complexity for try block

Original paper says:

Note that a catch only adds one point to the Cognitive Complexity score, no matter how many exception types are caught. try and finally blocks are ignored altogether.

Now try block is incremented by one, it should not

Not increment nesting for decorators

Python’s decorator idiom allows additional behavior to be added to an existing function
without modifying the function itself. This addition is accomplished with the use of nested
functions in the decorator providing the additional behavior. In order not to penalize Python
coders for the use of a common feature of their language, an exception has been added.
However, an attempt has been made to define the exception narrowly. Specifically, to be
eligible for the exception, a function may contain only a nested function and a return
statement.

This is valid after #3 is done.

Incorrect counting for sequences of binary logical operators

According to the Cognitive Complexity specification, sequences of binary logical operators receive a fundamental increment (B1) but not a nesting increment (B3). This is further supported by the overriddenSymbolFrom() example in appendix C.

The existing test_real_function() should be calculated as follows; note the +4 for the multiline if condition should be +2.

assert get_code_snippet_compexity("""
def process_raw_constant(constant, min_word_length):
    processed_words = []
    raw_camelcase_words = []
    for raw_word in re.findall(r'[a-z]+', constant):  # +1
        word = raw_word.strip()
        if (  # +2
            len(word) >= min_word_length
            and not (word.startswith('-') or word.endswith('-'))  # +2 (2 bool operator sequences)
        ):
            if is_camel_case_word(word):  # +2
                raw_camelcase_words.append(word)
            else:  # +1
                processed_words.append(word.lower())
    return processed_words, raw_camelcase_words
""") == 9  # not 11

Incorrect result for else/elif

Thanks for the great package and flake8 plugin.

I've noticed that else (and nested elif) seem to be counted incorrectly. Based on my reading of the whitepaper (section B3, the discussion of "hybrid" increments, overriddenSymbolFrom() and other examples in section C, and the whitepaper's change log), else and elif are not subject to the nesting increment.

Sample test cases:

# passes
def test_nested_if_condition_complexity():
    assert get_code_snippet_compexity("""
    def f(a, b):
        if a == b:  # +1
            if (a):  # +2 (nesting=1)
                return 1
        return 0
    """) == 3

# fails (actual=1, expected=2)
def test_simple_else_condition_complexity():
    assert get_code_snippet_compexity("""
    def f(a):
        if (a):  # +1
            return 1
        else:  # +1
            return 3
    """) == 2

# fails (actual=3, expected=4)
def test_nested_else_condition_complexity():
    assert get_code_snippet_compexity("""
    def f(a, b):
        if a == b:  # +1
            if (a):  # +2 (nesting=1)
                return 1
            else:  # +1
                return 3
        return 0
    """) == 4

# fails  (actual=6, expected=5)
def test_nested_elif_condition_complexity():
    assert get_code_snippet_compexity("""
    def f(a, b):
        if a == b:  # +1
            if (a):  # +2 (nesting=1)
                return 1
            elif (b):  # +1
                return 2
            else:  # +1
                return 3
        return 0
    """) == 5

I'm not terribly familiar with Python AST parsing. But if you like, I can try working on a PR if you want (and agree it's an actual bug).

Document try complexity computation

Hi, thanks for this great tool 😄 I was scratching my head when adding/removing any lines from try block was influencing cognitive complexity and searched in your documentation and then code why is that and found this line in code:

# add +1 for all try nodes except body

It means that any line added inside try block will increment complexity (code below gives complexity 4)

def a(b, c):
    try:
        print(1)
        print(2)
        print(3)
        print(4)
    except Exception:
        raise

This behavior is unexpected as it was not mentioned in SonarSource links provided, can we document it here or in flake8 extension? Thanks

Incorrect counting for break and continue

According to the Cognitive Complexity specification, a fundamental increment is assessed for "goto, and break or continue to a label." (page 7 and section B1; emphasis mine). Simple break and continue do not receive an increment, as illuminated by the example for addVersion() in Appendix C, and by the justification that early exit tends to improve readability (page 7). (Further, the break in linear flow is already accounted for in the if, as break and continue only make sense within a conditional.)

The implementation assesses a structural increment for these constructs, causing complexity scores to be inflated. For example, test_break_and_continue() should be:

assert get_code_snippet_compexity("""
def f(a):
    for a in range(10):  # +1
        if a % 2:  # +2
            continue  # no increment
        if a == 8:  # +2
            break  # no increment
""") == 5

Add motivation docs

Add article on comparing cognitive complexity to cyclomatic, show code samples, explain reasoning, show use cases.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.