Skip to content

complexity

Full name: tenets.core.examiner.complexity

complexity

Complexity analysis module for code examination.

This module provides deep complexity analysis for codebases, calculating various complexity metrics including cyclomatic complexity, cognitive complexity, and Halstead metrics. It identifies complex areas that may need refactoring and tracks complexity trends.

The complexity analyzer works with the examination system to provide detailed insights into code maintainability and potential problem areas.

Classes

ComplexityMetricsdataclass

Python
ComplexityMetrics(cyclomatic: int = 1, cognitive: int = 0, halstead_volume: float = 0.0, halstead_difficulty: float = 0.0, halstead_effort: float = 0.0, maintainability_index: float = 100.0, nesting_depth: int = 0, parameter_count: int = 0, line_count: int = 0, token_count: int = 0, operator_count: int = 0, operand_count: int = 0)

Detailed complexity metrics for a code element.

Captures various complexity measurements for functions, classes, or files, providing a comprehensive view of code complexity.

ATTRIBUTEDESCRIPTION
cyclomatic

McCabe's cyclomatic complexity

TYPE:int

cognitive

Cognitive complexity (how hard to understand)

TYPE:int

halstead_volume

Halstead volume metric

TYPE:float

halstead_difficulty

Halstead difficulty metric

TYPE:float

halstead_effort

Halstead effort metric

TYPE:float

maintainability_index

Maintainability index (0-100)

TYPE:float

nesting_depth

Maximum nesting depth

TYPE:int

parameter_count

Number of parameters (for functions)

TYPE:int

line_count

Number of lines

TYPE:int

token_count

Number of tokens

TYPE:int

operator_count

Number of unique operators

TYPE:int

operand_count

Number of unique operands

TYPE:int

Attributes
complexity_per_lineproperty
Python
complexity_per_line: float

Calculate complexity per line of code.

RETURNSDESCRIPTION
float

Cyclomatic complexity divided by lines

TYPE:float

risk_levelproperty
Python
risk_level: str

Determine risk level based on cyclomatic complexity.

Uses industry-standard thresholds to categorize risk.

RETURNSDESCRIPTION
str

Risk level (low, medium, high, very high)

TYPE:str

cognitive_risk_levelproperty
Python
cognitive_risk_level: str

Determine risk level based on cognitive complexity.

RETURNSDESCRIPTION
str

Cognitive risk level

TYPE:str

FunctionComplexitydataclass

Python
FunctionComplexity(name: str, full_name: str, file_path: str, line_start: int, line_end: int, metrics: ComplexityMetrics = ComplexityMetrics(), calls: Set[str] = set(), called_by: Set[str] = set(), is_recursive: bool = False, is_generator: bool = False, is_async: bool = False, has_decorator: bool = False, docstring: Optional[str] = None)

Complexity analysis for a single function or method.

Tracks detailed complexity metrics for individual functions, including their location, parameters, and various complexity scores.

ATTRIBUTEDESCRIPTION
name

Function name

TYPE:str

full_name

Fully qualified name (with class if method)

TYPE:str

file_path

Path to containing file

TYPE:str

line_start

Starting line number

TYPE:int

line_end

Ending line number

TYPE:int

metrics

Detailed complexity metrics

TYPE:ComplexityMetrics

calls

Functions called by this function

TYPE:Set[str]

called_by

Functions that call this function

TYPE:Set[str]

is_recursive

Whether function is recursive

TYPE:bool

is_generator

Whether function is a generator

TYPE:bool

is_async

Whether function is async

TYPE:bool

has_decorator

Whether function has decorators

TYPE:bool

docstring

Function docstring if present

TYPE:Optional[str]

Attributes
linesproperty
Python
lines: int

Get number of lines in function.

RETURNSDESCRIPTION
int

Line count

TYPE:int

has_documentationproperty
Python
has_documentation: bool

Check if function has documentation.

RETURNSDESCRIPTION
bool

True if docstring exists

TYPE:bool

ClassComplexitydataclass

Python
ClassComplexity(name: str, file_path: str, line_start: int, line_end: int, metrics: ComplexityMetrics = ComplexityMetrics(), methods: List[FunctionComplexity] = list(), nested_classes: List[ClassComplexity] = list(), inheritance_depth: int = 0, parent_classes: List[str] = list(), abstract_methods: int = 0, static_methods: int = 0, properties: int = 0, instance_attributes: int = 0)

Complexity analysis for a class.

Aggregates complexity metrics for an entire class including all its methods and nested classes.

