From b5b359a6dfe28ec5077dd2ebe67bee7cbb59a2c5 Mon Sep 17 00:00:00 2001 From: Jonathan Christensen Date: Wed, 28 Jan 2026 14:49:31 -0700 Subject: [PATCH] Fixed nesting depth calculation --- checkers/complexity.py | 59 ++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/checkers/complexity.py b/checkers/complexity.py index 0c79ffe..d142d90 100644 --- a/checkers/complexity.py +++ b/checkers/complexity.py @@ -117,45 +117,36 @@ def _is_too_deeply_indented(node: ast.FunctionDef | ast.AsyncFunctionDef, conten def _get_max_indent_depth_from_source(node: ast.FunctionDef | ast.AsyncFunctionDef, content: str) -> int: - """Calculate maximum indentation depth within a function using source code. - + """Calculate maximum nesting depth using AST to avoid formatting false positives. + Args: node: Function definition node - content: Original file content as string - + content: Original file content (unused in AST approach but kept for signature) + Returns: - Maximum indentation depth within the function + Maximum logic nesting depth """ - lines = content.split('\n') - - # Get the function's line range - start_line = node.lineno - 1 # Convert to 0-based indexing - - # Find the end line of the function - end_line = _find_function_end_line(lines, start_line) - - # Get function source lines - function_lines = lines[start_line:end_line + 1] - - # Find the base indentation of the function definition - func_def_line = function_lines[0] - base_indent = len(func_def_line) - len(func_def_line.lstrip()) - max_depth = 0 - - # Check indentation of each line within the function - for line in function_lines[1:]: # Skip the function definition line - if not line.strip(): - continue - current_indent = len(line) - len(line.lstrip()) - if current_indent <= base_indent: - continue - function_body_indent = base_indent + 4 - if current_indent < function_body_indent: + base_col = node.col_offset + + BLOCK_NODES = ( + ast.If, ast.For, ast.AsyncFor, ast.While, ast.Try, ast.With, ast.AsyncWith, + ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef, + getattr(ast, 'Match', type(None)), getattr(ast, 'Case', type(None)) + ) + + for child in ast.walk(node): + if child is node: continue - depth = (current_indent - function_body_indent) // 4 + 1 - max_depth = max(max_depth, depth) - + + if isinstance(child, BLOCK_NODES): + # Calculate depth based on column offset relative to the function definition. + # We assume standard 4-space indentation. + # (col_offset - base) // 4 gives the block level (0 for function body) + # We add 1 because the content *inside* this block is one level deeper. + depth = (child.col_offset - base_col) // 4 + 1 + max_depth = max(max_depth, depth) + return max_depth @@ -191,4 +182,4 @@ def _find_function_end_line(lines: list[str], start_line: int) -> int: current_line += 1 # If we reach the end of the file, the function ends at the last line - return len(lines) - 1 \ No newline at end of file + return len(lines) - 1