ATTRIBUTEDESCRIPTION
name

Class name

TYPE:str

file_path

Path to containing file

TYPE:str

line_start

Starting line number

TYPE:int

line_end

Ending line number

TYPE:int

metrics

Aggregated complexity metrics

TYPE:ComplexityMetrics

methods

List of method complexity analyses

TYPE:List[FunctionComplexity]

nested_classes

List of nested class complexities

TYPE:List[ClassComplexity]

inheritance_depth

Depth in inheritance hierarchy

TYPE:int

parent_classes

List of parent class names

TYPE:List[str]

abstract_methods

Count of abstract methods

TYPE:int

static_methods

Count of static methods

TYPE:int

properties

Count of properties

TYPE:int

instance_attributes

Count of instance attributes

TYPE:int

Attributes
total_methodsproperty
Python
total_methods: int

Get total number of methods.

RETURNSDESCRIPTION
int

Method count

TYPE:int

avg_method_complexityproperty
Python
avg_method_complexity: float

Calculate average method complexity.

RETURNSDESCRIPTION
float

Average cyclomatic complexity of methods

TYPE:float

weighted_methods_per_classproperty
Python
weighted_methods_per_class: int

Calculate WMC (Weighted Methods per Class) metric.

Sum of complexities of all methods in the class.

RETURNSDESCRIPTION
int

WMC metric value

TYPE:int

FileComplexitydataclass

Python
FileComplexity(path: str, name: str, language: str, metrics: ComplexityMetrics = ComplexityMetrics(), functions: List[FunctionComplexity] = list(), classes: List[ClassComplexity] = list(), total_complexity: int = 0, max_complexity: int = 0, complexity_hotspots: List[Dict[str, Any]] = list(), import_complexity: int = 0, coupling: float = 0.0, cohesion: float = 0.0)

Complexity analysis for an entire file.

Aggregates all complexity metrics for a source file including functions, classes, and overall file metrics.

ATTRIBUTEDESCRIPTION
path

File path

TYPE:str

name

File name

TYPE:str

language

Programming language

TYPE:str

metrics

File-level complexity metrics

TYPE:ComplexityMetrics

functions

List of function complexities

TYPE:List[FunctionComplexity]

classes

List of class complexities

TYPE:List[ClassComplexity]

total_complexity

Sum of all complexity in file

TYPE:int

max_complexity

Maximum complexity found in file

TYPE:int

complexity_hotspots

Areas of high complexity

TYPE:List[Dict[str, Any]]

import_complexity

Complexity from imports/dependencies

TYPE:int

coupling

Coupling metric

TYPE:float

cohesion

Cohesion metric

TYPE:float

Attributes
avg_complexityproperty
Python
avg_complexity: float

Calculate average complexity across all functions.

RETURNSDESCRIPTION
float

Average complexity

TYPE:float

needs_refactoringproperty
Python
needs_refactoring: bool

Determine if file needs refactoring based on complexity.

RETURNSDESCRIPTION
bool

True if refactoring is recommended

TYPE:bool

ComplexityReportdataclass

Python
ComplexityReport(total_files: int = 0, total_functions: int = 0, total_classes: int = 0, avg_complexity: float = 0.0, max_complexity: int = 0, median_complexity: float = 0.0, std_dev_complexity: float = 0.0, high_complexity_count: int = 0, very_high_complexity_count: int = 0, files: List[FileComplexity] = list(), top_complex_functions: List[FunctionComplexity] = list(), top_complex_classes: List[ClassComplexity] = list(), top_complex_files: List[FileComplexity] = list(), complexity_distribution: Dict[str, int] = dict(), refactoring_candidates: List[Dict[str, Any]] = list(), technical_debt_hours: float = 0.0, trend_direction: str = 'stable', recommendations: List[str] = list(), _override_complexity_score: Optional[float] = None)

Comprehensive complexity analysis report.

Aggregates complexity analysis across an entire codebase, providing statistics, trends, and actionable insights.

ATTRIBUTEDESCRIPTION
total_files

Total files analyzed

TYPE:int

total_functions

Total functions analyzed

TYPE:int

total_classes

Total classes analyzed

TYPE:int

avg_complexity

Average cyclomatic complexity

TYPE:float

max_complexity

Maximum cyclomatic complexity found

TYPE:int

median_complexity

Median cyclomatic complexity

TYPE:float

std_dev_complexity

Standard deviation of complexity

TYPE:float

high_complexity_count

Count of high complexity items

TYPE:int

very_high_complexity_count

Count of very high complexity items

TYPE:int

files

List of file complexity analyses

TYPE:List[FileComplexity]

top_complex_functions

Most complex functions

TYPE:List[FunctionComplexity]

top_complex_classes

Most complex classes

TYPE:List[ClassComplexity]

top_complex_files

Most complex files

TYPE:List[FileComplexity]

complexity_distribution

Distribution of complexity values

TYPE:Dict[str, int]

refactoring_candidates

Items recommended for refactoring

TYPE:List[Dict[str, Any]]

technical_debt_hours

Estimated hours to address complexity

TYPE:float

trend_direction

Whether complexity is increasing/decreasing

TYPE:str

recommendations

List of actionable recommendations

TYPE:List[str]

Attributes
complexity_scoreproperty
Python
complexity_score: float

Calculate overall complexity score (0-100).

Lower scores indicate better (less complex) code.

RETURNSDESCRIPTION
float

Complexity score

TYPE:float

Functions
to_dict
Python
to_dict() -> Dict[str, Any]

Convert report to dictionary.

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: Dictionary representation

Source code in tenets/core/examiner/complexity.py
Python
def to_dict(self) -> Dict[str, Any]:
    """Convert report to dictionary.

    Returns:
        Dict[str, Any]: Dictionary representation
    """
    return {
        "total_files": self.total_files,
        "total_functions": self.total_functions,
        "total_classes": self.total_classes,
        "avg_complexity": round(self.avg_complexity, 2),
        "max_complexity": self.max_complexity,
        "median_complexity": round(self.median_complexity, 2),
        "std_dev_complexity": round(self.std_dev_complexity, 2),
        "high_complexity_count": self.high_complexity_count,
        "very_high_complexity_count": self.very_high_complexity_count,
        "complexity_distribution": self.complexity_distribution,
        "refactoring_candidates": self.refactoring_candidates[:10],
        "technical_debt_hours": round(self.technical_debt_hours, 1),
        "trend_direction": self.trend_direction,
        "recommendations": self.recommendations,
    }

ComplexityAnalyzer

Python
ComplexityAnalyzer(config: TenetsConfig)

Analyzer for code complexity metrics.

Provides comprehensive complexity analysis including cyclomatic complexity, cognitive complexity, and various other metrics to assess code maintainability and identify refactoring opportunities.

ATTRIBUTEDESCRIPTION
config

Configuration object

logger

Logger instance

complexity_cache

Cache of computed complexities

TYPE:Dict[str, Any]

Initialize complexity analyzer.

PARAMETERDESCRIPTION
config

TenetsConfig instance

TYPE:TenetsConfig

Source code in tenets/core/examiner/complexity.py
Python
def __init__(self, config: TenetsConfig):
    """Initialize complexity analyzer.

    Args:
        config: TenetsConfig instance
    """
    self.config = config
    self.logger = get_logger(__name__)
    self.complexity_cache: Dict[str, Any] = {}
Functions
analyze
Python
analyze(files: List[Any], threshold: float = 10.0, deep: bool = False) -> ComplexityReport

Analyze complexity for a list of files.

Performs comprehensive complexity analysis across all provided files, calculating various metrics and identifying problem areas.

PARAMETERDESCRIPTION
files

List of analyzed file objects

TYPE:List[Any]

threshold

Complexity threshold for flagging

TYPE:floatDEFAULT:10.0

deep

Whether to perform deep analysis

TYPE:boolDEFAULT:False

RETURNSDESCRIPTION
ComplexityReport

Comprehensive complexity analysis

TYPE:ComplexityReport

Example

analyzer = ComplexityAnalyzer(config) report = analyzer.analyze(files, threshold=10) print(f"Average complexity: {report.avg_complexity}")

Source code in tenets/core/examiner/complexity.py
Python
def analyze(
    self, files: List[Any], threshold: float = 10.0, deep: bool = False
) -> ComplexityReport:
    """Analyze complexity for a list of files.

    Performs comprehensive complexity analysis across all provided
    files, calculating various metrics and identifying problem areas.

    Args:
        files: List of analyzed file objects
        threshold: Complexity threshold for flagging
        deep: Whether to perform deep analysis

    Returns:
        ComplexityReport: Comprehensive complexity analysis

    Example:
        >>> analyzer = ComplexityAnalyzer(config)
        >>> report = analyzer.analyze(files, threshold=10)
        >>> print(f"Average complexity: {report.avg_complexity}")
    """
    self.logger.debug(f"Analyzing complexity for {len(files)} files")

    report = ComplexityReport()
    all_complexities = []

    for file in files:
        if not self._should_analyze_file(file):
            continue

        # Analyze file complexity
        file_complexity = self._analyze_file_complexity(file, deep)
        if file_complexity:
            report.files.append(file_complexity)
            report.total_files += 1

            # Collect all function complexities
            for func in file_complexity.functions:
                all_complexities.append(func.metrics.cyclomatic)
                report.total_functions += 1

                # Track high complexity functions
                if func.metrics.cyclomatic > threshold:
                    report.high_complexity_count += 1
                    if func.metrics.cyclomatic > threshold * 2:
                        report.very_high_complexity_count += 1

                # Update max complexity
                report.max_complexity = max(report.max_complexity, func.metrics.cyclomatic)

            # Process classes
            for cls in file_complexity.classes:
                report.total_classes += 1
                for method in cls.methods:
                    all_complexities.append(method.metrics.cyclomatic)
                    report.total_functions += 1

                    if method.metrics.cyclomatic > threshold:
                        report.high_complexity_count += 1
                        if method.metrics.cyclomatic > threshold * 2:
                            report.very_high_complexity_count += 1

    # Calculate statistics
    if all_complexities:
        report.avg_complexity = sum(all_complexities) / len(all_complexities)
        report.median_complexity = self._calculate_median(all_complexities)
        report.std_dev_complexity = self._calculate_std_dev(all_complexities)

    # Calculate distribution
    report.complexity_distribution = self._calculate_distribution(all_complexities)

    # Identify top complex items
    self._identify_top_complex_items(report)

    # Identify refactoring candidates
    self._identify_refactoring_candidates(report, threshold)

    # Estimate technical debt
    report.technical_debt_hours = self._estimate_technical_debt(report)

    # Generate recommendations
    report.recommendations = self._generate_recommendations(report)

    self.logger.debug(f"Complexity analysis complete: avg={report.avg_complexity:.2f}")

    return report
analyze_file
Python
analyze_file(file_analysis: Any) -> Dict[str, Any]

Analyze complexity for a single file.

PARAMETERDESCRIPTION
file_analysis

Analyzed file object

TYPE:Any

RETURNSDESCRIPTION
Dict[str, Any]

Dict[str, Any]: File complexity details

Source code in tenets/core/examiner/complexity.py
Python
def analyze_file(self, file_analysis: Any) -> Dict[str, Any]:
    """Analyze complexity for a single file.

    Args:
        file_analysis: Analyzed file object

    Returns:
        Dict[str, Any]: File complexity details
    """
    file_complexity = self._analyze_file_complexity(file_analysis, deep=True)

    if not file_complexity:
        return {}

    return {
        "cyclomatic": file_complexity.metrics.cyclomatic,
        "cognitive": file_complexity.metrics.cognitive,
        "avg_complexity": file_complexity.avg_complexity,
        "max_complexity": file_complexity.max_complexity,
        "total_complexity": file_complexity.total_complexity,
        "functions": len(file_complexity.functions),
        "classes": len(file_complexity.classes),
        "needs_refactoring": file_complexity.needs_refactoring,
        "risk_level": file_complexity.metrics.risk_level,
        "maintainability_index": file_complexity.metrics.maintainability_index,
    }

Functions

analyze_complexity

Python
analyze_complexity(files: List[Any], threshold: int = 10, config: Optional[TenetsConfig] = None) -> ComplexityReport

Analyze complexity for a list of files.

Thin wrapper that constructs a ComplexityAnalyzer and returns its report.

PARAMETERDESCRIPTION
files

List of analyzed file-like objects

TYPE:List[Any]

threshold

Threshold for high/very high classification

TYPE:intDEFAULT:10

config

Optional TenetsConfig instance

TYPE:Optional[TenetsConfig]DEFAULT:None

RETURNSDESCRIPTION
ComplexityReport

ComplexityReport

Source code in tenets/core/examiner/complexity.py
Python
def analyze_complexity(
    files: List[Any], threshold: int = 10, config: Optional[TenetsConfig] = None
) -> ComplexityReport:
    """Analyze complexity for a list of files.

    Thin wrapper that constructs a ComplexityAnalyzer and returns its report.

    Args:
        files: List of analyzed file-like objects
        threshold: Threshold for high/very high classification
        config: Optional TenetsConfig instance

    Returns:
        ComplexityReport
    """
    cfg = config or TenetsConfig()
    analyzer = ComplexityAnalyzer(cfg)
    return analyzer.analyze(files, threshold=float(threshold), deep=False)